3.3 KiB
Native client contract
Audience: Implementers of native HAPI clients — the iOS app (ios/), the Android app (android/), and any other non-web client that talks to a hub's client API. These pages are the primary spec for that work: every claim is grounded in hub/web source, and each section names its source file so implementers (human or AI agent) can verify against code.
Scope: The HTTP contract between a client and one hub — pairing and auth, REST endpoints, SSE streaming, message pagination, message decoding, and error semantics. A client using only this contract can replicate the web app's core feature set over REST + SSE alone (no Socket.IO — that transport is CLI↔hub internal).
Pages
| Page | Contents |
|---|---|
| Auth | Pairing deeplink, access-token grammar, JWT exchange, silent re-auth, namespaces, credential storage |
| REST | Endpoint tables (v1-required and out-of-scope), request/response shapes, gzip negotiation |
| SSE | GET /api/events stream: subscription modes, resume handshake, event ids, reconnect policy |
| Pagination | Message window: composite cursors, epoch reset, optimistic-send reconciliation |
| Messages | DecryptedMessage.content decoding tree (codex / output / event families) |
| Errors | {status, code} table, error body shapes, RPC-wrapped failure modes |
Versioning
Source of truth: hub/src/web/server.ts (/health route), shared/src/version.ts.
GET /health requires no auth and returns:
{
"status": "ok",
"protocolVersion": 1,
"capabilities": {
"workGraph": true,
"titleSuggestion": false
}
}
protocolVersionis the wire-protocol generation (PROTOCOL_VERSIONinshared/src/version.ts, currently1). A client built against this contract targets version 1 and should surface an "update required" state if it ever sees a higher value.capabilitiesis additive: new hub features appear as new keys. Clients must ignore unknown keys and treat missing keys as "not supported". Feature-gate on capability keys, never on hub build versions.
Executable spec: golden fixtures
The prose in Messages describes the decoding tree, but the normative artifact is shared/fixtures/ — machine-generated golden files produced from the web implementation's chat pipeline (web/src/chat/). A native client's protocol module must reproduce those fixtures exactly; CI regenerates them whenever the web pipeline changes, so drift is caught automatically.
shared/fixtures/ is a companion deliverable of this contract and may not exist yet when you first read this — the fixture generator and batches land in later work packages of the same track. Until then, web/src/chat/ itself is the reference implementation.
Relationship to the companion push contract
docs/api/native-companion-contract.md is the FCM push contract: device registration (POST /api/devices/register) and the outbound push payload the hub sends through Firebase. It predates this contract and is unchanged. A native client implements both: this contract for everything interactive, the companion contract for background push. Where the two overlap (auth, send-message, approve/deny), this contract is the more detailed spec.