Skip to content
Agent Engineering Lab
Pattern

The Expiring Exception

An exception with a mandatory expiry is a control; without one it is a hole.

Kind
Pattern
Layer
Evidence
Stage
Govern
Status
Restated. Nearest prior description:
  • Temporary access granted without an expiry date routinely becomes permanent access, Microsoft
Forces
  • Approval is the visible event everyone remembers; duration is not, unless something forces the question to be asked again
  • A date field is not an expiry unless crossing it requires an active decision, rather than a default continuation
  • The same pressure that creates an exception argues against ever revisiting it, so exceptions decay exactly when nobody is watching
The Expiring Exception pattern diagram

The problem

Every guardrail programme runs into the same request inside its first quarter. A launch date will not move and enforcement needs to relax for it. A false positive rate breaks one workflow downstream. A tool cannot clear an approval gate before a freeze set months before anyone built the gate. ARCH-005 treats this as ordinary territory, not a symptom of anything gone wrong: exceptions are not a governance failure, and refusing to plan for them does not produce fewer of them, only undocumented ones.

The instinct that gets a programme into trouble is treating the exception itself as the thing to minimize. A team that reads every exception as a mark against the control starts under-recording them, or records one and never looks again, because looking again means admitting the relaxation is still live. Neither response makes the risk go away. It just stops anyone from seeing it.

Watch what happens to an exception a year after it was granted, in a programme that has not built for this on purpose. The launch shipped. The approver moved teams, or the ticket tracking it closed the week the launch went out, because the launch was what everyone was watching, not the exception behind it. The relaxation is still in effect, and no dashboard says otherwise, because the exception was recorded once, correctly, as temporary, and temporary is not a status a system tracks on its own. Someone has to keep asserting it.

That is the actual failure this pattern names, and it has nothing to do with whether the exception was properly signed off. A programme can have a spotless approval trail for every exception it has granted and still be carrying permanent, unreviewed holes in its control environment, each still wearing the paperwork of something temporary.

Forces

Approval is the visible event; duration is not. Signing off an exception is a moment everyone in the room can point to: a name, a date, a rationale. Nothing about it tells you when the relaxation stops, unless the record forces the question to be asked again. A programme that measures itself on whether an exception was approved correctly is measuring the part that was always going to go well, and missing the part that decides whether it is a control or a liability six months on.

A date field is not an expiry unless something happens when it passes. An exception record can carry an expires value and still be functionally permanent, if reaching that date triggers nothing, or if the standing behavior is to auto-extend unless someone raises an objection nobody is watching for. The difference between a control and a hole is not whether the schema has a date field. It is whether crossing that date requires someone to make a decision, on the record, or whether the relaxation simply continues by default.

The same pressure that creates an exception argues against ever revisiting it. A deadline, a broken workflow, an unready tool: the conditions that produced the request are exactly the conditions under which nobody wants the conversation reopened. Once the launch has shipped, the pressure that justified relaxing enforcement is gone, and so is anyone’s incentive to confirm the relaxation should end. An exception is hardest to revisit at precisely the moment revisiting it would cost the least.

The pattern

State the rule plainly: an exception is not a failure of the control, it is part of the control, and the one property deciding which side of that line it sits on is the expiry. Not the approval. Not the justification, however well argued. An exception approved by exactly the right person, with a compensating control that genuinely addresses the same harm, is still a permanent hole if nothing forces anyone to look at it again. One granted in a hurry, under a stretched approval process, is closer to a real control than that, if it carries a hard date and a review owner who has to act on it.

Microsoft’s guidance on least privilege for AI agents makes the same observation about a narrower kind of grant: temporary access that lacks an expiry mechanism becomes permanent access in practice, because nothing forces anyone to revisit it once issued. That was an observation about a resource grant to an agent, not a governance exception. Naming the same shape at the governance layer, an exception decaying into permanence the same way a stale credential does, is a restatement of an established observation in a new context, not a discovery, and the honest thing to do is say so plainly.

ARCH-005 specifies the record that carries this weight, trimmed here to what does the actual work:

exception:
  id: EXC-2026-0143
  control: pii_in_response.mask
  scope:                                  # never "global"
    system: rag-assistant-eu
    surface: internal_research_desk
  compensating_control: >
    Retrieval-layer entitlement filtering stays enforcing on this
    surface, so exposure is bounded to what the requester could
    already read.
  approved_by: risk.director.markets      # second line, not the platform team
  granted: 2026-08-19
  expires: 2026-11-19                     # required; lapses to enforcing, not a silent extension
  review_owner: platform.guardrails       # accountable for the renewal decision

The identifiers and dates are illustrative, carried over from ARCH-005’s own worked example; the fields are the point, not the values. Four of them carry the weight this pattern is named for. expires is mandatory, not advisory: crossing that date is a lapse back to enforcement, and getting the relaxation back needs a new record, not an edit to this one. compensating_control has to address the same harm the relaxed control did; sampling after the fact only detects a disclosure that already happened, it does not compensate for it. approved_by names a role, not a team, because shared ownership resolves to nobody when renewal comes due. review_owner is accountable for making that renewal an active decision, not letting the exception continue because nobody’s job included stopping it.

One correction worth making explicit, since it is easy to over-read approved_by above. Routing exception approval to a second-line risk role is a design choice this catalogue recommends, not something the Three Lines Model hands anyone. The Institute of Internal Auditors’ model gives the second line a role of “provide assistance with managing risk,” not approval authority, and states that responsibility for managing risk “remains a part of first line roles” regardless of who signs anything. A second-line signature is a good idea. It does not transfer the risk, and a programme that treats it as if it did is building on a misreading of the model it thinks it is following.

Worked example

Take the PII-masking control from ARCH-005’s own worked example: an enterprise RAG assistant masks PII in generated responses, and the citation renderer on one internal research desk breaks when account identifiers inside quoted passages get masked, because the masked text no longer matches the source document a reviewer needs to verify against.

The record above is what that relaxation produces, and everything past the justification is what makes it a control rather than a workaround. Retrieval-layer entitlement filtering keeps enforcing on that surface, so a requester still cannot pull a passage from a document they were never entitled to read; residual risk narrows from disclosure to a smaller, named exposure, onward sharing by someone already entitled to see the content. platform.guardrails owns the renewal decision; risk.director.markets is the name on the sign-off, not a shared inbox.

Run the clock forward past 2026-11-19 with nothing else changed. Under a silent-rollover design, the exception keeps working: no alert fires, no ticket opens, masking stays off indefinitely, and the only way anyone notices is a manual scan of a spreadsheet nobody was assigned to run. Under the design above, the control reverts to masking by default. If the renderer still cannot handle masked text, someone has to write a new exception record and argue the case again, rather than watch a three-month-old justification keep authorizing a decision made under a deadline long past. That second path is more friction, on purpose. The friction is the control.

The register this produces, sorted by how long each exception has been open, is worth more to a control programme than a dashboard of detector accuracy: it is the one artifact showing every live relaxation and how long each has gone unexamined. An exception renewed unchanged, quarter after quarter, is not evidence the process is working. It is evidence the underlying control is wrong for that surface, and nobody has said so out loud.

When not to use it

This pattern earns its keep on a live, standing relaxation of an enforcing control, the kind that stays in effect after the meeting that granted it ends. It is the wrong tool for a few adjacent situations that look similar and are not.

A detector that is not enforcing yet because nobody trusts its precision is not an exception. It is Shadow Before Enforce: the control records what it would have done without acting, and the question is whether to turn enforcement on at all, not whether to relax enforcement that already exists. Writing an exception against a control that was never live conflates “we have not earned enforcement yet” with “we are stepping back from enforcement we trust,” a much bigger claim.

A blocked request that needs a human right now is not an exception either. That is Escalation Path: where a specific case goes and who owns it in the next hour, not who owns a standing relaxation over the next quarter. An exception changes what the control does for everyone on a surface until it expires; an escalation changes what happens to one case. Confusing the two produces exception records written for single incidents, and escalation paths quietly turned permanent.

And an exception is not a substitute for owning that the control itself is wrong. If the same exception keeps coming back for the same surface, the honest move is to change the control or its threshold, not keep renewing a fix that has stopped being temporary in everything but name. Treating renewal as review’s default outcome, rather than a decision argued for again each time, turns an expiry into a formality, and a formality does none of the work this pattern is named for.

Escalation Path is the other pattern at this stage: where a single blocked case goes right now, not where a standing relaxation lives over its whole lifetime. Decision Record is what an action taken under an active exception still owes an auditor; relaxing a control does not relax the requirement to record what happened under it, policy version and all. Shadow Before Enforce is the right instrument when a control has never earned enforcement in the first place, not when a trusted one is deliberately stepped back from. Approval Gate gates a single irreversible action inside a running system; this pattern gates a change to the control environment itself, made once at grant time. Baseline and Floor worries about the same invisible erosion from a different angle, sub-threshold drops that never individually trip an alarm but compound; an exception register with no life cap is the governance version, one relaxation at a time, each individually defensible.

Specified in

Sources

  1. (2026) Least privilege for AI agents: Identity, access, and tool binding
  2. Institute of Internal Auditors (2020) The IIA's Three Lines Model: An Update of the Three Lines of Defense