ciris-server 0.5.203, exec'd node-only boot on macOS, CIRISAgent run #34228782947, live-qa-macos-ios → logs/ciris-macos/ciris-server.log.2026-09-08 and .boot.
Our gate logs in on :4243 and POSTs /v1/federation/announce (owner session). The node's log says the announce succeeded:
13:12:26 graph_config: wrote config entry key="net.announce_ownership" version=1
13:12:26 claim_remote: announce-self: owner-binding promoted to FEDERATION + net.announce_ownership=true (Reticulum identity announce takes effect on next boot)
13:12:26 auth::ownership: announce bundle row role="owner_key" … federation_visible=true
13:12:26 auth::ownership: announce bundle row role="node_key" … federation_visible=true
13:12:26 auth::ownership: announce bundle row role="owner_binding" … attestation_id="0200be1d-…"
13:12:27 node_control: SIGTERM broker installed
13:12:28 compose: resolved initial config:* snapshot …
13:12:28 compose: node already has a ROOT owner — no first-run claim PIN minted
13:12:28 compose: net.announce_ownership=true — owner binding promoted to federation scope; federation-identity-discoverable
and ciris-server.log.boot carries a boot marker at 13:12:27 — one second after the announce wrote its rows. The caller never received the response: httpx reported a bare ReadError on the POST. On Windows, Android and iOS in the same run the identical POST returned the bundle (ok -- 3/3 rows federation-visible); on macOS in run #34181104589 the same shape appeared as RemoteProtocolError: Server disconnected without sending a response.
So the sequence reads as: announce-self applies net.announce_ownership=true → the node re-composes ("takes effect on next boot", and the boot is immediate) → the in-flight HTTP response is lost in the re-compose. The write is durable and the re-composed node reports the promoted binding, so the state is right; only the response is dropped, and a client that takes a dropped response as failure (ours did, until today) reports a discoverable node as NOT discoverable.
Two questions rather than a prescription: is the immediate re-compose intended on this path, and if so should the response be flushed before it — or is a dropped response on announce-self the contract, in which case we will keep the client-side idempotent retry we are adding today and say so in our check. Either answer is fine; today neither is documented, and the difference between "announce failed" and "announce succeeded and the node restarted" is the difference between a P0 and a nit for anyone reading the gate.
ciris-server 0.5.203, exec'd node-only boot on macOS, CIRISAgent run #34228782947,
live-qa-macos-ios→logs/ciris-macos/ciris-server.log.2026-09-08and.boot.Our gate logs in on
:4243and POSTs/v1/federation/announce(owner session). The node's log says the announce succeeded:and
ciris-server.log.bootcarries a boot marker at 13:12:27 — one second after the announce wrote its rows. The caller never received the response: httpx reported a bareReadErroron the POST. On Windows, Android and iOS in the same run the identical POST returned the bundle (ok -- 3/3 rows federation-visible); on macOS in run #34181104589 the same shape appeared asRemoteProtocolError: Server disconnected without sending a response.So the sequence reads as: announce-self applies
net.announce_ownership=true→ the node re-composes ("takes effect on next boot", and the boot is immediate) → the in-flight HTTP response is lost in the re-compose. The write is durable and the re-composed node reports the promoted binding, so the state is right; only the response is dropped, and a client that takes a dropped response as failure (ours did, until today) reports a discoverable node as NOT discoverable.Two questions rather than a prescription: is the immediate re-compose intended on this path, and if so should the response be flushed before it — or is a dropped response on announce-self the contract, in which case we will keep the client-side idempotent retry we are adding today and say so in our check. Either answer is fine; today neither is documented, and the difference between "announce failed" and "announce succeeded and the node restarted" is the difference between a P0 and a nit for anyone reading the gate.