security: reserve daemon control namespaces (S3a) - #683
Merged
Merged
Conversation
Cherry-picked from red-steel `f731d3c0`, resolved against current `main`.
Reserves the daemon's own control namespaces so a generic fact-create or
`.cruxpack` import cannot write into them, and so agent-private
`__agent::<owner>::<logical>` entities must carry an explicit owner mapping
rather than being remapped by guesswork.
Resolution note: the three conflicts are all reserved-prefix lists where
BOTH sides had added entries since the fork — `main` contributed
`__escrow__::` and `__candidate_fact__::` (key escrow M3b, auto-capture
M1), red-steel contributed the daemon control set. Resolved as a union, not
by taking a side; the two entries that appeared on both sides were
deduplicated. `assert_unique_nonempty` and the cruxpack/fact_privacy drift
test both pass, which is what makes the union checkable rather than a
judgement call.
**This commit is a prerequisite for the rest of the tenant-isolation slice,
which is why it moved.** The plan filed it under S4, but `ba642868`
(tenant-scoped fact lifecycle) does not compile without it: `ba642868`
inherits the `__agent::` remapping block that binds `entity`, and
references `PackVerifyError::{InvalidAgentPrivateEntity, ReservedEntity,
AgentPrivateOwnerMappingRequired}` and
`ConsolidationErrorV1::TargetDaemonOwned` — every one of which is
introduced here. Traced by attributing each missing symbol to its
introducing commit rather than by guessing at the ordering.
Verified: `cargo check --workspace --all-targets --locked` clean;
corecrux-memory 335 + 7 tests, corecruxd/crux-mcp 2052 tests, 0 failures;
clippy at parity with `main` (both 0 under CI's `--workspace -- -D
warnings`, which is the actual gate — `--all-targets` reports 350 on `main`
too and is not what CI runs).
Refs #630. Slice S3a of redsteel-remediation-replay-2026-08-07.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Independently checked the load-bearing claim here — that the three conflicted reserved-prefix lists were resolved as a union rather than by taking a side. Compared each list at
So Auto-merge enabled; it will go in once Test and Coverage land. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice S3a of the red-steel remediation replay (#630). Cherry-pick of
f731d3c0, resolved against currentmain.What it does
Reserves the daemon's own control namespaces so a generic fact-create or a
.cruxpackimport cannot write into them, and requires agent-private__agent::<owner>::<logical>entities to carry an explicit owner mapping rather than being remapped by guesswork.Why this is S3a and not S4
The plan filed
f731d3c0under S4 (auth/authority binding). That was wrong, and it cost a build to find out.ba642868— the tenant-scoped fact lifecycle that S3 is actually about — does not compile without this commit. It inherits the__agent::remapping block that bindsentity, and referencesPackVerifyError::{InvalidAgentPrivateEntity, ReservedEntity, AgentPrivateOwnerMappingRequired}plusConsolidationErrorV1::TargetDaemonOwned. Every one of those is introduced here.I found it by attributing each missing symbol to its introducing commit rather than reasoning about the slice names:
InvalidAgentPrivateEntityf731d3c0ReservedEntityf731d3c0AgentPrivateOwnerMappingRequiredf731d3c0generic_create_reserved_entity_prefixf731d3c0TargetDaemonOwnedf731d3c0It is also markedly easier to land alone: 2 conflicted files / 3 hunks, against
ba642868's 7 files / 13 hunks.The resolution
All three conflicts are reserved-prefix lists where both sides added entries since the fork:
maincontributed__escrow__::(key escrow M3b) and__candidate_fact__::(auto-capture M1)Resolved as a union, not by taking a side — which is what the WIP branch's own analysis said these needed. The two entries present on both sides were deduplicated.
assert_unique_nonemptyand the cruxpack/fact_privacy drift test both pass, so the union is checkable rather than a judgement call.Order is not load-bearing in these lists (
.contains, no binary search), which is why a union is safe here.Verification
cargo check --workspace --all-targets --locked— cleancorecrux-memory335 unit + 7 integration;corecruxd+crux-mcp2052 — 0 failuresmain: both 0 under CI's actual gate (--workspace -- -D warnings). Worth noting for anyone checking:--all-targetsreports 350 onmainas well, and is not what CI runs — comparing against the wrong invocation makes this look like a regression when it is not.Next in the slice
ba642868+33ec4ed1(tenant-scoped fact lifecycle) stack on top of this, then426ea8a0+41ee2515, then16554b80.Plan and decision log:
PlanCrux/.agent/execplans/redsteel-remediation-replay-2026-08-07.md.🤖 Generated with Claude Code