From ee3fedf7941b35d745da55a63211dc214852095a Mon Sep 17 00:00:00 2001 From: TheRON Date: Sat, 12 Sep 2026 09:35:00 -0500 Subject: [PATCH] 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. --- docs/CONSUMER_INTERFACE_GATES.md | 251 +++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 docs/CONSUMER_INTERFACE_GATES.md diff --git a/docs/CONSUMER_INTERFACE_GATES.md b/docs/CONSUMER_INTERFACE_GATES.md new file mode 100644 index 0000000..c6e70c1 --- /dev/null +++ b/docs/CONSUMER_INTERFACE_GATES.md @@ -0,0 +1,251 @@ +# 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.