8000 feat(bep): keep a replaced client key verifying until its boxes end (T84) by minimal-foundry[bot] · Pull Request #2615 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content
{"props":{"contextRegion":{"crumbs":[{"crumb_type":"organization","label":"gominimal","is_root":false,"href":"/gominimal"},{"crumb_type":"repository","label":"minimal","is_root":false,"href":"/gominimal/minimal"}],"localNavigation":[{"id":"code","icon":"code","label":"Code","href":"/gominimal/minimal","selectedLinks":["repo_source","repo_downloads","repo_commits","repo_releases","repo_tags","repo_branches","repo_packages","repo_deployments","repo_attestations"],"popoverTarget":false,"commandId":"repositories:go-to-code","reactNav":{"appTarget":"code-view","anchor":"code-view-repo-link"},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"issues","icon":"issue-opened","label":"Issues","href":"/gominimal/minimal/issues","selectedLinks":["repo_issues","repo_labels","repo_milestones"],"count":240,"popoverTarget":false,"commandId":"repositories:go-to-issues","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"pull-requests","icon":"git-pull-request","label":"Pull requests","href":"/gominimal/minimal/pulls","selectedLinks":["repo_pulls","checks"],"count":31,"popoverTarget":false,"commandId":"repositories:go-to-pull-requests","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"discussions","icon":"comment-discussion","label":"Discussions","href":"/gominimal/minimal/discussions","selectedLinks":["repo_discussions"],"popoverTarget":false,"commandId":"repositories:go-to-discussions","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"actions","icon":"play","label":"Actions","href":"/gominimal/minimal/actions","selectedLinks":["repo_actions"],"popoverTarget":false,"commandId":"repositories:go-to-actions","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"security-and-quality","icon":"shield","label":"Security and quality","href":"/gominimal/minimal/security","selectedLinks":["security","overview","alerts","policy","token_scanning","code_scanning"],"count":0,"popoverTarget":false,"commandId":"repositories:go-to-security","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"insights","icon":"graph","label":"Insights","href":"/gominimal/minimal/pulse","selectedLinks":["repo_graphs","repo_contributors","dependency_graph","dependabot_updates","pulse","people","community"],"popoverTarget":false,"commandId":"repositories:go-to-insights","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}}],"localNavigationUpdateChannel":null,"selectedLink":"repo_pulls"},"owner":null,"headerLogo":{"href":"/","aria-label":"Homepage "},"notifications":{"indicatorMode":"disabled","websocketChannel":null,"fetchIndicatorSrc":"/notifications/indicator","fetchIndicatorEnabled":false},"issues":{"href":"/issues"},"pulls":{"href":"/pulls"},"contributedRepos":{"href":"/repos"},"copilot":{"show":false,"showAgentsButton":false,"showRelaunchAnnouncement":false,"copilotChatUrl":null,"copilotApiUrl":"https://api.githubcopilot.com"},"search":{"show":true,"showCommandPalette":false,"isSearchPage":false,"isJumpToSearch":false,"searchContext":{"scope":"repo:gominimal/minimal","current_repo_name":"minimal","current_repo_nwo":"gominimal/minimal","current_repo_org":"gominimal","user_id":"gominimal"}},"commandPalette":null,"enterpriseBar":{"show":false},"globalTransactionalMessage":[],"payloadsUrl":"/_global-navigation/payloads.json?can_toggle_site_admin_and_employee_status=0\u0026is_admin_mode_on=0\u0026is_ui_opted_out=0\u0026show_ui_opt_out=0\u0026v=8","contextRegionUrl":"/_global-navigation/context-region.json"}}

feat(bep): keep a replaced client key verifying until its boxes end (T84) - #2615

Merged
norrietaylor merged 9 commits into
mainfrom
agent/2605-keep-a-replaced-client-key-verifying-until-the-b
Oct 26, 2026
Merged

norrietaylor merged 9 commits into
mainfrom
agent/2605-keep-a-replaced-client-key-verifying-until-the-b

Conversation

@minimal-foundry
@minimal-foundry minimal-foundry Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor

T84 — Keep a replaced client key verifying until the boxes minted under it end

slice: S10
kind: task
covers: BEP-063
size: M
est: 160 code, 160 tests
executor: agent
difficulty: unknown ground
model: strongest
diagnostics: when every registered client key is in use and the bound refuses a registration, the box creation fails with this text on stderr: "min did not create the box: the Box Egress Proxy already holds 16 client keys, and running boxes use each one. A key is freed when the last box created under it ends."
observability: one info log line when a kept key is retired, naming its kid
layers:
- keep:
- crates/bep/src/control.rs: replace_client_key keeps a key registered while a running box's store handles or sign-in references are signed under it, and revokes it when the last such box ends; the bound drops the least recently registered key that no running box uses, and refuses the registration when every key is in use (owner ruling on gominimal/arch#144, 2026-10-26; #2605)
- crates/minimal/src/mint.rs: the replacement keeps its pending-revoke file and lock, and a bound refusal fails the creation with the diagnostics text
- docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md: the BEP-063 replace and bound sub-requirements state the keep and the in-use bound, name the two verify tests below, drop their known-gap notes, and the pending-revoke comment says the client removes the file (arch C1 on #2594)
test: cargo nextest run -p minimal a_replaced_client_key_keeps_verifying_until_its_boxes_end
test: cargo nextest run -p bep the_registry_bound_never_drops_a_key_a_running_box_uses
produces: none
consumes: none
proof: After a client key replacement, a box created under the old key keeps redeeming its store handles and sign-in references until it ends, and the registry bound never drops a key that a running box uses.
depends on:
- 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 #2543
- blocked by #2578

Proof

A client key is replaced after a refusal. A store handle minted under the old key for a running box still verifies at the proxy, also after a proxy restart. A box created under the old key with a GitHub sign-in reference keeps the old key registered. When the last of those boxes is forgotten, the proxy revokes the old key. The bound drops only a key that no running box uses. When running boxes use every key, the bound refuses the new key, and the creation fails with the fixed diagnostics text.

Notes from the agent: Wire change: register_client_key takes an optional box_id. The mint and the store handle mint send their box id, and forget_box ends the use. The proxy keeps each key's boxes, and a 'retired' flag, in the .client-keys file. A line with neither keeps the old 'key seen' format. A replaced key that a running box uses is retired and not revoked. The forget of its last box revokes it, with an info log line that names its kid. The bound refusal is the error text KEYS_IN_USE plus the bound. The client parses it with bep::control::keys_in_use_bound and maps it to MintError::KeysInUse, which prints the diagnostics text with the proxy's bound. Outside the layers: crates/bep/src/main.rs. Two test struct literals of Request::RegisterClientKey needed box_id: None to compile. There is no other change in that file. I replaced the old test a_replaced_client_key_is_revoked_at_the_proxy with the new verify test, as the spec planned. I also added a_replacement_past_a_bound_of_keys_in_use_fails_the_creation in mint.rs and a_replaced_key_stays_until_its_last_box_is_forgotten in control.rs. Known limit: a box that ends without a forget_box (for example a Ctrl-C before minvmd withdraws it) keeps its key in use until something forgets that box id. The pending-revoke file and lock needed no code change. I changed only the doc comment. just lint-prose did not run because vale is not installed on this box. The full bep suite passed (213 tests). The minimal mint and m…[truncated]

Tests

line exit tail
cargo nextest run -p minimal a_replaced_client_key_keeps_verifying_until_its_boxes_end 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-a34c... Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
cargo nextest run -p bep the_registry_bound_never_drops_a_key_a_running_box_uses 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-5472... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 25.93s ──────────── Nextest run ID 29d9b321-3bab-4bad-ae4f-a9f044114bec with nexte

Verify

min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

re/compose.rs:402:8
    |
402 | pub fn deferring_env() -> StoredEnv {
    |        ^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors

Base

The base branch moved while the coder worked; it was merged in before the tests ran.

Out of scope

These files are outside the task's layers:, so this PR is a draft:

  • crates/bep/src/main.rs

Layer exception

Round 1 (d1addbb) changed two files outside the task's layers, both required by the change:

  • crates/bep/src/main.rs: two call sites set the new box_id: None field that the registration record gains in control.rs.
  • crates/minimal/src/tests.rs: the test inventory names the new verify tests (a_replaced_client_key_keeps_verifying_until_its_boxes_end, a_replacement_past_a_bound_of_keys_in_use_fails_the_creation) in place of the old one.

The local verify ran under rustc 1.98, which the repository does not pin. CI on the pinned toolchain is the gate.

Closes #2605


Generated by Claude Code

register_client_key can name the box it signs for, and forget_box ends
that use. A replacement retires a key in use rather than revoking it,
and the proxy revokes it when the last such box is forgotten. The bound
drops only a key no running box uses, and refuses a new key when every
key is in use.
The mint names its box when it registers the client key, so the proxy
keeps a replaced key verifying until that box ends. A registration
that the proxy's full bound refuses fails the creation with text that
says why.

The replace and bound sub-requirements now keep a key that a running
box uses, name the tests that prove it, and drop the known-gap notes.
The pending-revoke note says the client removes the file.
@coderabbitai
coderabbitai Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d9af7c6b-a664-42fc-9879-86aa81c52aa1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@github-actions
github-actions Bot commented Oct 26, 2026 8000
Copy link
Copy Markdown
Contributor

Spec lint

docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md — 9 finding(s)

docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:113: P004 BEP-003 names test 'bep_second_box_needs_no_sign_in', which was not found in the repository
docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:170: P004 BEP-007 names test 'bep_box_env_holds_sealed_value_only', which was not found in the repository
docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:214: P004 BEP-011 names test 'bep_root_ca_present_in_box_trust_store', which was not found in the repository
docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:230: P004 BEP-012 names test 'bep_proxy_env_and_no_proxy_are_set', which was not found in the repository
docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:284: P004 BEP-015 names test 'bep_git_and_gh_against_private_repo', which was not found in the repository
docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:625: P004 BEP-043 names test 'bep_destroyed_box_values_refused_within_60s', which was not found in the repository
docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:634: P004 BEP-044 names test 'bep_logout_refuses_every_reference_at_next_request', which was not found in the repository
docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:679: P004 BEP-047 names test 'bep_and_gvproxy_are_separate_processes_and_users', which was not found in the repository
docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:688: P004 BEP-049 names test 'prop_audit_chain_detects_unrecomputed_edit', which was not found in the repository

Advisory. None of this blocks the merge; the review decides.

Advisory, and never a merge gate. Linter: gominimal/foundry@fb5932b8, spec format: How Minimal Writes Specs.

The inventory test failed CI because the branch renamed one mint test
and added two that serve a proxy control socket.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a failed check suite, pushed as d1addbbba8da.

line exit tail
cargo nextest run -p minimal a_replaced_client_key_keeps_verifying_until_its_boxes_end 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-3e59... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
cargo nextest run -p bep the_registry_bound_never_drops_a_key_a_running_box_uses 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-3d9f... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 15.56s ──────────── Nextest run ID dbb113bf-cee1-4389-92cf-a100ae63e451 with nexte

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

toredEnv {
    |        ^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.
10000
0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors
warning: build failed, waiting for other jobs to finish...

Outside the task's layers::

  • crates/bep/src/main.rs
  • crates/minimal/src/tests.rs

Converted to a draft: something above needs a person before review.

After a client key replacement, a box created under the old key keeps redeeming its store handles and sign-in references until it ends. The registry bound never drops a key that a running box uses. The CI tests job no longer fails on the daemon connect inventory.

Notes from the agent: The CI log excerpt did not name the failing test. A local run of the minimal crate found it: tests::every_daemon_connection_is_classified in crates/minimal/src/tests.rs. That test lists each connect site by name, and the branch's mint.rs tests changed the list. The branch renamed a_replaced_client_key_is_revoked_at_the_proxy to a_replaced_client_key_keeps_verifying_until_its_boxes_end, which has three connect sites, and added a_replacement_past_a_bound_of_keys_in_use_fails_the_creation. crates/minimal/src/tests.rs is outside the task's layers. I changed it because it is a registry table that must list the connect sites in mint.rs, and no change inside the layers can make it pass. ci-linux-native-success is the lane aggregator. It failed only because the tests job failed.

@norrietaylor
norrietaylor marked this pull request as ready for review October 26, 2026 12:00
@norrietaylor
norrietaylor requested a review from a team as a code owner October 26, 2026 12:00
@minimal-foundry
minimal-foundry Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor Author

Approved: every review thread resolved at 9432d2098da5.

@norrietaylor resolved the last thread, which releases the approval this review had withheld.

Nothing to do.

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: CONDITIONS · 1 condition · the full ruling

The keep and the in-use bound conform to Gatehouse §6.10 line 839. A replaced key keeps verifying for the life of the boxes minted under it. One item is open. The PR body names a known limit with no issue: a box that ends without forget_box keeps its key in use across restarts. With 16 such boxes, the bound refuses every new key. Rule 6 does not accept a residual with no issue. C1 files the issue and names the gap in the BEP-063 bound comment.

Ruled at d1addbb against gominimal/arch@109541a48c31 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/bep/src/control.rs Resolved
A box that ends without forget_box stays in use across restarts, so
sixteen such boxes make the bound refuse every new key. Also explain
why release updates the registry before it writes the file.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 2 of 10 on the runtime's review findings, pushed as 78a170038669.

line exit tail
cargo nextest run -p minimal a_replaced_client_key_keeps_verifying_until_its_boxes_end 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-13c1... Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
cargo nextest run -p bep the_registry_bound_never_drops_a_key_a_running_box_uses 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-9fea... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 14.08s ──────────── Nextest run ID 51e80d20-8cd9-4e8f-8b85-067cfe9376ca with nexte

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

toredEnv {
    |        ^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors
warning: build failed, waiting for other jobs to finish...

Outside the task's layers::

  • crates/bep/src/main.rs
  • crates/minimal/src/tests.rs

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

  • 👍 valid — docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:502: Added a known-gap clause to the BEP-063 replace comment: a box that ends with no forget_box (Ctrl-C before minvmd records it, or a stopped minvmd) stays in use across restarts, and 16 such boxes make the bound refuse every new key. I cannot file issues from this session, so the clause says the issue
  • 👎 invalid — crates/bep/src/control.rs:877: The memory-first order is deliberate and matches the revocation path in replace. With a failed write, memory-first revokes the retired key in this process, and a restart restores it. Write-first with an unchanged registry keeps the key verifying in this process too, so it revokes less. The in-memory

After a client key replacement, a box created under the old key keeps redeeming its store handles and sign-in references until it ends, and the registry bound never drops a key that a running box uses. The spec now also names the known gap of a box that ends with no forget_box.

Notes from the agent: Thread C1 asks for a filed issue and its link. This session has no credential to file an issue, so the known-gap clause says 'issue not yet filed'. A person must file the issue and replace that text with its link. just lint-prose did not run: vale is not installed on this box.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft October 26, 2026 12:13
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: CONDITIONS · 1 condition · the full ruling

The keep, the in-use bound and the refusal text conform to Gatehouse §6.10 lines 839 and 842. The spec now states a known gap: a box with no forget_box holds its key forever, and 16 such boxes block every new key. The spec marks it "(issue not yet filed)". A residual with no issue has no owner. C1 tells you to file the issue, link it from the spec, and add the failed release write as a second cause.

Ruled at 78a1700 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread crates/bep/src/control.rs Resolved
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 4 unresolved threads — minimal-arch[bot] docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:502, minimal-foundry[bot] crates/bep/src/control.rs:877, minimal-arch[bot] docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:494, minimal-arch[bot] crates/bep/src/control.rs:870. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Copy link
Copy Markdown
Member

/revise

Round 3 of #2615, on arch condition C1 at 78a1700. No round is in flight.

  1. C1. The stranded-box gap is filed as T90 — Free the client key of a box that ended without forget_box #2617. In docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md, in the BEP-063 replace sub-requirement comment (line 494), replace (issue not yet filed) with [#2617](https://github.com/gominimal/minimal/issues/2617). Add the second cause to the known-gap text: a failed write in KeyFile::release leaves the ended box in the file, so a restart restores the retired key as in use. Correct the new release comment that says "The next write records it", which is not so after a failed write. Name T90 — Free the client key of a box that ended without forget_box #2617 there too.
  2. In crates/minimal/src/tests.rs, a_replaced_client_key_keeps_verifying_until_its_boxes_end is listed three times in the inventory. List it once.
  3. In crates/bep/src/control.rs, the module docs still say "The proxy binary has no setting for the bound". bep serve --max-client-keys <N> sets it since T69. Say so (T108 — Say in control.rs that bep serve sets the client-key bound #2598).
  4. Change nothing else. Run cargo nextest run -p minimal a_replaced_client_key_keeps_verifying_until_its_boxes_end, cargo nextest run -p bep the_registry_bound_never_drops_a_key_a_running_box_uses, and clippy on both crates with --all-targets.

Generated by Claude Code

Name the second cause of the gap: a failed write of the registrations
file at a box's end leaves the ended box in the file across a restart.
Correct the release comment to match, and say in the control module
docs that bep serve --max-client-keys sets the bound.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 3 of 10 on a /revise note, pushed as 660385e93f69.

line exit tail
cargo nextest run -p minimal a_replaced_client_key_keeps_verifying_until_its_boxes_end 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-2672... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
cargo nextest run -p bep the_registry_bound_never_drops_a_key_a_running_box_uses 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-033a... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 15.09s ──────────── Nextest run ID af5a26b7-93ca-4fae-8220-1c31e6739f39 with nexte

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

toredEnv {
    |        ^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors
warning: build failed, waiting for other jobs to finish...

Outside the task's layers::

  • crates/bep/src/main.rs
  • crates/minimal/src/tests.rs

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

After a client key replacement, a box created under the old key keeps redeeming its store handles and sign-in references until it ends, and the registry bound never drops a key that a running box uses. This round only changes text: the spec gap names #2617 and both causes, and the control module docs name bep serve --max-client-keys.

Notes from the agent: Item 1 done: the spec gap links #2617 and adds the failed-write cause; the release comment now says a failed write leaves the ended box in the file until a later successful write, and a restart before it restores the retired key as in use (#2617). Item 3 done: the module docs say bep serve --max-client-keys sets the count, 16 by default. Item 2 not done: the inventory in crates/minimal/src/tests.rs lists one entry for each connection site, and a_replaced_client_key_keeps_verifying_until_its_boxes_end has three sites (as store_handle_signed_and_key_registered has two entries). With one entry, every_daemon_connection_is_classified fails, so I reverted that edit. just lint-prose did not run: vale is not installed on this box.

@norrietaylor
norrietaylor marked this pull request as ready for review October 26, 2026 12:49
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

The compare to this head changes only comments and the BEP-063 spec note. It answers the open points of the ruling on 78a1700. The stranded-box gap now links to #2617, which is the residual that owns it. The KeyFile::release comment and the module doc on --max-client-keys now match the code. The keep of a replaced key until it 10BC8 s boxes end conforms to Gatehouse §6.10 line 839.

Ruled at 660385e against gominimal/arch@109541a48c31 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/bep/src/control.rs Resolved
A box that ends with no forget keeps its retired client key verifying
with no time limit. The BEP-063 known gap now says so, and says why
neither a maximum age nor a reconcile at restore fits this task (#2617).
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

The new commit changes only the known-gap comment of the BEP-063 replace sub-requirement. It states the stranded-box gap more exactly and keeps the link to #2617. The design keeps handles working for the life of the box (Gatehouse §6.10 line 839). Each handle still carries its own exp (line 842). The PASS on 660385e stands. No condition is open.

Ruled at dfd737c against gominimal/arch@109541a48c31 by claude-opus-5-5.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 4 of 10 on the runtime's review findings, pushed as dfd737cbba43.

line exit tail
cargo nextest run -p minimal a_replaced_client_key_keeps_verifying_until_its_boxes_end 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-89e6... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
cargo nextest run -p bep the_registry_bound_never_drops_a_key_a_running_box_uses 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-7e31... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 19.14s ──────────── Nextest run ID f0d9bf28-2bdd-4414-9aaf-967a6a6d9dbf with nexte

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.


    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

    Checking unicode-truncate v2.0.1
error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors
warning: build failed, waiting for other jobs to finish...

Review threads the coder judged:

  • 👍 valid — crates/bep/src/control.rs:762: The premise holds: a stranded box keeps its retired key verifying with no time limit. The BEP-063 gap text now says this, also for a key replaced as suspect, under T90 — Free the client key of a box that ended without forget_box #2617. No max age was added, because it breaks the arch#144 keep for long-running boxes. No restore reconcile was added, because the pro

After a client key replacement, a box created under the old key keeps redeeming its store handles and sign-in references until it ends. The registry bound never drops a key that a running box uses. The BEP-063 known gap now also says that a box which ends with no forget keeps its retired key verifying with no time limit (#2617).

Notes from the agent: Round 4 changes only the BEP-063 known-gap comment in the spec. The code needs no change this round. A maximum age for a retired key conflicts with the gominimal/arch#144 ruling, because a box that runs longer than that age loses its keep. A reconcile at restore needs a list of live boxes, and the proxy does not hold one. That work is outside this task's layers and #2617 tracks it. Vale is not installed on this box, so just lint-prose did not run on the changed line.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 2 findings, 2 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/bep/src/control.rs Resolved
Comment thread crates/bep/src/control.rs Resolved
A key that a running box uses is never dropped, so it no longer keeps a
known key's registration off the fast path. A failed write at a box's
end makes the next registration write the file again.
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS · the full ruling

The compare conforms, and the PASS on dfd737cb stands for the rest of the change. within() now skips the kept key and keys in use, as enforce() does. So the fast path writes nothing only when the bound drops nothing. A failed write at the end of a box now makes the next registration write the file again. This keeps handles working for the life of the box, as Gatehouse §6.10 line 839 requires.

Ruled at 9432d20 against gominimal/arch@109541a48c31 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 6 unresolved threads — minimal-arch[bot] docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:502, minimal-arch[bot] docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md, minimal-arch[bot] crates/bep/src/control.rs:873, minimal-foundry[bot] crates/bep/src/control.rs:764, minimal-foundry[bot] crates/bep/src/control.rs, …. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 5 of 10 on the runtime's review findings, pushed as 9432d2098da5.

line exit tail
cargo nextest run -p minimal a_replaced_client_key_keeps_verifying_until_its_boxes_end 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-e519... Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
cargo nextest run -p bep the_registry_bound_never_drops_a_key_a_running_box_uses 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-ddc1... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 50.26s ──────────── Nextest run ID 90501443-7c34-40e6-a225-2960e15a050e with nexte

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

toredEnv {
    |        ^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors
warning: build failed, waiting for other jobs to finish...

Review threads the coder judged:

  • 👍 valid — crates/bep/src/control.rs: within now skips the registering key and every key in use, as enforce does, for both the count and the idle check. New test the_bound_check_skips_keys_in_use.
  • 👍 valid — crates/bep/src/control.rs:886: The key is already revoked in memory. A failed write in release now resets written, so the next registration of any key writes the file again. A restart before any successful write still restores the box, as the T90 — Free the client key of a box that ended without forget_box #2617 gap text in the spec says.

After a client key replacement, a box created under the old key keeps redeeming its store handles and sign-in references until it ends. The registry bound never drops a key that a running box uses, and a key in use no longer keeps every later registration of a known key off the fast path.

Notes from the agent: Round 5. within now takes the registering key and skips keys in use, as enforce does. A new unit test the_bound_check_skips_keys_in_use pins it. A failed write in KeyFile::release now resets written to NEVER_WRITTEN, so the next registration writes the file again. A restart before any successful write still restores the ended box. That gap stays tracked in #2617 and the spec text already says so. All 13 bep control tests pass. clippy -p bep --all-targets is clean.

@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Own review at 9432d20. replace_client_key keeps a key while a running box uses it and retires it when the last such box ends. The bound drops only an unused key and refuses with the diagnostics text when every key is in use. within and enforce agree on what can be dropped, and the spec states the keep. The stranded-box gap is #2617. Two security threads (4377402594 and 4377485218) wait on the epic owner.


Generated by Claude Code

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approved

Verdict APPROVE — every review thread is resolved; @norrietaylor closed the last one. The review of 9432d2098da5 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.

@minimal-foundry minimal-foundry Bot added the review:approved minimal-review approved the current head label Oct 26, 2026
@norrietaylor norrietaylor changed the title T84 — Keep a replaced client key verifying until the boxes minted under it end feat(bep): keep a replaced client key verifying until its boxes end (T84) Oct 26, 2026
@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Babysitter approval at 9432d20: every merge gate passes at this head (arch PASS at 9432d20, zero open threads, every lane aggregator green). Squash title feat(bep): keep a replaced client key verifying until its boxes end (T84) and the squashed message pass commitlint. Queued for squash merge.


Generated by Claude Code

@norrietaylor
norrietaylor added this pull request to the merge queue Oct 26, 2026
Merged via the queue into main with commit 4152396 Oct 26, 2026
38 checks passed
@norrietaylor
norrietaylor deleted the agent/2605-keep-a-replaced-client-key-verifying-until-the-b branch October 26, 2026 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review:approved minimal-review approved the current head

Projects

None yet

Development

Successfully merging this pull request may close these issues.

T84 — Keep a replaced client key verifying until the boxes minted under it end

1 participant

0