Skip to content
Cockpit0.29.0
A snapshot: read at commit 707a04c7ce8 on 2026-10-18T00:06:01Z by majordomus 0.29.0. Nothing on this page is read again. See it live

I2705

A node key can be rotated, peers follow the new key, and the old key is refused

Where it stands

devtask.issue
Readiness
ready no dependency and no gate holds it; nobody has started it
Status
READY
Can start
startable
Milestone
Milestone status
ACTIVE
Wave
1
Waiting on
none
Holds back
none
Behind it in all
0
Evidence
0 of 1
A move writes the repository: it stamps one field of this issue's record and appends one event to the ledger, and a commit will carry both.
The same moves from a terminal

majordomus plan start I2705

majordomus plan verify I2705

majordomus plan done I2705

What it is

Objective
Offer a node key rotation that peers which trusted the old key can follow to the new one, after which the old key's hello is refused, and purge a withdrawn key's events from the running journal without waiting for a restart.
Why
Split from I2134 on 2026-10-14. I2134 made a key withdrawn from trust.allow lose its links without a restart (Cooperation::retrust), and its desired_state said 'Not done here' of rotating a node key and of purging a withdrawn key's events from the running journal, while its acceptance criteria still required rotation, so it could never close. A compromised key can now be cut off live, but it cannot be replaced: there is no rotate flow (threat T11). Baseline audit of 2026-10-09 at master 1fb8d6be44, mesh gap 6 and the identity row.
Now
The node identity is created once and loaded from its key file (apps/majordomus-cli/src/mesh/identity.rs); nothing replaces it, and no message tells a peer that a key it trusts is succeeded by another. Cooperation::retrust (apps/majordomus-cli/src/mesh/cooperation.rs), called from the live reload (apps/majordomus-cli/src/live.rs) through capability::builtin::mesh::retrust, ends the links of keys no longer trusted; a withdrawn key's events stay in the running journal until the next restart's reload applies the trust in force (I2124). The key file is written at the umask's mode and chmodded to 0600 afterwards (apps/majordomus-cli/src/mesh/identity.rs); session prismatic-majordomus-6e is fixing exactly that on its own branch, and it is not this issue's work.
Wanted
A command rotates this node's key: the new identity is signed for by the old one, peers that trusted the old key accept the succession and link to the new key, and the old key's next hello is refused. A key withdrawn from the trust in force has its events dropped from the running journal at the reload that withdrew it. docs/MESH.md describes rotation and what a peer does on it.
Done when
unknown: the record declares no `completion`
Risk
unknown: the record declares no `risk`

Acceptance

  • After a rotation, peers that trusted the old key link to the new one, and the old key's next hello is refused
  • A key withdrawn from trust.allow on a running runtime has its events dropped from the running journal at the reload that withdrew it, with no restart
Validation
bin/majordomus plan validatecargo test --test mesh_cooperationcargo test --lib mesh::identity
Evidence required
key_rotation_test
Evidence present
unknown: the record carries no `evidence` entries

Scope

Touches
apps/majordomus-cli/src/mesh/identity.rsapps/majordomus-cli/src/mesh/trust.rsapps/majordomus-cli/src/mesh/cooperation.rsapps/majordomus-cli/src/mesh/journal.rsapps/majordomus-cli/src/capability/builtin/mesh.rsapps/majordomus-cli/tests/mesh_cooperation.rsdocs/MESH.md
Not
Ending a withdrawn key's links without a restart, which I2134 deliveredCreating the key file owner-only from its first byte, which session prismatic-majordomus-6e is fixing on its own branch under I2134The journal reload applying the trust in force, which is I2124's
Depends on
Priority
p0
Profile
implementation
Parallel safe
false
Owner
unknown: the record declares no `owner`

The work so far

Branches
none
Merged
none
Commits
0
Trunk
master
Sessions
none
Created
2026-10-14
Updated
2026-10-14
Started
unknown: the record declares no `started_at`
Verified
unknown: the record declares no `verified_at`
Completed
unknown: the record declares no `completed_at`

Synchronisation

Adapter
scripts/github-sync
Repository
unknown: the derived plan's header carries no repository
External issue
unknown: a live GitHub state; this executable makes no network call, so only `scripts/github-sync --check` can answer it
State there
unknown: a live GitHub state; this executable makes no network call, so only `scripts/github-sync --check` can answer it

Findings

LevelCodeMessageReproduce
WARNscope_conflictshares apps/majordomus-cli/src/mesh/journal.rs with I2706; they may not run concurrentlymajordomus plan validate
WARNscope_conflictshares apps/majordomus-cli/src/mesh/cooperation.rs with I2708; they may not run concurrentlymajordomus plan validate
WARNscope_conflictshares apps/majordomus-cli/src/mesh/identity.rs with I2709; they may not run concurrentlymajordomus plan validate