Concepts¶
The nouns, in dependency order. What each one owns is what decides where a setting lives.
Organisation¶
A tenant. Owns zones, users and tokens, and may carry a storage quota across all of them. Created by the operator with cdn create-org, because there is no self-service signup.
Zone¶
The unit of URL, configuration and statistics. Its name is the first path segment of every object in it, and names are global: they are part of a public URL, so two organisations cannot both hold assets.
A zone is storage or pull, and never changes kind — the two keep their bytes in different places, and switching would strand whichever copy the old kind owned. See Mirroring an origin.
Object¶
A file inside a storage zone, addressed by path. The database row is the index of record — path, size, content type, etag, timestamps, storage key, and any per-object caching override — while S3 holds the bytes.
Objects are not versioned. A PUT to an existing path replaces it and a DELETE removes it; both leave an audit entry.
Token¶
A machine credential, cdn_<key id>_<secret> on the wire. Only a hash of the secret is stored — the secret is 160 bits from the system RNG, so there is no dictionary to slow down and a password KDF would only add latency to every request.
A token carries:
- scopes:
read,write,delete,purge,stats; - an optional zone restriction, limiting it to one zone;
- an optional path prefix, limiting it to paths under that prefix.
The prefix covers reads and listings as well as writes. A restriction that stopped at writes would let a deploy key for releases/ list every path in the zone anyway, which is a restriction in name only.
Authorization is decided once, at the request boundary, producing a principal the rest of the request can trust.
Cached entry¶
A file on the local disk plus a metadata sidecar. Not a database row, and not durable: losing the cache directory costs latency, never data. Entries are keyed by zone id, so renaming a zone does not strand its cache.
Stat bucket¶
One counter: how much of one path of one zone went out in one period, at hourly or daily granularity. Those dimensions are its identity — a counter that could exist twice for the same ones would be a lost increment rather than a second fact. See Knowing what is downloaded.
Audit entry¶
Who did what, to what, from where. Append-only, kept a year.
The actor is described as well as referenced: a token that has since been revoked still has to have a name against the entries it left, or the log stops answering the question it exists for. The address recorded is the peer that sent the request, which behind a proxy is the proxy — the client's own address would need a trusted-proxy configuration this service does not have.
Reads are not recorded. That is what the statistics are for, and a log with a line per download is one nobody reads.
Roles¶
| what it may do | |
|---|---|
| member | use the zones and tokens of their organisation |
| owner | also invite people, and empty a whole zone's cache |
| admin | Abilian staff; sees every organisation |
URL layout¶
https://cdn.example.com/<zone>/<path> delivery
https://assets.acme.com/<path> delivery, via a zone's own hostname
https://cdn.example.com/_/ui/… the browser UI
https://cdn.example.com/_/api/v1/… the HTTP API
https://cdn.example.com/_/s3/<zone>/<path> the S3 endpoint
https://cdn.example.com/_/health the health check
Everything the service exposes for its own sake sits under the reserved /_/ prefix, because the top-level namespace outside it belongs to zone names.