Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The server

One download request

The whole access model is one table:

SituationAnswer
the public directorythe package, or 404
a protected directory, no live key401, whether or not the package exists
a protected directory, a live key without the grant404, the same as “no such package”
a protected directory, a live key with the grantthe package, or 404

There is no 403: “exists, but not for you” is the enumeration signal this avoids. /packages is the exception that proves the rule: it never answers 4xx, filters silently to the public and granted directories, and falls back to the public listing when the database is down. A key is validated with /whoami, not with /packages.

The URL parts (game, directory, name) are manifest lookup keys, never path fragments: only a manifest hit yields data/<game>/packages/<directory>/<name>.zip. That is what prevents traversal structurally, and what makes the {*name} wildcard safe.

Two smaller decisions the diagram shows: an Authorization value that cannot be a minted key is turned away before any query, so garbage stays cheap; and a file whose size disagrees with the manifest is refused with 503 rather than streamed — the client would fail its own sha256 check anyway.

Publishing

Publishing is copying a zip into place and running one command. The command is strict on purpose:

  • no schema.toml → the game publishes nothing (an error, not a warning);
  • a package in a category the schema does not declare → skipped, with a warning;
  • a sidecar with an unknown key → that package is withheld, the rest still publishes, and the run exits 2;
  • metadata the current manifest carries would disappear → refused, exit 1, nothing written, unless --accept-metadata-loss;
  • a game that is live now would vanish because its schema is missing → refused, exit 1, unless --accept-unpublish.

The manifest is a pure function of zips, sidecars and schemas: nothing is inherited from the previous one, so deleting a sidecar key removes it at the next publish. The two guards exist because that purity is also what lets an accidental upgrade empty a live catalogue.

manifest gen also reads the last 30 days of conflict reports and turns them into per-pair warnings: a user’s bad day becomes something the operator can fix in the catalogue.