8000 feat(bep): re-certify the published root when a store registration changes by minimal-foundry[bot] · Pull Request #2767 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

feat(bep): re-certify the published root when a store registration changes - #2767

Merged
norrietaylor merged 4 commits into
mainfrom
agent/2746-re-certify-bep-s-published-root-when-a-store-reg
Oct 31, 2026
Merged

norrietaylor merged 4 commits into
mainfrom
agent/2746-re-certify-bep-s-published-root-when-a-store-reg

Conversation

@minimal-foundry
Copy link
Copy Markdown
Contributor

T99 — Re-certify bep's published root when a store registration changes

slice: S13
kind: task
covers: BEP-013
size: M
est: 180 code, 240 tests
executor: agent
d 8000 ifficulty: needs care
model: standard
diagnostics: when a running proxy answers that it did not re-issue or publish the root, min secret set says that the rule is saved, name the upstream, and say that a box created before the proxy publishes a root with the change does not reach that upstream, pinned by secret_set_asks_a_running_proxy_to_recertify; with no proxy running it prints nothing new, because bep serve issues its root from the current rules when it starts
observability: bep serve logs one info line each time a registration change re-certifies the root, with the number of store rules and whether the publish succeeded; the existing error lines still name a failed re-issue or publish
layers:
- recertify:
- crates/bep/src/main.rs: StoreAdmission re-issues the root and publishes it to the identity file when the control socket reports a store registration change, not only at the next CONNECT, so the next box activation reads a root that admits the new upstream (#2746, arch condition C2 on #2612); the CONNECT path stays the fallback for a rule file edited by hand, and a failed re-issue or publish keeps today's retry
- crates/bep/src/control.rs: a control request that re-certifies at once and answers only after the re-issue and the publish, with ok or the reason they failed
test: cargo nextest run -p bep a_store_registration_change_recertifies_the_published_root_at_once
- client:
- crates/minimal/src/cmd/secret.rs: min secret set sends the re-certify request after it writes the rule, when a proxy answers on its control socket
- crates/minimal/src/mint.rs: the control-socket client that the mint path already uses carries the re-certify request
test: cargo nextest run -p minimal secret_set_asks_a_running_proxy_to_recertify
- e2e:
- scripts/session-e2e.sh: proof_bep_store_reference_end_to_end drops the bep stop and daemon restart that #2612 keeps after min secret set, and the comment that names #2746; the box activates against the proxy that was already running
test: ./scripts/session-e2e.sh bep_store_reference_end_to_end
produces: none
consumes: none
proof: A box activated right after min secret set adds an upstream trusts that upstream, with no restart of bep serve.
depends on:
- blocked by #2294
- blocked by #2618


Generated by Claude Code

Proof

After min secret set writes a rule that adds an upstream, the running bep serve re-issues its root and publishes it to the identity file before it answers. A box activated right after that trusts the new upstream, and bep serve does not restart. The e2e case bep_store_reference_end_to_end now activates its box against the proxy that ran before the set.

Notes from the agent: The control socket takes a new request, {"op":"recertify_root"}. The reply is the usual Reply, {"ok":true} or {"ok":false,"error":...}. StoreAdmission answers it at once and ignores the CONNECT retry delay. The CONNECT path stays the fallback for a rule file edited by hand. bep serve logs one info line for each re-certify, with store_rules and published. The failure text of min secret set goes to stderr: "min secret set saved the rule for . The Box Egress Proxy did not update its root certificate for : . A box created before the proxy updates its root certificate does not reach ." The task fixed no exact wording. The test secret_set_asks_a_running_proxy_to_recertify pins this text. The reason is the text the proxy sends, for example "the root certificate was not written to : ". A proxy older than this change refuses the unknown op, and then this notice prints with that proxy's reason. When no proxy answers on the control socket, the command prints nothing new. RuleTarget has a new field, control. The existing tests in secret.rs pass control: None. The e2e line ran and exited 0, but the case reported NOT RUN, because this box is Linux. The macOS VM lane owes the live evidence. The e2e case now records the proxy pids after the gate. It fails if min secret set printed the notice or if a different proxy serves before the activate.

Tests

line exit tail
cargo nextest run -p bep a_store_registration_change_recertifies_the_published_root_at_once 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-fed3... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling client-config v0.0.1 (/workbench/crates/client-config) Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test
cargo nextest run -p minimal secret_set_asks_a_running_proxy_to_recertify 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-71c3... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling client-config v0.0.1 (/wo
./scripts/session-e2e.sh bep_store_reference_end_to_end 0 the 'min' and 'minimald' under /work/build-cache/target/debug report different versions; rebuilding the pair no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/bu

Verify

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

", "cmd/list.rs::list_other_vm = ungated", "cmd/list.rs::list_selected_vm = gated", "cmd/mod.rs::arm_activation_interrupt = ungated", "cmd/mod.rs::connect_daemon_unchecked = ungated", "cmd/net.rs::cmd_net_forward = gated", "cmd/session.rs::cmd_attach = gated", "cmd/session.rs::cmd_exec = gated", "cmd/session.rs::cmd_session_run = gated", "cmd/session.rs::cmd_session_setup_zed = gated", "dash/rpc.rs::activate = gated", "dash/rpc.rs::connect_missing = gated", "dash/rpc.rs::discover = gated", "diag/net.rs::probe_socket = ungated", "mint.rs::a_refused_client_key_is_replaced_and_registered_before_the_mint = ungated", "mint.rs::a_replaced_client_key_is_revoked_at_the_proxy_after_a_failed_revoke = ungated", "mint.rs::a_replaced_client_key_is_revoked_at_the_proxy_once_for_two_creations = ungated", "mint.rs::a_replaced_client_key_keeps_verifying_until_its_boxes_end = ungated", "mint.rs::a_replaced_client_key_keeps_verifying_until_its_boxes_end = ungated", "mint.rs::a_replaced_client_key_keeps_verifying_until_its_boxes_end = ungated", "mint.rs::a_replacement_past_a_bound_of_keys_in_use_fails_the_creation = ungated", "mint.rs::a_replacement_the_store_does_not_keep_revokes_no_key = ungated", "mint.rs::create = ungated", "mint.rs::local_client_key_at = ungated", "mint.rs::revoke_others = ungated", "mint.rs::store_handle_signed_and_key_registered = ungated", "mint.rs::store_handle_signed_and_key_registered = ungated", "task.rs::arm_task_run_interrupt = ungated", "tests.rs::a_failed_box_reply_forgets_the_box_again = ungated", "tests.rs::a_refused_client_key_forgets_the_box_again = ungated", "tests.rs::an_identity_with_no_root_validity_mints_nothing = ungated", "tests.rs::attach_fall_through_hands_off_the_owning_vm = gated", "tests.rs::attach_refuses_a_box_name_two_vms_know = gated", "tests.rs::exec_fall_through_hands_off_the_owning_vm = gated", "tests.rs::grant_box_registers_its_declared_egress_with_the_proxy = ungated", "tests.rs::grant_box_registers_its_declared_egress_with_the_proxy = ungated", "tests.rs::grant_box_registers_its_declared_egress_with_the_proxy_until_the_creation_fails = ungated", "tests.rs::local_member_is_a_sign_in_reference_expiring_with_the_root = ungated", "tests.rs::mint_and_destroy_append_audit_records = ungated"]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   0.884s] ( 810/1045) minimal tests::attach_refuses_a_box_name_two_vms_know
        PASS [   0.724s] ( 811/1045) minimal tests::exec_fall_through_hands_off_the_owning_vm
        PASS [   1.247s] ( 812/1045) minimal tests::box_name_resolves_vm_without_flag
────────────
     Summary [  11.537s] 812/1045 tests run: 811 passed, 1 failed, 2 skipped
        FAIL [   0.073s] ( 809/1045) minimal tests::every_daemon_connection_is_classified
warning: 233/1045 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

Closes #2746

bep serve takes recertify_root on its control socket. It re-issues the
root for the current store rules, publishes it to the identity file,
and replies only after both, with ok or the reason. The CONNECT path
stays the fallback for a rule file edited by hand.
min secret set sends recertify_root on the proxy's control socket after
it writes a store rule. When the proxy did not re-issue or publish its
root, it says the rule is saved and names the upstream that a box
created before then does not reach. With no proxy running it prints
nothing new.
min secret set now re-certifies the running proxy's root, so the case
drops the bep stop and daemon restart that #2612 kept for #2746. It
checks that the same proxy serves before and after the set.
@coderabbitai
coderabbitai Bot commented Oct 30, 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: a5b28020-2f8f-4d61-9b5e-e4ce82b62897

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.

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

Reviewed: 1 finding, none blocking at 7e215e1946da.

Address the comments on the diff.

Clobber: none seen.

@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_WITH_CONDITIONS · 1 condition · the full ruling

The change conforms to Gatehouse §6.10 line 839. bep serve re-signs the root under the same key when a store rule changes, and boxes that exist keep their anchor. The new control op stays behind the peer-uid check, and a failure keeps the root in use. One condition is open. The e2e case proof_bep_store_reference_end_to_end reported NOT RUN on Linux, so get its PASS row from the macOS VM lane (C1). Separately, the verify log shows every_daemon_connection_is_classified failing, because the inventory does not list the new connect site in cmd/secret.rs. That is not a design item, but CI will stop on it.

Ruled at dfc01ec against gominimal/arch@42d214dc8ac8 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh 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: 1 unresolved thread — minimal-arch[bot] scripts/session-e2e.sh:12527. No findings.

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

min secret set now opens the egress proxy's control socket, so the
connection inventory records that site as ungated.
@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/minimal/src/mint.rs Resolved
@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_WITH_CONDITIONS · 1 condition · the full ruling

The change conforms to Gatehouse §6.10 line 839. bep serve re-self-signs the root under the same key when min secret set changes a rule, and publishes it before it replies. Running boxes keep their anchor. The compare only classifies the new control connection in a test. One condition stays open: the e2e leg reported NOT RUN on Linux. Get a PASS from the macOS VM lane on this head (C1).

Ruled at 7e215e1 against gominimal/arch@42d214dc8ac8 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

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

line exit tail
cargo nextest run -p bep a_store_registration_change_recertifies_the_published_root_at_once 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-55bc... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling client-config v0.0.1 (/workbench/crates/client-config) Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test
cargo nextest run -p minimal secret_set_asks_a_running_proxy_to_recertify 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-633d... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling client-config v0.0.1 (/wo
./scripts/session-e2e.sh bep_store_reference_end_to_end 0 no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/build-cache/target/debug/min and /work/build-cache/target/debug/minimald ::group::Box Egress Proxy: a Keychain

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

        closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "c696b4758d9e585c",
                "span_id": "d9683b0addb4fb73",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetNetSwitch",
                "parent_span_id": "c696b4758d9e585c",
                "span_id": "591648cebb19b6b9",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetDenyAllOptOut",
                "parent_span_id": "c696b4758d9e585c",
                "span_id": "136e8667af81fb6f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "c696b4758d9e585c",
                "span_id": "60ab03ae2fde3913",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "c696b4758d9e585c",
                "queued_behind": "0",
                "span_id": "b9cc84f3d3ce6550",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "c696b4758d9e585c",
                "queued_behind": "0",
                "span_id": "77beca84fd707fce",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "77beca84fd707fce",
                "span_id": "0857ac0832eba4e0",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 
────────────
     Summary [  36.751s] 1045 tests run: 1044 passed, 1 failed, 2 skipped
        FAIL [   2.905s] (1045/1045) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
error: test run failed

Outside the task's layers::

  • crates/minimal/src/tests.rs

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

Review threads the coder judged:

  • 👎 invalid — scripts/session-e2e.sh:12527: The fact is correct: bep_live_gate reports NOT RUN on Linux. But the finding asks for evidence, not a code change. The case body is complete, and no edit on this branch can make a PASS row. A macOS VM lane must run bep_store_reference_end_to_end at this head. This round did not run it, because the c

A box activated right after min secret set adds an upstream trusts that upstream, with no restart of bep serve: secret set asks the running proxy to re-certify, and bep re-issues and publishes its root at once. The e2e case that shows this end to end runs only on the macOS VM lane, and it has no PASS at this head yet.

Notes from the agent: The tests check failed in minimal tests::every_daemon_connection_is_classified. The new ControlClient::connect( call in cmd/secret.rs::recertify was not in the connection inventory. I added it as ungated, with a comment, in crates/minimal/src/tests.rs. That file is outside the layers, but the inventory test is there to make each new connection site get recorded. A Self::connect wrapper would get past the scanner without that record. ci-linux-native-success is the lane aggregator and failed only because tests failed. Before the fix, a full cargo nextest run -p minimal showed this as the only failure (810 passed, 1 failed). I did not run ./scripts/session-e2e.sh bep_store_reference_end_to_end. This box is Linux with no /dev/kvm, and bep_live_gate reports NOT RUN on any host that is not macOS.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft October 31, 2026 00:04
@norrietaylor
norrietaylor marked this pull request as ready for review October 31, 2026 00:29
@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.

Approve at 7e215e19.

  • bep serve now takes a recertify_root request on its control socket. It re-issues the root under the same key and subject for the current store rules, then publishes it to the identity file, and only then replies. So a box created after min secret set trusts the rule's upstream with no restart of bep serve (BEP-013). A box that already runs keeps its anchor.
  • The op sits behind the existing peer-uid check. A Control built without with_recertification refuses it. The re-issue runs on a blocking thread because it can wait on the Keychain. When the re-issue or the publish fails, the root in use stays, the rule stays saved, and min secret set names the reason.
  • The e2e case drops the #2612 restart interim. It checks that the proxy pid did not change, and that the box reaches the upstream.
  • Arch ruling 618 rules PASS_WITH_CONDITIONS. By the owner's ruling, its one condition (the macOS run of bep_store_reference_end_to_end) is deferred to the owner's close-out e2e run. The LOW finding on the 10 s control timeout stays as is: on a slow Keychain prompt, min secret set can report a failure that did not happen. Every lane is green.

Generated by Claude Code

@norrietaylor norrietaylor changed the title T99 — Re-certify bep's published root when a store registration changes feat(bep): re-certify the published root when a store registration changes Oct 31, 2026
@norrietaylor
norrietaylor added this pull request to the merge queue Oct 31, 2026
Merged via the queue into main with commit 642b738 Oct 31, 2026
36 checks passed
@norrietaylor
norrietaylor deleted the agent/2746-re-certify-bep-s-published-root-when-a-store-reg branch October 31, 2026 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

T99 — Re-certify bep's published root when a store registration changes

1 participant

0