# Node Federation P2 v0 — Threat Model & Design (shipped)

| | |
|---|---|
| **Status** | SHIPPED v0 (HTTPS JSON; read-only telemetry first) |
| **Transport** | Same-origin HTTP on the Command Center (`command-center-server.mjs`) — **not** libp2p. Nodes present `x-node-token`. |
| **Flag** | `CC_FEDERATION=1` required. Default OFF. Host must also `POST /api/federation/enable`. |

## Threat model (v0)

| Threat | Mitigation |
|---|---|
| Stolen host `.env` / `CC_CONTROL_TOKEN` via node API | Node tokens are **issued, hashed credentials** — never the host control token. Node responses never serialize env. |
| Rogue node joins without host consent | Federation flag off by default; host `enabled` flag; only owner can issue credentials. |
| Revoked node keeps working | `revoked:true` + token hash left in place so resolve fails; instant deny. |
| Node reads host admin telemetry | Node routes only own register/heartbeat/telemetry/knowledge-submit; admin routes require owner session. |
| Cross-tenant / other-node data leak | Telemetry and knowledge keyed by `nodeId` + optional `tenantId`; list endpoints owner-only. |
| Knowledge poisoning (P3) | All submits → **quarantine**; rate limit; promote only after corroboration (2+ nodes) or explicit owner promote; never silent overwrite of owner beliefs. |

## Capability scopes (v0)

Issued nodes get `capabilities: ['telemetry_write','knowledge_submit']` (read-only *from host's perspective* — node may **write its own** telemetry, not read host secrets).

## Protocol sketch

1. Owner: `POST /api/federation/enable` `{enabled:true}`
2. Owner: `POST /api/federation/nodes/issue` `{name}` → `{ nodeId, token }` once
3. Node: `POST /api/node/register` header `x-node-token` → session ack
4. Node: `POST /api/node/heartbeat` / `POST /api/node/telemetry`
5. Owner: `POST /api/federation/nodes/:id/revoke`

State: `state/federation.json` + `state/federation_quarantine.json` under `CC_STATE_DIR`.
