docs(adr): ADR-0028 — Principle II forbids network dependence, not availability - #144
Merged
Merged
Conversation
…ailability Feature 010's T093 could not be closed, and the reason was not the one it was recorded under. T093 discharges FR-050, whose second conjunct reads "network access is permitted **only** during dependency installation". That is false while `bun test` runs with ambient network, and it cannot be made true by effort: the suite contains the two-sided controls that prove the denial mechanism works, and a control that establishes denial cannot itself run under denial. Wrapping it was attempted on both platforms and fails differently on each — macOS `sandbox-exec` denies loopback (3 failures); Linux `unshare --net` brings `lo` up so that failure does not occur and 11 fail instead, because the denial-proving tests must nest a sandbox inside the one already wrapping them. The finding is that FR-050 is stricter than the law it cites. Principle II tests **dependence** in three places — "MUST require no ... network access", "Network-dependent tests ... are forbidden", "a change that makes any post-install gate ... require ... a network call is a defect" — and **availability** in one: "the install exception is limited to `bun install --frozen-lockfile`". `bun test` satisfies all three of the first kind and fails the fourth. FR-050 restated the principle using the fourth reading and presented it as a faithful derivation, so a task has been blocked by a feature requirement that overstates ratified law, with the record of it living in a task comment. This record resolves the reading — dependence is the operative test — and records the `bun test` step as the single named exemption, bounded by four conditions: it must be named where it occurs, justified by the nesting obstruction rather than convenience, accompanied by every other post-install step remaining wrapped, and it permits ambient availability but never use. FR-050 is amended by reference, the mechanism ADR-0014 used for ADR-0012 and ADR-0013. Option D — wrap the step and delete the denial-proving controls — is recorded as considered and refused, because it would satisfy the letter by removing the evidence that makes every other wrapped step meaningful. The 13-of-14 figure was counted from the workflow, not asserted: the `clean-clone-builds` job has 17 steps, 3 pre-install, 14 post-install, of which 13 reference `run-network-denied.ts` in their run command and exactly one does not — the `bun test` step this record names. `adr lint`: 28 records, 0 errors, 0 warnings. `adr queue`: empty. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: Mark Beacom <m@beacom.dev>
There was a problem hiding this comment.
Pull request overview
Records ADR-0028’s interpretation of Constitution Principle II and a bounded bun test exemption.
Changes:
- Defines network dependence as the operative compliance test.
- Documents the single exemption, constraints, alternatives, and follow-up work.
Suppressed comments (2)
docs/adr/0028-read-principle-ii-as-forbidding-network-dependence-and-exempt-the-step-that-proves-denial.md:87
- This factual claim contradicts the control that motivates the ADR. PR #98's probe deliberately fetches its loopback listener and asserts the unsandboxed result is
CONNECTED; this ADR also records that the full suite fails under both denial wrappers. Distinguish external-network dependence from the intentional hermetic loopback access instead of claiming that nothing reaches the network or that the suite passes with it gone.
Three statements test whether a step *depends on* the network. One tests whether
the network is *available to* it. `bun test` satisfies all three of the first
kind — nothing in the suite reaches the network, and it passes with the network
gone — and fails the fourth.
docs/adr/0028-read-principle-ii-as-forbidding-network-dependence-and-exempt-the-step-that-proves-denial.md:99
- The named suite does not satisfy this operative test as written: PR #98's denial control intentionally makes an unsandboxed loopback request, while condition 4 later says any test that reaches the network is a defect. Define the rule in terms of external network/egress with an explicit hermetic-loopback allowance, or make that specific control access part of the exemption; otherwise the ADR immediately classifies its own justification as noncompliant.
**Principle II's operative test is dependence, not availability. A post-install
step is compliant when it neither requires nor uses the network, whether or not
one happens to be reachable. The `bun test` step of `clean-clone-builds` is
recorded as a named, bounded exemption from the availability reading.**
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+18
to
+21
| - type: path | ||
| pattern: "specs/**/spec.md" | ||
| - type: path | ||
| pattern: "specs/**/tasks.md" |
mbeacom
added a commit
that referenced
this pull request
Aug 16, 2026
CI caught a real id collision that the local tree did not have: `main` merged a different ADR-0028 (portable agent plugin) while this branch was open, so `adr check` failed with `unique-id 0028 is used by multiple records`. self-dogfood, clean-clone-builds and both node-smoke jobs went red on it. This is the risk flagged when 0028 was first scaffolded — the number had already been used and reverted (#144/#145), so `adr new` offered it again and a concurrent branch took it first. The corpus is right to fail closed here; a duplicate id makes every `affects:` resolution ambiguous. Renumbered highest-first through placeholders so 0028 -> 0029 could not then be re-caught by the 0029 -> 0030 pass: 0028 scope-backstage-publication... -> 0029 0029 keep-extension-surfaces... -> 0030 0030 publish-a-narrow-consumer-sdk... -> 0031 Filenames, frontmatter ids, `# ADR-XXXX` headings, `relatesTo`, every cross-link between the three, the ADR-0031 amendment note on ADR-0029, and the ADR-0030 references in `scripts/check-deps.ts` and its test (comment, violation reason string, and the describe block) all moved together. Verified that no other record's number was touched: the only ADR references remaining in the three files are 0003, 0007, 0010, 0012, 0013, 0014, 0016, 0019, 0020, 0025 plus the new 0029/0030/0031. Ratification carries over unchanged — 0029 and 0030 remain accepted and ratified by @mbeacom, 0031 remains proposed. adr lint: 31 records, 0 errors, 0 warnings. typecheck clean, 2173 pass / 0 fail, check:deps ok. `adr check` over the branch diff now reports 0 changed-record errors, which is the failure CI reported. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: Mark Beacom <m@beacom.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Resolves an ambiguity in Constitution Principle II and records a single bounded exemption, unblocking feature 010's
T093.The finding
T093discharges FR-050, whose second conjunct reads "network access is permitted only during dependency installation". That is false whilebun testruns with ambient network, and it cannot be made true by effort: the suite contains the two-sided controls that prove the denial mechanism works, and a control that establishes denial cannot itself run under denial.Wrapping it was attempted on both platforms and fails differently on each, which is what makes the obstruction structural rather than a macOS quirk:
sandbox-execFailed to start serverunshare --netloup so that failure does not occur — 11 fail instead, because the denial-proving tests must nest a sandbox inside the one already wrapping themThe real problem is that FR-050 is stricter than the law it cites. Principle II tests dependence in three places and availability in one:
bun install --frozen-lockfile"bun testsatisfies all three of the first kind — nothing in the suite reaches the network, and it passes with the network gone — and fails the fourth. FR-050 restated the principle using the fourth reading and presented it as a faithful derivation. So a task has been blocked by a feature requirement that overstates ratified law, with the record of that living in a task comment rather than a decision.The decision
Principle II's operative test is dependence, not availability. A post-install step is compliant when it neither requires nor uses the network, whether or not one happens to be reachable. This changes no observable behavior — every gate that was green stays green, and no step gains permission to use a network it could not use before.
The
bun teststep ofclean-clone-buildsis recorded as the single authorized exemption, bounded by four conditions that must all hold or it lapses:FR-050 is amended by reference, the same mechanism ADR-0014 used for ADR-0012 and ADR-0013. Its remainder — no credential, no running service, nothing required by build, test, or generator invocation — stands unchanged and unweakened.
Options recorded, including the one refused
Option D — wrap the step and delete the denial-proving controls is named in the record as considered and refused. It would satisfy the letter by removing the evidence that makes every other wrapped step meaningful, trading real assurance for a green checkbox. It is written down so a future reader can see it was rejected rather than overlooked.
Option B (fix FR-050 silently in the spec) was rejected because Principle II's fourth bullet genuinely supports the stricter reading — this is a choice between two live readings of ratified law, and resolving that inside a feature spec is how a constitutional interpretation gets made by whoever happened to be writing a requirement that day.
Option C (split
T093) defers the decision and leaves the next feature citing Principle II with the same ambiguity and the same stall.Verification
The 13-of-14 figure was counted from the workflow, not asserted. The
clean-clone-buildsjob has 17 steps: 3 pre-install, 14 post-install, of which 13 referencerun-network-denied.tsin their run command and exactly one does not — thebun teststep this record names.adr lint— 28 records, 0 errors, 0 warningsadr queue— empty (this record isaccepted, ratified by@mbeacom)Follow-on
The four action items are tracked in the record and land in #98: amend FR-050 to cite this record, close
T093on the runner evidence, name the exemption in the workflow step, and state it as one step of fourteen wherever job coverage is described — never as "every step is denied".