ADR-0131: Role Substitution as Declared Adoption Edges — Emergency Cover Is Governed, Own-Name, Timed Staffing¶
- Status: accepted (2026-09-01 — his ruling verbatim: "I'd like to have it in 1.0 but agree that this should go in its own ADR and I like all your detailed descriptions and also limitations". The proposal was his: "our current system at ergon has rules what roles can substitute for other roles if the actual person with the target role is not available. We might make this functionality a feature of the system where we define which roles may take over which other role in case of emergencies. The project admin needs full rights, everybody else should only be able to adopt the roles for which they have 'substitution' rights.")
- Date: 2026-09-01
- Deciders: Nicolas Burri
- Relates to: ADR-0130 (the break-glass mechanism this stands on — timed staffing, predicate-enforced expiry, the three trail endings, the header chip, refusals-become-doors; §6 resequenced by this ADR), ADR-0117 (acting-as/impersonation rejected — that rejection is load-bearing here, and absence deputization was its original trigger), ADR-0128 (the permission classification column that makes the content-class-only constraint structural), ADR-0122 (organization-level administration — the lane that covers an absent administrator), ADR-0114 / the arrival-bundle format (the operating model the matrix travels with), ADR-0064 (workflow role bindings — why own-name adoption keeps four-eyes semantics intact).
Context¶
ADR-0130 built break-glass for the one caller who always had the master key: the Project
Administrator, whose ASSIGN_ROLES makes any escalation reachable, so the design question was
only witness and window. §4 of that ADR deliberately introduced the timed-staffing mechanism
through that single case and named the widening it declined to build: absence deputization,
ADR-0117's original trigger.
The widening arrived the same day. Ergon's existing QMS carries paper rules for which roles may substitute for which when the actual person is unavailable — tribal knowledge with a convention around it. His proposal: make those rules a feature of the system — a declared matrix of "role A may take over role B in an emergency" — with the administrator keeping full break-glass and everyone else bounded by their declared substitution rights.
Decision¶
1. Own-name staffing, never impersonation¶
A substitution edge "role A may take over role B" authorizes a holder of A to self-staff
into B — own name, witnessed, timed, exactly ADR-0130's mechanism: expires_at enforced in the
authorization predicate, the three trail endings (removed / expired-as-declared / extended as a
fresh act), the header chip, the refusal-door offering the act inline.
ADR-0117's rejection of acting-as stands untouched and is the load-bearing choice: four-eyes stays semantically intact because a substitute approving as B is a different person approving — which is exactly the fact four-eyes exists to establish. Impersonation would have destroyed that fact while appearing to preserve the process. The trail says "she held QMB, from then until then", never "she acted for him".
2. The matrix is operating-model content¶
Substitution edges are governance configuration of the same rank as review policies:
- Declared per scope, by whoever governs roles there, as an audited governance act.
- Traveling in the arrival bundle with the rest of the operating model (format extension at
build time, beside role mapping and review policies).
Amendment (2026-09-09, register row 76): PROMISE FULFILLED — bundle format 1.3. The extension this bullet named was never built, and the manual lane found it by verifying the guide against the code: the matrix was the one operating-model member that did not travel, silently. It now does —
operating-model.json.substitutionEdges[] {sourceRole, targetRole}, exported, landed through the same audited declaration this ADR defines, and proved by an export→land→re-export round trip. The RULE travels; the declaration ACT does not (ADR-0075, format §14): the receiving operator declares each edge in their own name, which is this section's own sentence read literally — a qualification statement cannot be inherited from another instance's trail. - The declaration act IS the qualification statement. "We judged A-holders competent to cover B" is precisely what an auditor asks about substitution arrangements — and here it is a witnessed governance judgment with a name and a date, not tribal knowledge. Ergon's paper substitution rules become declared, exported, auditable system configuration: the opinionated-system principle applied to emergency cover.
3. Hard constraint: content-class targets only¶
Substitution edges may only target CONTENT-class roles. An edge into an ADMINISTRATIVE-class role is refused at declaration time, structurally, via the ADR-0128 classification column — essentially for free.
Rationale: an edge into an administrative role would hand ASSIGN_ROLES transitively — the
master key through a side door — defeating ADR-0130's pairing argument (self-granting and acting
separated in time, witnessed). An absent Project Administrator is covered through the
organization level (ADR-0122's lane), never through the matrix. His own line draws the same
boundary: the project admin needs full rights, everybody else only substitution rights — the
administrator's fullness comes from ASSIGN_ROLES and ADR-0130, not from matrix edges.
4. Emergency is not planned absence¶
The matrix carries the short windows — the ADR-0130 presets (30 minutes / 60 minutes / 1 day, default 60 minutes) — and answers "the role-holder is unreachable and the act is stuck NOW."
A planned absence (a vacation, a leave) is ordinary, deliberate staffing of a deputy by the administrator — possibly with the ADR-0130 timer generalized to ordinary staffing — and never self-service substitution. Folding vacations into the self-service path would normalize the exceptional act, which is the exact failure mode this whole design exists to prevent: the matrix is glass to break, not a schedule.
5. Composition — what comes for free¶
- The refusal-door (ADR-0130 §2) gains a second hinge: "you hold RE, which may take over QMB — take it over; this will be recorded."
- The header chip is the same chip; multiple adoptions stack as chips.
Amendment (2026-09-06, his nod on the implementation's measurement): they stack as full chips from 2100px — the first width at which two fit — and below that fold into one counted trigger whose menu carries every window's Extend/End-now; measured against a toolbar with no slack at review widths (breakglass-ui-lane-report.md §6), chosen over two ellipsized stubs saying nothing.
- The trail endings, the extension act, the janitor, the pre-expiry warning: unchanged, shared.
- The administrator's break-glass is not expressed as matrix edges; it remains the
ASSIGN_ROLESdoor of ADR-0130.
6. Sequencing: in 1.0 — and ADR-0130 §6 is resequenced¶
His ruling puts substitution in 1.0. Since it stands on the timed-staffing mechanism, ADR-0130's "implementation after the 1.0-blocking fix waves; nothing here is a 1.0 gate" is resequenced: the mechanism moves into the 1.0 runway, and both ADRs' implementation lands after the 1.0-blocking fix waves as one arc (mechanism first, matrix on top). ADR-0130 §6 carries a dated amendment note recording this.
Not built, by decision¶
- Transitive edges. A-covers-B plus B-covers-C grants A nothing toward C. Every edge is its own declared qualification judgment; transitivity would manufacture judgments nobody made.
- Cross-scope edges. The matrix is per-scope governance, like the role activations it ranges over. Cover across scopes is staffing, not substitution.
- Impersonation. Permanently, per ADR-0117. Own-name authority is not a limitation of this design; it is the design.
Consequences¶
- A new governance vocabulary (the edge: source role, target role, declared-by, declared-at) with declaration-time validation against the ADR-0128 classification; its audit events; its rows in the arrival bundle's operating model; the schema-extension lifecycle sweep applies (RLS inventory, export/import shape, dissolution's delete set).
- The self-staffing authorization check gains a second path:
ASSIGN_ROLES(ADR-0130) or a matrix edge from a role the caller holds — evaluated at the moment of the act, own scope only. - The refusal-presentation work (ADR-0130 §2) now serves three caller classes: the administrator, the edge-holder, and everyone else — still one presentation rule, built once.
- The November-audit story gains its second written answer: "what happens when the QMB is unavailable?" — a declared, witnessed, self-expiring cover act, with the qualification judgment on record.