Repository navigation
feat(bep): admit a widened store rule without restarting bep serve (T91) - #2663
norrietaylor merged 3 commits into
Conversation
Admission now asks a source for the store authorities at each CONNECT. bep serve gives it a source over the client's secret-store rules. When the rules change, the source re-issues the root under the same key and subject with the new names, publishes it to the identity file, and admits the rules' authorities that the root in use permits. One info line names the change in the admitted set.
|
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: CONDITIONS · 2 conditions · the full ruling
The re-issue keeps the key and subject, publishes for new boxes only, and keeps admission fail-closed, as Gatehouse §6.10 lines 834 and 839 require. Two paths in StoreAdmission deviate from line 839. A serving proxy can publish a root under a key that bep --replace-key root replaced, because reissue() does not check the key in the identity file. Make the change in C1. A failed re-issue or publish records the new rules as applied, so nothing retries before a restart. Make the change in C2.
Ruled at 1fd0f5f against gominimal/arch@109541a48c31 by claude-opus-5-5.
Record the store rules only after the re-issue and the publish succeed, so the next CONNECT tries a failed one again. Publish the re-issued root only to an identity file that names the root key the CA holds.
|
Round 1 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
With bep serve running, a store rule that adds an upstream is admitted at the next CONNECT with no restart. The root is re-issued under the same key and published to the identity file. A failed publish is tried again at the next CONNECT. An identity file whose root key was replaced is left as it is. Notes from the agent: Revise round 1. Only crates/bep/src/main.rs changed. StoreAdmission now holds the kid of the CA's root key, and an unpublished flag. cargo clippy -p bep --all-targets is clean. When the root key in the file does not match, bep serve logs an error at each CONNECT until a restart, because the rules stay unrecorded. Fail-closed authorities are as before: the admitted set follows the union of the root the CA holds. |
There was a problem hiding this comment.
arch-review: PASS · the full ruling
The compare fixes the two open points on the re-issue path. A failed re-issue or publish now leaves Admitted.rules unchanged, so the next CONNECT tries again. StoreAdmission::publish refuses an identity file that names a different root key, as §6.10 line 839 requires for a replaced root. The root is re-issued under the same key and subject, and running boxes keep their anchor (lines 834 and 839). BEP-032 conforms, and no condition is open.
Ruled at a2c9ab1 against gominimal/arch@109541a48c31 by claude-opus-5-5.
A failed re-issue or publish no longer reads the identity file and logs an error at every CONNECT. The same rules are tried again after 60 s, and a change of the rules tries again at once.
|
Round 2 of 10 on the runtime's review findings, pushed as
Verify Review threads the coder judged:
A store rule that adds an upstream is admitted at the next CONNECT without restarting bep serve. The root is re-issued under the same key and published. A failed publish no longer retries and logs at every CONNECT: it is tried again after 60 s, or at once when the rules change. Notes from the agent: Revise round 2: added a retry delay (REISSUE_RETRY, 60 s) for a failed root re-issue or publish while the rules stay the same. The test now checks that a CONNECT inside the delay does not retry, and that the first CONNECT after it does. One info log line names the retry delay after a failure. cargo clippy -p bep --all-targets and cargo fmt --check are clean. |
There was a problem hiding this comment.
arch-review: PASS · the full ruling
The change conforms to Gatehouse §6.10 line 839. The new commit adds a 60 s wait before bep serve tries a failed re-issue or publish again for the same rules. During the wait, a CONNECT gets the set that the root in use permits for the current rules. A narrowed rule still applies at the next CONNECT. The ruling on a2c9ab19 stands for the rest of the change.
Ruled at 84c2092 against gominimal/arch@109541a48c31 by claude-opus-5-5.
There was a problem hiding this comment.
minimal-review — approval withheld
Verdict COMMENT — APPROVE withheld: 4 unresolved threads — minimal-arch[bot] crates/bep/src/main.rs, minimal-arch[bot] crates/bep/src/main.rs, minimal-foundry[bot] crates/bep/src/main.rs, minimal-foundry[bot] crates/bep/src/main.rs:499. No findings.
Panel: 3 of 3 personas ran (correctness, security, supply-chain).
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 84c2092a68c1 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.
Own review at 84c2092. A changed [secret-store-rules] now reaches bep serve without a restart. At the next CONNECT, StoreAdmission re-issues the root under the same key with the new names, publishes it to the identity file, and widens the admitted set. The set is always cut to the names the root in use permits, so a failed re-issue or publish fails closed. publish refuses a file whose root key was replaced by a separate bep --replace-key root. The rules are recorded only on success, and a failure is retried after 60 s or at once when the rules change.
Generated by Claude Code
There was a problem hiding this comment.
Babysitter approval at 84c2092: every merge gate passes at this head (arch PASS at 84c2092, zero open threads, every lane aggregator green). Squash title feat(bep): admit a widened store rule without restarting bep serve (T91) and the squashed message pass commitlint. Queued for squash merge.
Generated by Claude Code
T91 — Admit a widened store rule without restarting bep serve
slice: S12
kind: task
covers: BEP-032
size: M
est: 120 code, 100 tests
executor: agent
difficulty: unknown ground
model: strongest
diagnostics: none: a widened rule admits its upstream as any other admitted upstream, and the log line names the re-sign.
observability: one info log line when the root re-signs or the admitted set changes
layers:
- admit:
- crates/bep/src/main.rs: a changed
[secret-store-rules]re-signs the root with the new names under the same key and subject, and rebuilds theAdmissionset (#2618)- crates/bep/src/proxy.rs:
Admissiontakes a source that it asks at each CONNECTtest: cargo nextest run -p bep a_widened_store_rule_is_admitted_without_a_restart
produces: none
consumes: none
proof: A store rule that adds an upstream is admitted without restarting bep serve.
depends on:
- blocked by #2599
- blocked by #2257
Generated by Claude Code
Proof
With bep serve running, a person adds a [secret-store-rules] entry for a new upstream to config.toml. The next CONNECT to that upstream is admitted, the published identity file carries a root re-issued under the same key with the new name, and bep serve did not restart. A narrowed rule takes the upstream out again on the next CONNECT.
Notes from the agent: Admission (proxy.rs) now has Admission::with_source, which asks a StoreAuthorities source at each CONNECT. Admission::new keeps a fixed list for the existing tests. Admission no longer derives PartialEq/Eq, because nothing compared it. In main.rs, StoreAdmission reads ClientRules::current() at each CONNECT. When the rules change, it calls the existing Ca::reissue_root, writes the new root into the identity file, and admits only the authorities that the CA's current names permit. If the re-issue fails, the old names stay admitted and an error line is logged. If the publish fails, an error line is logged and the new root is still used for leaves. The ca.rs re-issue line and one new info line in main.rs record the change. The admission(rules) helper is now #[cfg(test)], because serve no longer uses it. Limit: a box created before the widen trusts the root that it got at creation. That root does not name the new host, so a TLS client that enforces the root's name constraints refuses leaves for that host in such a box. Boxes created after the widen get the new root. The interception root that Proxy::new removes from the upstream trust store is still the start-time certificate. A re-issued root has the same key and subject but different constraints. clippy -p bep --all-targets is clean. just clippy-strict was not run.
Tests
cargo nextest run -p bep a_widened_store_rule_is_admitted_without_a_restartVerify
min task run agent-verifypassed ([tasks.verify]).Closes #2618