Repository navigation
test(e2e): walk the round-two BEP conditions end to end (T76) - #2665
Conversation
Add bep_round_two_conditions_closed. Its legs check the store rules that bep serve holds, a replaced client key, the audit jti, the key bound, the QUIC cohort flows and race, the revoked id and the quarantine start. Each leg prints PASS or NOT RUN with its gate.
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
|
Approved: every review thread resolved at @norrietaylor resolved the last thread, which releases the approval this review had withheld. Nothing to do. |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 2 conditions · the full ruling
The walk's checks agree with Gatehouse §6.10 lines 839 and 842 and Networking line 150. But no leg ran on this head, so no requirement is proven yet. The cohort and quarantine legs print NOT RUN with no owning issue. C1 adds that issue to their reasons. C2 keeps each requirement open until a lane prints the leg's PASS line.
Ruled at cf635fd against gominimal/arch@109541a48c31 by claude-opus-5-5.
The key leg now runs under CI, or with E2E_BEP_KEY_REPLACE=1, so a local run does not replace the developer's client signing key. The teardown trap deletes a refused key value that a failed leg leaves in the keychain. It also stops the quarantine leg's bep serve, removes its sockets, and takes the unreadable line back out of the audit segment on every exit path.
…conditions-closed-end-to-end
|
Round 1 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
A person can run ./scripts/session-e2e.sh bep_round_two_conditions_closed. The case walks the round-two conditions: the store rules that bep serve holds, a replaced client key that keeps verifying until box A ends, one audit jti per box, the --max-client-keys bound, the cohort flows, the revoked id that never returns, and the quarantine start. Each leg prints PASS, or NOT RUN with its gate. This round, a local run no longer replaces the developer's client key unless they opt in. A failed leg no longer leaves a refused key, an unreadable audit line, or a running bep serve behind. Notes from the agent: Revise round 1. This box is Linux, so the live legs (store, key, quarantine) and the cohort leg did not run here. They need the macOS VM lane with a GitHub sign-in, and the QUIC block for the cohort leg. I tested the new rt_quarantine_unwrite helper by itself on a temporary file: it cut the appended line and kept the earlier record. The original client key is not backed up and restored. The proxy revokes it when box A ends, so a restored copy cannot verify. Also, a read of the item through 'security find-generic-password -w' can block on a keychain access prompt on a headless runner. The key leg is gated instead: it runs when CI is set (GitHub Actions sets it), or with E2E_BEP_KEY_REPLACE=1. |
|
The runtime will not revise this pull request again on its own: the diff is +521/-2 (523 lines), past 3x the plan's estimate of 120 lines (est: 0 code, 120 tests, as #2591 reads now), at round 1 (the last trigger was the runtime's review findings). A person decides now. Remove |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 2 conditions · the full ruling
The compare runs the key leg only under CI or with E2E_BEP_KEY_REPLACE=1. It also adds teardown that puts the keychain and the audit segment back. That teardown removes only the test's own unchained line, so the §6.10 hash chain stays whole. No requirement deviates. Every leg is NOT RUN on this head, so C1 keeps the legs open on #2500. C2 keeps BEP-032 injection open on #2525.
Ruled at 039f4fd against gominimal/arch@109541a48c31 by claude-opus-5-5.
|
/revise Revise round on the arch conditions and review findings at
Generated by Claude Code |
…conditions-closed-end-to-end
The cohort leg polls for box A's leaf in quic443_blocked_leaves instead of a fixed window, and accepts EPERM. The store leg prints a PASS line for its rules check.
|
Round 2 of 10 on a /revise note, pushed as
Verify Review threads the coder judged:
A person can run ./scripts/session-e2e.sh bep_round_two_conditions_closed and see each leg print PASS or NOT RUN with its gate. On the native Linux CI lane, the cohort leg now fails with '::error::a CI native lane must be able to load the classifier table: ' when the QUIC block is missing, and it waits for box A's leaf in quic443_blocked_leaves before it checks the refusals. Under CI the quarantine leg runs without E2E_BEP_QUARANTINE=1. The store leg prints a PASS line for its rules check. On this box every leg printed NOT RUN, so this round proves no leg yet. The store, key and quarantine legs need the macOS lane with a live proxy (#2500), and the injection check needs #2525. Notes from the agent: Item 3: no change was necessary. proof_bep_round_two_conditions_closed is already in the whole-lane order (scripts/session-e2e.sh, the no-argument dispatch), and no OS branch guards it. Item 1: the CI error also covers a missing passwordless sudo, as proof_host_ip_deny_all does, because the leg cannot place the daemon in the classifier tree without it. Off CI the reason names the native Linux CI lane (ci-linux-native). The uname/E2E_VM gate stays NOT RUN under CI, because the VM lanes run the same whole-lane order. Item 4: the earlier flows now last 120 s, so a slow activation of box B cannot end them before the block. After box B's activation and first exec, the leg polls 'nft -j list set inet minimal_class quic443_blocked_leaves' for box A's own leaf (its box id, which sanitize_box_id keeps as is) for up to 30 s. Each flow must end refused between the start of box B's activation and 2 s after the block was seen. The injected probe must be refused within 2 s, timed inside the box. 'Operation not permitted' counts as a refusal everywhere 'Connection refused' did. I did not run the cohort leg on a host with the classifier installed, so its new poll is not observed yet. just clippy-strict was not run (no Rust changed). |
There was a problem hiding this comment.
arch-review: CONDITIONS · 3 conditions · the full ruling
The compare makes the cohort and quarantine legs run under CI, and each new path has a defect. Under CI the quarantine leg moves the real audit segment of the persistent macOS runner into quarantine. Gatehouse §6.10 line 839 says start restores the revocation records from every retained segment. Restore the opt-in (C1). Under CI the cohort leg fails when no classifier is installed before the walk, and no native job installs one. Install it in the leg, as proof_host_ip_deny_all does (C2). The EPERM match also accepts a silent drop. Assert the reject rule when the flow sees EPERM (C3).
Ruled at b5bdba0 against gominimal/arch@109541a48c31 by claude-opus-5-5.
|
/revise Revise round on the arch CONDITIONS at
Change nothing else. Run Generated by Claude Code |
Keep the quarantine leg opt-in only, since the macOS runner keeps its real audit log. Under CI the cohort leg installs and removes its own classifier, and an EPERM refusal must show the reject rule in the table.
…conditions-closed-end-to-end # Conflicts: # scripts/session-e2e.sh
|
Round 3 of 10 on a /revise note, pushed as Resolved conflicts in:
Verify Review threads the coder judged:
The walk scripts/session-e2e.sh bep_round_two_conditions_closed covers the round-two conditions. Under CI the quarantine leg no longer runs, so the real audit log of the persistent macOS runner stays as it is. Under CI the cohort leg now installs the classifier itself and removes it again. An 'Operation not permitted' refusal now counts only when the table holds the active reject rule. On this box every leg prints NOT RUN with its gate, so no leg shows PASS here. Notes from the agent: C1: the quarantine gate is E2E_BEP_QUARANTINE=1 only. The CI comment is deleted, and 'and always on under CI' is gone from the case header. C2: under CI, when the helper or the table marker is missing, the cohort leg checks the gates of proof_host_ip_deny_all (nft, ip, sudo -n, the --print-ruleset mount rehearsal, the default-route source address). It then stops the daemon, sets CO_CLASSIFIER_INSTALLED and runs the install with --cohort-address and --node-plane-address. It calls fail only when a gate or the install fails. teardown() runs --uninstall when the flag is set. Both not_run reasons no longer name ci-linux-native. One addition beyond the literal note: the leg also uninstalls on its own pass path, after it stops the daemon. The whole-lane order runs this walk before proof_host_ip_deny_all and the daemon-fetch proof, and both refuse a host that still carries a classifier install, so a leftover install would turn those cases red under CI. C3: co_eperm_is_reject runs after each flow check and after the probe while blocked. When the output has 'Operation not permitted' and no 'Connection refused', it reads 'sudo -n nft list table inet minimal_class' and calls co_fail unless the output contains '@quic443_blocked_leaves udp dport 443 reject with icmpx port-unreachable'. Risk: some nft versions list the reject as 'icmpx type port-unreachable'. On such a host the needle in the note does not match, and the leg fails. The release probe after box B ends is not checked, becaus…[truncated] |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
This head closes the conditions from the b5bdba0 review. The cohort leg installs the classifier under CI and fails closed when a gate is missing. EPERM counts as a refusal only when the table holds the reject rule, as networking §5.3 requires (an active reject, never a silent drop). The quarantine leg is opt-in again, so CI does not write into a real audit log. One condition is left: the quarantine NOT RUN reason says a CI lane runs the leg, and at this head no lane does. Make the change in C1. The store, key and quarantine legs stay open on #2525 and #2500.
Ruled at 2b9a7f2 against gominimal/arch@109541a48c31 by claude-opus-5-5.
There was a problem hiding this comment.
minimal-review — approval withheld
Verdict COMMENT — APPROVE withheld: 16 unresolved threads — minimal-foundry[bot] scripts/session-e2e.sh:13461, minimal-foundry[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh:13887, …. No findings.
Panel: 3 of 3 personas ran (correctness, security, supply-chain).
|
/revise Revise round on the red The failure.
Generated by Claude Code |
nft list prints the default port-unreachable reject of an inet table as a bare 'reject'. Match that form, and refuse a drop or another reject type.
|
Round 4 of 10 on a /revise note, pushed as
Verify Review threads the coder judged:
In the cohort leg of bep_round_two_conditions_closed, co_eperm_is_reject now accepts the rule as nft list prints it (a bare 'reject' after '@quic443_blocked_leaves udp dport 443'). It still fails on a drop or on a reject type other than port-unreachable. The table the CI run printed now passes this check. Notes from the agent: The directive limited this round to co_eperm_is_reject. I did not run ./scripts/session-e2e.sh bep_round_two_conditions_closed on this box, because it needs a live daemon, the classifier install and passwordless sudo. I ran the new match in a small bash harness against five inputs: a bare reject (accepted), 'reject with icmpx port-unreachable' (accepted), 'reject with icmpx admin-prohibited' (refused), 'drop' (refused) and an empty table (refused). Thread PRRT_kwDOPdfcxM6wkJAr is a correct finding, but this round's note said to change nothing else. Also, I do not know an issue that files a lane with E2E_BEP_QUARANTINE=1, so I cannot name one. |
|
The runtime will not revise this pull request again on its own: the diff is +649/-1 (650 lines), past 3x the plan's estimate of 120 lines (est: 0 code, 120 tests, as #2591 reads now), at round 6 (the last trigger was a /revise note). A person decides now. Remove |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The compare changes one thing: the key leg now runs only with E2E_BEP_KEY_REPLACE=1, CI included. That consent gate is correct, because the leg writes to the login keychain. But no lane sets the variable, so the leg is NOT RUN everywhere. Its NOT RUN line does not say which lane runs it. Gatehouse §6.10 line 839 is what the leg proves, and an open leg needs an owner. Make the edit in C1. The leg then stays open on #2500, and the merge can proceed.
Ruled at fda5893 against gominimal/arch@109541a48c31 by claude-opus-5-5.
There was a problem hiding this comment.
APPROVE withheld: 16 unresolved threads — minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh:13900, minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh:13790, ….
minimal-review — advisory review
Verdict COMMENT — No findings.
Panel: 2 of 3 personas ran (security, supply-chain); did not complete: correctness.
|
/revise Close arch condition C1 from the ruling at
Generated by Claude Code |
…conditions-closed-end-to-end
The key leg runs only with E2E_BEP_KEY_REPLACE=1, and no automated lane sets it. Its NOT RUN reason and the walk's header entry now name the manual macOS lane (#2500), as the quarantine leg does.
|
Round 1 of 10 on a /revise note, pushed as
Verify Review threads the coder judged:
The key leg of bep_round_two_conditions_closed now prints NOT RUN with a reason that names the manual macOS lane that runs it (#2500), the same as the quarantine leg. The walk's header comment says the same for the key entry. The legs themselves still print NOT RUN on this box, so this round closes only arch condition C1 and proves no leg PASS. Notes from the agent: Text only, as the /revise note asked. The header sentence goes right after the E2E_BEP_KEY_REPLACE=1 10BC8 gate, so 'it' clearly means the key leg. Two comment lines were reflowed to keep the width. No other change. |
|
The runtime will not revise this pull request again on its own: the diff is +650/-1 (651 lines), past 3x the plan's estimate of 120 lines (est: 0 code, 120 tests, as #2591 reads now), at round 1 (the last trigger was a /revise note). A person decides now. Remove |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 2 conditions · the full ruling
The compare only changes the key leg's NOT RUN reason so that it names the manual macOS lane (#2500). The gate and the checks are unchanged, so the earlier ruling stands. The key and quarantine legs are NOT RUN at this head, and a NOT RUN leg is open. Run them on the manual macOS lane and record the PASS rows (C1). Store injection stays open on #2525 (C2).
Ruled at d6fbeff against gominimal/arch@109541a48c31 by claude-opus-5-5.
There was a problem hiding this comment.
APPROVE withheld: 17 unresolved threads — minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh:13925, minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh:13815, ….
minimal-review — advisory review
Verdict COMMENT — No findings.
Panel: 1 of 3 personas ran (security); did not complete: correctness, supply-chain.
d6fbeff to
8324f08
Compare
There was a problem hiding this comment.
minimal-review — approval withheld
Verdict COMMENT — APPROVE withheld: 17 unresolved threads — minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh:13925, minimal-arch[bot] scripts/session-e2e.sh, minimal-arch[bot] scripts/session-e2e.sh:13815, …. No findings.
Panel: 3 of 3 personas ran (correctness, security, supply-chain).
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 3 conditions · the full ruling
The walk checks what Gatehouse §6.10 lines 836, 839 and 842 and networking §5.3 line 150 require. This head changes only the commit message of the ruled head d6fbeff3, so that ruling stands. Three legs are open. Store injection is NOT RUN until a box carries a store handle (C1, #2525). The key leg and the quarantine leg run only on the manual macOS lane (C2, C3, #2500). Record each leg's PASS on its issue to close it.
Ruled at 8324f08 against gominimal/arch@109541a48c31 by claude-opus-5-5.
There was a problem hiding this comment.
minimal-review — approved
Verdict APPROVE — every review thread is resolved; @norrietaylor closed the last one. The review of 8324f08efce3 withheld this approval on the threads open then. Posted as a comment: the App cannot approve its own pull request; the check and the label carry it.
There was a problem hiding this comment.
Babysitter review at 8324f08e. I read the walk bep_round_two_conditions_closed in scripts/session-e2e.sh against T76's plan block. Each round-two residual has a leg that prints PASS or NOT RUN with its gate and owning issue. The key leg now needs E2E_BEP_KEY_REPLACE=1 on every host (the owner's ruling on the security finding), so no CI shell touches the login keychain. The quarantine leg needs E2E_BEP_QUARANTINE=1, and both name the manual macOS lane (#2500). The cohort leg installs and removes the classifier itself, and an EPERM passes only when the table holds the quic443_blocked_leaves reject rule, so a silent drop cannot pass. The open legs are held on #2525 (store injection) and #2500 (key and quarantine PASS lines), as the PR body's "Arch conditions" table records. No further findings.
Generated by Claude Code
There was a problem hiding this comment.
Babysitter approval at 8324f08: every merge gate passes at this head (arch PASS at 8324f08, zero open threads, every lane aggregator green). Squash title test(e2e): walk the round-two BEP conditions end to end (T76) and the squashed message pass commitlint. Queued for squash merge.
Generated by Claude Code
T76 — Round-two conditions closed, end to end
slice: S10
kind: integration
covers: BEP-032, BEP-067, BEP-063, BEP-018, BEP-070, BEP-068
size: M
est: 0 code, 120 tests
executor: agent
difficulty: needs care
model: standard
diagnostics: each case prints PASS or NOT RUN with its gate
observability: none beyond the cases' own output
layers:
- e2e:
- scripts/session-e2e.sh: one walk over the round-two conditions: a store value injected by
bep serveunder a client rule, a replaced client key that keeps verifying, the auditjti, the key bound, the cohort flows and race, the revoked-id collision and the quarantine start; NOT RUN where its gate is missing (#2500)test: ./scripts/session-e2e.sh bep_round_two_conditions_closed
produces: none
consumes: none
proof: The second round of residuals is done: bep serve injects store values under the client's store rules, a replaced client key keeps verifying until its boxes end, the audit record carries the handle's jti, the key bound and kid diagnostics are in place, BEP-063 states revocation and replacement, a blocked cohort ends its earlier UDP 443 flows and its injected processes, a revoked id never returns, and an unreadable audit line has a chain-preserving way out. Its tasks re-cover requirements whose origin tasks merged with an arch condition held on a filed residual; the owner accepted that double coverage on 2026-10-26 so the residuals dispatch as slices.
depends on:
- blocked by #2257
- assumes OQ3 (the mint reads the root certificate's own expiry, and the root is generated with a fixed default validity in one constant that gominimal/arch#85's ruling replaces)
- blocked by #2586
- blocked by #2576
- blocked by #2579
- blocked by #2580
- blocked by #2578
- blocked by #2558
- blocked by #2559
- blocked by #2585
- blocked by #2588
- blocked by #2599
- blocked by #2605
Proof
A person can run './scripts/session-e2e.sh bep_round_two_conditions_closed' and see one walk over the round-two conditions. Each leg prints PASS, or NOT RUN with its gate. On a macOS lane with a live proxy, the key leg does these checks. It writes a value that is no key into the client key's keychain item, and the next box replaces the key. The proxy keeps the replaced key, named by its kid, and the earlier box still answers 'gh api user'. Each box's admit records carry a jti of their own. The destroy records a revocation, and the proxy then revokes the replaced key by its kid. The re-created box gets a new UUIDv7 id. 'bep serve --help' names --max-client-keys. On native Linux with the QUIC block installed, the cohort leg checks that earlier UDP 443 flows, and injections made during and after the turn, all end with 'Connection refused', and that box A sends UDP 443 again when the last blocking box ends. With E2E_BEP_QUARANTINE=1, the quarantine leg checks that an unreadable audit line refuses a box creation and a plain 'bep serve'. It then checks that 'bep serve --quarantine-unreadable' moves the segment aside, writes a chained quarantine record and serves. The store leg checks that bep serve read the client's store rules. Store injection itself stays NOT RUN, because no box can carry a store handle yet (#2525). This box ran no leg, so no leg's PASS is observed yet.
Notes from the agent: On this Linux box every leg is NOT RUN, so the walk's checks are not yet observed. They need a macOS lane with a live proxy, a native Linux lane with the QUIC block installed, and E2E_BEP_QUARANTINE=1. shellcheck -x on the script is clean. Gaps: (1) BEP-032 injection is NOT RUN against #2525, because mint_store_handle has no caller and no box carries a store handle. The leg checks only that bep serve logs that it holds the client's secret-store rules. (2) A colliding box id cannot be produced from the CLI. The walk checks the revocation record, a new UUIDv7 id on re-cre…[truncated]
Arch conditions at
8324f08eE2E_BEP_KEY_REPLACE=1on every host, CI included (the owner's ruling on the security thread). Its PASS line is recorded on #2500.E2E_BEP_QUARANTINE=1on a host whose audit log may be moved aside. Its PASS line is recorded on #2500.Tests
ci-linux-nativenative-daemon-e2eat0685ee75, whole-lane order, cohort leg (https://github.com/gominimal/minimal/actions/runs/40459955593/job/122048969812)./scripts/session-e2e.sh bep_round_two_conditions_closedVerify
min task run agent-verifypassed ([tasks.verify]).Closes #2591
Generated by Claude Code