Repository navigation
Conversation
…s (H149) Fails on origin/main 95822ce: a persona PERSON mints a PERSON on an unrooted vault (put_structural), as the embedded owner does.
…er alone, and a self-hosted root binds that owner (H149) On a vault with no authority root, verify_owner_actor_binding_in_txn passed every live PERSON, so a persona or agent row named "human" could mint, retract and delete as the owner. Now only the vault's own live embedded owner passes there; every other PERSON gets OWNER_BINDING_REQUIRED with the rooting advice. Multi-root stays INVALID_STATE. A self-hosted genesis (ensure_host_root_slip on an empty log) binds the embedded owner as human, epoch 1, in the same transaction. Hosted and relay roots bind no one; a hard-deleted owner stays unbound. Test fixtures that used an arbitrary PERSON as the owner of an unrooted vault now use the embedded owner, or root the vault and bind theirs.
…dict take the shared owner check (H149 review round 1) Both kept their own copy of the owner predicate, which passed every human PERSON on a vault with no authority root (Astra R1 F1, F2). They now ask verify_owner_actor_binding_in_txn, so on an unrooted vault only the embedded owner retracts or explicitly replaces another actor's expression preference, or records an owner verdict. The promoted-session test keeps its own speaker, distinct from the owner who promotes, and reads the promoted turn as the owner (Sol R1 F1).
|
Warning Review limit reached
This review includes 92 billable files and costs up to $23.00.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 23 minutes for your next included review. View limit details
Comment |
… turned up (H149) Each of these tests acted as an arbitrary PERSON that held the owner verbs or the owner's reads on a vault with no authority root. They now act as the vault's embedded owner, or root the vault and bind the test's owner before they measure or read. The rooted-authority booking test opens its vault unrooted, since it writes its own genesis.
… a redundant clone)
…t is (H149 review round 2) verify_owner_write_actor_in_txn checked the Human class and stopped there; it now asks verify_owner_actor_binding_in_txn, as every owner verb does, so on an unrooted vault only the embedded owner writes learning settings, binds preference principals, reads the optimizer brief for a principal, resolves the inbox as itself, and edits project depth or the subject model. record_proposal_outcome_for_ramp, demote_scope_to_propose and the selection law's Owner writer revalidated a native owner proof for liveness only. They now take revalidate_as_vault_owner_in_txn, so a live person of this vault who is not its owner rules nothing and amends no owner-locked law. Checks that fail on main: a non-owner person's proof is refused by both graduation doors and by the selection Owner writer, and a non-owner Human moves no learning-setting floor. Fixtures that named an arbitrary person as owner of these doors now use the embedded owner; Bob reads his own room message under a read grant, and the decisions census signs principal autonomy as the embedded owner.
…heck (H149 review round 3) Round 3 (Sol F1, Astra F1): with only the owner binding a preference principal, the second principal in three isolation tests was refused at the owner check and never reached the filters the tests are about. B's receipt in the miner threshold test is now bound as by an earlier owner, through the binding row's in-transaction door, so it is real evidence the miner keeps apart from A's; B binding more evidence through the public door is refused. The two brief tests keep the public refusal and also read B's brief past the owner check (optimize_brief_bound_at), which carries none of A's corrections or rejected drafts.
…r (H149 r4) The owner-write verifier now refuses a Human PERSON who is not the owner, so the two unrooted subject-model tests check that refusal and then write as the embedded owner, and the archive test's source facts are authored by the source's embedded owner. In the mixed-room fixture Bob is not the vault's owner, and the room's rows carry no record scope a read grant could name, so a read permit gives him no read. The owner resolves and reads Bob's message instead, before and after the tombstone and after Bob's erasure.
…H149, main's #1477 test) Its imported evidence is private, which only the vault's owner reads; the test named a fresh PERSON, the owner only through the unrooted pass-through.
…8 tier flip, #1476 r3 tables) A denial names no addressee, and self-heal reads each denied receipt as the owner's signal, so a non-owner's refusal must not land. The weave digest schedule is owner-authorized even for a person's own reader. Both move from the person tier back to the owner tier and join the owner-door table check.
# Conflicts: # crates/oneiron/src/channel_identity_selection/selection_rules.rs # crates/oneiron/src/channel_identity_selection/tests.rs # crates/oneiron/src/memory/tests/commit_claims.rs
…s unused (clippy)
…149 refuses an unbound PERSON)
|
Automatic reviews are disabled for this repository. |
PR SummaryHigh Risk Overview Self-hosted genesis now binds that embedded owner as Owner enforcement is centralized: The bulk of the diff updates tests and fixtures ( Reviewed by Cursor Bugbot for commit 8db67b5. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8db67b5. Configure here.
| authority_key: issuer.public_key(), | ||
| actor_ref: owner, | ||
| actor_class: ACTOR_CLASS_HUMAN.into(), | ||
| epoch: 1, |
There was a problem hiding this comment.
Soft-deleted owner rebound at root
Medium Severity
bind_rooted_owner_in_txn skips only a hard-deleted embedded owner, then writes an active human bind for a user-deleted shell. After a self-hosted root, owner verbs consult that bind and not liveness, so a UserDelete of the owner that already strips the verbs on an unrooted vault restores them as soon as the vault is rooted.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 8db67b5. Configure here.


H149: on a vault with no authority root, any PERSON could take the owner verbs (medium; triage W3-T7 in the Codex security scan triage,
triage-W3.mdH149)Finding
verify_owner_actor_binding_in_txn(memory/support.rs) asks the authority log whether an actor is the owner: an activehumanbinding under an owner-capable key. A vault with no folded genesis skipped that question and passed every live PERSON. A default embedded vault is unrooted, so a host acting as any PERSON row, an agent's persona included (napias_actor("human:<persona>")), could mint PERSON rows, retract another actor's claims and safe-delete as the owner. Rooted vaults were also unfinished: no production path bound the owner, so a rooted vault refused its own owner.Checks (fail before)
In
memory/tests/authority_revocation.rs:an_unrooted_vault_gives_no_other_person_the_owner_verbs: a persona row named "human" and a second PERSON are refused the PERSON mint, the cross-actor retract and the safe-delete.an_unrooted_vault_keeps_the_owner_verbs_for_its_embedded_owner: the positive control.a_deleted_embedded_owner_holds_no_owner_verbs: after a user delete, OWNER_BINDING_REQUIRED; after a hard delete, refused.a_self_hosted_root_binds_its_owner_and_no_one_else: afterensure_host_root_slip, the embedded owner passes and the persona is refused.owner_verbs_require_active_owner_binding_when_rooted(on main already) still passes.In
claim/tests.rs,expression_preference_override_refuses_a_human_who_is_not_the_owner: a PERSON named human neither retracts an agent's preference nor replaces it with an explicit one. Incritic/review/tests.rs,document_and_claim_reviews_persist_and_learn_dismissalsnow also has a delegate PERSON refused the owner verdict.The owner-write verifier and the owner-proof doors:
only_the_owner_or_the_scope_actor_takes_a_standing_grant_away(consent_graduation/tests.rs): a native owner proof for a live PERSON of this vault who is not its owner neither demotes the owner's standing grant nor rules on a proposal.a_person_who_is_not_the_owner_cannot_write_as_the_owner(channel_identity_selection/tests.rs): that proof amends no owner-locked selection law, and nothing is stored.an_unclear_verdict_changes_no_reliability_and_files_one_note(skill_attribution/tests/sweep.rs): a Human who is not the owner moves no learning-setting floor (put_setting_row, throughverify_owner_write_actor_in_txn).Fail-before: main 14fcd7d's code in the nine non-test files this PR changes (
authority/host_actor.rsremoved), with this branch's tests. 8 of the 10 checks fail at their assertions: the four newauthority_revocationchecks,expression_preference_override_refuses_a_human_who_is_not_the_owner,document_and_claim_reviews_persist_and_learn_dismissals,only_the_owner_or_the_scope_actor_takes_a_standing_grant_away,a_person_who_is_not_the_owner_cannot_write_as_the_ownerandan_unclear_verdict_changes_no_reliability_and_files_one_note. The other two pass on main as they should: the positive controlan_unrooted_vault_keeps_the_owner_verbs_for_its_embedded_ownerandowner_verbs_require_active_owner_binding_when_rooted.Fix
embedded_owner_actor_id(), live, passes. Every other PERSON gets OWNER_BINDING_REQUIRED, with the advice to root the vault under its host key. Multi-root stays INVALID_STATE.explicit_claim_override_in_txn) and the critic's owner verdict kept their own copy of the predicate, with the same unrooted pass-through. They now callverify_owner_actor_binding_in_txn.verify_owner_write_actor_in_txn(authority/write_authorization.rs) checked the Human class only, and so passed any PERSON on an unrooted vault. It now also callsverify_owner_actor_binding_in_txn. Its callers: learning settings, preference-principal binds, the optimizer brief and job for a principal, inbox resolution as an actor, project depth, the subject model and its restore review, cloud account recovery, and machine-claim approval.AuthenticatedOwnershows a live PERSON, not that the PERSON owns this vault.record_proposal_outcome_for_rampanddemote_scope_to_propose(consent_graduation/doors.rs), and the selection law's Owner writer (channel_identity_selection/selection_rules.rs), revalidated for liveness only. They now takerevalidate_as_vault_owner_in_txn, whose body is unchanged.ensure_host_root_slipwrites the genesis, and the vault's posture is SelfHostLocal, the same write transaction binds the embedded owner ashuman, epoch 1, under the host root key (authority/host_actor.rs). A hosted root is the operator's key, never the owner's, and a relay refuses rooting. Neither binds anyone; there the owner binds from a device of their own. A hard-deleted owner is not brought back, so that vault stays rooted with no owner bound.oneiron servein dev mode with no auth secret stays loopback-only unless--allow-unauthenticated(crates/oneiron-server/src/commands.rs:618).Test fixtures
Tests that named an arbitrary PERSON as the owner of an unrooted vault relied on the pass-through, about 300 of them across the workspace. On main each of those PERSONs held the owner verbs, so each fixture now names the owner explicitly:
put_owner,session_owner_fixtureandensure_embedded_owner_actorin the memory, entity_doc, off_record, workspace_roster, recovery and napi tests).test_util::bind_test_owner, which roots the vault under the test host and binds the test's own owner, where the test needs a specific id (booking publication, connector keys, script runtime, share, tagging, outbound consent and others).bind_host_actor_for_testand the server'sbinding_oprebind the key one epoch on when a fixture names another actor, and are no-ops when it already holds that binding.unrooted_anchor_uses_canonical_human_owner_semanticsandunrooted_substrate_uses_canonical_human_owner_semanticstested the old unrooted rule; they now check that a Human PERSON who is not the owner is refused, then write as the embedded owner.bind_amendment_preference_principal_in_txn, the binding row's in-transaction door), and its brief is read throughoptimize_brief_bound_at. The public doors refuse it.slip_tests.rs,tests/machine_write.rs) now read them from the fold, since the root writes one more entry.owner_approval_and_machine_supersession_follow_signed_historyuses the owner the root bound in place of a hand-signed bind.Overlap with #1422
#1422 (not merged) edits three files this PR touches, on other lines:
authority/slip_vault.rs: world privacy P6b: per-world keys, a this-device-only keystore and the hosted-root posture stamp #1422 changesissuer.root_device()and the genesis-branchfold_authority_logcall inensure_host_root_slip_in_txn. This PR adds the owner bind afterHOST_ROOT_SLIP_CACHE.putin the same function, a doc line onensure_host_root_slip, and the test-only bind helpers.authority/mod.rs: world privacy P6b: per-world keys, a this-device-only keystore and the hosted-root posture stamp #1422 adds modules aftermod install_fold;. This PR addsmod host_actor;aftermod history_transfer;.oneiron-server/src/test_credentials.rs: world privacy P6b: per-world keys, a this-device-only keystore and the hosted-root posture stamp #1422 changes the head walk inbind_actor. This PR addsbinding_opabove it and uses it for the op.Production binds under the host key
A host key holds one live binding, so anything else bound under the root key after genesis would rebind it away from the owner. No production path does that. The only production
BindActorwriters are the owner bind here (authority/host_actor.rs) and machine enrollment (authority/machine_enroll.rs:107-117), which binds the machine's own fresh key (engine machines included). Agent provisioning (ensure_agent_principal) writes a PERSON row and no binding. Token bootstrap, pairing and serve-time root slips mint slips under the root key and bind no one. A HostedNode profile is a machine-role admission rule (authority/machine_profile.rs:199), not a bind. Re-root runsensure_host_root_slip_in_txnon a non-empty log, so it writes no genesis and no owner bind. Only the test fixtures rebind the host key.Follow-ups
actor_is_vault_owner_in_txn(memory/credential_key.rs:128) andowner_live_in(claim/scoped_read/admission.rs:346) both pass the embedded id outright. This is unchanged from main and is a read path, not an owner verb (Sol R1 F2, Astra R1 F3; logged by the Engine as a medium follow-up).policy_model::is_live_vault_owner_in_txnnames the embedded owner of a personal vault without asking the authority log, so after an actor rebind on a rooted vault it still names the former owner. That set backsrevalidate_as_vault_owner_in_txnand the F26 weave-correction owner exemption (claim/scoped_read/weave_correction.rs:80-97). Unify it with the authority binding (Astra R2 F3).AuthenticatedOwnerand revalidate it for liveness only, so a live PERSON's native proof passes them (consentapprove_onceand standing grants, owner reasons, widen acceptance, manifest and pack policy, imports, checkpoints, cleanup, project mint and goals, and others; Sol R3 F2, Astra R3 F2). Unchanged from main. This PR switches only the F24 doors; the tier flip (sec2/forged-authority-tier, stacked on security: owner proofs act only in the vault and tier that authenticated them (F18, H397, H224) #1458) closes the rest, since every one of them revalidates throughrevalidate_in_txn.FORBIDDEN, orBAD_REQUESTfrom the preference retract's own fold check), notINVALID_STATE(Sol R2 F3, Astra R2 F4; low). The same holds for a fold past its budget (security: bound authority-fold work, hold rows no owner signed, floor-check cosigners (H72, H71 residual) #1449,FoldBudgetExceeded) and for a storage error.as_actordocs.Pushbacks
legacy_evidence_and_other_principals_do_not_cross_the_miner_threshold, B's inbox refusal still stops at the owner check, not the decider check. A vault has one owner, so no second owner exists to reach the decider check.Reviews
Gate
GREEN on 8db67b5 (gce-3, 24G, 10 threads, 8 test threads; fleet job 1016-011215-66a2):
The gate before it, on 0bf2034, went red at clippy on an unused test binding (fixed in e818ef4). Two checks that main's #1458 added also failed, because their owner helper used an unbound PERSON (
connector_key::tests::foreign_owner_proof; 8db67b5 binds it).