An enforced operation allowlist breaks any unregistered document — how do you set enforcement and retention policy when old app builds stay pinned for months?
answer
- The gate closes on your own users
- Watch before you enforce
- Retention follows versions, not days
- Plan the exit before the incident
- Frozen text, unfrozen values
basics
~20 sRun in log-only mode until the miss log holds no legitimate callers, then enforce. Tie document retention to the client-version support window rather than a fixed timer, scope the set per client, and keep an audited operator escape hatch.
solid answer
~50 sEnforcement is a fail-closed gate, so every policy question is about who it closes on. Start in **log-only mode**: record each miss with its caller, credential and client version, and hold that for at least a full release cycle before switching on. Retention of old documents is then a function of your **client-version support window**, not a fixed number of days — a pinned build in the field is a document you may not delete. **Scope the set per client identity**, so a public app's credentials cannot run a back-office document. Keep an audited **break-glass path** for arbitrary documents, because an incident will need a query nobody registered. The trap to name unprompted: the allowlist freezes the *document*, not the *response*. A pinned build's hash is unchanged when you add an enum value, so the gate admits it and the old client still breaks.
code
graphql · 7 linesenum AppointmentStatus {
BOOKED
CHECKED_IN
COMPLETED
CANCELLED
RESCHEDULED_BY_CLINIC
}go deeper
Understand that enforcement is fail-closed: a client holding a document nobody registered simply stops working. That is why the switch is preceded by a watching period rather than flipped on a Friday.
Be able to describe the rollout — log misses with caller and client version, enforce only once every miss is explained — and why a registered document cannot be deleted while a pinned build still sends it.
Bring the operational detail: per-client scoping, release-tagged sets, an audited break-glass path, and the durability requirement that enforcement puts on the document store.
Price the trade. You are exchanging a smaller, enumerable attack surface for schema evolution gated on client adoption, and you are taking on an inventory obligation. Say when that trade is not worth making.
## What you are really deciding Enabling an operation allowlist is not a feature flag; it is a commitment that the endpoint will refuse anything the organisation has not pre-agreed to serve. That is exactly the property you want as a security control, and it makes the client release train a hard dependency of the graph. Every hard question that follows is a variant of one question: *what happens to a caller who is holding a document you no longer serve?* ## Rollout: log-only long enough to be boring Enforce nothing on day one. Run the membership check, record every miss, and serve the request anyway. The log entry needs the caller identity, the credential, the client version and the document — enough to distinguish an unmigrated internal tool from a scraper. Hold that mode for a full release cycle at minimum; on a mobile client, hold it for longer than your slowest adopters take to roll forward, because you are measuring the tail, not the median. The exit criterion is not "the miss rate is low". It is "every miss in the log is explained", which is a different and much stronger statement. A 0.3% miss rate that turns out to be the entire clinician tablet fleet is not a rounding error. ## Retention: keyed to versions, not to days A document is removable when no supported client can still send it. That makes retention a function of the client-version support window and of the actual version distribution in the field, and it means a fixed thirty- or ninety-day timer is the wrong instrument — it will either delete documents a pinned build still needs, or hoard documents from builds nobody has run in a year. What makes this tractable is scoping the registered set per client identity and per release. If each release's documents are tagged, then "which documents can I retire" reduces to "which releases are below the supported floor", which is a number the mobile team already tracks. Without that tagging the set is one undifferentiated pile and nothing can safely be removed, which is how allowlists silently become append-only. ## Per-client scoping One global set is the default and the wrong default. If the public app's credential can execute any registered document, then every internal tool's document — the bulk export, the administrative reassignment mutation — is reachable with a patient's session. Scoping the set to the client identity restores least privilege to a control that otherwise widens it, and it gives you the release tagging that retention needs. ## The escape hatch, designed before it is needed During an incident somebody will need a query that nobody registered. If there is no legitimate path for that, the gate gets switched off globally at 3 a.m. and, in practice, never gets switched back on. Design the exit deliberately: arbitrary documents accepted only for an operator credential, on an audited path, ideally read-only, with an expiry on the grant. A break-glass mechanism that logs who used it and closes itself is a control; a global toggle is a liability. ## The trap: the allowlist freezes documents, not responses Here is the failure that makes this a lead-level topic. In a hospital appointment graph, a mobile build shipped eleven months ago registered an `AppointmentCard` document selecting `appointment { id scheduledFor status }`. This year the clinic-operations team adds `RESCHEDULED_BY_CLINIC` to the `AppointmentStatus` enum — an additive schema change, non-breaking by every conventional rule, requiring no client change. The old build's document text is unchanged, so its hash is unchanged, so the allowlist admits it exactly as before. The response now carries an enum value nobody handled: the pinned build's switch over statuses falls through to a branch that renders an empty card, and for a fortnight a slice of patients see appointments with no state at all. Nothing in the security control fired, because nothing about the *document* changed. Two lessons come out of this, and they are the ones worth leading with in an interview. First, an allowlist gives you no protection against response-level evolution — enum additions, a field that starts returning null, an error where a value used to be. Second, and more usefully, the allowlist is the best inventory you will ever have of who selects what: because the set is finite and tagged by release, you can answer "which live builds select `status`" exactly, rather than inferring it from sampled field-usage telemetry. Use it that way — as a ledger — and enum additions get the same review as deletions when a pinned client is in scope. ## The cost you are signing up for The union of registered documents is a contract you cannot break unilaterally. Every field selected by a document belonging to a supported build has to keep working, so schema deletions now require a version-distribution argument rather than a deprecation period. That is a real tax, and the honest principal answer prices it: you are trading a much smaller, enumerable attack surface for a graph whose evolution is gated on client adoption. On a public endpoint with mobile clients that is usually worth it. On an internal graph consumed by services you deploy yourself, the same rigidity buys much less, and lighter controls may be the better call.
- An incident needs a query nobody registered. What is the plan?A pre-agreed break-glass path: arbitrary documents accepted only for an operator credential, on an audited route, ideally read-only, with the grant expiring on its own. Design it before you need it. A fail-closed gate with no legitimate exit gets disabled globally under pressure and stays disabled.
- Should every client share one registered set?No. Scope the set to the client identity, or a patient's session can execute the back-office export document simply because it is registered. Per-client scoping also gives you the release tagging that retention decisions need — without it the set is one undifferentiated pile and nothing can safely be removed.
- A pinned build's registered document is unchanged, yet the old app started rendering blanks. How?The allowlist gates document text, not response values. Adding an enum value, or changing when a field returns null, leaves the hash identical, so the gate admits the request and the old client meets a value it has no branch for. Additive schema changes still need a version-distribution review when pinned clients are in scope.
- How do you decide when a registered document can finally be deleted?When no supported client version can send it. That needs the set tagged by release and a real view of the version distribution in the field, so the question becomes which releases are below the supported floor. A fixed calendar timer answers a different question and gets it wrong in both directions.
saying these in an interview costs you the question
- Switches enforcement on with no shadow period
- Expires registered documents on a fixed calendar timer
- Thinks an allowlist protects pinned clients from schema changes
- Has no audited path for an unregistered incident query
- Shares one global registered set across every client
- Treats an enum addition as safe with pinned clients