Summary
A node whose configured key is an actor gets a separate node key minted (CC 3.4.7.3 Clause A, working as designed). The owner-binding then cannot follow onto it — owner_of(node) never resolves — and from that point the node can never re-author its own consent rows:
RuntimeError: re-author consent ciris-node-bootstrap-<x> -> ciris-canonical-1-<y>:
refusing to emit a consent grant naming "ciris-node-bootstrap-<x>": this engine
signs as "ciris-agent-bootstrap-<z>", and a consent grant is self-attested
(CEG 1.0-RC29 §5.6.8.15)
Because the agent treats node-fails ⇒ agent-fails, the whole app stops starting. A user hit this in the field on 2026-09-01 (ciris-server 0.5.196): setup completed, then every subsequent launch died in ~9s.
The substrate names the remedy in its own warning:
WARN ciris_server::node_key: the configured key is an ACTOR, so it is not this node's
identity. Minted and registered a separate node key (CC 3.4.7.3 Clause A). The actor
key is UNCHANGED and keeps everything it authored. The node's owner-binding must be
re-issued onto the node key — see `plan_owner_binding_move`.
configured_key_id=ciris-agent-bootstrap-<z> configured_roles=["agent"]
node_key_id=ciris-node-bootstrap-<x>
WARN ciris_server::compose: the node key was minted but no owner signer is on disk, so
its owner-binding could not follow. `owner_of(node)` does not resolve
plan_owner_binding_move is not exposed in ciris_server 0.5.196's Python API. dir(ciris_server) offers provision_node_identity, node_identity, node_state, install_node, author_federation_consent, analyze_consent_stance — nothing to perform or schedule the binding move. So the caller is told what must happen and given no way to make it happen.
Reproduction (local, ~4 minutes, no OAuth or browser needed)
export CIRIS_HOME=$(mktemp -d)
python3 main.py --adapter api --mock-llm --port 8099
Observed on a clean home, ciris-server 0.5.196, agent 2.9.47:
[NODE-KEY] node identity provisioned: ciris-node-bootstrap-zv2osrj64p
Node fold: identity resolution — alias=ciris-agent-bootstrap
[CONSENT] trace consent ARMED — source=config/env role=community_trust target=canonical-community
consent-CEG: emitted directed traces-consent grant <uuid> → community
consent-CEG: promoted directed grant <uuid> to federation tier
Node fold: serve_with_python_adapter exited/failed: RuntimeError: re-author consent …
[FAIL] Start Adapters failed: node fold failed to start (node-fails ⇒ agent-fails)
The alias passed to serve_with_python_adapter is deliberately the engine's, as CIRISServer#380 requires — we verified the alternative: passing the provisioned node alias yields TWO FEDERATION IDENTITIES IN ONE NODE — refusing to start. So there is no alias choice that avoids this; both branches fail, differently.
Why this cannot be worked around at the agent tier
Ownership is the fabric's to produce (CEG §0.0); we can only surface it.
Ask
Either of:
- Perform the owner-binding move at mint time, when the substrate already knows both keys — it is the only party that can.
- Fail closed at mint instead of booting into a state that is fatal on the next start. The current behaviour is the worst of both: the first boot succeeds, setup writes a consent row, and the install is dead from then on. A refusal at mint time would be diagnosable immediately.
- Failing those, expose
plan_owner_binding_move so the caller can complete what the warning instructs.
(2) alone would have prevented the field failure entirely.
Impact
Any install where the configured key is an actor and setup completes. The agent has no way to detect it before setup, and the user cannot be told anything afterwards because the app will not start. Filed with agent-side receipts at CIRISAI/CIRISAgent#1130.
Summary
A node whose configured key is an actor gets a separate node key minted (CC 3.4.7.3 Clause A, working as designed). The owner-binding then cannot follow onto it —
owner_of(node)never resolves — and from that point the node can never re-author its own consent rows:Because the agent treats node-fails ⇒ agent-fails, the whole app stops starting. A user hit this in the field on 2026-09-01 (ciris-server 0.5.196): setup completed, then every subsequent launch died in ~9s.
The substrate names the remedy in its own warning:
plan_owner_binding_moveis not exposed inciris_server0.5.196's Python API.dir(ciris_server)offersprovision_node_identity,node_identity,node_state,install_node,author_federation_consent,analyze_consent_stance— nothing to perform or schedule the binding move. So the caller is told what must happen and given no way to make it happen.Reproduction (local, ~4 minutes, no OAuth or browser needed)
Observed on a clean home, ciris-server 0.5.196, agent 2.9.47:
The alias passed to
serve_with_python_adapteris deliberately the engine's, as CIRISServer#380 requires — we verified the alternative: passing the provisioned node alias yieldsTWO FEDERATION IDENTITIES IN ONE NODE — refusing to start. So there is no alias choice that avoids this; both branches fail, differently.Why this cannot be worked around at the agent tier
Ownership is the fabric's to produce (CEG §0.0); we can only surface it.
Ask
Either of:
plan_owner_binding_moveso the caller can complete what the warning instructs.(2) alone would have prevented the field failure entirely.
Impact
Any install where the configured key is an actor and setup completes. The agent has no way to detect it before setup, and the user cannot be told anything afterwards because the app will not start. Filed with agent-side receipts at CIRISAI/CIRISAgent#1130.