Skip to content

I2135 — The trust root is read from the default branch, not from whatever the checkout holds

Let a working tree narrow the mesh's trust and never widen it: obey the working tree's declaration with every widening of the trunk's committed copy removed, report each ignored line, and refuse a committed declaration that trusts on first use.

DONE wave 0 · p0 · implementation profile · runs alone

Part of runtime-trust — A runtime is safe to reach from another machine, and joining the mesh trusts nobody by accident.

Objective

Let a working tree narrow the mesh's trust and never widen it: obey the working tree's declaration with every widening of the trunk's committed copy removed, report each ignored line, and refuse a committed declaration that trusts on first use.

Why

The server reads .ai/repo/mesh/ from the checkout's working tree once at start (apps/majordomus-cli/src/shared.rs:34-48,164-174). A branch, or an uncommitted edit, can add a key to trust.allow, add seeds or rendezvous.endpoints that make the runtime post its card and envelope to a host of the branch author's choosing, or set policy tofu, and that checkout's runtime obeys it (threat T12); peers judge by their own file, so the damage is local to that checkout, which is the one a reviewer runs a contributor's branch in. docs/MESH.md:365,382-399 and ADR 0050 rule 6 say the declaration is committed; ADR 0059 records this class of incident. No CI gate refuses a committed tofu declaration (enforcement table, 'no unknown remote auto-trust': unit tests only, apps/majordomus-cli/src/mesh/trust.rs:25-35, apps/majordomus-cli/src/mesh/config.rs:397). Baseline audit of 2026-10-09 at master 1fb8d6be44, mesh gap 10 and drift 12.

Current state

Delivered by 4816d7c8ad and 11472da40d: mesh::root::resolve narrows the working tree's declaration to the trunk's committed copy (the trunk is the local branch the repository names as its trunk; a stale local trunk is older trust, the safe direction), every reader asks it, mesh doctor names each ignored line, and scripts/ci/mesh-check refuses a committed tofu, which case 301 now drives.

Desired state

mesh::root::resolve holds the working tree's declaration against the trunk's committed copy: enabled only if both are, a policy no looser than the trunk's, keys, endpoints, seeds and networks only as the trunk lists them (loopback endpoints and seeds admitted); with no trunk copy, tofu is refused. Every reader of the declaration asks it. mesh doctor's trust-root check names every ignored line; mesh-check refuses a committed tofu. Reading only the trunk was rejected: it broke loopback-worktree discovery and every fixture that declares a mesh, for no security gain over narrowing.

Scope

  • apps/majordomus-cli/src/shared.rs
  • apps/majordomus-cli/src/mesh/config.rs
  • apps/majordomus-cli/src/mesh/doctor.rs
  • scripts/ci/mesh-check
  • apps/majordomus-cli/src/mesh/root.rs
  • apps/majordomus-cli/src/capability/builtin/mesh.rs
  • apps/majordomus-cli/tests/mesh.rs
  • apps/majordomus-cli/tests/mesh_trust_root.rs
  • test/cases
  • docs/MESH.md

Dependencies

None. This issue is a root of the graph.

Acceptance criteria

  • A working-tree edit that adds a key to trust.allow does not admit that key, and mesh doctor names the difference
  • A branch that adds a rendezvous endpoint does not make its runtime post to it until the change is on the default branch
  • A committed declaration with policy tofu fails scripts/ci/mesh-check

Validation

  • bin/majordomus plan validate
  • cargo test --test mesh
  • MJ_TEST_JOBS=4 bash test/run.sh 301_the_mesh_stays_one_subsystem 494_the_mesh_is_declared_and_held

Evidence required

  • working_tree_trust_edit_ignored_test
  • tofu_declaration_refused_case

Evidence

coverstypecommandresultat commit
working_tree_trust_edit_ignored_testcigh run view 38635619021 --json jobs (validate on master c0e3585dc8, push); job 116098148455 rust (3) runs tests/mesh_trust_root.rstest result: ok. 4 passed; 0 failed at master c0e3585dc8 (Rust tree identical to e8505a431d): a_working_tree_edit_that_widens_trust_is_not_obeyed (an uncommitted edit adding key B, policy tofu and endpoint 198.51.100.7 leaves allow=[A], deny_unknown, no endpoint, 3 narrowed lines, and mesh doctor's trust-root check fails naming B, 198.51.100.7 and tofu), a_branch_that_commits_a_widening_is_held_to_the_trunk (a branch commit adding a rendezvous endpoint is not posted to until the trunk lists it), trust_on_first_use_is_honoured_only_from_a_committed_copy, a_working_tree_that_narrows_trust_is_obeyed_as_written; delivered by 4816d7c8ad and 11472da40d (mesh::root::resolve, the trunk being the local branch the repository names as its trunk)c0e3585
tofu_declaration_refused_casetestMJ_TEST_JOBS=2 bash test/run.sh 301_the_mesh_stays_one_subsystem 494_the_mesh_is_declared_and_held 1023_a_branch_cannot_widen_the_mesh_trust3 passed on branch chore/the-trust-root-is-the-default-branch-is-done (master c0e3585dc8 + case 301 section 4): a committed .ai/repo/mesh/majordomus.yaml with trust.policy tofu makes scripts/ci/mesh-check exit 10 naming the file and the policy; the same declaration with deny_unknown passes; an untracked tofu is left to the runtime. Mutation: with the gate's tofu pattern disabled case 301 fails (expected exit 10, got 0). Case 1023 holds a branch's tofu, second key and hub out of forcec0e3585

Timeline

started
2026-10-15T01:28:05Z
verified
2026-10-15T01:28:17Z
completed
2026-10-15T01:28:23Z

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I2135.yaml. Read it back with majordomus plan show I2135.

Searches the titles and descriptions of every page this site publishes.