8000 feat(bep): give bep serve the client's store rules so a store member is admitted (T83) by minimal-foundry[bot] · Pull Request #2614 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

feat(bep): give bep serve the client's store rules so a store member is admitted (T83) - #2614

Merged
norrietaylor merged 12 commits into
mainfrom
agent/2599-give-bep-serve-the-client-s-store-rules-so-a-sto
Oct 27, 2026
Merged

norrietaylor merged 12 commits into
mainfrom
agent/2599-give-bep-serve-the-client-s-store-rules-so-a-sto

Conversation

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

T83 — Give bep serve the client's store rules so a store member is admitted

slice: S10
kind: task
covers: BEP-032
size: M
est: 140 code, 140 tests
executor: agent
difficulty: unknown ground
model: strongest
diagnostics: a CONNECT to an authority that no module and no store rule admits stays refused off_module in min box audit, and a store handle with no matching rule stays refused store_handle_invalid
observability: one info log line at start naming the count of store rules bep serve holds, never a value
layers:
- rules:
- crates/bep/src/main.rs: bep serve gets the client's [secret-store-rules] with the BEP-034 refusals applied and gives them to BoxRedeemer::with_rules; the rules' authorities join registered_union and the admitted set, less the deny set; the three interim notes that still name T25 (#2280) are removed (#2599); how the rules reach bep serve (a read of the user-level config.toml, or a control-socket op that min sends) is this task's choice, left to the implementer and the arch review by the epic owner on 2026-10-26
- crates/bep/src/redeemer.rs: the facts doc names the rules bep serve gives in place of the interim note
test: cargo nextest run -p bep serve_admits_a_store_member_under_the_clients_rule
produces: none
consumes: none
proof: A box's request to a [secret-store-rules] rule's registered upstream, sent through a running bep serve, reaches that upstream with the stored key in the rule's injection form.
depends on:
- blocked by #2257
- blocked by #2586
- blocked by #2280

Proof

bep serve now reads the user-level config.toml [secret-store-rules], which min secret set writes. It drops each rule that the BEP-034 check refuses and gives the rest to the redeemer. Each rule's authority joins the root CA's names and the admitted CONNECT set, less the deny set. A box's request to that upstream, with a store handle under the rule, is admitted as a store member in the rule's injection form. The forwarder then puts the stored key in that form, as the existing serve_injects_a_stored_key_for_an_admitted_store_member test shows for a redeemer with these rules.

Notes from the agent: Choice: bep serve reads the user-level config.toml at start. It does not use a control-socket op. To parse and check the rules with the same code that min uses (boxes::client::config::read_config_or_default and boxes::core::bep::check_store_rules), bep now depends on the boxes and paths crates. That adds lines to crates/bep/Cargo.toml and Cargo.lock, which are outside the layers. boxes pulls common (nickel, google-cloud-storage) into the bep binary's dependency graph. The other choices were a copy of the BEP-034 check in bep, or a control-socket op, which needs changes in control.rs and the minimal crate. Gaps: (1) bep reads only the user file, not the organization file /etc/minimal/config.toml that min merges. A handle that min mints under an org-only rule is refused store_handle_invalid. (2) The rules are read once at start. A changed rule needs a restart of bep serve, and the CONNECT set and the root's names need a restart in any case. (3) A rule with action = "deny" is not held, so its handle is refused. (4) A config.toml that does not read or parse gives no rules and one error log line. The proxy still starts for GitHub. Refused rules get one warn log line each, with the refusal text. The start info line logs store_rules = . The new test in main.rs checks the redeemer's Redeemed::Store decision and its injection form. It does not forward byt…[truncated]

Tests

line exit tail
cargo nextest run -p bep serve_admits_a_store_member_under_the_clients_rule 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-f607... 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 common v0.0.1 (/workbench

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

Out of scope

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

  • crates/bep/Cargo.toml

Layer exception

The epic owner accepted these files outside T83's layers on 2026-10-27, for the security finding on crates/bep/Cargo.toml (round 8):

  • Cargo.toml, crates/client-config/ (new crate), crates/boxes/Cargo.toml, crates/boxes/src/lib.rs, crates/boxes/src/client/config.rs and crates/boxes/src/core/bep.rs: the client's config.toml reader and the [secret-store-rules] checks move into client-config, which does not depend on common. boxes re-exports them under their old paths, so min calls the same merge.
  • crates/bep/Cargo.toml and Cargo.lock: bep depends on client-config in place of boxes. cargo tree -p bep -e normal lists no boxes, common, nickel-lang-core, google-cloud-storage or reqwest.

crates/boxes/src/client/config.rs and crates/minimal/src/config.rs carry the organization merge from round 2, as arch C2 required. The restart and --config-dir limits are T91 (#2618) and T92 (#2620) in the plan.

Residuals

Closes #2599


Generated by Claude Code

bep serve reads [secret-store-rules] from the user-level config.toml,
applies the BEP-034 refusals with the same check min uses, and gives
the rules to BoxRedeemer::with_rules. The rules' authorities join the
root's names and the admitted set, less the deny set, so a store member
under a rule is admitted in the rule's injection form (BEP-032).

bep now depends on boxes and paths for the config reader.
@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: e8a56843-fc1e-4da1-b37e-5888a9d4e6a9

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 26, 2026 •
Copy link
Copy Markdown
8000 Contributor Author

Approved: every review thread resolved at f8d2558e9fa5.

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

Nothing to do.

@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/main.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: CONDITIONS · 3 conditions · the full ruling

The design allows bep serve to read the client configuration, and the new boxes dependency keeps one BEP-034 check. But bep holds a different rule set from the one min resolves. bep reads only the user file, so org rules do not apply and a user rule overrides an org deny. Gatehouse §6.10 line 849 and architecture line 1210 do not allow this. C1 fixes it. bep also reads the rules once per boot, so a narrowed rule continues to admit. Line 842 says the current rule decides each request. C2 fixes it. C3 files the boot-time refresh of the root and the admitted set as a named residual.

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

Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
bep serve reads config.toml from the default config dir once at start.
minvmd starts it and does not know a min --config-dir override. The
start log line now names the file, and the doc states both limits.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on the runtime's review findings, pushed as 1788b7adbfed.

line exit tail
cargo nextest run -p bep serve_admits_a_store_member_under_the_clients_rule 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-fceb... 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 common v0.0.1 (/workbench

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

Outside the task's layers::

  • crates/bep/Cargo.toml

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

Review threads the coder judged:

  • 👍 valid — crates/bep/src/main.rs: The bep start log line now names the config.toml it read, once at start. The client_store_rules doc states both limits. A real fix for --config-dir needs minvmd, which starts bep serve, to pass the dir on. minvmd is outside this task's layers, so that fix is left for a follow-up.

A box's request to a [secret-store-rules] rule's registered upstream, sent through a running bep serve, reaches that upstream with the stored key in the rule's injection form. The bep start log line now also names the config.toml that the rules came from.

Notes from the agent: Revise round 1. The review finding holds in part. minvmd starts bep serve (crates/minvmd/src/cmd/run.rs), not min, so min's --config-dir cannot reach bep unless minvmd passes it on. min has no environment variable for --config-dir. A real fix needs a change in minvmd or a control-socket op, and both are outside this task's layers. Inside the layers, the start info line now names the file it read and says that it reads the file once at start. The client_store_rules doc also states both limits. That line is a log record, not a message for the user. A follow-up task can carry the override from min to bep, or reload the rules on change.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft October 26, 2026 12:24
@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-foundry[bot] crates/bep/src/main.rs, minimal-arch[bot] crates/bep/src/main.rs:412, minimal-arch[bot] crates/bep/src/main.rs:765, minimal-arch[bot] crates/bep/src/main.rs:391. No findings.

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

@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 · 3 conditions · the full ruling

The admit path is correct for a rule that does not change. Gatehouse §6.10 line 842 says a rule that narrows or changes its injection form refuses the handle. wire() gives the redeemer a fixed list from start, so a narrowed rule keeps admitting until restart. C1 makes the redeemer read the current file. bep also reads only the user file, and min mints under the user rules merged over the organization rules. C2 moves that merge into boxes so both binaries use it. C3 files the restart limit for the root and the CONNECT set as a residual with an issue.

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

Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
Copy link
Copy Markdown
Member

/revise

Round 2 of #2614, on arch conditions C1, C2 and C3 at 1788b7a (CONDITIONS). No round is in flight. The arch review accepted the delivery shape (bep reads the client config.toml through boxes and paths) and the Cargo.toml/Cargo.lock change.

  1. C1, crates/bep/src/main.rs. Replace the fixed .with_rules(Arc::new(rules)) in wire() with a bep::handle::Rules source that bep serve owns. For example: struct ClientRules { path, cache: Mutex<(Option<(SystemTime, u64)>, Vec<StoreRule>)> }. Its rule(store, id) stats config.toml and re-runs store_rules_in when the mtime or the length changes, then looks the rule up. A file that is gone or does not parse gives no rules. StoreRules in redeemer.rs is already asked at each request. Add a test beside serve_admits_a_store_member_under_the_clients_rule: admit a handle, narrow the rule's upstream, and show that the same handle is refused.
  2. C2. bep holds the same merged rules that min mints under. Move the store-rule half of read_client_and_org_config out of crates/minimal/src/config.rs into boxes: merge_store_rules, keep_read_actions, deny_refused_items, and the organization read of ORGANIZATION_CONFIG_PATH. Make it one function that takes the user path and the organization path and returns the checked StoreRules. Make min call it, and make store_rules_in in crates/bep/src/main.rs call it in place of read_config_or_default and check_store_rules. An organization file that exists and does not read or parse gives bep no store rules, as min's org_required path refuses. Add a test where an organization deny holds against a user allow.
  3. C3. Filed as T91 — Admit a widened store rule without restarting bep serve #2618: the root's re-sign and the Admission set still need a restart for a widened rule. Name https://github.com/gominimal/minimal/issues/2618 in the client_store_rules doc comment beside that limit. I list it in the PR body.
  4. Change nothing else. Run cargo nextest run -p bep serve_admits_a_store_member_under_the_clients_rule, the new tests, cargo nextest run -p minimal for the moved merge, and clippy on bep, boxes and minimal with --all-targets.

Generated by Claude Code

Move the store-rule merge of the user and the organization client
configuration from min into boxes::client::config, so min and bep serve
read the same merged rules.
bep serve now owns a rules source that stats the user and organization
config.toml and reads them again when the mtime or the length changes,
so a narrowed rule refuses the next request. It reads the rules through
the boxes merge that min mints under, so an organization deny holds.
The root's names and the admitted set still take the rules at start
only, tracked in #2618.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 2 of 10 on a /revise note, pushed as 360cc593877b.

line exit tail
cargo nextest run -p bep serve_admits_a_store_member_under_the_clients_rule 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-1778... 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 common v0.0.1 (/workbench

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.

nformation 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...
error: could not compile `boxes` (lib test) due to 6 previous errors

Outside the task's layers::

  • crates/bep/Cargo.toml
  • crates/boxes/src/client/config.rs
  • crates/minimal/src/config.rs

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

Review threads the coder judged:

  • 👍 valid — crates/bep/src/main.rs: Moved the user/organization merge into boxes::client::config::read_client_store_rules. min and bep's store_rules_in both call it, so an organization deny is final in bep too.
  • 👍 valid — crates/bep/src/main.rs: wire() now takes a StoreRules source. bep serve gives it ClientRules, which re-reads config.toml on a change. Added edited_store_rule_applies_to_next_request.
  • 👍 valid — crates/bep/src/main.rs:392: The client_store_rules doc names T91 — Admit a widened store rule without restarting bep serve #2618 for the root re-sign and the admitted set, which still take the rules at start. The serve comment names it too. The flip condition is T91 — Admit a widened store rule without restarting bep serve #2618 landing.
  • 👍 valid — crates/bep/src/main.rs: Replaced the fixed list with ClientRules. It stats the user and organization files and calls store_rules_in again when the mtime or the length changes.
  • 👍 valid — crates/bep/src/main.rs: store_rules_in now calls boxes::client::config::read_client_store_rules, the same merge min calls. An organization file that does not parse gives no rules.
  • 👍 valid — crates/bep/src/main.rs: The doc now says that redemption reads the current rules at each request, and names T91 — Admit a widened store rule without restarting bep serve #2618 for the root names and the admitted CONNECT set.

A box's request to the registered upstream of a [secret-store-rules] rule, sent through a running bep serve, is admitted and gets the stored key in the rule's injection form. The rules are the same merged user and organization rules that min mints under. The rule in force at that moment decides each request, so a narrowed rule refuses the same handle on its next request with no proxy restart.

Notes from the agent: Round 2 addresses C1, C2 and C3. C2 touches crates/boxes/src/client/config.rs and crates/minimal/src/config.rs, which are outside the task's layers. The /revise note asked for that move. New in boxes::client::config: ORGANIZATION_CONFIG_PATH, read_config_parts, read_client_store_rules (returns ClientStoreRules: the config, the merged rules, the refusals and organization_error), merge_store_rules, keep_read_actions, deny_refused_items. min re-exports ORGANIZATION_CONFIG_PATH and wraps read_config_parts, so cmd/secret.rs does not change. The three merge tests moved from minimal to boxes. They now use a test deny set in place of min's refuse_store_rules. min's printed text does not change: the refusal lines and the organization-file error print as before, once per file in a process. bep: ClientRules implements bep::handle::Rules. It stats both files and reads them again on a change of mtime or length. A user or organization file that exists and does not read or parse gives no rules. The root's names and the admitted CONNECT set still take the rules at start only. The client_store_rules doc and a comment in serve name #2618 for this. The start info log line no longer says 'read once at start'. A re-read logs an info line with only the rule count. just clippy-strict was not run.

@minimal-foundry minimal-foundry Bot added the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Oct 26, 2026
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

The runtime will not revise this pull request again on its own: the diff is +839/-234 (1073 lines), past 3x the plan's estimate of 280 lines (est: 140 code, 140 tests, as #2599 reads now), at round 2 (the last trigger was a /revise note). A person decides now. Remove needs-human from this pull request to let /revise <note> or the automatic rounds resume, or finish #2599 by hand.

@norrietaylor norrietaylor removed the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Oct 26, 2026
Copy link
Copy Markdown
Member

/revise

Round 3 of #2614, on a CI failure at 360cc59. No round is in flight. The size cap is lifted for this epic, so the diff size is not a reason to stop.

  1. clippy (ci-success red). cargo clippy --workspace --all-targets --locked -- -D warnings fails in boxes (lib test) with clippy::assert_is_empty at the test line assert!(read.rules["leak"].upstream.is_empty()); (line 855). Use assert_eq!(read.rules["leak"].upstream, Vec::<String>::new());. Fix any other assert!(... .is_empty()) this PR adds the same way.
  2. Run cargo clippy --workspace --all-targets --locked -- -D warnings on the pinned toolchain until it reports nothing, then the tests this PR names.
  3. Change nothing else.

Generated by Claude Code

The pinned clippy refuses assert!(x.is_empty()) as assert_is_empty.
The tests this pull request adds now compare against an empty value.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a /revise note, pushed as b1928cad7cfb.

line exit tail
cargo nextest run -p bep serve_admits_a_store_member_under_the_clients_rule 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-3138... 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 common v0.0.1 (/workbench

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.

nformation 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...
error: could not compile `boxes` (lib test) due to 6 previous errors

Outside the task's layers::

  • crates/bep/Cargo.toml
  • crates/boxes/src/client/config.rs
  • crates/minimal/src/config.rs

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

A box's request to a [secret-store-rules] rule's registered upstream, sent through a running bep serve, reaches that upstream with the stored key in the rule's injection form. serve_admits_a_store_member_under_the_clients_rule still passes, and the tests this pull request adds no longer use assert!(x.is_empty()).

Notes from the agent: Directive item 1: I changed all six assert!(... .is_empty()) lines that this pull request adds to assert_eq! against an empty value. Three are in crates/boxes/src/client/config.rs (lines 784, 818, 855) and three are in crates/bep/src/main.rs (store_rules_in tests). I did not change the assert!(upstream.is_empty()) lines in redeemer.rs or minimal/src/config.rs, because they were on main before this pull request and CI did not flag them. Directive item 2: I was not able to verify the workspace clippy on the pinned toolchain. This box has rustc and clippy 1.98.1 and no rustup, and rust-toolchain.toml pins 1.99.0. Clippy 1.98.1 does not have assert_is_empty. It fails first on six must_use lints in crates/boxes/src/core/compose.rs and primitives.rs, files that this pull request does not touch, so it stops before it lints bep. CI on 1.99.0 is the record for item 2. Item 3: I changed nothing else.

@minimal-foundry minimal-foundry Bot added the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Oct 26, 2026
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

The runtime will not revise this pull request again on its own: the diff is +848/-234 (1082 lines), past 3x the plan's estimate of 280 lines (est: 140 code, 140 tests, as #2599 reads now), at round 1 (the last trigger was a /revise note). A person decides now. Remove needs-human from this pull request to let /revise <note> or the automatic rounds resume, or finish #2599 by hand.

@norrietaylor norrietaylor removed the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Oct 26, 2026
@norrietaylor
norrietaylor marked this pull request as ready for review October 26, 2026 13:47
@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 — 3 findings, 3 inline.

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

Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
An edit that keeps the length and the modification time (cp -p,
touch -r, rsync -t) now changes the stamp, and settled() decides on
the later of the modification time and the change time. The test now
asserts that such a rewrite is read. The merge of main also needed
box_id on one RegisterClientKey in a test.
@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 · 2 conditions · the full ruling

The new commit closes the open point of the last ruling. The store-rule stamp now holds the change time and the inode. Thus an edit that keeps the length and the modification time is read again, and a narrowed rule refuses (Gatehouse §6.10 line 842). C1 (#2618) and C2 (#2620) stay open as filed residuals, as the ruling on 1c0609b accepted. You can merge the change with them open.

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

Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a /revise note, pushed as 172c9382a8b7.

line exit tail
cargo nextest run -p bep serve_admits_a_store_member_under_the_clients_rule 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-d7ad... 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 common v0.0.1 (/workbench

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/main.rs:480: Stamp now carries ctime, ctime_nsec, ino and dev from MetadataExt on unix, and settled() decides on the later of the mtime and the ctime.
  • 👍 valid — crates/bep/src/main.rs: The step now asserts current() returns no rules after write(&blank, old), followed by a second current() call with no write between them.
  • 👎 invalid — crates/bep/src/main.rs:521: The premise holds: a future or recent mtime/ctime re-reads and re-logs refusals on each redemption. This round's /revise note says to change nothing beyond C1 and the test, so it is not changed here. A follow-up can log refusals only when the stamps change.
  • 👎 invalid — crates/bep/Cargo.toml:15: This is a deliberate tradeoff. The task's layers were amended on 2026-10-26 after the arch review on feat(bep): give bep serve the client's store rules so a store member is admitted (T83) #2614 accepted bep depending on boxes and paths, so that bep and min share one merge of the store rules (arch C2). A new crate is outside this task's layers.

bep serve admits a CONNECT to a store member under the client's [secret-store-rules] rule. A rule file edited in a way that keeps its length and modification time (cp -p, touch -r, rsync -t) is now read again on the next redemption, so a narrowed rule refuses.

Notes from the agent: Item 1: the merge of origin/main (d97ad33) was already on the branch when the session started. Cargo.lock has zstd 0.14.3, zstd-safe 8.2.0 and zstd-sys 2.1.2 from #2627. That merge broke the bep test build: T84 (#2615) added box_id to Request::RegisterClientKey, and one test in main.rs from this branch did not set it. I added box_id: None there. Items 2 and 3 are done in commit 172c938. Stamp is now Option, which holds the mtime, the length and, on unix, the ctime (with ctime_nsec) and (dev, ino). settled() uses the later of the mtime and the ctime. The test asserts that a same-length, same-mtime rewrite is read, and then makes a second current() call with no write. Because the ctime of a fresh write is within the 2 s racy window, that second call reads the file again and does not hit the cache. It asserts the same empty rules. Not run: cargo deny check advisories, because cargo-deny is not installed on this box. Not run: cargo clippy --workspace --all-targets --locked -- -D warnings. My instructions forbid workspace-wide builds unless a test: line names one. With -D warnings, the bep clippy run fails only on the boxes warnings listed above, which come from the toolchain mismatch.

@minimal-foundry minimal-foundry Bot added the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Oct 26, 2026
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

The runtime will not revise this pull request again on its own: the diff is +979/-232 (1211 lines), past 3x the plan's estimate of 280 lines (est: 140 code, 140 tests, as #2599 reads now), at round 1 (the last trigger was a /revise note). A person decides now. Remove needs-human from this pull request to let /revise <note> or the automatic rounds resume, or finish #2599 by hand.

@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: 2 of 3 personas ran (correctness, security); did not complete: supply-chain.

Comment thread crates/bep/Cargo.toml Resolved
@norrietaylor norrietaylor removed the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Oct 26, 2026
Copy link
Copy Markdown
Member

/revise

Round 8 of #2614, on the security thread at crates/bep/Cargo.toml:16 (#2614 (comment)). No round is in flight. The epic owner ruled on 2026-10-27: narrow the dependency in this PR. The size cap is lifted for this epic. The owner accepts the files outside T83's layers that this needs, as a layer exception. Add a "Layer exception" section to the PR body that names them.

  1. The goal. bep holds the sealing and CA keys. It must not link common or what common brings in. After this round, cargo tree -p bep -e normal --prefix none lists none of common, nickel-lang-core, google-cloud-storage, google-cloud-auth or reqwest.
  2. The mechanism. Inside boxes, only crates/boxes/src/store.rs uses common. Move the client store-rules reader (boxes::client::config::read_client_store_rules and the types it needs from boxes::core::bep and boxes::keys) into a new small workspace crate that does not depend on common. boxes re-exports it under the same paths, so min keeps calling the same function. bep depends on the new crate in place of boxes. Give the new crate a Cargo.toml description, and add it to [workspace.dependencies]. Do not use a cargo feature on boxes for this: workspace builds unify features, so bep would still link common.
  3. Keep the behaviour and the tests as they are. min and bep serve still read the user and organization rules through one merge, and an organization deny is still final in both.
  4. Change nothing else. Run cargo tree -p bep -e normal --prefix none and check the list in step 1. Then run cargo clippy --workspace --all-targets --locked -- -D warnings, cargo deny check, cargo nextest run -p bep, cargo nextest run -p boxes and cargo nextest run -p minimal.

Generated by Claude Code

bep holds the sealing and CA keys. It linked boxes for one reader and
one check, and boxes pulls in common, nickel and google-cloud-storage.
The client config, the session keys and the secret-store rules now live
in a new client-config crate. boxes re-exports them under the same
paths, so min keeps calling the same merge. bep depends on client-config
in place of boxes.
@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 · 2 conditions · the full ruling

The new commit moves the client config and the store-rule reader from boxes into a new client-config crate. The move keeps the code and its behaviour. The design of record does not own crate dependencies, so the move is not a deviation. The merge of main is clean. The ruling on 172c9382 stands. C1 (#2618) and C2 (#2620) stay open as filed residuals.

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

Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/bep/src/main.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: 3 unresolved threads — minimal-foundry[bot] crates/bep/Cargo.toml, minimal-arch[bot] crates/bep/src/main.rs:427, minimal-arch[bot] crates/bep/src/main.rs:424. No findings.

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

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a /revise note, pushed as f8d2558e9fa5.

line exit tail
cargo nextest run -p bep serve_admits_a_store_member_under_the_clients_rule 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-fba3... 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

Verify min task run agent-verify exited 100.

        closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "b635bcd3e5801ad5",
                "span_id": "a9f37779b1a5c21d",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetNetSwitch",
                "parent_span_id": "b635bcd3e5801ad5",
                "span_id": "25486af4e1799c4a",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetDenyAllOptOut",
                "parent_span_id": "b635bcd3e5801ad5",
                "span_id": "41e8dbb9f93f3bb6",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "b635bcd3e5801ad5",
                "span_id": "864317f05b439857",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "b635bcd3e5801ad5",
                "queued_behind": "0",
                "span_id": "1d59f8158c0e9a8f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "b635bcd3e5801ad5",
                "queued_behind": "0",
                "span_id": "82a1c9f18c0cfe49",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "82a1c9f18c0cfe49",
                "span_id": "b3bf6251e9a578e8",
                "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 [  37.527s] 1676 tests run: 1675 passed, 1 failed, 2 skipped
        FAIL [   2.804s] (1676/1676) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
error: test run failed

Outside the task's layers::

  • Cargo.toml
  • crates/boxes/Cargo.toml
  • crates/boxes/src/core/bep.rs
  • crates/boxes/src/lib.rs
  • crates/client-config/Cargo.toml
  • crates/client-config/src/config.rs
  • crates/client-config/src/keys.rs
  • crates/client-config/src/lib.rs
  • crates/client-config/src/store_rules.rs

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

Review threads the coder judged:

  • 👍 valid — crates/bep/Cargo.toml: Moved the store-rule reader and check_store_rules into a new client-config crate. bep now depends on it in place of boxes, so it no longer links common, nickel or google-cloud-storage.

A box's request to a [secret-store-rules] rule's registered upstream, sent through a running bep serve, reaches that upstream with the stored key in the rule's injection form. This round, bep reads those rules through the new client-config crate, and cargo tree -p bep -e normal no longer lists common, nickel-lang-core, google-cloud-storage, google-cloud-auth, reqwest or boxes.

Notes from the agent: Layer exception, as the epic owner ruled on 2026-10-27. The PR body must name these files, which are outside the T83 layers: crates/client-config/Cargo.toml (new), crates/client-config/src/lib.rs (new), crates/client-config/src/config.rs (moved from crates/boxes/src/client/config.rs), crates/client-config/src/keys.rs (moved from crates/boxes/src/keys.rs), crates/client-config/src/store_rules.rs (new, the store-rule items cut from crates/boxes/src/core/bep.rs), Cargo.toml (workspace member and [workspace.dependencies] entry), crates/boxes/Cargo.toml, crates/boxes/src/lib.rs, crates/boxes/src/core/bep.rs. What moved: the whole client config module (the reader returns the full Config, and Config denies unknown fields, so it needs the session-keys types), the keys module, and DENIED_HEADERS, StoreAction, StoreRuleConfig, StoreRules, StoreDenySet, StoreRuleRefusal, StoreRuleRefused, check_store_rules, StoreConsent and store_consent with their private helpers. boxes re-exports all of them under the old paths (boxes::keys, boxes::client::config::, boxes::core::bep::Store), so min and every other caller compile unchanged. Two methods became pub because boxes calls them across the crate line: StoreRuleConfig::upstream_hosts and StoreDenySet::is_sign_in_item. normalize_host is pub in client-config so boxes and the deny check compare hosts the same way. No cargo feature was used. The tests are unchanged: the config.rs tests moved with the file, and one test now names crate::store_rules::store_consent in place of crate::core::bep::store_consent. The store-rule tests …[truncated]

@minimal-foundry
minimal-foundry Bot marked this pull request as draft October 27, 2026 01:08
@minimal-foundry minimal-foundry Bot added the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Oct 27, 2026
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

The runtime will not revise this pull request again on its own: the diff is +2044/-1204 (3248 lines), past 3x the plan's estimate of 280 lines (est: 140 code, 140 tests, as #2599 reads now), at round 1 (the last trigger was a /revise note). A person decides now. Remove needs-human from this pull request to let /revise <note> or the automatic rounds resume, or finish #2599 by hand.

@norrietaylor norrietaylor removed the needs-human An agent handed off; a human must act, then clear this label. Set by defer and handoffs. label Oct 27, 2026
@norrietaylor
norrietaylor marked this pull request as ready for review October 27, 2026 02:03
@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 f8d2558. bep serve reads the client's [secret-store-rules] through the new client-config crate, the same user-and-organization merge min calls, and admits a store member under the current rule. The rules are re-read when the file's stamp changes, and the stamp includes ctime and inode. bep no longer links boxes or common (cargo tree -p bep checked). The restart and --config-dir limits are plan tasks T91 (#2618) and T92 (#2620).


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 f8d2558e9fa5 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 27, 2026
@norrietaylor norrietaylor changed the title T83 — Give bep serve the client's store rules so a store member is admitted feat(bep): give bep serve the client's store rules so a store member is admitted (T83) Oct 27, 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 f8d2558: every merge gate passes at this head (arch PASS at f8d2558, zero open threads, every lane aggregator green). Squash title feat(bep): give bep serve the client's store rules so a store member is admitted (T83) 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 27, 2026
Merged via the queue into main with commit dbba22b Oct 27, 2026
37 checks passed
@norrietaylor
norrietaylor deleted the agent/2599-give-bep-serve-the-client-s-store-rules-so-a-sto branch October 27, 2026 03:39
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.

T83 — Give bep serve the client's store rules so a store member is admitted

1 participant

0