informed-decision/INTENT.md
tegwick 13ee949982 Raise INFD-IN-0006: is §3's layer vocabulary closed, and what is surface?
The custodian's estate-wide sweep (2026-09-21), extending flex-auth's boundaries
review FLEX-WP-0030, found this repository declaring `layer: surface` against a
§3 vocabulary that does not enumerate it. flex-auth's validator admits only
{Staff, Engine, Tooling}, so this fails on the value rather than on casing or on
B1's precedence question. It was never raised here directly and it is not the
nine-repository defect: both our files say `surface`, in the same casing.

`surface` denotes the presentation-and-binding tier — the runtime a human
touches, where a decision rendered elsewhere is shown to a named person, that
person binds their identity to the act, and the evidence that the presentation
happened is produced. It was chosen by elimination on 2026-09-09 (f6376dd),
because GH-DEC-2026-012 R1 ruled us out of Engine and left the layer ours to
declare, and each remaining value is false of us: not Staff (deterministic by
construction, and holding state audit-core depends on at runtime, which §3.4
forbids Staff), not Tooling (we persist nothing another layer reads), not
Taxonomy (we are nothing but a runtime position). Faced with a false value that
satisfies a validator or the true word and a finding, the true word was written.

Position: `surface` names a real tier §3 does not enumerate. The sharpest form
is that a standing ruling plus a closed vocabulary leaves this repository no
conforming declaration available — the §9.1 defect applied to conformance that
§11 names against itself. But the ruling is gate-house's and we do not claim it
must go our way: if the vocabulary is ruled closed and a value named, both files
change the same day without argument. We ask only that such a ruling show how
§3's determinism cut reaches that value given GH-DEC-2026-012 R1, because the
next repository in this position will reason from it — and the tier a human
touches having no owner is exactly what produced approval-engine's unowned
inbox, key-cape's blocked client_id, and this repository.

Two observations offered: flex-auth's validator admits three values where §3
enumerates four, so railiance-master's `Taxonomy` fails the validator rather
than the standard and is separable without any ruling, leaving `surface` as the
only surveyed value outside §3 itself; and §3's row label is `Engines` while
declarations use `Engine`, which should be written out as declaration values if
the set is ruled closed.

The declared value is UNCHANGED on purpose. Changing it ahead of the ruling
would pre-empt gate-house and throw away the evidence of what was concluded.
layer.yaml, INTENT.md and AGENTS.md now say so in place, so the value is not
read as unexamined and no later agent silently "fixes" it. AGENTS.md's layer
section was also stale — it still said layer.yaml was unwritten.

28 layer conformance tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
2026-09-21 02:11:59 +02:00

308 lines
15 KiB
Markdown

---
project: informed-decision
product: Informed Decision
status: draft
intent_version: 0.1.0
date: "2026-09-09"
domain: infotech
topic_slug: netkingdom
layer: surface
role: pep-shaped # confirmed by GH-DEC-2026-012; see layer.yaml
standard: net-kingdom/canon/standards/security-layer-model_v0.7.md
companion: net-kingdom/SECURITY-COMPANION.md
---
# INTENT
> This file captures why this repository exists and the kind of system it is
> meant to become. It is aspirational and stable, not a description of current
> implementation. Implemented boundary belongs in `SCOPE.md`; the current stage
> belongs in `GOAL.md`; current work belongs in `workplans/`.
## Purpose
> **informed-decision owns the surface on which a human is shown a decision and
> binds their identity to it — and owns the evidence that the presentation
> actually happened.**
It answers one question, totally and decidably:
> **What was this person shown, in what role, at the moment they bound
> themselves to this act — and can that be proven afterwards?**
Nothing else. It does not decide whether the act is permitted (`access-engine`),
does not own the approval object (`approval-engine`), does not author the
doctrine that requires an approval (`gate-house`), does not authenticate the
person (`key-cape`), and does not archive the trail (`audit-core`).
## Why This Exists
Every layer of the NetKingdom estate has an owner except the one a human
actually touches.
`approval-engine`'s `INTENT.md` names it under Non-Goals, twice and
deliberately: *"Not a workflow or ticketing system"*, *"Not an approvals inbox
or notification surface."* That exclusion is correct — an engine that renders
its own object is self-dealing — but it leaves a hole, and the hole is now
load-bearing:
- `approval-engine` is a bearer-token resource server with no Ingress, no
redirect endpoint and no browser client
(`deploy/approval-engine.yaml`: Namespace + ClusterIP + StatefulSet).
- `key-cape` (`KEY-WP-0013-T02`) asked approval-engine for the human approver
client's `client_id` and callback URI on 2026-09-08.
- approval-engine correctly refused to invent them, recording in
`docs/keycape-service-registrations.md`: *"The human approver flow therefore
belongs to whichever browser-facing approver UI presents `approval:approve`
tokens to this engine. That component is not in this repo."*
So the approver UI is not merely missing. It is a **named, unassigned
dependency** that currently blocks an OIDC client registration in another
repository. **This repository claims it.**
The claim is not opportunistic. The founding exploration
(`history/20260909-initial-exploration/`) arrived at the same object from the
opposite direction — the German *Umlaufmappe* / *Zeichnungsbuch*, a portable
decision object that carries a question, the context needed to answer it, the
requested act, and a cryptographic binding between *identity*, *what was shown*,
and *what was bound*. That is exactly the artifact the estate is missing, and it
generalizes past approvals without ever becoming a decision point.
## The Concept — the Decision Memo
A **Decision Memo** is a portable object presented to one human who holds a
mandate. It carries:
- a **question** that must be answered, and a **requested act**;
- the **brief and consequences** a reasonable decision-maker needs;
- a **packet** of hashed documents and **highlights** pointing into it;
- a **binding slice** — the identity and scope being committed, which is signed;
- an **awareness slice** — orientation (proposed role, other roles, other
tenants, last session), which is shown and hashed but **not** signed;
- a **route** (`Zeichnungsleiste`), a **thread**, and a record of every
**presentation** and **disposition**;
- an append-only **evidence** chain.
Two hashes are computed over every presentation:
| Hash | Over | Signed? |
| --- | --- | --- |
| `view_hash` | the binding document | yes, from organizational level up |
| `awareness_hash` | the awareness document | no, unless a field was promoted |
`view_hash` is the mechanism. It is what turns *"the file was signed"* into
*"this person, in this role, was shown this view, and bound this act."*
## Scale Invariance Is the Thesis
One object model, one evidence model, one UX grammar, from a ten-second login
to a multi-party instrument:
| Level | Act | Typical binding |
| --- | --- | --- |
| L0 | Informed login / session | acknowledgment / organizational |
| L1 | Privileged authorization (JIT elevation) | organizational |
| L2 | Formal ADR / decision-record accept | organizational / AES |
| L3 | Management approval | organizational / AES |
| L4 | Contract / instrument | AES / QES |
| L5 | Multi-party international instrument | QES per party (horizon, not v1) |
If L0 and L3 share the schema, the transitions, and the two hashes, the thesis
holds. If they fork, it does not — and the estate has bought a bespoke approvals
inbox instead of a decision surface.
**The approval approver UI is L3.** It is the first stage precisely because it
is a real consumer with a real blocking dependency, not a demo.
## The Disposition Vocabulary
The differentiator is not another workflow engine. It is that *approve/reject*
is the wrong vocabulary for judgment. The verbs are:
`comment` · `discuss` (Rücksprache) · `return` for improvement (Rückgabe) ·
`forward` · `escalate` · `acknowledge` (Kenntnisnahme) · `accept`
(Mitzeichnung / Schlusszeichnung) · `decline` · `withdraw` · `configure`
`accept` on a Kenntnisnahme step is **illegal on purpose**. **Return is success,
not failure** — a memo sent back for improvement is the surface working.
## What informed-decision Owns
- the **Decision Memo** object, its versions, and its lifecycle;
- the **presentation record** — what was rendered, to whom, when, in which
locale and UI release;
- **canonicalization** of the binding and awareness documents, and the
computation of `view_hash` / `awareness_hash`;
- **highlight acknowledgment** — required highlights acked before a bind is
permitted;
- the **disposition vocabulary** and its legality tables;
- the **evidence bundle** as an export — the reconstructable answer to *who
decided what, having seen what*;
- the **browser-facing OIDC client** for human principals, including the
`client_id` and callback URI that `key-cape` is waiting for;
- the **pre-sign / post-sign split**: identity and bind-scope are committed;
hats, last-used role, and other-tenant orientation are awareness unless
explicitly promoted.
## What informed-decision Does Not Own
- **the decision** — `access-engine`, always and only (statute §6). This
repository renders a question and records an answer; it never evaluates
whether an actor may do a thing;
- **the approval object** — `approval-engine`. This surface calls that engine's
mutations with an `approval:approve`-scoped token; it never holds approval
current-state and never answers "is this approval valid";
- **approval doctrine** — which acts need approval, how many approvers, which
separations of duty — `gate-house`;
- **identity and authentication** — `key-cape`. Identity is *imported*
(OIDC, passkeys, eID, EUDI Wallet, QTSP), never invented here;
- **the evidence archive** — `audit-core`. This repository emits and exports;
the trail is held there;
- **credentials materialized after a decision** — `secrets-engine`;
- **notification transport** — a memo may be announced by other means; the
dialogue stays on the object.
## Design Principles
1. **One object, many depths.** Login and instrument share a schema.
2. **Presentation is part of the signed payload.** Dynamic linking, not a
signature over a file nobody read.
3. **Competence before convenience.** Routing follows mandate.
4. **Return is success.**
5. **Dialogue stays on the object.** Side-channel email is an anti-pattern.
6. **Binding level is explicit.** Kenntnisnahme ≠ Mitzeichnung ≠ QES.
7. **Evidence is an export, not a screenshot.**
8. **Least privilege of attention.** Highlights first, full packet available,
no dark patterns — and the UI must make unmistakable that the *whole*
instrument is bound, not only the highlights.
9. **Identity is imported.**
10. **Humans bind, agents draft.** An agent may assemble a memo. It may never
complete the binding act on the principal's surface.
11. **Awareness is not consent.** Defaulting a role to last-used is required
for situational awareness and forbidden from silently entering `view_hash`.
12. **Informedness without surveillance.** Evidence is the hash of the
presented view plus explicit highlight acknowledgment — never keystroke
analytics, dwell timers, or attention theater.
## Layer Placement — Ruled
**PEP-shaped**, confirmed by `GH-DEC-2026-012` (answering `INFD-IN-0001`).
Not an Engine: this repository holds no state another layer reads at runtime for
a verdict, and renders no decision. Companion §5 is owed and statute §6.4
applies in full. The declaration is `layer.yaml`, in this repository's own voice
— a layer someone else states about you is not a declaration.
The **shape** is ruled; the **layer value** is open. `GH-DEC-2026-012` R1 left
the layer to this repository to declare, and `surface` was written by
elimination — the presentation-and-binding tier, the runtime a human touches.
§3 of the model does not enumerate it, which the custodian's estate-wide sweep
surfaced on 2026-09-21. This repository holds that `surface` names a real tier
§3 omits, and will change the value without argument if `gate-house` rules the
vocabulary closed and names which of the four applies. Open as `INFD-IN-0006`;
the argument is `docs/gate-house-decision-request-layer-vocabulary.md`. The
frontmatter value is unchanged pending that ruling, on purpose.
The ruling also confirmed that emitting a **presentation claim** does not
require a second catalog row: PEP and PIP are shapes a repository has, and §4
records the layers it occupies. That permission carries three limits, and they
are the substance of it rather than caveats on it:
1. **The claim carries presentation and nothing else.** It must never carry,
restate, summarise or imply the decision, the verdict, or whether the act was
permitted. A consumer learns from it only what was *shown*, never what was
*decided*.
2. **The claim must not be an input to the decision it presents for.** A policy
reading `view_hash` to decide whether an act is permitted would let the
presenting surface contribute to its own authorization.
3. **The evidence copy reaches `audit-core` independently of this repository.**
The claim endpoint and the evidence path are different things and neither
substitutes for the other.
Limit 2 is load-bearing. `GH-DEC-2026-012` accepted this repository's argument
that a renderer attesting its own rendering is not the self-dealing that kept
the approval object out of `access-engine` — *but only because that limit
holds*. Without it, the two collapse into the same failure.
Limit 3 is the one that most shapes the architecture: audit evidence is
protected from the actor being audited, and here the actor and the source are
the same component.
### `view_hash` and the binding digest
Ruled as option (b): they are **distinct attestations with an authority rule**.
- `approval-engine`'s binding digest is authoritative for **what the request
is**.
- `view_hash` is authoritative for **what was shown**, and nothing else.
- Neither may be substituted for the other.
- **A disagreement between them is a finding against the presenting surface,
never a fact about the request.**
They link by **co-reference**, not nesting: the presentation record carries the
approval or binding identifier explicitly, and both attestations are read
against that one reference. This repository must never recompute or restate
`approval-engine`'s binding digest in its own vocabulary — it references the
digest that layer computed and recorded.
Nesting was refused for a reason worth carrying: it reproduces the hash cycle
that made `GH-DEC-2026-008` unimplementable, where a claim had to name the
digest of a request that would come to contain it, and a fail-closed consumer
obeying it would deny permanently.
### An inherited gap, stated rather than glossed
`GH-DEC-2026-010` requires a decision be **attributable** to `access-engine`.
No consumer can satisfy that today: the decision envelope is unsigned, a
declared §13 gap tracked as `FLEX-WP-0024`. This repository's record can show
that a decision was obtained and what it said; it cannot yet show that
`access-engine` said it. The decision path must not be described as validated
while that is open.
## What Would Make This Repository Wrong
- **It starts deciding.** Any surface that answers "may this actor do X" rather
than "here is the question, and here is what you were shown" is the failure
statute §6 names.
- **It becomes an approvals inbox and nothing else.** If the object that ships
cannot also carry an L0 login banner and an L2 ADR accept, the scale-invariance
thesis is dead and the estate bought a queue.
- **It forks the schema per level.** Three levels, three object models, one
broken promise.
- **Awareness leaks into the signature.** If a last-used role or a tenant
orientation hint enters `view_hash`, the surface signs something the person
did not commit to.
- **Highlights shrink the legal object.** If acking three highlights is
presented as binding only those three sections, the UI has produced a lie.
- **An agent binds.** If any automation can complete a disposition on a
principal's behalf, the identity half is fiction.
- **It renders `approved` as permission to act.** `approved` is a state of an
object, not authorization. `approval-engine` actively refuses to serialize a
decision. A surface that presents approval status as "you may now do the
thing" has re-implemented a PDP in the browser — the same failure as an
authorization endpoint, wearing UI copy instead of an API.
- **It reimplements `approval-engine`.** Caching approval validity, inferring
consumption from a decision record, or holding approval current-state here
breaks `GH-DEC-2026-003` and the atomicity contract.
- **It invents identity.** A local password, a local session token that is not
derived from `key-cape`, or a self-issued assurance level.
- **Nobody uses it.** If `approval-engine` never receives an `approval:approve`
token from this component's client, the surface is decorative and the gap it
claimed to close is still open.
## Success Criteria
1. `key-cape` holds a registered browser client whose `client_id` and callback
URI this repository owns and published, and `KEY-WP-0013-T02` is unblocked.
2. A human approver completes an approval entry against `approval-engine`
entirely through this surface, with an access token carrying
`aud=approval-engine`, `principal_type: human`, and scope `approval:approve`.
3. The approval entry is reconstructable from a `view_hash` — the estate can
show what the approver was looking at.
4. Required highlights cannot be bypassed: a bind attempt without acks fails.
5. `return`, `discuss`, and `escalate` are exercisable on a real approval and
are not modelled as `decline`.
6. The same schema renders an L0 login banner and an L2 ADR accept, with the
binding/awareness split intact and the isolation vectors green.
7. An evidence bundle exports and verifies offline against
`audit-core`'s record of the same transitions.
8. No endpoint in this repository answers an authorization question.