# InfiniBot Federation — Use Cases & Upgrade Tiers

> **Audience:** An engineer who has already read `docs/federation.md`, `FEDERATION_SECURITY_README.md`,
> `SATELLITE_MESH.md`, `src/federation/CAPABILITY_ROUTING.md`, and
> `docs/research/federation-satellite-audit.md`. That material covers the wire protocol, security
> model, peer-mesh topology, and satellite data-source gaps. This document does not repeat it —
> it references those docs where relevant and focuses on value, use cases, and what the system
> could become.

---

## 1. What the federation actually is today

### Topology

```
                    ┌─────────────────────────────────────────────────┐
                    │              MASTER GATEWAY                      │
                    │  FederationHub (port 47913/federation)           │
                    │  ┌──────────┐ ┌─────────────┐ ┌─────────────┐  │
                    │  │CapRouter │ │ LoadBalancer│ │FailoverMgr  │  │
                    │  └──────────┘ └─────────────┘ └─────────────┘  │
                    │  ┌──────────┐ ┌─────────────┐ ┌─────────────┐  │
                    │  │MemSync   │ │ IdentitySync│ │ DeliveryMgr │  │
                    │  └──────────┘ └─────────────┘ └─────────────┘  │
                    └────────┬───────────────┬───────────────┬────────┘
                             │ ws            │ ws            │ ws
                     ┌───────▼─────┐ ┌──────▼──────┐ ┌─────▼───────┐
                     │ SATELLITE A │ │ SATELLITE B │ │ SATELLITE C │
                     │ (desktop/  │ │ (home       │ │ (mobile /   │
                     │  GPU box)  │ │  server)    │ │  laptop)    │
                     └──────┬──────┘ └──────┬──────┘ └─────────────┘
                            │  P2P (port 47914)
                            └──────────────────
                             peer-mesh direct
                             (hub used as fallback)
```

mDNS auto-discovery (`discovery.ts`, `@homebridge/ciao`) lets satellites find the master on the
LAN without manual URL entry. For cross-network setups (Tailscale, WAN), the `masterUrl` is
configured explicitly in `gateway.federation.masterUrl`.

### Capabilities in the wire protocol today

- **Remote session spawn/send** — `session.spawn` / `session.send` messages routed from master to
  any connected satellite. Idempotency via `messageId` prevents double-fire on retry
  (`protocol.ts`:`buildRegisterAckMessage`, `delivery-manager.ts`:`GUARANTEED_MESSAGE_TYPES`).

- **Generic RPC proxy** — `federation.node.invoke` proxies any method registered on a satellite's
  gateway (`hub.ts`). Powers cross-device PTYs: a terminal created with `nodeId: "satellite-A"`
  actually spawns the PTY on that satellite; keystrokes and output stream through the federation
  websocket. See `docs/federation.md` for the full list of proxied methods.

- **Event broadcast reverse channel** — satellites forward `terminal.output`, `chat`, and `agent`
  lifecycle events upstream with a `federationNodeId` tag injected (`hub.ts`:`buildFederationEventMessage`).
  Other events (presence, health ticks) stay local to avoid wire noise.

- **Capability-based auto-routing** — spawns declare `requiredCapabilities` (hard filter) and
  `preferredCapabilities` (scoring bonus). The capability router scores nodes using a weighted
  formula: base 50 + 30/requirement + load penalty 0–40 + VRAM bonus. See
  `src/federation/CAPABILITY_ROUTING.md` for the full scoring breakdown.

- **Weighted load balancing** — `load-balancer.ts` scores nodes at weights: CPU 0.30, memory 0.25,
  GPU 0.20, active sessions 0.15, pending queue 0.10. Overload threshold default 80%, stale
  metrics window 60 s.

- **Hardware telemetry** — `hardware-collector.ts` emits a `HardwareSnapshot` (CPU%, per-core,
  load avg, RAM, GPU VRAM usage, disk mounts, network throughput, top processes). Satellites push
  snapshots when they meaningfully change (`snapshotMeaningfullyChanged`). The master aggregates
  these for the hardware fleet view.

- **Identity sync** — master pushes `SOUL.md`, `USER.md`, `AGENTS.md`, `IDENTITY.md`, `MEMORY.md`,
  `TOOLS.md`, `HEARTBEAT.md`, gateway password, API keys, and selected `sharedConfig` blocks
  (Notion DBs, provider keys, MCP wiring) to all satellites at connect time
  (`identity-sync.ts`:`IDENTITY_FILES`, `IdentitySyncPayload.sharedConfig`).

- **Bidirectional memory sync** — `memory-sync.ts` propagates `MEMORY.md` changes in both
  directions using last-write-wins with vector clocks for concurrent updates; append-only sections
  use operational transform; unresolvable conflicts get `<<<<<<<`/`>>>>>>>` markers for manual
  resolution. Broadcast path: `MemoryBroadcastMessage` sent to all satellites after each merge.

- **On-demand transcript sync** — `transcript-sync.ts` allows any node to request the message
  history of a session owned by a different node. Vector-clock-stamped `SessionHistoryMessage`
  records are stored in a per-node SQLite via `session-sync.ts`:`SessionHistoryStore`.

- **Peer-to-peer satellite mesh** — `peer-mesh.ts` lets satellites connect directly on port 47914,
  bypassing hub for latency-sensitive paths. Hub is used for discovery and as fallback. Documented
  fully in `SATELLITE_MESH.md`.

- **Reliability layer** — three-tier: `retry-manager.ts` (exponential backoff, alternate-node
  selection on failure), `failover-manager.ts` (re-spawns sessions tracked on a dead node onto an
  alternative), `dead-letter-queue.ts` (captures messages that exhausted retries for inspection and
  manual replay). `delivery-manager.ts` adds ACK-based guaranteed delivery with deduplication
  (cache up to 1 000 message IDs per sender). See `FEDERATION_RETRY_TESTING.md` for retry
  semantics.

- **Security** — RSA-2048 key exchange at handshake, AES-256-CBC payload encryption, per-satellite
  token with `full` / `spawn-only` / `read-only` permission levels, operation-level rate limiting,
  append-only JSONL audit log with checksum chain. Covered fully in `FEDERATION_SECURITY_README.md`.

- **mDNS discovery** — `discovery.ts` advertises and scans for `_infinibot-federation._tcp` TXT
  records. Satellite can set `autoDiscover: true` and `continuousDiscovery: true` to re-evaluate
  masters as they appear. Covered in `docs/federation/satellite-setup.md`.

- **Federated resource aggregation** — `federation-resources.ts` handlers fan out `kanban.list`,
  `agents.list`, `mcp.list`, `businesses.list`, `directories.list` to all connected nodes and
  merge with `sourceNode` + `nodeName` tags. What the activity feed, device pickers, and directory
  choosers display.

- **CRDT mesh state** — `mesh-state.ts` uses `LWWMap` (from `crdt.ts`, LWW-register backed) for
  agent registry and inter-agent messaging across nodes. Enables the orchestrator chains
  (parent/child `sessionKey` trees) to be visible across the mesh.

- **Session migration (experimental)** — `session-migration.ts` orchestrates a multi-step
  serialize → transfer → restore → verify pipeline (`MigrationStep` enum). Wired into
  `getMigrationManager()`. This is infrastructure-level scaffolding; end-to-end promotion to
  production is a medium-tier upgrade (see §4.2).

### What the wire protocol does NOT give you today

- **Cross-node atomic transactions.** There is no two-phase commit or consensus protocol. The
  vector clock model is eventually consistent; conflicting concurrent writes to the same resource
  resolve via LWW tiebreaker, not coordination. If you need "either both nodes commit or neither
  does," federation does not provide it.

- **Vault / secret replication.** `identity-sync.ts` does push API keys and the gateway password,
  but there is no secret rotation protocol, no per-secret access policy, and no audit trail
  scoped to secret reads. The `FEDERATION_SECURITY_README.md` flags this as a future enhancement.

- **Live workload migration.** The plumbing in `session-migration.ts` exists but is not wired into
  automatic triggers. A running coder agent cannot be handed to another node mid-task through
  production-ready tooling today (see §4.2).

- **Multi-tenant (user-level) identity isolation.** The permission model in `security.ts` is
  per-satellite-token, not per-human-user. There is no user directory, no per-user workspace
  boundary, and no cross-user audit separation. The current model suits a single operator running
  multiple devices; it does not suit multiple unrelated users sharing a hub (see §4.3).

- **Federated MCP server auto-mount.** `mcp-proxy.ts` lets you invoke an MCP server on a remote
  node on demand, but a satellite does not automatically see or mount the master's registered MCP
  servers as local tools. Discovery is manual.

---

## 2. Concrete benefits — why this design is worth the complexity

- **GPU-compute decoupling without a cloud.** Without federation, a laptop running the UI cannot
  use a desktop GPU for Ollama inference or ComfyUI image generation. The bottleneck is that
  capability detection and routing are local. With federation, `compute-manifest.ts` detects NVIDIA
  via `nvidia-smi` or AMD via `rocm-smi`, reports it in `NodeCapabilities`, and the capability
  router (`capability-router.ts`) scores that node higher for GPU-tagged spawns. The laptop's UI
  issues a `session.spawn` with `requiredCapabilities: ["gpu"]`; the hub routes it to the right
  machine transparently.

- **Always-on hub, ephemeral satellites.** A home server running as master keeps channels (Telegram,
  iMessage), cron workflows, and the kanban live even when all laptops are off. When a satellite
  reconnects, `identity-sync.ts` brings it up to date (SOUL.md, API keys, shared config) and
  `memory-sync.ts` resolves any MEMORY.md divergence. Without federation, every device is its own
  island — you'd need to manually copy config and memory files.

- **Workload isolation without siloing data.** Sessions spawned on satellite A are visible from
  master's activity feed because `event.broadcast` forwards `agent` lifecycle events upstream with
  `federationNodeId` injected. The `federation-resources.ts` aggregator merges tasks and projects
  from all nodes into a single view. The bottleneck without federation is that you'd need separate
  UI windows per machine, each with their own context.

- **Resilience under satellite dropout.** The `failover-manager.ts` re-spawns tracked sessions on
  an alternative node when a satellite disconnects. `retry-manager.ts` selects alternate nodes on
  spawn failure. `dead-letter-queue.ts` captures anything that exhausted retries for inspection.
  Without this stack, any satellite dropout silently kills its in-flight agents.

- **Unified identity across heterogeneous hardware.** The same SOUL.md, AGENTS.md, and gateway
  password live on every node automatically after the initial handshake. An agent spawned on a
  budget ARM box behaves identically to one spawned on the flagship desktop because the personality
  and tool configuration are pushed by `identity-sync.ts`. Without federation, each box has its own
  diverging config.

- **P2P latency optimization at no protocol cost.** The peer-mesh layer (`peer-mesh.ts`, port 47914)
  allows satellites that are directly reachable to skip the hub entirely for session messages, cutting
  one network hop and one WebSocket relay. Fallback to hub relay is automatic when the P2P path
  fails. The hub never becomes a single-point-of-performance-bottleneck for inter-satellite
  traffic.

---

## 3. Use cases — TODAY (works on current code)

### 3.1 Heavy GPU workstation + thin laptop

**Who:** Solo developer or indie creator. Owns a desktop with an RTX GPU (running Ollama, ComfyUI,
stable-diffusion tooling) and a MacBook as their daily driver.

**Workflow:** Laptop is configured as master (always on when home) or connects to the desktop as a
satellite. The operator spawns a session with `requiredCapabilities: ["gpu", "ollama"]` from the
laptop's UI. `capability-router.ts` scores the desktop at 184+ points against the laptop's ~50
(no GPU), routes the spawn to the desktop. Outputs stream back via `event.broadcast` and appear in
the laptop's activity feed with a node badge.

**Federation primitives used:** `session.spawn` with capability requirements, `capability-router.ts`
scoring, `hardware-collector.ts` VRAM detection, `event.broadcast` for streaming output.

**Win vs. single-box:** The laptop never needs Ollama or 16 GB of GPU VRAM. Every heavy model call
routes to the box that has them. When the desktop is off, the laptop falls back to routing via the
API — no config change needed.

---

### 3.2 Always-on hub, ephemeral travel satellite

**Who:** Developer who has a home server (Raspberry Pi, NUC, or headless desktop) and wants their
agent environment to persist 24/7 regardless of what laptop they're carrying.

**Workflow:** Home server is master. Cron workflows (scheduled via the gateway's cron system),
always-on Telegram/Discord channels, and the kanban live on the home server. When the developer
opens their laptop (satellite mode, `autoDiscover: true`), the satellite reconnects via mDNS on
the home LAN (or via Tailscale IP when travelling), `identity-sync.ts` pushes the latest SOUL.md
and shared config, `memory-sync.ts` reconciles any MEMORY.md edits made offline. The developer's
UI immediately shows all running sessions on the home server via `event.broadcast`.

**Federation primitives used:** mDNS auto-discovery (`discovery.ts`), identity sync, memory sync,
`event.broadcast` forwarding, federated resource aggregation in `federation-resources.ts`.

**Win vs. single-box:** Channels and cron jobs don't stop when the laptop lid closes. The laptop is
stateless — you could nuke it, re-install InfiniBot, point it at the home master, and get back to
full context in seconds.

---

### 3.3 Pair of developers with shared kanban and agent mesh

**Who:** Two developers collaborating on a project. Each has their own machine. One volunteers their
desktop as master; the other connects as a satellite.

**Workflow:** The master's `federation-resources.ts` aggregates both nodes' kanban tasks and
projects. Agents spawned on either machine appear in the shared activity feed. They use
`mesh-state.ts` orchestration chains to coordinate multi-agent workflows: dev A's orchestrator
spawns a coder agent on dev B's machine (`session.spawn` with `nodeId: "dev-b"`), dev B's terminal
events stream back to dev A's activity feed.

**Federation primitives used:** `federation-resources.ts` (shared kanban/projects), `mesh-state.ts`
(parent/child agent trees), `session.spawn` cross-node, `event.broadcast` reverse channel.

**Win vs. single-box:** No shared service to set up (no shared database, no VPN with port
forwarding). The hub is on one of their machines; the satellite just dials in. The project state
is aggregated without replication — each machine's SQLite is the source of truth for its own rows,
the aggregator merges them at query time.

---

### 3.4 Single-developer offloading coder-agent spawns to a spare PC

**Who:** Developer with one main workstation and an older PC sitting idle.

**Workflow:** Spare PC is configured as satellite with `spawn-only` permission token
(`security.ts`:`DEFAULT_PERMISSIONS.spawnOnly`). When the developer's orchestrator needs to
parallelize work (four coder agents simultaneously), the hub uses `load-balancer.ts` to split
spawns: two go to the main machine, two go to the spare PC. The spare PC's sessions report back
via the event channel.

**Federation primitives used:** `security.ts` `spawn-only` permission token, `load-balancer.ts`
overload detection, `retry-manager.ts` alternate-node selection.

**Win vs. single-box:** No additional API cost (both machines use the same API key pushed by
`identity-sync.ts`). The spare PC's CPU and RAM absorb the parallelism that would otherwise queue
on the main machine. When the spare PC is off, retries route all spawns back to the main machine
automatically.

---

### 3.5 Mobile device as a thin satellite for voice-in / work-happens-on-workstation

**Who:** Developer using the InfiniBot mobile gateway (or a lightweight Raspberry Pi Zero) as a
voice interface.

**Workflow:** Mobile device runs a satellite with `hasVoice: true` in its capabilities. The user
speaks a task; the voice pipeline on the mobile node transcribes it and issues a
`session.spawn` to the master. The master's capability router routes the heavy LLM work to the
best-equipped node in the mesh. The mobile device shows a live feed of the session via
`event.broadcast`. Voice audio routing is already handled: `satellite.ts:959-1041` auto-wires
`livekitUrl`, `kokoroUrl`, `speachesUrl` to the master's host on connect, so the mobile device's
voice streams go to the master's LiveKit server without configuration.

**Federation primitives used:** `hasVoice` capability flag, auto-wiring of voice URLs in
`satellite.ts`, `session.spawn` with capability routing, `event.broadcast`.

**Win vs. single-box:** The mobile device never needs to run a local LLM. Its only job is
capturing and playing audio. The entire inference stack runs on the workstation.

---

### 3.6 Scheduled cron workflows running on hub, observed from anywhere

**Who:** Any operator who wants persistent automation (daily digests, scheduled research, timed
kanban reviews).

**Workflow:** Cron entries live on the master. They fire on schedule regardless of which satellite
is connected. The operator observes running scheduled sessions from any satellite's UI via
`event.broadcast`. If a satellite is offline during a cron fire, the master executes the workflow
locally; the satellite picks up the session state when it reconnects via `transcript-sync.ts`
on-demand pull.

**Federation primitives used:** Master-local cron execution, `event.broadcast` for visibility,
`transcript-sync.ts` for post-hoc history retrieval.

**Win vs. single-box:** Cron is decoupled from the device the developer happens to be using. No
laptop needs to stay awake for scheduled automation to run.

---

## 4. Upgrade tiers — what could this become

### 4.1 Small upgrades (days, additive, low risk)

#### 4.1.1 Per-resource node label on every data surface

**Added capability:** Every kanban row, note, client entry, and agent card shows which federation
node owns it.

**Unlocks:** At a glance, the operator knows whether a task lives on the home server or the
laptop without clicking into it. In a pair-dev setup, each person can see whose machine owns
each record.

**Implementation surface:** `federation-resources.ts` already injects `sourceNode` and `nodeName`
on project and agent records at aggregation time. The gap is in the UI components for kanban,
notes, and the CRM — add a small `<federation-chip>` tag component (note: `federation-chip.ts`
exists in `ui/src/ui/components/` as of the current branch; extend it to carry `nodeName` and
surface it in list items). On the backend side, the kanban handler in
`src/gateway/server-methods/databases.ts` would need a satellite-proxy switch (already scoped
as P0 in `docs/research/federation-satellite-audit.md`).

**Risk / cost:** Purely additive. No schema changes. Risk is UI visual clutter if
labels are not styled subtly.

---

#### 4.1.2 Federation-aware notification routing

**Added capability:** Push notifications route to the device where the user is currently active,
not to all nodes.

**Unlocks:** When the developer is on the laptop, mobile pings don't also fire on the home server.
When they switch to mobile, notifications follow. Reduces noise significantly in multi-device
setups.

**Implementation surface:** The master already tracks `lastHeartbeat` and `activeSessions` per
node in `hub.ts`:`ConnectedNode`. Add a `lastUIActivity` timestamp field updated when a node
receives a UI event (easy hook point: any `state.sync` or `session.send` from a UI client updates
it). Notification dispatch logic (wherever push notifications are sent) checks which node has the
most recent `lastUIActivity` and routes there via `federation.node.invoke`.

**Risk / cost:** Depends on which notification backend is in use. Core federation changes are
minimal; the routing shim is a handful of lines. Risk: timestamp clock skew between nodes could
cause routing flaps — add a minimum hysteresis window (e.g., 30 s).

---

#### 4.1.3 Health badges on every long-running surface

**Added capability:** Hardware-page fleet-view style health indicators appear on every card that
represents a remote session or device.

**Unlocks:** The operator can see at a glance if the GPU node is 90% CPU-loaded before spawning
another heavy task on it.

**Implementation surface:** `hardware-collector.ts` already pushes `HardwareSnapshot` to the
master on meaningful change. `federation-dashboard.ts` and `federation-control-center.ts` already
render fleet health. The work is exposing the per-node metrics via a lightweight API (e.g., extend
`federation.nodes.list` to include the latest snapshot) and threading a `NodeHealthBadge` component
through the activity page's running-agent cards and the terminal picker's node rows.

**Risk / cost:** No backend changes to the federation core. UI-only work. Risk is performance
if health badges trigger re-renders on every hardware tick — debounce at 15 s to match the load
balancer's `metricsIntervalMs` default.

---

#### 4.1.4 Saved "federation contexts" — one-click default-node swap

**Added capability:** Named presets (e.g., "GPU session", "home server cron", "local-only") that
set the default `nodeId` and capability requirements for all new spawns.

**Unlocks:** Power users who routinely switch between "do this on the GPU box" and "do this
locally" can do so without re-entering `requiredCapabilities` on every spawn. Especially useful
in the setup where the developer alternates between local development work and heavy AI generation.

**Implementation surface:** A small `FederationContext` record in the gateway config (or a new
`federation.contexts.*` RPC group). The `sessions_spawn` tool already accepts `requiredCapabilities`
and `nodeId` as parameters — a context preset is just a named bundle of those parameters. A
dropdown in the spawn UI or terminal launcher header applies the preset before sending.

**Risk / cost:** Config-only change, no protocol change. Low risk. Risk: stale presets pointing
at nodes that have since disconnected — resolve by greying out presets whose target node is offline.

---

#### 4.1.5 Per-node MCP enable/disable matrix in settings UI

**Added capability:** The federation settings panel shows which MCP servers are active on each
node and lets the operator toggle them per-node without SSH-ing in.

**Unlocks:** An operator can disable an experimental MCP server on the home server without
touching the laptop's config. Reduces risk of a broken MCP bringing down the wrong machine's
session capability.

**Implementation surface:** `federation.node.invoke` already proxies arbitrary RPCs. Add
`mcp.enable` and `mcp.disable` as methods on the satellite's local gateway (if not already
present), then expose them in `federation-settings.ts` as a per-node toggle grid. The existing
`mcp.list` federated call provides the current state.

**Risk / cost:** Moderate — depends on whether the local MCP management RPCs already exist.
If they do, this is a UI-only change. If not, add two small gateway methods. Low protocol risk.

---

### 4.2 Medium upgrades (weeks, structural, moderate risk)

#### 4.2.1 Live workload migration mid-run

**Added capability:** A running coder agent on satellite A can be moved to satellite B without
losing its current conversation context or in-progress file edits.

**Unlocks:** Rescues work when a machine needs to reboot for an update, or when the load balancer
detects that the originating node is about to be overloaded. Enables a "follow me" mode where the
agent migrates to whichever machine the developer is actively using.

**Implementation surface:** `session-migration.ts` already defines the full `MigrationStep` state
machine (initiated → validating → serializing → transferring → restoring → verifying → cleanup →
completed). `session-state.ts` already exports `serializeSession` / `restoreSession`. What is
missing: (a) a production-level trigger in `failover-manager.ts` that fires migration instead of
re-spawn when the original node is still reachable; (b) file-state transfer for in-progress edits
(the migration payload currently transfers message history via `SessionHistoryStore`, but open
file buffers are not part of the serialized state); (c) a UI affordance to trigger manual migration.

**Risk / cost:** Medium-high. The serialization/restore pipeline is present but untested in
production. Open file buffers are the hard part — they either need to be flushed to disk before
migration or streamed as binary blobs. A naive implementation that only migrates message context
(not file state) is achievable in a week and useful for stateless tasks. Full file-state migration
is a month-scale effort.

---

#### 4.2.2 Cross-node shared filesystem view

**Added capability:** The file browser and directory picker in the UI can browse any registered
satellite directory, not just local ones.

**Unlocks:** The developer on the laptop can open, read, and write files on the home server's
project directories without SSH or a separate mount. Agents spawned on the master can read source
files that live on a satellite's disk.

**Implementation surface:** `federation-satellite-audit.md` (P3) identifies that satellite
directories are not federation-shared today. The fix: a `federation.directories.list` RPC in
`federation.ts` that aggregates from all nodes, and `federation.node.invoke` wrappers for
`files.read` / `files.write` that relay to the owning node. The existing `directories/store.ts`
provides local directory registration; the RPC just needs to fan out. The file browser UI needs a
`nodeId` selector to route read/write operations to the correct satellite.

**Risk / cost:** Moderate. The RPC plumbing is a day's work; the UI picker changes are a day or
two. The risk is permission model: the current `security.ts` permission levels don't have a
`filesystem` operation type — add one to avoid unintended read/write access from `spawn-only`
satellites. No schema changes needed if operations route through the proxy layer.

---

#### 4.2.3 Federated kanban with bidirectional writes and conflict resolution

**Added capability:** Writes to the kanban board from any satellite are persisted on the master,
and master kanban state is visible from satellite UIs without the proxy-every-read approach.

**Unlocks:** Today, as noted in `federation-satellite-audit.md` (P0), satellite kanban reads return
local SQLite rows. The P0 fix (proxy reads to master) works but adds RTT to every kanban load.
The upgrade: a lightweight replication protocol where the master's kanban is the authoritative
store, satellites maintain a local cache with a dirty flag, writes are forwarded, and reads serve
the cache with a background sync.

**Implementation surface:** `src/databases/kanban-store-ops.ts` (currently in another agent's lane
per the audit doc) would need a `sourceNode` column to track origin. The vector clock machinery in
`vector-clock.ts` is already available; `LWWMap` from `crdt.ts` provides the conflict resolution
primitive. The sync protocol mirrors `memory-sync.ts` — push on write, broadcast on master accept,
ACK-back to satellite. Estimated files: `kanban-store-ops.ts`, `databases.ts` handler, a new
`src/federation/kanban-sync.ts` following the `memory-sync.ts` pattern.

**Risk / cost:** Moderate. Requires coordination with the kanban agent lane (the audit doc flags
`src/databases/store.ts` and `src/databases/kanban-store-ops.ts` as owned by a different agent).
The LWW conflict model works for most kanban mutations (task status, assignment); concurrent
description edits on the same task will last-write-win, which may surprise users. An OT-based
approach for text fields would be safer but is a multi-week effort.

---

#### 4.2.4 Spectator / read-only guest satellite

**Added capability:** A third party (or an auditor's machine) can connect with `read-only`
permission and observe all running sessions, kanban state, and event streams without any write
access.

**Unlocks:** A manager or stakeholder can watch an agent mesh in real-time from their own machine.
A monitoring system (Grafana, custom dashboard) can subscribe to federation events without being
trusted to spawn agents.

**Implementation surface:** `security.ts` already defines `read-only` as a permission level with
`allowedOperations: ["state.sync", "peer.discovery"]`. The gap is that `read-only` satellites
are not explicitly handled in `hub.ts` message routing: `session.spawn` and `session.send` would
be blocked by `checkPermission`, but `event.broadcast` forwarding is not currently scoped to
permission level. Add: (a) a `read-only` connection type that receives broadcasts but whose
outbound RPCs are dropped at the hub; (b) a UI mode that disables all write affordances when
`permissionLevel === "read-only"`.

**Risk / cost:** Low-moderate. The security model is already designed for this; the wiring is
incomplete. Two to three days of hub changes plus UI guard mode. Risk: event broadcast volume
may be high for a monitoring use case — add subscription filtering so read-only nodes can
declare which event types they want.

---

#### 4.2.5 Mesh-wide secret vault with per-node access policies

**Added capability:** A single secret store on the master distributes secrets to satellites on
demand, with per-node access lists and automatic rotation.

**Unlocks:** API keys don't need to be manually configured on every satellite. A satellite that
needs a secret (e.g., a Telegram bot token) requests it; the master checks an access policy and
pushes it encrypted. Key rotation is managed once on the master and propagates automatically.

**Implementation surface:** `identity-sync.ts` already pushes `apiKeys` (Anthropic, OpenAI,
Google, Replicate, XAI) as part of the identity sync payload. This is a push model with no
access policy. The upgrade: (a) move API key distribution from `identity-sync.ts` to a
dedicated `vault-sync.ts` that reads from a new `secrets` table in the master's SQLite; (b) add
a per-satellite access list to `FederationSecurity.createSatelliteToken`; (c) derive
per-delivery encryption from the existing RSA session key exchange rather than including keys
in cleartext in the identity payload.

**Risk / cost:** High-moderate. Touching the security model is risky. The existing
`FEDERATION_SECURITY_README.md` flags certificate-based auth as a planned enhancement — this
upgrade is a step in that direction. Risk: if the vault push is disrupted mid-sync, a satellite
may start a session without required secrets. Add a pre-flight check in the spawn path that
verifies required secrets are present before `session.spawn` fires.

---

### 4.3 Large upgrades (months, foundational, higher risk)

#### 4.3.1 Multi-tenant federation: per-user auth boundaries

**Added capability:** Multiple unrelated users (not just multiple devices belonging to one person)
can share a hub with strict identity isolation — each user's sessions, memory, kanban, and channels
are invisible to others.

**Unlocks:** InfiniBot as a hosted service or household-shared installation. A small agency can run
one hub and give each team member their own scoped satellite without any risk of cross-user data
leakage. The activity feed for user A never shows user B's sessions.

**Implementation surface:** The current security model (`security.ts`) is per-satellite-token with
no concept of a human user. This requires: (a) a `User` entity in the master's database with its
own auth token; (b) per-user workspace namespacing (SOUL.md, MEMORY.md, kanban, sessions scoped
to a `userId` prefix); (c) the hub routing inbound `event.broadcast` events only to satellites
belonging to the same user; (d) `identity-sync.ts` delivering per-user identity files; (e) the
gateway RPC layer checking `userId` on every request. This touches nearly every server-method
handler. Estimated blast radius: 20–30 files.

**Risk / cost:** High. A mistake in the isolation layer leaks private data across users. Requires
a security audit before deployment. The vector-clock and CRDT layers would need to partition by
`userId` to avoid cross-user state bleed. Estimated: 1–2 months of careful work plus testing.

---

#### 4.3.2 Geo-replicated hubs with eventual consistency on shared resources

**Added capability:** Multiple master-class nodes (e.g., home server + cloud VPS) replicate shared
state to each other. If one master goes offline, satellites fail over to the other.

**Unlocks:** Zero-downtime federation for users who can't afford to have their home server as a
single point of failure. A travel scenario where a cloud VPS acts as "always reachable" master
and the home server acts as the high-capability hub — satellites connect to whichever is reachable.

**Implementation surface:** Today the topology is strictly hub-and-spoke: one master, N satellites.
Satellites have no mechanism to communicate with a peer master. This would require: (a) a new
`FederationPeer` role (master ↔ master replication) with its own message types; (b) a per-resource
replication log (the `VectorClock` + `LWWMap` infrastructure is present but scoped to
single-master use); (c) a conflict resolution policy for hub-level state (the current model
assumes master is always authoritative — with two masters, you need a tie-breaker for concurrent
writes). This is greenfield territory: none of the existing hub-side protocol handles peer-master
handshakes or replication streams.

**Risk / cost:** Very high. Distributed consensus is hard. Even with eventually-consistent CRDTs,
the operational complexity of a two-master topology (split-brain detection, reconnect reconciliation,
UI routing when a satellite can reach both masters) is substantial. Recommend solving
§4.2.1 (live migration) and §4.2.3 (kanban sync) first — they will expose the conflict resolution
model's rough edges before scaling to peer masters.

---

#### 4.3.3 Federated MCP server discovery and auto-mount

**Added capability:** When a satellite connects, it automatically discovers and locally mounts MCP
servers registered on the master (and other satellites). An agent on any node can call any MCP
tool in the mesh without specifying a `nodeId`.

**Unlocks:** The operator installs a complex MCP server (e.g., Playwright, a custom database
connector) on the GPU desktop once. Every satellite in the mesh can use it without installing
anything. A coder agent on the laptop calls `playwright.screenshot()` and the hub routes the
invocation to the desktop transparently.

**Implementation surface:** `mcp-proxy.ts` already handles on-demand cross-node MCP invocation
when the caller specifies the target node. The upgrade: (a) extend `federation-resources.ts`
aggregation to include a `mcp.list` across nodes; (b) add a discovery push at satellite
registration time that tells the satellite which MCP servers are available on which nodes;
(c) modify the satellite's MCP tool registry to register "virtual" tools that proxy to the
owning node's `mcp.invoke` via `federation.node.invoke`. The hard part is transparent routing:
the agent's tool list must show the remote tool as if it were local, with latency and failure
handled gracefully.

**Risk / cost:** High. The MCP protocol assumes tools are available synchronously; adding network
latency and partial-failure modes to tool invocations requires careful error propagation. If the
owning node goes offline mid-tool-call, the agent gets a tool error that may be hard to recover
from. Recommend as a discrete opt-in feature per tool rather than automatic global mount.

---

## 5. Anti-recommendations

- **Don't add strong consistency (quorum writes) across nodes.** The current vector-clock /
  LWW model is fit for purpose: agent memory, kanban tasks, and session state can tolerate
  seconds of eventual convergence. Adding Raft or Paxos would balloon implementation complexity,
  require a minimum quorum (breaking single-node and two-node setups), and add latency to every
  write. The conflict resolution in `vector-clock.ts` + `crdt.ts` handles the concurrent-write
  case adequately for the current workload. If you encounter cases where LWW is wrong, add
  semantic conflict handlers per resource type (like the OT approach already in `memory-sync.ts`
  for append-only sections) rather than replacing the whole model.

- **Don't replicate vault secrets eagerly to all satellites by default.** `identity-sync.ts`
  already pushes API keys to all satellites. Extending this to all secrets (database passwords,
  OAuth tokens, channel bot tokens) would mean a compromised satellite grants access to every
  secret in the mesh. The §4.2.5 upgrade (per-node access policies) must precede any expansion of
  what crosses the wire in identity sync. Eager replication to all nodes is a mistake even if
  encrypted; the exposure surface grows with the number of satellites.

- **Don't implement NAT traversal (STUN/TURN) inside the peer-mesh.** `SATELLITE_MESH.md` lists
  NAT traversal as a future enhancement for `peer-mesh.ts`. It is not worth the complexity.
  The hub-relay fallback already handles the case where satellites can't reach each other directly.
  Operators who want direct P2P across NAT should use Tailscale or a WireGuard overlay — that
  is a solved problem at the network layer and keeps the federation code simple. Embedding a
  STUN/TURN client in `peer-mesh.ts` adds 500+ lines of ICE negotiation for a marginal latency
  improvement that Tailscale already provides for free.

- **Don't build a "marketplace of satellite skills" before skill lifecycle management is stable.**
  The concept (a satellite offers a remote-only capability installable by other nodes) is appealing,
  but skills currently lack versioning, health checks, or uninstall guarantees in the local
  skill system. Distributing them across federation nodes before that foundation is solid would
  spread partially-installed or version-mismatched skill state across the mesh, which is harder to
  debug than a single-node problem. Nail the local skill lifecycle first.

---

## 6. Open questions

These decisions cannot be scoped without user/operator input:

1. **Satellite data model: proxy vs. replicate.** The `federation-satellite-audit.md` P0 gap
   (kanban/CRM/notes reads going to local SQLite) can be fixed two ways: (a) proxy every read/write
   to the master at runtime, accepting RTT on every query; or (b) replicate master state to the
   satellite's local SQLite with a sync protocol. Option (a) is simpler but requires the satellite
   to be online for any data operation. Option (b) supports offline use but requires conflict
   resolution on writes. Which failure mode is acceptable: stale reads, or blocked writes when
   disconnected?

2. **Multi-user support: is it a goal?** The §4.3.1 upgrade requires a fundamental redesign of
   the identity and workspace model. If InfiniBot is always single-operator (one human, many
   devices), the current token-per-satellite model is correct and §4.3.1 is out of scope. If
   household or team sharing is a goal, that scope needs to be decided before any of the data
   model work in §4.2.3 (kanban sync) is done — adding `userId` partitioning after the fact is
   much harder than designing for it from the start.

3. **Live migration scope: message context only, or full file state?** §4.2.1 describes a
   staged approach. The wire for context migration is already 80% present (`session-migration.ts`,
   `session-state.ts`). The question is whether file-edit state (open buffers, git working tree)
   also needs to migrate, or whether the workflow is "finish the current edit, then migrate."
   The answer drives whether the migration serialization payload needs binary file blobs or just
   message history.

4. **Federation as a product surface: should satellites be visible to users or an implementation
   detail?** The activity page federation chips and the terminal node picker expose federation to
   the user directly. But `federation-satellite-audit.md` notes there's no persistent status
   indicator showing "you are on satellite X." The design question: is federation intended to be
   explicitly managed by the user (pick which node to run on), or should the system route
   transparently with the user rarely needing to think about nodes? The answer shapes how much
   surface area the §4.1.x small upgrades should add.

5. **Secret rotation protocol ownership.** `identity-sync.ts` currently pushes API keys at
   connection time with no rotation trigger. If keys rotate (Anthropic key gets cycled, a provider
   credential expires), there is no mechanism to push the new value to connected satellites without
   a reconnect. Should rotation be hub-triggered (master pushes on change), satellite-polled
   (satellite periodically re-requests identity), or out-of-band (operator reconnects each
   satellite manually)? This is a minor operational pain today but becomes critical at scale.
