gate-house ruled the section 3 vocabulary closed at four case-insensitive tokens and named Staff (role pep-shaped unchanged). Both files were changed the same day, as this repository had committed to. INTENT.md now governs. layer.yaml is marked derived from INTENT.md and carries no standard or companion version. The reasoning behind `surface` stays in layer.yaml as history. INFD-IN-0006 is closed. INFD-IN-0007 asks once more how section 3.4's Staff definition fits a deterministic, non-agentic, evidence-holding repository. It is a question only: nothing waits on it. Section 4 answer: yes, as a Staff / pep-shaped / evidence-source row. The emission guarantee is owed per event class: presentation (volume), disposition (rare), stance-application (rare). See docs/section-4-catalog-row.md. 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
363 lines
19 KiB
Markdown
363 lines
19 KiB
Markdown
---
|
|
project: informed-decision
|
|
product: Informed Decision
|
|
status: draft
|
|
intent_version: 0.1.0
|
|
date: "2026-09-09"
|
|
domain: infotech
|
|
topic_slug: netkingdom
|
|
# NetKingdom security layer declaration (security-layer-model §11).
|
|
# THIS FRONTMATTER IS THE DECLARATION. GH-DEC-2026-017 §1 rules that INTENT.md
|
|
# governs and that `layer.yaml` is a DERIVED artifact which must agree with it.
|
|
#
|
|
# `layer: surface` stood here from 2026-09-09 to 2026-09-21. GH-DEC-2026-017 §3
|
|
# ruled the §3 vocabulary closed at four tokens — Taxonomy, Tooling, Engine,
|
|
# Staff — and named Staff for this repository. Changed the same day, without
|
|
# argument, as this repository pre-committed in
|
|
# docs/gate-house-decision-request-layer-vocabulary.md §3. The reasoning that
|
|
# produced `surface` is kept as history in layer.yaml; it is not erased.
|
|
#
|
|
# No standard version is carried, per GH-DEC-2026-017 §5 / A12: this declares a
|
|
# standing property, and a version here would read as a validity condition that
|
|
# every revision of the standard invalidated. Version-scoped state belongs in
|
|
# the derived conformance record.
|
|
layer: Staff
|
|
role: pep-shaped # §6.4 shape, confirmed by GH-DEC-2026-012 R1; a role is not a layer
|
|
standard: net-kingdom/canon/standards/ # the body, unversioned on purpose
|
|
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
|
|
|
|
**Layer: `Staff`. Role: PEP-shaped.** Both are ruled.
|
|
|
|
The **shape** was ruled by `GH-DEC-2026-012` R1 (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 **layer value** was ruled by `GH-DEC-2026-017` §3 (answering `INFD-IN-0006`)
|
|
on 2026-09-21. §3's vocabulary is **closed** and has four tokens — `Taxonomy`,
|
|
`Tooling`, `Engine`, `Staff`; comparison is ASCII case-insensitive and nobody is
|
|
asked to re-spell anything. `surface` is not among them, and the correct value
|
|
here is `Staff`, with `role: pep-shaped` untouched. `ops-mason` and `ops-warden`
|
|
are the precedent: Staff in the layer column, PEP-shaped in the role column.
|
|
|
|
This repository had pre-committed to changing both files the same day, without
|
|
argument, if the vocabulary was ruled closed and a value was named
|
|
(`docs/gate-house-decision-request-layer-vocabulary.md` §3). It did. **The
|
|
reasoning that produced `surface` is not erased** — it is kept as history in
|
|
`layer.yaml`, because a value written by elimination against a vocabulary that
|
|
turned out to be closed is evidence about the vocabulary, not carelessness.
|
|
|
|
Two things follow, and are recorded rather than argued:
|
|
|
|
- **`informed-decision` was never a §11 non-conformance.** §11's obligations
|
|
attach to estate-authored repositories **in §4**, and this repository holds no
|
|
§4 catalog row. `GH-DEC-2026-017` §4 states that a run which grades it is
|
|
over-scoped, and requires every conformance run to state its scope. The
|
|
correct report is *declared voluntarily, outside catalog scope; value not in
|
|
the vocabulary, correction identified*. The correction was this repository's
|
|
to make and it made it.
|
|
- **The declaration's form changed too.** `INTENT.md` frontmatter **governs**;
|
|
`layer.yaml` is a **derived artifact** that must be marked derived, must name
|
|
`INTENT.md` as what it derives from, and must agree with it
|
|
(`GH-DEC-2026-017` §1 / A11). A declaration carries **no standard version**
|
|
(§5 / A12), so the `standard_version: "0.7"` this repository flagged is gone.
|
|
`ops-warden` owns the reference sidecar form and is updating it; this
|
|
repository applied the two ruled properties and follows that form for the rest.
|
|
|
|
One thing the ruling did **not** settle, carried as `INFD-IN-0007` rather than
|
|
treated as settled: §3.4 says Staff *"MUST NOT hold state that another layer
|
|
depends on at runtime"*, and this repository's presentation records are exactly
|
|
state `audit-core` depends on. The ruling reaches `Staff` by elimination — not
|
|
Engine per `GH-DEC-2026-012` R1, and nothing else in the four is true — which is
|
|
the same route this repository walked, and it gives the value. It does not say
|
|
how a deterministic, non-agentic repository that holds evidentiary state sits
|
|
inside the layer defined by non-determinism and agentic capability. **The value
|
|
is applied regardless**; the question is asked for the next repository in this
|
|
position, not as a condition on the change.
|
|
|
|
### §4 catalog membership — answered: yes
|
|
|
|
`GH-DEC-2026-017` §4 deliberately did **not** enrol this repository, because a
|
|
layer stated about a repository by another is not a declaration and that rule
|
|
applies to catalogue membership at least as strongly. The question was asked,
|
|
and this repository's answer is **yes**: see `docs/section-4-catalog-row.md`.
|
|
|
|
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.
|