Files
Outpost/docs/ARCHITECTURE.md
T

39 lines
3.5 KiB
Markdown

# Architecture Notes
Deeper technical reference backing `CLAUDE.md`. Update this as decisions are made — treat it as a living design doc, not a one-time spec.
## 1. Outline API surface
- **Base**: `https://<your-instance>/api/*`, RPC-style (POST for nearly everything, not strict REST verbs).
- **Auth**: `Authorization: Bearer <API_KEY>` header. Keys are created per-user under Settings → API Keys on the Outline instance. Store in Keychain, scope a dedicated key to this app rather than reusing a personal one.
- **Core endpoints to wrap first**: `documents.info`, `documents.list`, `documents.search`, `documents.create`, `documents.update`, `collections.list`, `collections.info`, `users.info`.
- Full reference: your instance's `/developers` page (same docs as getoutline.com/developers, versioned per Outline release — check against your self-hosted version, not just the public docs).
## 2. Realtime collaboration transport
- Endpoint: `wss://<your-instance>/collaboration/document.<document-id>`.
- Protocol: Hocuspocus (a Yjs-CRDT-over-WebSocket server implementation). This is **not** the same socket as any notification/presence channel — it's the actual document edit transport.
- Payload: binary Yjs update messages (Yjs update format v1/v2) plus the Yjs awareness protocol for cursor/selection presence.
- Your reverse proxy (Caddy, in your homelab) must forward `Upgrade`/`Connection` headers correctly or collaboration silently falls back to "no live sync" while REST edits still work — worth a smoke test against your own Caddy config early.
## 3. CRDT engine — YSwift
- Repo: `y-crdt/yswift`. Swift bindings over `yrs` (Rust) via UniFFI, distributed with a prebuilt XCFramework.
- Status as of mid-2026: WIP, pre-1.0, small but active contributor base. Not all Yrs/Yjs features are exposed yet.
- Integration point: YSwift gives you a local `Y.Doc` you mutate; a Hocuspocus-compatible WebSocket provider (you'll likely need to write this provider yourself in Swift — no off-the-shelf Swift Hocuspocus client exists yet) syncs that doc's binary updates with the server.
- Fallback if YSwift blocks progress: vendor the C FFI (`yffi`) directly and write a thinner Swift wrapper for just the operations you need (XML fragment read/write, update encode/decode, state vector diffing).
## 4. Document schema mapping
Outline's editor is ProseMirror-based; the Yjs doc stores document structure as a `Y.XmlFragment` mirroring the ProseMirror schema (paragraphs, headings, bullet/ordered/checklist lists, tables, code blocks, blockquotes, embeds, comments-as-marks). Native editor work breaks into:
- **Read path**: Y.XmlFragment → your own document model → `AttributedString`/TextKit 2 layout.
- **Write path**: local edit → diff against your document model → Yjs transaction on the XmlFragment → binary update sent over the Hocuspocus socket.
- Build the node-type mapping table (ProseMirror node/mark name → native representation) as an explicit, tested module — this is the piece most likely to silently drift from Outline's actual schema as Outline ships updates.
## 5. Known risk areas (revisit as the project progresses)
- YSwift feature gaps vs. full Yjs (undo/redo manager, relative positions) — check current state before Phase 2 starts, this library moves fast.
- Table and embed support are the least standardized part of ProseMirror schemas generally — budget them last.
- Outline server version drift: self-hosted instance upgrades could change API shapes or the collaboration payload; pin against your actual running version, not assumptions from docs.