8000 feat(bep): inject a stored key in its registered form per request (T28) by minimal-foundry[bot] · Pull Request #2574 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

feat(bep): inject a stored key in its registered form per request (T28) - #2574

Merged
norrietaylor merged 13 commits into
mainfrom
agent/2292-inject-a-stored-key-in-the-registered-form-read
Oct 26, 2026
Merged

norrietaylor merged 13 commits into
mainfrom
agent/2292-inject-a-stored-key-in-the-registered-form-read

Conversation

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

T28 — Inject a stored key in the registered form, read from the Keychain per request

slice: S3
kind: task
covers: BEP-032, BEP-033, BEP-045, BEP-054, BEP-065, BEP-066
size: L
est: 380 code, 420 tests
executor: agent
difficulty: needs care
model: strongest
diagnostics: min box audit <box> shows each injection's store and identifier, and a refused one marked injection_invalid or as a deleted item, never the value
observability: one debug log line per injection naming the store, the identifier and the header, never the value
layers:
- inject:
- crates/bep/src/inject.rs (new): emits the registered prefix and the value as the header's value, or one basic_auth field; refuses CR or LF in a value or prefix
- crates/bep/src/store.rs: reads the value per request, writes it nowhere, refuses a deleted or disabled item
- crates/bep/src/forward.rs: injects for an admitted store reference; refuses a sign-in reference naming another instance
- crates/bep/src/lib.rs: module line
test: cargo nextest run -p bep store_reference_injects_in_registered_form
test: cargo nextest run -p bep store_value_read_per_request_never_written
test: cargo nextest run -p bep deleted_keychain_item_refuses_next_injection
test: cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused
test: cargo nextest run -p bep replaced_secret_is_injected_on_next_request
test: cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value
test: cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection
produces: none
consumes:
- crates/bep/src/store.rs
proof: A request to the rule's upstream carries the stored key in the registered header, and a replaced key is sent next time.
depends on:
- blocked by #2287
- blocked by #2288
- blocked by #2257

Proof

At the forwarder, a request that carries a sealed store reference reaches the rule's upstream with the stored key in the registered header (for example authorization: Bearer <key> or x-api-key: <key>), or in one basic_auth field. After min secret set replaces the item, the next request on the same flow carries the new key. The forwarder tests in crates/bep/src/forward.rs show this. In bep serve this does not happen yet, because BoxRedeemer admits no store reference (see notes).

Notes from the agent: Design: the Redeemer trait gets a default method redeem_reference that returns Redeemed::Verdict or Redeemed::Store(StoreAdmit). The forwarder calls it. Existing redeemers stay unchanged, so redeemer.rs, proxy.rs and main.rs need no edit. On an admitted store reference, Flow reads the value through a new store::ValueReader (set with Flow::with_store) for each request. Then inject::inject removes the header that carried the sealed value and writes the registered form. carried() now searches every header for a sealed value, not only Authorization, so a client that sends its key in x-api-key works. Two sealed values in one request, or a sealed Authorization beside another Authorization header, is still refused as mixed_authorization. New audit markers: store_item_deleted, store_item_disabled, store_item_unreadable (no store in the flow, or the store failed). injection_invalid also covers a NUL byte, a ':' in the basic_auth user field, an unknown basic_auth field, and a header name that is not a token. Each injection writes one debug line with the store, the identifier, the header and the outcome, and never the value. Follow-up work outside these layers: (1) BoxRedeemer (redeemer.rs) must override redeem_reference to return Redeemed::Store for an admitted store-handle member. Its store rules are still empty until T25. (2) proxy.rs must call Flow::with_store(Arc::new(HostStore)) where it builds a Flow. Until both land, `b…[truncated]

Tests

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-9d49... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 15.61s ──────────── Nextest run ID 58c1797c-2d0d-4897-9c2c-31736456ab24 with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-4630... Finished 'test' profile [unoptimized] target(s) in 0.32s ──────────── Nextest run ID 6ad39ab4-a586-4210-923f-75d4896f5b7d with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-60cf... Finished 'test' profile [unoptimized] target(s) in 0.33s ──────────── Nextest run ID bf028cc0-d41e-4951-bc65-ff9ecc12a016 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-989f... Finished 'test' profile [unoptimized] target(s) in 0.33s ──────────── Nextest run ID 45ff71e4-29cc-4600-a1a1-c97fd0632327 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-7aff... Finished 'test' profile [unoptimized] target(s) in 0.34s ──────────── Nextest run ID 60e6d6b1-2249-4f08-83a3-7964ff8d6b6b with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-12e1... Finished 'test' profile [unoptimized] target(s) in 0.36s ──────────── Nextest run ID 29b29788-badc-4cc6-9254-40376303e460 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-bca7... Finished 'test' profile [unoptimized] target(s) in 0.38s ──────────── Nextest run ID 9d02835b-e83f-4a5e-b0ee-dceefc18db45 with nextest profile: default Starting 2 tests across 2

Verify

min task run agent-verify passed ([tasks.verify]).

Base

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

Residuals

  • T67 — Inject store values in bep serve #2586 (arch C1): bep serve does not inject a store value yet. The T28 proof holds in the forwarder only until BoxRedeemer overrides redeem_reference (crates/bep/src/redeemer.rs) and bep serve calls Flow::with_store(Arc::new(HostStore)) (crates/bep/src/proxy.rs). BEP-032 stays open until then. The epic owner keeps Closes #2292 and files the open part.

Closes #2292


Generated by Claude Code

The forwarder reads a store reference's value from the store for each
request and puts it in the rule's header, with its prefix, or in one
basic_auth field. A deleted or disabled item, or a value or prefix with
a line break, refuses the request and is audited.
@coderabbitai
coderabbitai Bot commented Oct 25, 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: a414cac5-57b1-434e-8d0d-92d27364f8f1

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

Approved: every review thread resolved at ac87b37ed9e0.

@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/store.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 store injection, the per-request read and the deletion refusal conform to Gatehouse §6.10. One deviation remains. carried() now takes a sealed value from any header, and no path checks that header. Line 849 says the handle is located where the injection format says the value rides. C1 adds the check on the store path, before the Keychain read. C2 keeps the GitHub module credential in Authorization only. C3 files the two wiring follow-ups as issues, because bep serve injects no store reference until they land.

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

Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.rs Resolved
An item that does not let the proxy read it raised a system dialog and
blocked the request. With prompts off, the read returns
errSecInteractionNotAllowed and the request fails as store_item_disabled.
A mutex serialises reads, because the prompt setting is process-wide.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on the runtime's review findings, pushed as 9680aeaf16ea.

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-e7cf... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 16.68s ──────────── Nextest run ID ca5196ad-e21b-4921-95f7-b3014a484fe3 with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-aae8... Finished 'test' profile [unoptimized] target(s) in 0.35s ──────────── Nextest run ID 8912dba6-56b5-4517-a55f-c6560f962dea with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-5ba7... Finished 'test' profile [unoptimized] target(s) in 0.37s ──────────── Nextest run ID dcd7ff95-6606-436a-949c-9af6cef2a97f with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-ffb7... Finished 'test' profile [unoptimized] target(s) in 0.33s ──────────── Nextest run ID 9d68b439-b49d-4215-a92d-d4d55fa2536f with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-d46e... Finished 'test' profile [unoptimized] target(s) in 0.35s ──────────── Nextest run ID 29452230-3acf-42ba-9b35-962e91bb950b with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-e7ca... Finished 'test' profile [unoptimized] target(s) in 0.35s ──────────── Nextest run ID 75d852d4-a157-42aa-a28a-feac028fa8d0 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-594b... Finished 'test' profile [unoptimized] target(s) in 0.36s ──────────── Nextest run ID 873dbd91-3db9-4db4-b800-d29529203dc3 with nextest profile: default Starting 2 tests across 2

Verify min task run agent-verify passed.

Review threads the coder judged:

  • 👍 valid — crates/bep/src/store.rs:868: host::read now turns off Keychain prompts with SecKeychain::disable_user_interaction() for each read. A mutex serialises the reads, because that setting is process-wide. A denied item now returns errSecInteractionNotAllowed (store_item_disabled) and does not block on a dialog.

A request to the rule's upstream carries the stored key in the registered header, and a replaced key is sent next time. On macOS, a Keychain item that does not let the proxy read it now fails the request as store_item_disabled and does not wait on a system dialog.

Notes from the agent: Revise round 1. The macOS host::read now holds a process-wide mutex and calls SecKeychain::disable_user_interaction() for the duration of get_generic_password. The guard turns prompts back on when it drops. The mutex is necessary because the prompt setting is process-wide. Without it, one read can turn prompts back on while another read is in progress. This box has no macOS target, so the changed code was not compiled. I checked the API against the security-framework 3.7.0 source: os::macos::keychain::SecKeychain::disable_user_interaction returns Result. Linux clippy and all seven test lines pass, but they do not compile the macOS module. A macOS lane (ci-macos) must confirm that it builds.

@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/forward.rs Resolved
Comment thread crates/bep/src/forward.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 · 2 conditions · the full ruling

The forwarder injects a store value in the registered form. But it takes the sealed value from whichever header it is found in. Gatehouse §6.10 line 849 says the handle is located where the injection format says the value rides. Make inject_store() refuse a sealed value outside the registered header or basic_auth field (C1). The running proxy also admits no store reference yet, and that follow-up has no issue. File it and name it in the PR body (C2). The Keychain prompt change in the compare fails closed and conforms.

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

Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.rs Resolved
A store reference must sit in the header or basic_auth field its rule
names, and a sign-in reference in Authorization. Otherwise the proxy
refuses it as sealed_header_misplaced and does not read the store.
The mixed-credential refusal text now covers two sealed headers, and
the store wiring comments say it is interim.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

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

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-d262... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 15.50s ──────────── Nextest run ID 882f8fdc-a09b-4c28-b931-780b8590c4d6 with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-0cba... Finished 'test' profile [unoptimized] target(s) in 0.31s ──────────── Nextest run ID 262e6bac-f855-4df5-b5ce-8b744958c039 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-dffa... Finished 'test' profile [unoptimized] target(s) in 0.33s ──────────── Nextest run ID 8b4a034c-639f-4bda-a0ec-f0b366fc4608 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-3e9e... Finished 'test' profile [unoptimized] target(s) in 0.34s ──────────── Nextest run ID 0c7335f2-a614-4711-9eb9-5f2fdddc1214 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-f59e... Finished 'test' profile [unoptimized] target(s) in 0.34s ──────────── Nextest run ID 3d331194-1144-4e69-b9eb-7d2b8c651321 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-c2a2... Finished 'test' profile [unoptimized] target(s) in 0.33s ──────────── Nextest run ID fe29b75f-a1a4-4718-a55a-d0ab6bbc5cb4 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-54c4... Finished 'test' profile [unoptimized] target(s) in 0.34s ──────────── Nextest run ID 5c276825-b93e-4afe-885b-4bcd392b59b9 with nextest profile: default Starting 2 tests across 2

Verify min task run agent-verify passed.

Review threads the coder judged:

  • 👍 valid — crates/bep/src/forward.rs:793: inject_store now refuses with sealed_header_misplaced before the store read when the sealed header is not the registered header, or not the Authorization Basic field that the rule names. A test checks that the store sees zero reads.
  • 👍 valid — crates/bep/src/forward.rs:935: On Verdict::Admit, a sealed value outside an Authorization header is refused as sealed_header_misplaced. The request is left unchanged. Covered by sign_in_reference_outside_authorization_is_refused.
  • 👍 valid — crates/bep/src/forward.rs:779: The doc comments on with_store and Redeemer::redeem_reference are now marked interim. They name the missing wiring: the BoxRedeemer override and the bep serve call. This session has no GitHub credential, so I opened no issues. A person must open them and link them.
  • 👍 valid — crates/bep/src/forward.rs:583: The mixed_authorization refusal now says the request carries a credential in more than one header. It tells the user to send one sealed credential, in one header. The text covers both cases.
  • 👎 invalid — crates/bep/src/forward.rs:782: The premise is correct, but the wiring is outside this task's layers. It needs crates/bep/src/redeemer.rs (BoxRedeemer::redeem_reference) and the bep serve path, which this task does not name. The interim doc comments on with_store and redeem_reference now say this.

A request to the rule's upstream carries the stored key in the registered header, and a replaced key is sent next time. A sealed value in any other header is now refused as sealed_header_misplaced, and the proxy does not read the store for it. These facts hold in the bep flow tests. bep serve does not wire the store yet, so a running proxy does not inject a stored key.

Notes from the agent: Revise round 2. New marker SEALED_HEADER_MISPLACED, with new refusal text. This round also adds two tests: store_reference_in_unregistered_header_is_refused and sign_in_reference_outside_authorization_is_refused. The MIXED_AUTHORIZATION text now reads 'because it carries a credential in more than one header. Send one sealed credential, in one header.' No test or doc pinned the old text. The store path is not wired in production. BoxRedeemer (crates/bep/src/redeemer.rs) does not override redeem_reference, and bep serve does not call Flow::with_store. Both files are outside this task's layers. I did not open follow-up issues because this session has no GitHub credential. A person must open them and link them from the two interim comments. The full bep suite passed (178 tests) and clippy -p bep --all-targets is clean. I did not run just clippy-strict.

@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/store.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 now conforms to Gatehouse §6.10 line 849, step 4. The proxy reads the store only when the sealed value is in the header or basic_auth field that the rule names. Otherwise it refuses as sealed_header_misplaced. One item is open. The two interim notes in forward.rs say "a follow-up task outside T28" and link no issue. Link the issue that owns the BoxRedeemer override and the bep serve store wiring, as C1 says.

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

Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.rs Resolved
The injection_invalid text named a line break only. The marker also
covers NUL, a colon in the user field, and a bad header name or field.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

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

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-68a1... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 11.92s ──────────── Nextest run ID 852b5bf8-54e8-4c41-b11c-1c3fbed0f394 with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-9bba... Finished 'test' profile [unoptimized] target(s) in 0.24s ──────────── Nextest run ID bff93c51-3040-4ec7-a6de-e9e341d0bb4f with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-3a51... Finished 'test' profile [unoptimized] target(s) in 0.24s ──────────── Nextest run ID b84cb0dc-f7b4-4a44-9a8e-a6bfbec77682 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-400f... Finished 'test' profile [unoptimized] target(s) in 0.23s ──────────── Nextest run ID 4d8586f8-e7eb-45f8-9edc-2a1f324a00a8 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-0ad5... Finished 'test' profile [unoptimized] target(s) in 0.24s ──────────── Nextest run ID 699700cc-e43e-43a2-ab81-935bc8d3df89 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-1690... Finished 'test' profile [unoptimized] target(s) in 0.22s ──────────── Nextest run ID c413fbff-932c-4d32-ad64-9a9c47d95599 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-aa54... Finished 'test' profile [unoptimized] target(s) in 0.24s ──────────── Nextest run ID d2205e7d-8151-4c28-84ba-ba9021e3ba21 with nextest profile: default Starting 2 tests across 2

Verify min task run agent-verify passed.

Review threads the coder judged:

  • 👎 invalid — crates/bep/src/forward.rs: Already so on this branch. inject_store checks placement before the store read: the registered header for a header form, and Authorization: Basic with the sealed value in the registered field for basic_auth (forward.rs lines 805-826). A mismatch is refused before the read. Its marker is sealed_heade
  • 👍 valid — crates/bep/src/forward.rs: The injection_invalid text now says the stored secret and the form its secret store rule sets do not make a valid request header. That holds for CR, LF, NUL, a colon in the user, and a bad name or field. A header mismatch has its own marker. The crlf test pins the text.
  • 👎 invalid — crates/bep/src/forward.rs:934: The gap is real but outside this task's layers. The fix needs the BoxRedeemer and proxy.rs. The coder has no gh credential to file an issue or edit the PR body. with_store and redeem_reference already carry interim comments. result.json notes ask a person to file the issue and name it as a residual.
  • 👎 invalid — crates/bep/src/store.rs:874: The caller runs on a blocking thread: proxy.rs relay runs forward_requests in tokio::task::spawn_blocking. In store.rs, set, list and remove run the security tool in a child process, so this process's prompt setting does not reach them. keys.rs is outside this task's layers. It loads keys at start,

In the bep tests, a request to the rule's upstream carries the stored key in the registered header, and a replaced key goes upstream on the next request. bep serve does not yet do this, because no production redeemer returns a store reference and proxy.rs does not call with_store.

Notes from the agent: This round changes one thing. The injection_invalid refusal text now holds for each of its causes, and the crlf test pins the new text. The C2 wiring (BoxRedeemer returns Redeemed::Store, proxy.rs calls with_store) is outside this task's layers. The coder has no gh credential, so it did not file the issue. A person must file it and name it in the PR body as a residual. Until then, bep serve refuses every store reference. clippy -p bep --all-targets is clean.

@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 compare rewords the injection_invalid refusal so that it holds for each cause the marker covers, and a test pins the text. That conforms. The marker and the audit record are unchanged (§6.10 line 849). One condition stays open. The interim comments on redeem_reference and with_store defer the bep serve wiring to an unnamed follow-up task. C1 links each one to a filed issue with its flip condition.

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

Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.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 — advisory review

Verdict COMMENT — 3 findings, 3 inline.

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

Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.rs Resolved
The default redeem_reference now takes the sealed value's header name and
refuses one outside Authorization before redeem runs, so no sign-in token
is renewed for it. The forwarder zeroizes the header a store value was
injected in, whatever its name, and inject moves the value into the
request in place of a copy. The interim notes link #2280 and state when
they stop being true.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

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

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-2137... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 16.98s ──────────── Nextest run ID d749ea25-4093-4005-80e9-84b7dabd1379 with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-65da... Finished 'test' profile [unoptimized] target(s) in 0.36s ──────────── Nextest run ID 8f2105dd-51ef-4555-b7be-2c62609863c8 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-0674... Finished 'test' profile [unoptimized] target(s) in 0.37s ──────────── Nextest run ID d52a8054-df8f-4ffc-8eca-071f3efa16c3 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-308a... Finished 'test' profile [unoptimized] target(s) in 0.38s ──────────── Nextest run ID 89ad2dec-87ac-4b29-a072-c4cd69bab00b with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-c0cd... Finished 'test' profile [unoptimized] target(s) in 0.37s ──────────── Nextest run ID 172b3202-2b70-4f97-ab91-e0872565d9f8 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-ebf6... Finished 'test' profile [unoptimized] target(s) in 0.38s ──────────── Nextest run ID 9bb23c73-3dcb-4ac0-9b3a-652a29f07856 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-6753... Finished 'test' profile [unoptimized] target(s) in 0.43s ──────────── Nextest run ID 176141f3-69cb-4e2f-8b50-b48997ed0ad5 with nextest profile: default Starting 2 tests across 2

Verify min task run agent-verify passed.

Review threads the coder judged:

A request to the rule's upstream carries the stored key in the registered header. A replaced key is sent on the next request. The forward tests show both against a memory store. A served flow does not inject yet: bep serve does not call Flow::with_store, and no redeemer returns Redeemed::Store until the store rules land (#2280).

Notes from the agent: Round 4. Redeemer::redeem_reference now takes the name of the header that carries the sealed value. Its default refuses a value outside Authorization as sealed_header_misplaced before redeem runs. Only the AdmitsStore test overrides it. The placement check after a sign-in admit stays as a second guard for an override. A new private Flow::decide_injected returns the injected header name, and forward_requests zeroizes that header after it writes the head. Flow::decide keeps its signature. inject now moves the value out of its Zeroizing buffer and does not copy it. I cannot file issues from this box. So the interim notes link #2280, the issue that redeemer.rs and main.rs give for store rules, and each note states its flip condition. The PR body must name #2280 as the residual for the BoxRedeemer override and the bep serve with_store wiring. If #2483 owns the serve wiring, a person can relink it. Two new tests: sign_in_reference_outside_authorization_is_not_redeemed and injected_header_is_named_for_zeroizing.

10BC8
@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 compare closes the open points of the ruling on 4ee866a4. A sign-in value outside Authorization is now refused before the redeemer runs, so nothing is renewed (§6.10 lines 839 and 849). The injected header is zeroized whatever its name. The interim notes link #2280 and state when they stop being true. One condition stays open as a filed residual: bep serve admits no store reference until #2280 lands (C1).

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

Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.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 — advisory review

Verdict COMMENT — 1 finding, 1 inline.

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

Comment thread crates/bep/src/forward.rs Resolved
A sealed value in a header such as x-api-key, beside an Authorization
header that does not hold it, is now mixed and refused. The upstream
can honour either header.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 5 of 10 on the runtime's review findings, pushed as 8a505ad20adf.

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-ed12... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 17.62s ──────────── Nextest run ID 1945cad6-5760-4e97-b5d6-22990eb556c6 with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-b525... Finished 'test' profile [unoptimized] target(s) in 0.39s ──────────── Nextest run ID e4a3f527-7eaa-4489-91ef-8ca17641ccd6 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-14eb... Finished 'test' profile [unoptimized] target(s) in 0.41s ──────────── Nextest run ID bb42362b-2fb2-4d3c-8414-fe93246ce185 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-255d... Finished 'test' profile [unoptimized] target(s) in 0.38s ──────────── Nextest run ID 8b37d9e4-61ee-4602-869d-0d696300c31d with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-bc14... Finished 'test' profile [unoptimized] target(s) in 0.39s ──────────── Nextest run ID 52baf764-bffb-45fa-80e8-af3c5d1d131c with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-15b9... Finished 'test' profile [unoptimized] target(s) in 0.38s ──────────── Nextest run ID 9446ec37-668c-4ede-8e2d-e27603f32a2f with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-cdef... Finished 'test' profile [unoptimized] target(s) in 0.40s ──────────── Nextest run ID 4e6cbd95-b99b-4b5c-b4fd-f3a1415a1083 with nextest profile: default Starting 2 tests across 2

Verify min task run agent-verify passed.

Review threads the coder judged:

A request to the rule's upstream carries the stored key in the registered header, and a replaced key is sent on the next request. A sealed value in a header such as x-api-key beside the box's own Authorization header is now refused as mixed_authorization.

Notes from the agent: Revise round 5. Only crates/bep/src/forward.rs changed: carried() returns Mixed when any Authorization header that does not hold the sealed value is beside it, with the new test sealed_in_other_header_beside_authorization_is_mixed. The full bep suite passes (181). The two minimal-arch interim-note threads describe work for #2280 and the bep serve wiring. The notes already link #2280 and state the flip condition, so this round changes nothing for them. just clippy-strict was not run.

@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 compare refuses a sealed key in any header beside the box's own Authorization header. That is fail-closed, and it conforms to Gatehouse §6.10 line 849. The baseline ruling stands for the rest of the change. The bep serve path does not inject a store value yet, and #2280 owns that work. Make the change in C1, so that the PR does not close #2292 while the serve-path proof is open.

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

Comment thread crates/bep/src/forward.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

This push has the same tree as 8a505ad2, so the ruling on that head stands. The injection matches Gatehouse §6.10 line 849: exactly prefix plus value, no CR or LF, and an audit without the value. One condition stays open. C1, filed as #2586, wires BoxRedeemer::redeem_reference and Flow::with_store into bep serve. Until then bep serve refuses store members, and BEP-032 holds in the forwarder only.

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

Comment thread crates/bep/src/forward.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 — advisory review

Verdict COMMENT — 1 finding, 1 inline.

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

Comment thread crates/bep/src/inject.rs Resolved
A rule that names content-length, host, connection or another framing
or hop-by-hop header is refused as injection_invalid. The interim notes
now name #2586 and the two edits that end them.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 6 of 10 on the runtime's review findings, pushed as 91c6c78e72ae.

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-5c9c... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 18.00s ──────────── Nextest run ID 101f2e2e-3087-4a60-8b4a-f79187faebd6 with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-3fa5... Finished 'test' profile [unoptimized] target(s) in 0.37s ──────────── Nextest run ID 086f3309-c94d-48ad-a269-e4a3ae7080eb with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-4f6a... Finished 'test' profile [unoptimized] target(s) in 0.36s ──────────── Nextest run ID 272891f6-20be-4bed-8046-614e3a1dfe05 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-6777... Finished 'test' profile [unoptimized] target(s) in 0.34s ──────────── Nextest run ID e22e588e-ef3b-47a2-accb-286593ce23a0 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-b85a... Finished 'test' profile [unoptimized] target(s) in 0.37s ──────────── Nextest run ID 1caf3011-153b-4d56-b880-97ce19c2de67 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-75ae... Finished 'test' profile [unoptimized] target(s) in 0.37s ──────────── Nextest run ID d9eed817-bfb3-48c0-bea1-42a9ef37eb6d with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-2413... Finished 'test' profile [unoptimized] target(s) in 0.36s ──────────── Nextest run ID 30775e9a-9250-43f5-b6fa-1ee2d8b896e8 with nextest profile: default Starting 2 tests across 2

Verify min task run agent-verify passed.

Review threads the coder judged:

In the crate's tests, a request to the rule's upstream carries the stored key in the registered header, and a replaced key is sent on the next request. A rule that names a framing header such as content-length is now refused as injection_invalid. bep serve does not inject yet: that waits on #2586.

Notes from the agent: Revise round 6. inject.rs refuses framing and hop-by-hop header names (connection, content-length, host, keep-alive, proxy-authorization, proxy-connection, te, trailer, transfer-encoding, upgrade) as injection_invalid. The two interim notes in forward.rs now link #2586 and name both edits that end them. The PR body is written by the runner, not by this branch: it must say 'Part of #2292', not 'Closes #2292', because bep serve does not inject until #2586 lands. The full bep suite passed once at the end (192 passed).

@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/store.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 compare changes the PR's own code in one commit only. The merge of main leaves the PR's lines unchanged. Commit 91c6c78e refuses a framing or hop-by-hop header as an injection target. This agrees with Gatehouse §6.10 line 849. The rule layer in crates/boxes/src/core/bep.rs enforces the full line 849 deny set, so the shorter list in inject.rs is an extra check. The interim notes now name #2586 and both flip edits. C1, the bep serve path, stays open as that residual.

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

Comment thread crates/bep/src/forward.rs Resolved
errSecInteractionNotAllowed also comes from a locked keychain when
prompts are off. Report it as a store refusal that names both causes.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 7 of 10 on the runtime's review findings, pushed as fe47db23ba2c.

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-b8c0... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 16.82s ──────────── Nextest run ID 4f7da71b-89fb-4aaa-9344-9b9ece890061 with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-823a... Finished 'test' profile [unoptimized] target(s) in 0.31s ──────────── Nextest run ID f9c97360-a025-4dcd-8c50-9b4f8f611c6d with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-00ec... Finished 'test' profile [unoptimized] target(s) in 0.34s ──────────── Nextest run ID 609d661d-f394-4289-9066-ed7865f6e6fe with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-7c0b... Finished 'test' profile [unoptimized] target(s) in 0.36s ──────────── Nextest run ID 6ed137ff-2ded-4aad-8077-c80182d28b45 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-e218... Finished 'test' profile [unoptimized] target(s) in 0.32s ──────────── Nextest run ID 0bfde760-658f-4a94-b91b-eebc171b76f2 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-8aed... Finished 'test' profile [unoptimized] target(s) in 0.35s ──────────── Nextest run ID 33a73b6a-f071-4a98-b8c2-b6349e3e888e with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-e5d6... Finished 'test' profile [unoptimized] target(s) in 0.32s ──────────── Nextest run ID 27907372-e789-443b-ae29-7fbde5999289 with nextest profile: default Starting 2 tests across 2

Verify min task run agent-verify passed.

Review threads the coder judged:

  • 👍 valid — crates/bep/src/store.rs: Removed -25308 from DENIED. It now maps to ReadError::Store, and the detail names both causes: a locked keychain, or a secret that does not let the proxy read it without a prompt.

A request to the rule's upstream carries the stored key in the registered header, and a replaced key is sent next time. This round, a read that fails with errSecInteractionNotAllowed no longer says that the secret does not let the proxy read it. The refusal now says that the keychain is locked, or that the secret does not let the Box Egress Proxy read it without a prompt.

Notes from the agent: The changed code is in the macOS-only host module of store.rs. This Linux box does not compile it, so no build or test here checks the change. The macOS lane must compile it. The test lines passed on Linux, but they do not reach this code path.

@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 compare moves errSecInteractionNotAllowed out of the disabled-item codes. A locked keychain is now recorded as store_item_unreadable, and the request is still refused. Gatehouse §6.10 line 844 requires the read under the store's ACL, and this record is more exact than before. The baseline condition stays open as C1 and the filed residual #2586: bep serve does not inject a store value yet.

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

Comment thread crates/bep/src/forward.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 — advisory review

Verdict COMMENT — 2 findings, 2 inline.

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

Comment thread crates/bep/src/store.rs Resolved
Comment thread crates/bep/src/inject.rs Resolved
A store reference whose store failed the read now gets its own refusal
text, not the generic one. The base64 form of a basic_auth pair is now
encoded straight into the zeroizing header buffer.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 8 of 10 on the runtime's review findings, pushed as fec6f0b495e3.

line exit tail
cargo nextest run -p bep store_reference_injects_in_registered_form 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-d453... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 13.05s ──────────── Nextest run ID 67b96539-7058-4207-a52d-e67fe52fdd2a with nexte
cargo nextest run -p bep store_value_read_per_request_never_written 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-60c5... Finished 'test' profile [unoptimized] target(s) in 0.27s ──────────── Nextest run ID 9c65a9ba-7faa-468d-b2fd-c7e220cbfd08 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep deleted_keychain_item_refuses_next_injection 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-83ef... Finished 'test' profile [unoptimized] target(s) in 0.24s ──────────── Nextest run ID 6182fc75-948e-4127-969c-cab0451acb8b with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep reference_to_another_sign_in_instance_is_refused 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-eef1... Finished 'test' profile [unoptimized] target(s) in 0.28s ──────────── Nextest run ID b8dec784-f7b0-45d8-be67-71402b128a98 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep replaced_secret_is_injected_on_next_request 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-d205... Finished 'test' profile [unoptimized] target(s) in 0.26s ──────────── Nextest run ID 735329d8-ff43-4546-8c5d-2616d4521e04 with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep injected_value_is_exactly_prefix_plus_value 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-bd96... Finished 'test' profile [unoptimized] target(s) in 0.30s ──────────── Nextest run ID c8eefac5-fff1-4ba2-8b77-e7a0be38d93a with nextest profile: default Starting 1 test across 2
cargo nextest run -p bep crlf_in_value_or_prefix_refuses_injection 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-d4d4... Finished 'test' profile [unoptimized] target(s) in 0.27s ──────────── Nextest run ID 34a00f1a-91d2-4148-9eb4-53b93d516095 with nextest profile: default Starting 2 tests across 2

Verify min task run agent-verify passed.

Review threads the coder judged:

  • 👎 invalid — crates/bep/src/forward.rs:326: The remaining work is the BoxRedeemer override in crates/bep/src/redeemer.rs and the Flow::with_store call in crates/bep/src/proxy.rs. Neither file is in this task's layers. T67 — Inject store values in bep serve #2586 tracks it, and the interim notes stay until that lands.
  • 👎 invalid — crates/bep/src/forward.rs:326: The requested edits are in crates/bep/src/redeemer.rs and crates/bep/src/proxy.rs. Neither file is in this task's layers. T67 — Inject store values in bep serve #2586 tracks them. The two interim notes are to be removed in that change, not in this one.
  • 👍 valid — crates/bep/src/store.rs:882: Added a refusal body for store_item_unreadable ('was not able to read the stored secret') and asserted it in a test. The -25308 mapping stays unreadable, because a locked keychain also returns it.
  • 👍 valid — crates/bep/src/inject.rs: header_for now encodes the basic pair with encode_slice directly into the presized Zeroizing buffer. No intermediate String is made.

In the bep flow tests, a request to the rule's upstream carries the stored key in the registered header, and a key that is replaced in the store is sent on the next request. bep serve does not inject a store value yet. That wiring is in redeemer.rs and proxy.rs, outside this task, and issue #2586 tracks it.

Notes from the agent: Round 8. A store read failure now has its own refusal text. The base64 basic_auth pair is now encoded straight into the zeroizing buffer. errSecInteractionNotAllowed stays mapped to store_item_unreadable, because a locked keychain also returns it (a thread from an earlier round). The two C1 threads ask for changes in redeemer.rs and proxy.rs, which are outside this task's layers. The full bep suite passed once at the end: 192 passed.

@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 new push conforms. The store_item_unreadable refusal now states the real cause, and the basic_auth value stays in one zeroizing buffer with the same bytes. Section 6.10 line 849 still holds for the injection form. C1 from the last ruling stays open: bep serve does not inject a store value until BoxRedeemer and proxy.rs are wired. That work is filed as #2586, so the change can merge.

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

Comment thread crates/bep/src/forward.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 — advisory review

Verdict COMMENT — 1 finding, 1 inline.

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

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

Round 9 of 10 on the runtime's review findings: the coder changed nothing. Revise round 9. I judged both open threads invalid, so this round has no code change. The head commit fec6f0b is unchanged, and all seven test lines pass on it. The C1 wiring (proxy.rs calls Flow::with_store, and BoxRedeemer overrides redeem_reference) is in crates/bep/src/proxy.rs and the redeemer. Those files are outside this task's layers, and #2586 tracks the change.

Review threads the coder judged:

  • 👎 invalid — crates/bep/src/forward.rs:794: The change belongs outside this task's layers. It is in crates/bep/src/proxy.rs (the call to Flow::with_store with HostStore) and in the BoxRedeemer override of redeem_reference. This task's layers are inject.rs, store.rs, forward.rs and lib.rs. T67 — Inject store values in bep serve #2586 tracks the wiring, and the interim note on with_
  • 👎 invalid — crates/bep/src/forward.rs:68: mixed_authorization is an audit marker that is already on main (forward.rs:65 there), so existing audit records use it. A rename changes that vocabulary and must go in a separate pull request, per AGENTS.md. Both cases are the same refusal: more than one header can carry a credential. The doc commen

@norrietaylor
norrietaylor force-pushed the agent/2292-inject-a-stored-key-in-the-registered-form-read branch from fec6f0b to ac87b37 Compare October 26, 2026 01:47
@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

This head has the same content as fec6f0b4, so the earlier ruling stands. The injection allowlist, the read for each request and the deleted-item refusal conform to Gatehouse §6.10 lines 844 and 849. bep serve does not inject a store value yet, because BoxRedeemer does not return Redeemed::Store and proxy.rs does not call Flow::with_store. C1 covers that wiring. It is filed as #2586 and can stay open at merge.

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

Comment thread crates/bep/src/forward.rs Resolved
Comment thread crates/bep/src/forward.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: 7 unresolved threads — minimal-arch[bot] crates/bep/src/forward.rs:326, minimal-arch[bot] crates/bep/src/forward.rs:326, minimal-arch[bot] crates/bep/src/forward.rs:326, minimal-arch[bot] crates/bep/src/forward.rs:794, minimal-foundry[bot] crates/bep/src/forward.rs:68, …. No findings.

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

@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 ac87b37ed9e0 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 T28 — Inject a stored key in the registered form, read from the Keychain per request feat(bep): inject a stored key in its registered form per request (T28) 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 ac87b37: every merge gate passes at this head (arch PASS at ac87b37, zero open threads, every lane aggregator green). Squash title feat(bep): inject a stored key in its registered form per request (T28) 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 bec5136 Oct 26, 2026
42 of 44 checks passed
@norrietaylor
norrietaylor deleted the agent/2292-inject-a-stored-key-in-the-registered-form-read branch October 26, 2026 04: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.

T28 — Inject a stored key in the registered form, read from the Keychain per request

1 participant

0