T02 — intake INFD-IN-0001 filed with gate-house and messages sent to gate-house, key-cape and approval-engine. Status progress; it now waits on an external ruling. key-cape was told explicitly why T07 is not answering KEY-WP-0013-T02 yet — a placeholder callback URI would either fail closed or register an origin no component owns — and given the token shape to check now rather than at T07. T03 — ProductRequirementsDocument.md. 30 requirements, each traced to a GOAL.md DoD item, an INTENT principle or wrongness condition, a state-transition guard, or a named external contract, and each with an observable pass condition. Anti-requirements are stated as testable absences: no dwell timers, no attention analytics, no dark patterns, no auto-approval, no approval-state caching, no authorization endpoint. Four limitations are recorded up front, including that escalate without a mandate graph is forwarding and that view_hash is computed by the renderer. T04 — UseCaseCatalog.md. L0-L5 with counterparties, plus ten negative cases bound to guards and isolation vectors. Each case records the constraint it places on the shared schema, so scale invariance is testable rather than asserted. Closes with the four changes that would fork the object. T05 and T07 remain gated on the ruling. T06 is independent and is next. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR Assistant: claude-code Assistant-Model: opus Assistant-Process: 1565372@bnt-lap001 Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
12 KiB
Use Case Catalog
Repo: informed-decision
Workplan task: INFD-WP-0001-T04
Status: draft, pending review
Companion specs: ProductRequirementsDocument.md (Stage 1 scope),
ArchitectureBlueprint.md, EvidenceModel.md
Why this catalog exists
Scale invariance is the thesis of this repository: one object model from a ten-second login to a multi-party instrument. A thesis stated in a vision document is decoration. This catalog exists to make it testable — every case below must map onto the single Decision Memo schema with no level-specific object.
Only UC-30 is in Stage 1 build scope. The rest are here to constrain the schema now, so it cannot fork later when they arrive.
The test this catalog applies to every case: can it be expressed with the
fields in decision-memo.schema.json plus values, or does it need a new field?
A new field is permitted only if it is also expressible for UC-00 — the login
banner, the shallowest case. A field that only makes sense at L4 is a fork.
Depth spectrum overview
| Case | L | Act | Binding | Counterparty | Stage |
|---|---|---|---|---|---|
| UC-00 | L0 | Informed login | acknowledgment / organizational | key-cape |
2 |
| UC-10 | L1 | JIT privilege elevation | organizational | key-cape, secrets-engine |
2 |
| UC-20 | L2 | Formal ADR accept | organizational / AES | estate decision records | 2 |
| UC-30 | L3 | Approval entry | organizational | approval-engine |
1 |
| UC-40 | L4 | Contract / instrument | AES / QES | external counterparty | horizon |
| UC-50 | L5 | Multi-party instrument | QES per party | multiple | horizon |
UC-00 — Informed login (L0)
Actor: any principal signing in.
Trigger: authentication at a system boundary.
Question: "Sign in to Payroll-Prod as Bernd Worsch?"
Requested act: login.
Binding slice (signed): which identity (ordinary vs break-glass), which scope/tenant/system, privileges granted at the gate, monitoring and consent terms.
Awareness slice (shown, hashed, not signed): the role you will wear after
login and where that default came from (last_used | system_default |
policy | explicit); other roles available inside the bound scope; other
tenants you support; last session summary.
Verbs: acknowledge (completes), decline, discuss. Not accept —
this is Kenntnisnahme.
Post-bind: configure(hat) for non-elevating roles only, while
session.status = active. Switching to a tenant with requires_new_bind opens
a child memo, never a silent scope change.
Evidence: presentation with both hashes; session.hat_selected events that
do not rewrite view_hash.
Why it constrains the schema: UC-00 is the shallowest case and therefore the
strictest constraint. It forced the pre-sign/post-sign split that now applies at
every level — see INTENT.md principle 11. Any field proposed for a deeper case
must be expressible here or be justified as genuinely level-specific.
UC-10 — JIT privilege elevation (L1)
Actor: an operator needing elevated privilege for a bounded task.
Question: "Elevate to Payroll Admin on ACME/Payroll-Prod for 60 minutes?"
Requested act: elevate.
Binding slice: the privilege, the scope, the validity window, the stated justification, the monitoring terms. Awareness slice: current role, what the elevation adds, prior elevations.
Verbs: acknowledge or accept depending on whether the elevation is
self-service-with-record or requires a co-signer; decline; escalate where
the operator's own mandate is insufficient.
Counterparty: key-cape for identity; secrets-engine if the elevation
materialises credentials — which this repository never does itself.
Constraint contributed: an elevating role can never be reached by
configure. It requires either promotion into the binding slice with a new memo
version, or its own elevation memo. Guard G_HAT.
UC-20 — Formal ADR accept (L2)
Actor: an architect or owner with the mandate to accept a decision record.
Question: "Accept ADR-0042 — Adopt the local outbox pattern?"
Requested act: accept_adr.
Binding slice: the ADR id and version, the decision statement, consequences,
the accepting role.
Packet: the ADR document, plus any superseded record.
Highlights: the consequences section, typically required_ack: true.
Verbs: the full set. return with coded reasons is the common path and is
the point — an ADR sent back for a clearer consequences section is the surface
working.
Constraint contributed: "accepted" must stop being a Git status and become
an identity act. The evidence must answer who accepted it, in what role, having
seen which version. This is the case that most directly tests whether view_hash
carries enough to be useful.
Note: the estate's own decision records (GH-DEC-*, FLEX-DEC-*,
APPROVAL-*) are the natural first real consumer of UC-20. Stage 2.
UC-30 — Approval entry (L3) — Stage 1
Actor: a human approver holding the mandate, authenticated by key-cape.
Trigger: an approval exists in approval-engine in state requested,
awaiting an authenticated approval entry.
Question: "Approve rotation of the production database credential for
task T-1183?"
Requested act: approve.
Binding slice: the approval id; the action and target it authorizes; the actor who may use it and the principal on whose behalf; the purpose; the validity window; the approving identity and tenant.
Awareness slice: the approver's current role; other approvals pending for them (orientation only — see PRD open question 1); prior related approvals.
Packet: the change or task the approval is for, and any policy citation
supplied by the requester.
Highlights: the target and the validity window, typically
required_ack: true — these are the two fields whose misreading is most costly.
Verbs: accept (submits the approval entry), decline, return with coded
reasons, discuss, forward, escalate, comment.
Boundary — the part that must not drift:
- The surface calls
approval-engine's approval-entry mutation with a token carrying scopeapproval:approve. It never mutates approval state itself. - It never requests or performs
approval:consume. Consumption is the PEP's, at the moment of use, perGH-DEC-2026-003. - It never caches or serves approval validity.
- It never answers whether the underlying action is permitted. That is
access-engine.
Evidence: presentation record with view_hash, the disposition, and the
approval entry id returned by approval-engine, so the entry is reconstructable
back to what the approver saw.
Why this is Stage 1: it is the only case currently costing another
repository progress. key-cape's KEY-WP-0013-T02 is blocked on a browser
client for exactly this flow.
UC-40 — Contract or instrument (L4) — horizon
Actor: a signatory with commercial authority.
Binding: AES or QES. Identity imported from a QTSP or EUDI Wallet, never
issued here.
Constraint contributed: the signed attributes carry memo_id,
memo_version, disposition.verb and presentation.view_hash — and not
awareness_hash unless promotion ran. This is dynamic linking: the
human-readable content actually presented is bound into the signature.
Open, not scoped: retention and qualified archive (exploration open question 6).
UC-50 — Multi-party international instrument (L5) — horizon
Actors: several parties, each with their own QTSP and jurisdiction.
Constraint contributed: parallel Mitzeichnung, per-party signature levels,
and per-party presentations of the same memo version. The schema must already
tolerate parties[] and multiple presentations per version — which it does.
Explicitly not v1, and named here only so nothing shipped earlier forecloses it.
Negative cases
These are as load-bearing as the positive ones. Each protects a named invariant and each must be a test.
NC-01 — accept on a Kenntnisnahme step
Attempt: the approver presses accept on an inform/review/acknowledge
step.
Required behaviour: the verb is absent from the UI, not present and
disabled; an API call attempting it is refused.
Invariant protected: Kenntnisnahme is not approval. Collapsing them is how
"I saw it" silently becomes "I approved it".
state-transitions.md §B2 · PR-31
NC-02 — Bind with unacknowledged required highlights
Attempt: accept while a required_ack highlight is unacked.
Required behaviour: fail closed; no disposition created; error names the
outstanding highlight ids.
Invariant protected: the acknowledgment gate is the only positive evidence
of informedness the model has.
guard G_ACK · DoD-4 · PR-20
NC-03 — Agent attempts a disposition
Attempt: a principal with actor.kind = agent submits any binding verb.
Required behaviour: refused at the API, not merely hidden in the UI.
Invariant protected: humans bind, agents draft.
guard G_NOAGENT · P-10 · W-"An agent binds"
NC-04 — Tenant switch requiring a new bind
Attempt: after an L0/L1 bind, the subject selects a tenant marked
requires_new_bind.
Required behaviour: scope.rebind_required is set and a child memo is
opened. The current session's view_hash is not rewritten.
Invariant protected: scope is committed, not configured.
guard G_HAT · isolation vector 4
NC-05 — Awareness field edited after presentation
Attempt: the proposed role or last-session summary changes between render
and bind.
Required behaviour: awareness_hash changes; view_hash does not; the
bind remains valid.
Invariant protected: the person is bound to what they committed to, not to
orientation material.
isolation vector 2 · PR-40
NC-06 — Binding target changed
Attempt: binding.target is altered from ACME to Beta.
Required behaviour: view_hash changes, invalidating any outstanding
presentation.
Invariant protected: the binding slice is genuinely covered by the hash —
the positive control for NC-05's negative one.
isolation vector 3
NC-07 — Bind against a stale memo version
Attempt: a presentation taken at version n is used to bind after the memo
advanced to n+1.
Required behaviour: version conflict; no silent upgrade.
Invariant protected: binding acts reference a presentation of the same
version.
guard G_PRES · PR-14
NC-08 — return with no coded reason
Attempt: return with free text only.
Required behaviour: refused.
Invariant protected: return is structured feedback, not a shrug.
guard G_REASONS · PR-32
NC-09 — escalate to an equal or lower mandate
Attempt: escalate to a target whose mandate is not strictly higher.
Required behaviour: refused as an escalation; offered as forward.
Stage 1 caveat: without the mandate graph this guard cannot be fully
evaluated. Stage 1 records the asserted intent and marks it unverified
rather than pretending the guard passed.
guard G_ESC · limitation L-01
NC-10 — Key shuffling
Attempt: serialise the same binding document with object keys in a different
order.
Required behaviour: identical view_hash.
Invariant protected: canonicalization is real; otherwise every hash is an
artifact of serialisation order.
isolation vector 1
Schema pressure — cases that would fork the object
Recorded so a future contributor recognises them as forks rather than features:
- A level-specific status. e.g.
awaiting_notarisationfor L4. Belongs as a step kind or a route step, never a new memo status. - Multiple questions per memo. An approval bundling three unrelated acts is
three memos. The single-question invariant is what makes
view_hashmean something. - A per-level packet model. L4 attachments are packet items, hashed exactly like an L0 consent text.
- An approvals-inbox object. A list of memos is a query result, not a schema entity. If it acquires state, the product has become a queue.