8000 T114 — Steer a dns box's store-rule authorities to the proxy by minimal-foundry[bot] · Pull Request #2822 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

T114 — Steer a dns box's store-rule authorities to the proxy - #2822

Merged
norrietaylor merged 2 commits into
mainfrom
agent/2575-steer-a-dns-box-s-store-rule-authorities-to-the
Nov 1, 2026
Merged

norrietaylor merged 2 commits into
mainfrom
agent/2575-steer-a-dns-box-s-store-rule-authorities-to-the

Conversation

@minimal-foundry
Copy link
Copy Markdown
Contributor

T114 — Steer a dns box's store-rule authorities to the proxy

slice: S16
kind: task
covers: BEP-062
size: M
est: 140 code, 180 8000 tests
executor: agent
difficulty: needs care
model: standard
diagnostics: a dns-steered box with a store reference resolves its rule's upstream, such as api.openai.com, to the proxy's address while the proxy listens, and gets SERVFAIL while it does not, pinned by store_authority_of_a_dns_box_resolves_to_the_proxy
observability: the gate's existing debug line for a steered answer names the box and the steered name
layers:
- policy:
- crates/boxes/src/lib.rs: CredentialedUpstream carries the upstream authorities of the store rules the creation accepted, written only when the box has one, so a daemon that predates the field still reads a policy without store references
- crates/minimal/src/cmd/boxes/create.rs: creation puts each accepted store rule's upstream into the box's policy beside its grants (#2575)
test: cargo nextest run -p minimal accepted_store_rule_authorities_reach_the_box_policy
- gate:
- crates/minimald/src/net/switch.rs: the steered set of a dns or both box is the GitHub module's hosts and the store-rule authorities its policy carries, in place of credential_module_hosts() alone; the full literals of CredentialedUpstream in this file's tests gain the field
- crates/minimald/src/net/dns_gate.rs: the full literals of CredentialedUpstream in this file's tests gain the field
- crates/minimald/src/box_manager/tests.rs: the full literals of CredentialedUpstream gain the field
test: cargo nextest run -p minimald store_authority_of_a_dns_box_resolves_to_the_proxy
produces: none
consumes: none
proof: A dns-steered box that references a stored key resolves its rule's upstream to the proxy, and the request carries the stored key while the key never enters the box.
depends on:
- blocked by #2523
- blocked by #2525

Original issue text

Residual from T58 #2567, arch C1 (ruling), epic #1501.

Networking §5.3 line 151 steers every declared credentialed hostname of a dns or both box to the Box Egress Proxy. The spec counts [secret-store-rules] authorities among those names (BEP-013, BEP-029). credential_module_hosts in crates/minimald/src/net/switch.rs steers only bep::module::GITHUB.

No box reaches the gap today: admission refuses dns steering for any box with a broker grant (BEP-017, refusals in crates/boxes/src/core/bep.rs, !host.box_zone_resolver). Once that refusal lifts, a store authority under dns steering would resolve through real DNS, which BEP-062 forbids.

What closes this

  • When the box-zone resolver lifts the BEP-017 refusal, the steered set also holds the authorities the operator's [secret-store-rules] register for the box's store references, beside bep::module::GITHUB.
  • The doc comment of credential_module_hosts links this issue until then.
  • A test pins that a store authority of a dns box resolves to the proxy address.

Generated by Claude Code

Proof

A dns- or both-steered box whose store reference a [secret-store-rules] rule accepted now carries that rule's upstream in its policy (credentialed_upstream.store_upstreams). Its lookup of the upstream host, such as api.openai.com, resolves to the Box Egress Proxy's address while the proxy listens, and gets SERVFAIL while it does not. The GitHub hosts stay steered too. So the box's request for that host goes to the proxy, and the proxy injects the stored key that the box never holds. This branch proves the DNS steering and the policy field. The key injection itself comes from the existing store-handle mint and the proxy, which this task does not change.

Notes from the agent: The new field is CredentialedUpstream.store_upstreams (Vec, authorities as host or host:port). It is skipped when empty, so a policy without store references serializes as before. CredentialedUpstream::store_upstream_hosts() removes the port before the gate matches names. crates/minimald/src/box_manager/tests.rs needed no change: its one literal already ends in ..Default::default(). The other literals outside the layers (box_runtime.rs, minvmd, dash) also use Default, so no file outside the layers changed. clippy -p boxes -p minimal -p minimald --all-targets is clean. The existing steered-answer debug line names the switch address and the name. The SERVFAIL warning names session_id and the name, and the new test pins that for api.openai.com.

Tests

line exit tail
cargo nextest run -p minimal accepted_store_rule_authorities_reach_the_box_policy 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-a565... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling client-config v0.0.1 (/wo
cargo nextest run -p minimald store_authority_of_a_dns_box_resolves_to_the_proxy 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-b8da... Compiling paths v0.0.1 (/workbench/crates/paths) Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling client-config v0.0.1 (/wo

Verify

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

ent_span_id": "3e487e448b4f14d5",
                "span_id": "13779e327207dd1f",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetDenyAllOptOut",
                "parent_span_id": "3e487e448b4f14d5",
                "span_id": "9cb82fdc3ec0190b",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "GetPaths",
                "parent_span_id": "3e487e448b4f14d5",
                "span_id": "3311b7230549b164",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "GetRecord",
                "parent_span_id": "3e487e448b4f14d5",
                "queued_behind": "0",
                "span_id": "7e6cb5618afbd209",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "sessions.manager.message",
            fields: {
                "kind": "DeleteSession",
                "parent_span_id": "3e487e448b4f14d5",
                "queued_behind": "0",
                "span_id": "e5c722598240ad28",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
        LoggedSpan {
            name: "session.message",
            fields: {
                "kind": "Destroy",
                "parent_span_id": "e5c722598240ad28",
                "span_id": "c10ecc6f8adc99e2",
                "trace_id": "0af7651916cd43dd8448eb211c803111",
            },
            parent: None,
            closed: true,
        },
    ]
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

  Cancelling due to test failure: 3 tests still running
        PASS [   2.309s] (1490/2741) minimald box_actor::tests::a_box_destroyed_between_enumeration_and_grant_is_released_once
        PASS [   2.319s] (1491/2741) minimald box_actor::tests::a_box_destroyed_inside_the_landing_window_is_not_resurrected
        PASS [   2.335s] (1492/2741) minimald box_actor::tests::a_box_holding_a_host_row_refuses_remint_after_its_host_loop_ends
────────────
     Summary [  41.009s] 1492/2741 tests run: 1491 passed, 1 failed, 25 skipped
        FAIL [   2.907s] (1489/2741) minimal::otel_cli exec_run_attach_and_task_run_share_the_commands_trace
warning: 1249/2741 tests were not run due to test failure (run with --no-fail-fast to run all tests, or run with --max-fail)
error: test run failed

Closes #2575

Creation puts each accepted [secret-store-rules] upstream into the
credentialed-upstream declaration beside its grants (BEP-062). The field
is skipped when empty, so a policy without store references reads as
before.
The steered set of a dns or both box is now the GitHub module's hosts
and the store-rule upstream hosts its policy carries (BEP-062).
@coderabbitai
coderabbitai Bot commented Oct 31, 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: 47de2602-0806-4d6b-b8d0-80dd9a2717ca

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

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

Approved: no findings at 5be5fd6cae4e.

Nothing to do.

Verdict APPROVE, posted as a comment: the App cannot review its own pull request; the check and the label carry it.

Clobber: none seen.

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

Choose a reason for hiding this comment

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

arch-review: PASS · the full ruling

The change conforms to §5.3 line 151 and §5.4 line 169. A dns or both box resolves its credentialed hostnames to the proxy. Gatehouse §6.10 line 834 puts the [secret-store-rules] authorities in that credentialed set. The set comes from the operator's accepted rules, not from the spec, as §5.4 line 157 requires. The gate still refuses a name outside the egress allow-list before it steers. The new test pins SERVFAIL while the proxy is down.

Ruled at 5be5fd6 against gominimal/arch@8640f85e193d by claude-opus-5-5.

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

Choose a reason for hiding this comment

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

minimal-review — approved

Verdict APPROVE — No findings.

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

@minimal-foundry minimal-foundry Bot added the review:approved minimal-review approved the current head label Oct 31, 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.

Approving at 5be5fd6. A dns or both box now steers the host of each accepted [secret-store-rules] upstream to the proxy, beside the GitHub hosts.

How the names stay bounded:

  • put_store_upstreams fills store_upstreams only from the rules accept_store_references accepted for this box.
  • steered_hosts(policy) reads them per box, in for_session_steered.
  • They share answer_steered with the GitHub hosts: the proxy address while the listener is live, SERVFAIL while it is down. AAAA, HTTPS and SVCB get NODATA.
  • REFUSED and NXDOMAIN still run first, so steering never bypasses the allow-list.
  • Mixed case and a trailing dot are normalised on both sides.

Admission is unchanged, so dns stays refused as #2797 left it, and the path is reached through both on the VM host. Arch: local review and the minimal-arch check both PASS.

Non-blocking: store_authority_of_a_dns_box_resolves_to_the_proxy runs with the default (dns) steering. The gate branches only on needs_resolver(), so it still proves the gate, but a Steering::Both case would pin the configuration that reaches it.

@norrietaylor
norrietaylor added this pull request to the merge queue Nov 1, 2026
Merged via the queue into main with commit ea5b21a Nov 1, 2026
36 checks passed
@norrietaylor
norrietaylor deleted the agent/2575-steer-a-dns-box-s-store-rule-authorities-to-the branch November 1, 2026 02:03
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.

T114 — Steer a dns box's store-rule authorities to the proxy

1 participant

0