Why bind an ingest key's permissions and its rate ceiling to the key itself rather than to the partner account behind it?
answer
- one station, several jobs
- the key is the unit of authority
- narrow at creation, not later
- restriction, never a grant
- ceiling per key isolates a backfill
basics
~20 sBecause a station holds several keys for different jobs. Per-key permissions mean a leak exposes only what that job needed; per-key ceilings stop a runaway backfill starving the live feed; and revoking one key leaves the others running. Effective authority is the key's scope intersected with the account's.
solid answer
~40 sA partner station is not one caller. It has a field logger that writes its own channel, a backfill script that replays archives, and a dashboard that reads. Give each its own key, and bind both the permissions and the rate ceiling to the **key row**, not to the station account. Three payoffs: a leaked logger key can write one series and read nothing; a backfill that goes into a retry storm hits its own ceiling instead of the station's shared one; and revoking one key does not take the partner offline. The rule that keeps this sound is **intersection** — the effective authority is the key's scope *and* the account's current entitlements, evaluated per request, so removing an entitlement at the account level cannot be outlived by a wide key scope.
code
json · 13 lines[
{ "key_id": "7f3a91c4", "label": "field logger",
"scope": ["readings:write:GSN-0142/BHZ"],
"quota_per_minute": 600 },
{ "key_id": "c20be714", "label": "archive backfill",
"scope": ["readings:write:GSN-0142/*", "readings:replay:GSN-0142/*"],
"quota_per_minute": 120 },
{ "key_id": "aa4f0d92", "label": "dept dashboard",
"scope": ["readings:read:GSN-0142/*"],
"quota_per_minute": 60 }
]go deeper
Recall that one partner usually holds several keys, and each one should be able to do only its own job, so that losing one exposes as little as possible.
Design the row: resource-shaped scope entries, a ceiling on the key as well as on the account, and the intersection rule that stops a key outliving an entitlement.
Bring the operational argument — which of a partner's workloads must never be refused, and why the isolation that guarantees it has to live on the key rather than the account.
Set the default. Whether the console's easiest path creates a narrow key or a full-privilege one decides what the estate looks like in a year, more than any policy document will.
## The unit of authority is the key, not the partner Station `GSN-0142` is a building with three things in it that talk to your ingest service: a field logger in the vault writing a continuous channel, a technician's backfill script that replays a disk of archived readings after an outage, and a departmental dashboard that reads the last 24 hours. Modelling all three as 'the station's credential' means one string with the union of everything they need — write anything, read anything, at whatever rate the account allows. Making the **key** the unit of authority breaks that union apart. ## What per-key scope buys - **Blast radius.** A logger key pasted into a public notebook can write one channel of one station. It cannot read the network's other series, and it cannot delete anything. The incident is bounded before it happens. - **Least privilege that is actually achievable.** Nobody will narrow an account's permissions, because the account has to be able to do everything anyone at that station does. A key issued for one job is narrowed at the moment of creation, when the narrowest scope is obvious. - **Independent revocation.** Killing the backfill key does not stop the live feed. If all three jobs shared one credential, every revocation is an outage, and you learn to hesitate before revoking — which is the failure mode that turns a small leak into a long one. - **Attribution.** Every accepted request is recorded against a key identifier, so 'who wrote these malformed samples at 02:00' has an answer more precise than 'the station'. ## The intersection rule Scope on a key is a *restriction*, never a grant. A key may narrow what its account can do; it can never widen it. ``` effective = key.scope INTERSECT account.entitlements(now) ``` The `now` matters. The account's entitlements are read at request time, not frozen into the key at issuance. If the partnership with a station ends and the account loses `readings:write`, every key it ever issued goes dead in the same instant, with no sweep over key rows. A key's own scope is ordinary data on the row and can be edited — but widening it is an audited event with an actor and a reason, precisely because it is the one edit that can increase authority. ## Quota on the key, not on the account | Ceiling attached to | What a retry storm does | What you can tell the partner | |---|---|---| | The station account | The backfill consumes the shared budget and the live feed starts getting refused | 'Your station is over its limit' — true, useless | | Each key | The backfill hits its own ceiling; the logger's continuous writes are untouched | 'Your backfill key is saturated, your feed is fine' | That is the whole argument for per-key ceilings: **isolation between a partner's own workloads**. The live channel is the one that must never be refused; a replay job that finishes an hour later has cost nobody anything. Attaching the ceiling to the key is what lets you say so in configuration rather than in an incident review. You will usually want both — a per-key ceiling *and* a per-account ceiling above it — because the account ceiling is what protects you from a partner with forty keys. How any ceiling is counted, what happens to a burst, and what the refusal response carries are a rate-limiting subject in their own right; the decision on this leaf is only what the ceiling is **attached to**. ## Modelling it Keep the scope as data on the key row rather than as a role name, because the interesting scopes are resource-shaped: this key may write *this station's* channels, that key may read *these* series. A scope entry that names the resource is checkable with the same expression whichever job presents it. A practical default at creation: the console proposes the narrowest scope that matches the stated purpose, and widening is an explicit action. The opposite default — every new key gets everything, narrow it later — produces four hundred fully privileged keys within a year, because nobody comes back later. ## The failure modes to name - **Scope creep at issuance.** The console makes 'all permissions' one click and the narrow scope three; within a year the model is decorative. - **Unscoped legacy keys.** Keys issued before scopes existed, still live, still unlimited. They need an inventory, a deadline and a migration, not a note in a wiki. - **Quota only at the account.** One partner's retry storm refuses that partner's own live feed — and seismic data arriving late is data arriving useless. - **Treating scope as identity.** A key's scope says what it may do; it does not say who the human behind it was. If you need that, record it separately at issuance.
- A partner asks for one key that does everything, because managing three is a nuisance. What do you say?Say yes only if you also say what it costs them: any leak of that key exposes every series they can reach, and any revocation takes their live feed down with it. Usually the nuisance is a tooling problem — a console that creates a correctly scoped key per job in one click, and shows last-used so stale ones are obvious, removes most of the objection.
- The station account loses an entitlement. Do you have to sweep its keys?No, if the check is an intersection evaluated at request time: the account's entitlements are read live, so every key narrows immediately with no sweep. You do sweep for hygiene — a key whose scope is now entirely outside the account's entitlements is dead weight and should be revoked — but correctness does not depend on that job running.
- Should the key's scope be checked at the edge or in the application?Whichever component you can guarantee is on every path. An edge check is cheap and catches the obvious, but the authoritative check belongs where the resource is known — the handler that knows this write targets series `GSN-0142/BHZ` is the only place that can compare it against a resource-shaped scope. If both run, the edge is an optimisation, never the decision.
saying these in an interview costs you the question
- Gives every key the account's full permissions and plans to narrow them later
- Treats a key's scope as able to grant more than the account holds
- Puts the only rate ceiling on the account, so a backfill refuses the live feed
- Says one key per partner is simpler, without pricing the outage a revocation causes
- Freezes the account's entitlements into the key at issuance and never re-reads them
- Uses a coarse role name where the scope needs to name the resource