# 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: ```json { "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