InternalsPackages

daemon-ably

daemon-ably

daemon-ably is the daemon-managed Ably transport sidecar used by both Falco (egress) and Nagato (ingress).

It centralizes:

  • Ably connectivity and reconnect behavior
  • audience-scoped broker token usage (daemon_falco, daemon_nagato)
  • local IPC transport for sidecars on ~/.unbound/ably.sock
  • message delivery for Falco/Nagato (presence heartbeats now use a DO stream)

Core Purpose

One local Ably transport, shared by all daemon sidecars.

Falco and Nagato no longer create their own Ably SDK clients. They use daemon-ably-client over a Unix socket while daemon-ably owns realtime sessions and subscription restore behavior.

Architecture

┌──────────────────────────────────────────────────────────────────────┐
│                         unbound-daemon                               │
│                                                                      │
│  starts token broker (~/.unbound/ably-auth.sock)                    │
│  starts daemon-ably (~/.unbound/ably.sock)                           │
└──────────────────────────────────────────────────────────────────────┘

                │ local IPC (`UNBOUND_ABLY_SOCKET`)

┌──────────────────────────────────────────────────────────────────────┐
│                           daemon-ably                                │
│                                                                      │
│  Falco client (publish)                  Nagato client (subscribe/ack) │
│  audience: daemon_falco                   audience: daemon_nagato    │
│                                                                      │
│  IPC ops: publish.v1, publish.ack.v1, subscribe.v1, message.v1      │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

                │ Ably Realtime

┌──────────────────────────────────────────────────────────────────────┐
│                               Ably                                   │
└──────────────────────────────────────────────────────────────────────┘

Heartbeat Contract (Legacy Ably)

daemon-ably publishes daemon availability as a message stream (not native Ably Presence API).

FieldValue
Channelpresence:{user_id}
Eventdaemon.presence.v1
Sourcedaemon-ably
Status valuesonline, offline
BehaviorPublish immediate online, then periodic online; best-effort offline on graceful shutdown

Payload schema:

{
  "schema_version": 1,
  "user_id": "user-uuid",
  "device_id": "device-uuid",
  "status": "online",
  "source": "daemon-ably",
  "sent_at_ms": 1739030400000
}

Durable Object Presence Contract (Target)

Presence heartbeats are migrating to a Cloudflare Durable Object stream that preserves the same online/offline semantics used by iOS gating.

{
  "schema_version": 1,
  "user_id": "user-uuid-lowercase",
  "device_id": "device-uuid-lowercase",
  "status": "online|offline",
  "source": "daemon-do",
  "sent_at_ms": 1739030400000,
  "seq": 42,
  "ttl_ms": 12000
}

Local IPC Protocol (NDJSON)

All messages are newline-delimited JSON frames over Unix domain socket.

Requests

opPurpose
publish.v1Publish using Falco transport client
publish.ack.v1Publish using Nagato transport client (ACK path)
subscribe.v1Register channel/event subscription

Responses / Push

opPurpose
publish.ack.v1Acknowledges publish.v1 and publish.ack.v1 requests
subscribe.ack.v1Acknowledges subscribe.v1 requests
message.v1Server push for subscribed Ably messages

Example Frames

Publish request:

{
  "op": "publish.v1",
  "request_id": "uuid",
  "channel": "session:123:conversation",
  "event": "conversation.message.v1",
  "payload_b64": "eyJzY2hlbWFfdmVyc2lvbiI6MX0=",
  "timeout_ms": 5000
}

Subscription request:

{
  "op": "subscribe.v1",
  "request_id": "uuid",
  "subscription_id": "nagato",
  "channel": "remote:device-uuid:commands",
  "event": "remote.command.v1"
}

Inbound push frame:

{
  "op": "message.v1",
  "subscription_id": "nagato",
  "message_id": "ably-msg-id",
  "channel": "remote:device-uuid:commands",
  "event": "remote.command.v1",
  "payload_b64": "AAEC",
  "received_at_ms": 1739030400000
}

Configuration

VariableDefaultDescription
UNBOUND_ABLY_SOCKET~/.unbound/ably.sockLocal IPC socket path
UNBOUND_ABLY_BROKER_SOCKET(required)Broker socket path from daemon (~/.unbound/ably-auth.sock)
UNBOUND_ABLY_BROKER_TOKEN_FALCO(required)Audience token used by Falco publish client
UNBOUND_ABLY_BROKER_TOKEN_NAGATO(required)Audience token used by Nagato subscribe/ack client
DAEMON_ABLY_MAX_FRAME_BYTES2097152Maximum NDJSON frame size accepted on IPC socket
DAEMON_ABLY_HEARTBEAT_INTERVAL5Heartbeat interval in seconds
DAEMON_ABLY_PUBLISH_TIMEOUT5Publish/subscribe timeout in seconds
DAEMON_ABLY_SHUTDOWN_TIMEOUT2Graceful shutdown timeout in seconds
UNBOUND_PRESENCE_DO_HEARTBEAT_URL(required)DO presence heartbeat ingest endpoint
UNBOUND_PRESENCE_DO_TOKEN(optional)Bearer token for DO heartbeat ingest
UNBOUND_PRESENCE_DO_TTL_MS12000TTL used by DO payloads for offline gating
UNBOUND_BASE_DIR$HOME/.unboundBase dir for default socket path resolution

CLI flags:

  • --device-id (required)
  • --user-id (required)
  • --debug (optional)

Package Structure

packages/daemon-ably/
├── cmd/daemon-ably/main.go  # Process entrypoint
├── config/config.go         # Env/flag config and validation
├── runtime/broker.go        # Ably auth callback via broker socket
├── runtime/runtime.go       # Ably manager + heartbeat + subscriptions
├── runtime/server.go        # NDJSON IPC server
├── go.mod
├── go.sum
└── README.md

Regression Matrix

ScenarioExpected Result
Falco publish through publish.v1Side-effects are acknowledged and egress reaches Ably
Nagato subscribe through subscribe.v1message.v1 frames are delivered for remote.command.v1
ACK publish through publish.ack.v1remote.command.ack.v1 publishes succeed via Nagato audience
Ably reconnect while process stays alivedaemon-ably reconnects and restores active subscriptions
malformed NDJSON framerequest is rejected, connection remains usable
oversized NDJSON frameconnection closes and logs max-frame violation
graceful shutdownsidecar attempts offline heartbeat and removes ably.sock
daemon-ably