diff --git a/docs/gate-house-decision-request-layer-placement.md b/docs/gate-house-decision-request-layer-placement.md new file mode 100644 index 0000000..f2a84d6 --- /dev/null +++ b/docs/gate-house-decision-request-layer-placement.md @@ -0,0 +1,175 @@ +# Decision request to gate-house — layer placement and approver-UI ownership + +**From:** informed-decision +**Raised:** 2026-09-09 +**Intake:** `INFD-IN-0001` +**Blocks:** `INFD-WP-0001-T02`, and through it T05 and T07 +**Standard:** `net-kingdom/canon/standards/security-layer-model_v0.7.md`, +companion v0.2 + +--- + +## 1. The gap being closed + +`approval-engine` names an approvals inbox under Non-Goals, deliberately and +correctly — an engine that renders its own object is self-dealing, and the same +reasoning kept the approval object out of `access-engine`. + +The consequence is that the surface a human actually touches has no owner. This +is no longer theoretical: + +- `approval-engine` is a bearer-token resource server with no Ingress, no + redirect endpoint and no browser client (`deploy/approval-engine.yaml` is + Namespace + ClusterIP + StatefulSet). +- On 2026-09-08 `key-cape` (`KEY-WP-0013-T02`) asked `approval-engine` for the + human approver client's `client_id` and full callback URI. +- `approval-engine` declined to invent them and recorded 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 and is not named in + `APPROVAL-WP-0002`."* +- `APPROVAL-WP-0002-T01` remains `progress` in part because of it. + +`informed-decision` exists to take this. **We are not asking whether the work is +ours to do. We are asking what layer the statute says we are, and asking it +before we build, so the answer constrains the architecture rather than being +retrofitted to it.** + +## 2. What is being asked + +Three rulings, in dependency order. R3 is the one we least want to get wrong. + +### R1 — Layer and role + +**Proposal:** `informed-decision` is **PEP-shaped** under statute §6.4 and owes +companion §5. + +Reasoning: it is browser-facing and it causes a protected side effect on the far +side of a decision — it submits an approval entry to `approval-engine` carrying +an authenticated human's identity. `approval-engine`'s own INTENT anticipates +exactly this class of caller: *"Callers that do are PEP-shaped and owe +companion §5 / statute §6.4."* + +We are **not** proposing an Engine row. We hold no state another layer reads at +runtime to reach a verdict. + +### R2 — Does a presentation record make this a PIP as well? + +`informed-decision` produces one fact other layers may want as a claim: **what +was presented, to whom, in what version** — carried as `view_hash`. We do not +evaluate that fact; we emit it. + +**Proposal:** the presentation attestation is a PIP-like claim emitted by a +PEP-shaped component, not a second catalog row. If the statute does not permit +a component to be both, we ask which one governs and whether the presentation +claim must instead be published as evidence to `audit-core` and read from there. + +We flag §17: the shared request-claim schema has **no assigned owner**. Whatever +shape we publish must yield to that schema when it exists rather than becoming a +permanent local invention — the same position `approval-engine` took in +`APPROVAL-IN-0001`. + +### R3 — `view_hash` versus the approval binding digest + +**This is the highest-risk item in the request and the reason it is filed before +any code.** + +`approval-engine`'s claim already carries *"a digest over the same canonical +binding the decision point already computes, so that approved and approved for +this exact request are distinguishable at decision time."* + +`informed-decision` computes `view_hash`: a SHA-256 over a canonicalized +*binding document* — the memo id and version, question, requested act, binding +level, brief, locale, UI release, normalized packet and highlights, and the +identity/scope being committed. Algorithm and vectors: +`history/20260909-initial-exploration/canonicalize.md`. + +These are **not obviously the same hash**, and they are **not obviously +different**. Both claim to canonicalize "the binding". They differ in what they +cover: + +| | approval-engine binding digest | informed-decision `view_hash` | +| --- | --- | --- | +| Covers action, target, actor, principal, purpose | yes | yes, as `binding` | +| Covers the brief, packet and highlights shown to the human | no | yes | +| Covers locale and UI release | no | yes | +| Exists when no human is in the loop | yes | no | +| Purpose | replay protection at decision time | proof of what was presented | + +Three candidate rulings, with what each costs: + +- **(a) They are the same digest.** Cleanest for the estate — one + canonicalization, one authority. Cost: the approval binding digest would have + to cover presentation material that does not exist for machine-to-machine + approvals, or `view_hash` would have to drop the packet and highlights, which + destroys the property this repository exists to provide. +- **(b) `view_hash` is a distinct presentation attestation carried alongside the + binding digest.** Our proposal. Cost: two hashes over one act, requiring an + explicit rule that the binding digest is authoritative for replay protection + and `view_hash` is authoritative only for *what was shown*. Neither may be + substituted for the other. +- **(c) `view_hash` contains the binding digest as a field.** Composition rather + than duplication; `view_hash` becomes a superset commitment. Cost: ordering + dependency — the approval must exist before a memo can be rendered. + +**We propose (b) and will implement whichever is ruled.** What we ask gate-house +to prevent is the outcome where both hashes ship without a stated relationship +and the estate later discovers it has two canonicalizations of the same act with +no rule for which one governs. + +## 3. The self-dealing objection, stated against ourselves + +A surface that renders both the question and the answer sits close to the +objection that kept the approval object out of `access-engine` and the inbox out +of `approval-engine`. We think it is not the same failure, and we would rather +argue it here than be told later: + +- `access-engine` could not own the approval object because an evaluator that + owns what it evaluates can grade its own inputs. +- `approval-engine` could not own the inbox because an engine that renders its + own object controls the presentation of the evidence it issues. +- `informed-decision` **holds no state any layer reads as authority.** It does + not evaluate, does not issue the approval, and does not archive the trail. + The presentation record is evidence *about* the act, produced by the party + that performed the presentation — which is the only party that can produce it. + +The residual we accept and do not paper over: **a compromised surface can +present X and attest Y.** `view_hash` is computed by the same component that +renders. This is structurally the same residual `approval-engine` names for +adversarial omission at a compromised source, and we make the same claim it +does — atomicity and attestation cover accident and later tampering, not a +compromised source. We do not claim otherwise, and we ask that any ruling not +credit us with closing it. + +## 4. What we are not asking + +- Not asking for approval doctrine. Which acts need approval, how many + approvers, and which separations of duty apply stay `gate-house`'s. +- Not asking to render decisions. No endpoint here answers "may this actor do + X"; `access-engine` remains the only PDP. +- Not asking to hold approval state. `approval-engine` remains the sole + mutator, and `GH-DEC-2026-003` ordering is honoured unchanged. +- Not asking for a Railiance operational axis. + +## 5. What we do on each answer + +| Ruling | Consequence | +| --- | --- | +| R1 confirms PEP-shaped | `layer.yaml` written as such; companion §5 declared shapes enumerated in T05 | +| R1 places us elsewhere | `INTENT.md`, `GOAL.md`, `SCOPE.md` amended to match; the ruling wins | +| R2 permits a presentation claim | Published at our boundary, explicitly yielding to §17 | +| R2 refuses it | Presentation evidence goes to `audit-core` only; no claim endpoint | +| R3 = (a) | One digest; `view_hash` is retired or redefined as its input | +| R3 = (b) | Both ship with a stated authority rule, recorded as a decision | +| R3 = (c) | Composition; memo rendering is ordered after approval issuance | + +Until R1 and R3 are answered, `INFD-WP-0001-T05` (ArchitectureBlueprint) and +T07 (the `key-cape` client registration) do not proceed. T03, T04 and T06 are +independent of the ruling and continue. + +## 6. Cost of delay + +`KEY-WP-0013-T02` is blocked today on two strings this repository now owns and +cannot responsibly publish until it knows what it is. Registering a redirect URI +for a component whose layer is unsettled is the drift statute §17 exists to +prevent. diff --git a/intakes/intakes.md b/intakes/intakes.md new file mode 100644 index 0000000..2073e80 --- /dev/null +++ b/intakes/intakes.md @@ -0,0 +1,39 @@ +# Intake records + +## INFD-IN-0001 — Layer placement and approver-UI ownership + +```yaml +id: INFD-IN-0001 +kind: intake +title: Layer placement and approver-UI ownership +status: open +origin: coordination +origin_ref: INFD-WP-0001-T02 +priority: high +owner: gate-house +repo: informed-decision +lane: blue +tags: +- decision-request +- cross-repo +created: '2026-09-09' +updated: '2026-09-09' +description: >- + approval-engine names an approvals inbox under Non-Goals, leaving the + browser-facing approver UI unowned; key-cape KEY-WP-0013-T02 is blocked on a + client_id and callback URI no component has claimed, and approval-engine + recorded in docs/keycape-service-registrations.md that they must come from + that component's owner. informed-decision claims the surface and asks + gate-house to rule on three things before any code is written: (R1) layer and + role, proposed PEP-shaped under statute §6.4 and companion §5; (R2) whether a + presentation attestation makes this a PIP as well, or whether presentation + evidence must reach consumers only via audit-core, noting §17 has no assigned + request-claim schema owner; (R3) the relationship between informed-decision's + view_hash and approval-engine's binding digest, which both claim to + canonicalize "the binding" but cover different material. R3 is the highest + risk: shipping both without a stated authority rule leaves the estate with two + canonicalizations of one act. Proposal is (b) — distinct attestations with the + binding digest authoritative for replay and view_hash authoritative only for + what was shown. Full request: docs/gate-house-decision-request-layer-placement.md. + Blocks INFD-WP-0001 T05 and T07; T03, T04 and T06 proceed regardless. +```