informed-decision/history/20260909-initial-exploration/decision-memo-schema.md
tegwick ee2cca579c Establish INTENT, Stage 1 GOAL, and founding workplan
Claim ownership of the browser-facing approver UI that approval-engine
deliberately does not contain. approval-engine's INTENT names an approvals
inbox under Non-Goals, and docs/keycape-service-registrations.md records that
the human approver client's client_id and callback URI "must come from its
owner once it exists" — leaving key-cape's KEY-WP-0013-T02 blocked on an
unassigned component.

- INTENT.md: Decision Memo concept, the binding/awareness split and the two
  hashes, ownership and non-ownership against the named estate repositories,
  and a provisional PEP-shaped layer placement flagged for a gate-house ruling
  rather than asserted.
- GOAL.md: Stage 1 is the L3 approval approver surface — the narrowest real
  consumer with a live blocking dependency — plus the written answer to who
  owns the approver UI.
- workplans/INFD-WP-0001: founding documents, the gate-house layer/ownership
  ruling, the four specs (PRD, UseCaseCatalog, ArchitectureBlueprint,
  EvidenceModel), schema and canonicalizer promotion out of history/ with the
  isolation vectors under test, the key-cape client registration, and a
  walking skeleton that includes return and discuss.

history/ is preserved unmodified as provenance.

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
2026-09-09 10:47:36 +02:00

7.2 KiB

Decision Memo object schema v0.2

Machine-readable schema: decision-memo.schema.json
Worked example: decision-memo.example.json

The Decision Memo is one object at every depth (L0 login banner through L5 multi-party instrument). Depth changes which fields are populated, not which types exist.

1. Object graph

DecisionMemo
├── requester / subject / parties[]          identity + mandate
├── question + requested_act + binding_level what is being asked
├── brief + consequences
├── identity_context.binding                 PRE-SIGN identity + scope (in view_hash)
├── identity_context.awareness               hats, last-used, other tenants (awareness_hash)
├── session                                  POST-SIGN live hat inside the bound scope
├── packet[]                                 files, hashed
├── highlights[]                             pointers into packet
├── route.steps[]                            Laufweg / Zeichnungsleiste
├── thread[]                                 discussion stays on the object
├── presentations[]                          what each actor was shown
├── dispositions[]                           comment | return | forward | accept…
├── relations[]                              supersedes / relates_to
└── evidence                                 hash-chained event log + optional seal

2. Lifecycle

draft
  → submitted
    → circulating / awaiting_actor / in_discussion
      → returned ──(new version)──→ submitted
      → completed (outcome set)
      → withdrawn | expired
completed ─(new memo)→ superseded

Rules:

  • Edits in draft bump version without a new id.
  • After submitted, content edits that change brief, packet, or highlights must bump version and invalidate unused presentations.
  • return sets status returned, does not mutate the sealed packet in place. Requester opens version N+1, which supersedes the circulation of N.
  • forward replaces the current step assignee. escalate adds or replaces a step of higher competence.
  • Terminal statuses: completed, withdrawn, expired, superseded.
  • outcome is only set when status=completed (or timed-out/cancelled mappings).

3. Invariants

I1. One question. question is a single present-tense sentence. If you need two questions, you need two memos.

I2. Presentation binds the act. Every disposition with verb in {acknowledge, accept, decline, abstain, recuse, sign} MUST reference a presentation_id whose memo_version equals the memo version at act time.

I3. Dynamic linking. Binding acts at aes or higher MUST set signature.presentation_bound=true and include presentation.view_hash in the signed attributes.

I4. Required highlights. If any highlight has required_ack=true, a binding act is invalid unless those ids are in presentation.acked_highlight_ids.

I5. Mandate fit. The actor on a schlusszeichnung / sign step MUST carry a mandate whose scope covers requested_act and any legal / value constraints.

I6. Packet integrity. packet[].hash is content-addressed. Replacing bytes is a new item.id (or a new item version + replaces).

I7. Evidence is append-only. evidence.events[].event_hash = H(seq || type || at || payload_hash || prev_hash). head_hash is the last event_hash.

I8. Agents may draft, not bind. party.kind=agent may create highlights and brief text. Agents MUST NOT emit binding verbs.

I9. Return is data. verb=return requires return.reasons[]. Empty “please fix” is invalid.

I10. Whole instrument vs excerpt. Highlights never narrow the legal object. legal and the primary packet item define what is bound; highlights are attention, not scope.

I11. Pre-sign vs post-sign. identity_context.binding is in view_hash. identity_context.awareness is only in awareness_hash. Binding verbs sign the former. configure mutates session after bind and never rewrites binding.

I12. Hats are not scopes. A hat (elevates=false) is a perspective inside an already bound scope. A scope with requires_new_bind=true (other tenant, other identity, elevating hat) is a new memo.

I13. Defaults are awareness. proposed_hat_source of last_used or system_default must be shown and must not be silently copied into view_hash.

4. Disposition verbs

Verb Changes route? Binding? Required payload
comment no no body
discuss may set in_discussion no body + optional transfer.to for requester
return yes → requester no return.reasons
forward yes → peer assignee no transfer.to
escalate yes → higher mandate no transfer.to + reason
acknowledge completes inform/review step weak presentation_id
accept may complete memo yes presentation_id + optional signature
decline may complete memo yes presentation_id + body
abstain / recuse completes step for actor yes presentation_id + reason
withdraw terminal requester only body
stamp no system/org seal signature on listed items

5. Canonical view_hash

Serialize, UTF-8, JCS (RFC 8785), then hash:

{
  "memo_id": "...",
  "memo_version": 2,
  "question": "...",
  "requested_act": "accept",
  "binding_level": "aes",
  "brief": "...",
  "packet": [{"item_id":"...","hash":"sha256:..."}],
  "highlights": [{"id":"...","item_id":"...","locator":{...},"required_ack":true}],
  "ui_release": "informed-decision@0.3.1",
  "locale": "en"
}

That document is what “informed” means in the evidence bundle.

6. Evidence event minimum set

For a completed accept:

  1. memo.created
  2. memo.submitted
  3. packet.attached (per item)
  4. highlight.added (per required highlight)
  5. route.started
  6. identity.authenticated
  7. presentation.opened
  8. presentation.highlight_acked
  9. disposition.recorded (accept)
  10. signature.created (if aes/qes)
  11. timestamp.qualified (if qes / long retention)
  12. file.stamped (per is_to_be_stamped)
  13. bundle.sealed

7. Field usage by depth

Field L0 login L1 elevate L2 ADR L3 approval L4 contract L5 treaty
identity_context required required optional optional rare rare
packet optional ticket + change ADR + links memo + annexes contract + annexes instruments + translations
highlights optional blast-radius rollback / cost risk spans clauses reservations
binding_level acknowledgment / organizational organizational organizational / aes organizational / aes aes / qes qes per party
route one step requester → approver review → accept matrix sequential/parallel signers hybrid + deposit
legal.form_requirement none none none none / textform textform / schriftform varies by party

8. What is deliberately not in v0.1

  • Full mandate-graph resolution (referenced by mandate.policy_ref, not modelled here)
  • Payment / consideration objects
  • Translation alignment and reservation semantics for L5
  • Raw PII in evidence (use ip_hash, identifier schemes)
  • UI widget tree — only ui_release + canonical view