Files
mechanical-compiler/docs/CONSUMER_INTERFACE_GATES.md
TheRON ee3fedf794 docs: our side of the cross-project gate register
Kane Fabric recorded a gate register against this project at its 5df8801. This
is the same instrument pointed the other way, plus the defects that review
found in our own contract.

A gate is a disagreement, an unmade decision, or an assumption two projects
hold differently and have not had to reconcile. Recording one is not scheduling
work on it. The failure this prevents is specific: when two systems meet, the
pull is to fix the mismatch immediately, usually by one side quietly adopting
the other's model in a commit that looks like integration and is actually a
surrendered boundary.

G-1 and G-2 are the two defects, corrected in the previous commit and recorded
here because the class of mistake will recur.

G-3 is the one that does not dissolve. This compiler records a stable
identifier in a document built to stay legible for years; the civic direction
is address-bound, opaque, epoch-scoped participation that deliberately avoids
durable person identity. The mechanical part is already free -- Author.email
takes an opaque token without a schema change. What remains is that a record
naming a token whose epoch has closed has an author line nobody can ever
resolve again. That may be exactly right as privacy policy and is still a
permanent loss of provenance for a physical object somebody is holding. Two
goods in conflict, owned jointly, settled by neither side writing its document
second.

G-4 and G-5 are the residue of the two new invariants: nothing verifies that
exactly one hop decides, and fail-closed makes the eligibility endpoint a hard
dependency of every gated route. Both recorded rather than designed around.
G-6 notes that a shape is not a vocabulary -- two deployments can comply and
still disagree about what "verified" means, which is tolerable only while the
record states the method verbatim and claims nothing beyond it.

N-1 through N-4 record what was raised against us that is correctly not ours:
buildings against delivery-point geography, the local secure origin MS5-004
needs, the wg-pk fleet question, and credential hierarchies. Written down so a
successor does not mistake them for work or rediscover them as new.

Section 4 records that both projects independently drew the same junction --
geography, then a membership system, then a minimal decision, then this
compiler, one direction only. That is the strongest evidence available that the
shape is right. It also states where the two must not meet: if this compiler
ever reads parcels, delivery points or buildings, the membership layer has been
bypassed and every gate here is void.
2026-09-12 09:35:00 -05:00

252 lines
11 KiB
Markdown

# CONSUMER_INTERFACE_GATES.md
Cross-project concerns raised by, or raised against, the systems this compiler
expects to sit beside. Non-normative.
| | |
|---|---|
| Created | 2026-09-12 |
| Status | A register. Nothing here blocks current work. |
| Peer | Kane Fabric's `docs/CONSUMER_INTERFACE_GATES.md`, at `5df8801` |
| Normative counterpart | `IDENTITY-CONTRACT.md` |
---
## 0. What this file is for, and what it is not for
A gate is a disagreement, an unmade decision, or an assumption that two projects
hold differently and have not yet had to reconcile. Recording one is not the
same as scheduling work on it, and it is not an invitation to negotiate.
The failure this prevents is specific. When two systems meet, the pull is to fix
the mismatch immediately — usually by one side quietly adopting the other's
model, in a commit that looks like integration and is actually a surrendered
boundary. A register makes the mismatch visible without making it urgent, so
that when it does have to be resolved, both sides can see what was known at the
time and who it belonged to.
Kane Fabric wrote the first of these against this project. This is the same
instrument pointed the other way, plus the defects that review found in our own
document.
**Entries are not requirements on anyone.** An entry owned by another project is
a statement that we are waiting, not that they are late.
---
## 1. Defects in our own contract, found by external review
These are corrections we owe, not disagreements. Both are addressed in the same
commit that adds this file; they are recorded because the *class* of mistake
will recur.
### G-1 — an illustrative value read as an expectation
`IDENTITY-CONTRACT.md` gave `kane-fabric/oidc` as an example authentication
method. Kane Fabric has no OIDC service, no user database, and no
person-authentication role. The example named a capability in another project
that does not exist and was never asked for.
An example in an interface contract is read as an expectation by the next person
to implement against it. This is the same failure as the "acceptable for a
development name" sentence that survived three documents: a plausible clause,
never challenged, hardening into a constraint.
**Corrected.** Method strings are now specified by shape rather than by example.
**Owner:** this project. **Blocks:** nothing. **Standing lesson:** an interface
document should contain no example that names a system outside it.
### G-2 — a jurisdiction baked into the wire format
The headers were `X-Kane-Auth-Email` and `X-Kane-Auth-Method`.
Two things wrong. The contract insists at length that the compiler must never
learn a membership concept, then puts a county in the header name — a deployment
fact in an invariant place. And `-Email` names a format rather than a role, in a
field that is explicitly allowed to hold something else (see G-3).
**Corrected** to `X-Mechcomp-Auth-Id` and `X-Mechcomp-Auth-Method`. The receiver
is the invariant; the jurisdiction is not.
**Residue:** the header lands in `design_record.Author.email`, a field named for
what it holds today. Renaming it is a format change to every stored record and
is deliberately not done now. Noted so the mismatch is on record rather than
discovered.
**Owner:** this project. **Blocks:** nothing.
---
## 2. Open gates
### G-3 — persistent person identity against epoch-scoped participation
**The disagreement.** This compiler records a stable identifier for the author
of a design, in a document built to remain legible for years. The civic
direction is address-bound, opaque and epoch-scoped participation, which
deliberately avoids durable person identity.
These are not two spellings of one idea. They disagree about whether a person
should remain identifiable over time.
**What already accommodates it.** Nothing in `design_record.py` requires the
string to be an email. `Author.email` holds an identifier; `verified` and
`method` state what it is worth. An opaque, epoch-scoped token fits the existing
field without a schema change, and `Author.handle` already exists for a display
name that is explicitly not the identity.
**What does not dissolve.** A design record is meant to be readable by someone
who has none of this software, years from now. An epoch-scoped identifier is
meant to stop resolving. A record naming a token whose epoch has closed has an
author line that can never again be resolved to anyone — which may be exactly
right as privacy policy, and is still a permanent loss of provenance for a
physical object somebody is holding.
That is a conflict between two goods. It is not a bug in either design and it
cannot be settled by whichever side writes its document second.
**What this project will not do:** pre-emptively adopt either model, or add an
identity-mode switch to the record format before there is a second consumer to
justify one.
**Owner:** joint — this project and whatever membership system reaches
production first. **Blocks:** nothing today. Becomes blocking at the first
implementation of `IDENTITY-CONTRACT.md` §7, and is cheap until then only
because no record with a verified author yet exists anywhere.
### G-4 — the chain may grow, and exactly one hop may decide
`IDENTITY-CONTRACT.md` names CT 101 as the decider because CT 101 is what exists.
Additional containers are expected to insert themselves between the browser and
this application, possibly several, possibly owned by other projects.
The invariant that matters is not which box decides. It is that **exactly one
does, and that it is the last hop before the application.** Two intermediaries
both setting the identity headers is a forgery vector wearing the costume of a
deployment change: the second one wins, the first one believes it decided, and
nothing in the chain reports a conflict.
**Corrected in the contract** by restating the strip and the decision as
properties of the chain rather than duties assigned to a named container.
**Residue:** nothing verifies the property. A check that the application is
reachable only from its declared decider would be a `ct-baseline.sh`-shaped
test — binary, checkable, not a matter of judgement — but that script is host
property covering three projects and adding to it is a CIVICVS decision. Carried
as `HANDOFF.md` open question 11, which asks the same thing about working-tree
ownership.
**Owner:** this project for the contract; CIVICVS for whether it is enforced.
**Blocks:** nothing.
### G-5 — what happens when the decider cannot answer
The contract specified `2xx` and `401`. It said nothing about the eligibility
endpoint being unreachable, slow, or returning something unparseable. Across a
chain of unknown length and multiple owners, unreachable is the ordinary case
rather than the exotic one.
Fail-open and fail-closed are both defensible and they are not the same system.
Discovering which one was built during an outage is the worst way to find out.
**Corrected in the contract:** anything that is not an affirmative permission is
a refusal. Unreachable, timed out, malformed, and `5xx` all deny.
**Residue:** this makes the eligibility endpoint a hard dependency for every
gated route. Whether that is acceptable is a question for whoever operates the
membership system, and the answer may be that gated routes need a degraded mode.
Not designed. Recorded.
**Owner:** joint. **Blocks:** nothing today; `/m/` is not yet gated.
### G-6 — method strings need a vocabulary, not examples
If `X-Mechcomp-Auth-Method` is free text, every consumer invents its own, and a
record written by one deployment is uninterpretable by another. If it is an
enumeration, this project is dictating mechanisms to systems it refuses to know
anything about.
**Corrected in the contract** by specifying a shape — issuer, mechanism, and
what was actually verified — while leaving every value open.
**Residue:** a shape is not a vocabulary. Two deployments can comply and still
disagree about what "verified" means. That is tolerable while the record states
the method verbatim and makes no claim beyond it, and it stops being tolerable
the moment anything filters or aggregates on the field.
**Owner:** this project. **Blocks:** nothing.
---
## 3. Raised against us, and correctly not ours
Recorded so that a successor does not mistake them for work, and does not
rediscover them as though they were new.
### N-1 — buildings against delivery-point geography
Kane Fabric observes that membership is described as attaching to buildings
while this compiler insists it must never know what a building is.
That is not a contradiction, it is the boundary working. The compiler receives a
decision, not the facts behind it. Whether "building" is the right primitive
against parcel and delivery-point geography is membership semantics, upstream of
anything here, and a correction there requires no change to
`IDENTITY-CONTRACT.md`.
**Not ours.** The compiler's only stake is that the answer stays an answer.
### N-2 — the local secure origin
MS5 needs a browser to establish a secure context with a local edge while
central infrastructure is unavailable. This project has centrally terminated
public TLS and internal proxy TLS, which solves a different problem and offers
nothing to that one.
**Not ours.** No claim is made that our TLS architecture is a model for it.
### N-3 — the `wg-pk` fleet question
Peer lifecycle, key replacement, address allocation and hub ownership do not
extrapolate from the current manual administration. This project depends on the
hub as transport and deliberately refuses to make it an authorization authority
— `IDENTITY-CONTRACT.md` §2 — but the fleet design is estate work.
**Not ours.** Our only requirement is that the hub stays transport.
### N-4 — credential hierarchies stay separate
Proxy TLS, edge TLS, WireGuard keys, membership credentials and signing
authority have no reason to merge. We agree, and note it here so that nobody
proposes a unification on our behalf.
**Not ours, and not wanted.**
---
## 4. The shape of the eventual junction
Recorded because both projects independently drew the same picture, which is the
strongest evidence available that it is right.
```
geography facts
|
v
a membership or participation system
|
v a minimal authorization decision
|
v
this compiler
```
One direction. The compiler's need for authentication does not oblige the
geography layer to acquire authentication, and the geography layer's model of
participation does not reach this application except as a verdict.
Where the two must not meet: this compiler and geography, directly. If a future
design has us reading parcels, delivery points or buildings, the membership
layer has been bypassed and G-3 through G-6 are all void.