Raise INFD-IN-0001: layer placement and approver-UI ownership

File the gate-house decision request that gates INFD-WP-0001-T02, before any
architecture is written, so the ruling constrains the design rather than being
retrofitted to it.

Three rulings requested: layer and role (proposed PEP-shaped, §6.4/companion
§5); whether a presentation attestation also makes this a PIP or must reach
consumers only through audit-core; and the relationship between view_hash and
approval-engine's binding digest.

The third is the highest risk and the reason this is filed first. Both digests
claim to canonicalize "the binding" but cover different material — the approval
digest exists without a human in the loop, view_hash covers the brief, packet,
highlights, locale and UI release. Three candidate rulings are set out with what
each costs; the proposal is distinct attestations with an explicit authority
rule, but any of the three is implementable. The outcome to avoid is both
shipping with no stated relationship.

The self-dealing objection is argued against ourselves rather than left for
review, and the residual is stated plainly: a compromised surface can present X
and attest Y, structurally the same residual approval-engine names for
adversarial omission at a compromised source. No claim is made to close it.

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
This commit is contained in:
tegwick 2026-09-09 14:07:13 +02:00
parent ebfa558eb0
commit ebd35b59cf
2 changed files with 214 additions and 0 deletions

View file

@ -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.

39
intakes/intakes.md Normal file
View file

@ -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.
```