KeyAuth
Sign in

Releases and files

Your payload lives here. A release is a versioned bundle of files, each addressed by a JSON key your client reads.

The model

  • An application owns many releases. A release is a version label plus one or more files.
  • Exactly one release is active. Only the active one is ever delivered.
  • Each file has a JSON key you choose, such as core or driver.
  • The same key intentionally repeats across releases. That is what makes an update a swap.

A release version is not the client version. It is never compared against the build your loader reports. See core concepts.

How it reaches the client

On a successful login the server returns the active release and its files:

login response
"release": { "version": "1.4.2", "notes": "…", "files": 2 },
"files": [
  { "key": "core",   "size": 300000, "chunks": 5, "chunk_bytes": 65536,
    "compression": "deflate", "sha256": "…", "inline": false },
  { "key": "driver", "size": 5400,   "chunks": 1, "chunk_bytes": 65536,
    "compression": "deflate", "sha256": "…", "inline": true,
    "data": "<base64>" }
]
File sizeHow it travels
At or below the inline limitBase64 in the login response itself. One round trip, bytes ready immediately.
LargerMetadata only. The client pulls encrypted chunks with file.chunk.

The limit is Inline delivery limit in application settings, 256 KB by default. Raising it far is a bad idea: base64 of a 50 MB module expands to roughly 67 MB held in memory on both sides of a single request.

In the SDK both paths look identical, because download() resolves whichever applies:

cpp
for (const keyauth::FileInfo&amp; info : client.files()) {
    std::vector&lt;std::uint8_t&gt; payload;
    client.download(info.key, payload);   // inline or chunked, digest verified
}

How files are stored

Each upload is compressed with deflate, split into chunks, and every chunk is encrypted with its own AES-256-GCM tag bound to its index. Chunks therefore cannot be reordered, swapped between files or replayed. The SHA-256 of the original plaintext is kept so the client can verify what it rebuilt. If a payload does not compress, it is stored uncompressed rather than padded.

Shipping an update

  1. Create a new release, for example 1.4.3.
  2. Upload the files, reusing the same JSON keys.
  3. Press Make active.

Clients receive the new bundle on their next login with no code change. Keep the previous release around and you can roll back by activating it again.

Level gating

A release declares a minimum level. Keys below it receive no release at all, not an empty one. Individual files can also be disabled, which hides them from clients while keeping them uploaded.

A release with no enabled file cannot be activated, and deleting a release deletes its stored blobs. Both are deliberate: the first prevents shipping an empty bundle, the second prevents orphaned files filling the disk.