You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Attribution requires Rooted, no production agent can root, and the self-attribution hole that hid it is closed: the trace plane has been dark since 2026-09-18 #659
Attribution requires Rooted, no production agent can be Rooted, and the hole that hid it is now closed — the trace plane has been dark since 2026-09-18
Full RCA with the read-only evidence: CIRISAI/CIRISServer#632 (comment of 2026-09-23). The short form, and the ask.
What happened
SourceKeyId::from_rooted_binding admits an inbound frame's source only when the peer is Rooted ∧ owns_key. Unchanged since v19; correct as a trust statement.
No production agent's key roots at the accord anchor: every agent/node/owner chain terminates at a self-signed row, so persist's root_binding answers NotRootedAtSteward for all of them. Also correct.
For months the canonical held itself in its peers map as Rooted (a server-side boot-prime bug, CIRISServer#607). Link attribution's destination branch therefore resolved every otherwise-unattributable inbound link to the canonical's own key, which passed both conditions, and every unrooted peer's frames were admitted as the canonical's own (the responder then replied to itself: no route to peer: key_id=<own key>). That hole was the only path production agents ever had.
Attribution answers who sent this frame. Rooting answers what this peer may be served. The gate conflates them, and your own comments already draw the line ("routing ≠ trust", "served no trace:*").
Proposed rule — a frame is attributed to key K when:
the link's proven transport identity equals the transport identity in a hybrid-verified SignedTransportDestination for K (today's item 2), and
K's registered pubkey matched at cold start (owns_key, i.e. any rejection after the pubkey match, or Confirmed).
provenance (Rooted / Advisory) is carried on the attributed source and gates serving exactly as it does now; the trace:* serve gate stays Rooted-only. ResolvedToSelf stays a drop. Admission stays the trust boundary — persist hybrid-verifies every row against the directory under Strict and refuses an unregistered attester regardless of which link carried it, so attributing on the transport binding widens nothing at rest.
This makes the bootstrap carve-out the general case rather than an exception: a peer whose Key + TransportDestination crossed (both verified at admission) is thereby attributable; a peer that never proved control of its transport identity is not.
Three observability asks, from the same day
They each cost an inference step that the log should simply have stated:
the cold-start rooting rejection is logged only at debug — an operator never learns why a peer is Advisory (UnknownKeyId vs NotRootedAtSteward is the whole story here);
link_attribution_miss_log throttles per key, so after the first miss every further drop is silent (suppressed_prev=22 on a canonical that was dropping every frame);
The unthrottled DIAG#632 lines used for this RCA (attribution operands incl. item 2; every advisory admit with its rejection; every door decision with both identities) are on a throwaway worktree at v29.5.0; happy to send them as a PR if you want them as the permanent shape.
Attribution requires
Rooted, no production agent can beRooted, and the hole that hid it is now closed — the trace plane has been dark since 2026-09-18Full RCA with the read-only evidence: CIRISAI/CIRISServer#632 (comment of 2026-09-23). The short form, and the ask.
What happened
SourceKeyId::from_rooted_bindingadmits an inbound frame's source only when the peer isRooted ∧ owns_key. Unchanged since v19; correct as a trust statement.root_bindinganswersNotRootedAtStewardfor all of them. Also correct.Rooted(a server-side boot-prime bug, CIRISServer#607). Link attribution's destination branch therefore resolved every otherwise-unattributable inbound link to the canonical's own key, which passed both conditions, and every unrooted peer's frames were admitted as the canonical's own (the responder then replied to itself:no route to peer: key_id=<own key>). That hole was the only path production agents ever had.862b0a8here (Branch-B link attribution can resolve an inbound link to the LOCAL node's own key when the peers map holds a self-entry — the responder then replies to itself; refuse self and name it #621/fix(621): inbound attribution never resolves to this node's own key; no responder is ever built for ourselves #623, v29.1) addedResolvedToSelf → drop. Both right. Since 22:41Z on 09-18, zero non-bootstrap rows from any agent have landed on the canonical (keys admitted per day vs rows landed: 09-21 10/0, 09-22 12/0, 09-23 35/0).Rooted;heal_or_report_attribution_misscorrectly refuses the peer's ownrootedSignedTransportDestination(StoreClaimUnrooted); the v25.3.0+ regression: the #624 bootstrap equality drops third-party records and the canonical's own record — the link never attributes, every non-bootstrap frame on it is dropped, chat ladder bound=0 on v26.0.0 #636 bootstrap door only runs for links with no candidate key, and an announced peer always has one (decision=not_applicable, verified with an unthrottled diagnostic build on a production-faithful harness:resolved=(Advisory, owns_key=true, 0),item2_binding_exists=false).The ask: separate attribution from rooting
Attribution answers who sent this frame. Rooting answers what this peer may be served. The gate conflates them, and your own comments already draw the line ("routing ≠ trust", "served no
trace:*").Proposed rule — a frame is attributed to key
Kwhen:SignedTransportDestinationforK(today's item 2), andK's registered pubkey matched at cold start (owns_key, i.e. any rejection after the pubkey match, orConfirmed).provenance(Rooted/Advisory) is carried on the attributed source and gates serving exactly as it does now; thetrace:*serve gate staysRooted-only.ResolvedToSelfstays a drop. Admission stays the trust boundary — persist hybrid-verifies every row against the directory underStrictand refuses an unregistered attester regardless of which link carried it, so attributing on the transport binding widens nothing at rest.This makes the bootstrap carve-out the general case rather than an exception: a peer whose Key + TransportDestination crossed (both verified at admission) is thereby attributable; a peer that never proved control of its transport identity is not.
Three observability asks, from the same day
They each cost an inference step that the log should simply have stated:
debug— an operator never learns why a peer is Advisory (UnknownKeyIdvsNotRootedAtStewardis the whole story here);link_attribution_miss_logthrottles per key, so after the first miss every further drop is silent (suppressed_prev=22on a canonical that was dropping every frame);(Advisory, owns_key=true)hint says "a churn downgrade (owner reroute overwrote a Rooted binding)" — for a peer that was never Rooted (stored_provenance=None), which sent the first read of feat(25.4.0): adopt CIRISPersist v44.8.0 — the consent scope grammar; the transfer grant's principle is pinned to propagate #632 the wrong way.The unthrottled
DIAG#632lines used for this RCA (attribution operands incl. item 2; every advisory admit with its rejection; every door decision with both identities) are on a throwaway worktree at v29.5.0; happy to send them as a PR if you want them as the permanent shape.Refs: CIRISServer#632 (RCA), CIRISServer#607, #621/#623, #636, #393.