Collaboration server skeleton (Hocuspocus) with container and compose service #33

Closed
opened 2026-07-04 14:52:14 +02:00 by fable-5 · 2 comments
Collaborator

Context

M3 replaces REST persistence with live sync. First step: a running, deployable collab service (ADR 0003).

Scope

Bootstrap apps/collab: Hocuspocus server with config/logging consistent with the API (pino JSON, env validation via shared schemas), /healthz (process + DB ping), Dockerfile, compose service on both networks, /collab reverse-proxy route with WebSocket upgrade (update deployment docs + stage proxies), CI build + deploy integration.

Acceptance criteria

  • docker compose up includes collab; /collab accepts a WebSocket handshake (unauthenticated close for now is fine)
  • healthz wired into compose healthcheck and pipeline smoke test
  • structured logs show connection open/close events

Technical notes

  • ADR 0003, deployment.md (routing), realtime-collaboration.md.

Dependencies

Depends on #6, #8, #9.

Size: ~1 day


Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add de and en), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.

## Context M3 replaces REST persistence with live sync. First step: a running, deployable collab service (ADR 0003). ## Scope Bootstrap `apps/collab`: Hocuspocus server with config/logging consistent with the API (pino JSON, env validation via shared schemas), `/healthz` (process + DB ping), Dockerfile, compose service on both networks, `/collab` reverse-proxy route with WebSocket upgrade (update deployment docs + stage proxies), CI build + deploy integration. ## Acceptance criteria - [ ] `docker compose up` includes collab; `/collab` accepts a WebSocket handshake (unauthenticated close for now is fine) - [ ] healthz wired into compose healthcheck and pipeline smoke test - [ ] structured logs show connection open/close events ## Technical notes - ADR 0003, deployment.md (routing), realtime-collaboration.md. ## Dependencies Depends on #6, #8, #9. **Size**: ~1 day --- *Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add `de` **and** `en`), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.*
fable-5 added this to the M3 — Real-time collaboration & history milestone 2026-07-04 14:52:14 +02:00
fable-5 added the
collab
deployment
labels 2026-07-04 14:52:14 +02:00
Owner

erified on Test and Int (commit 8316c61, pipeline green — all CI + CD jobs, incl. the new /collab/healthz smoke assertion and Int promotion).

  • docker compose now includes the collab service on both stages; both dorfteich-{test,int}-collab-1 containers report Up (healthy) — the compose healthcheck hits /healthz (process liveness + DB ping).
  • https://test.dorfteich.cloud/collab/healthz and https://int.dorfteich.cloud/collab/healthz → 200 {"status":"ok","service":"collab",...,"checks":[{"name":"database","status":"ok"}]} through the reverse proxy (/collab* → 8102/8112, WebSocket upgrade passes through in Caddy).
  • Structured pino logs (service=collab) emit connection open/close events; a WebSocket handshake is accepted for now — authentication arrives with #34, document persistence with #35.

Implementation notes for follow-ups:

  • apps/collab is built as ESM ("type": "module"), because Hocuspocus v4 depends on the ESM-only crossws. Relative imports use .js extensions.
  • /healthz is served via the Hocuspocus onRequest hook: write the response, then reject with a falsy reason to stop the hook chain (a truthy reject would crash the request handler). Non-health requests fall through to Hocuspocus.

Operational note: the CD pipeline does not sync docker-compose.yml to the stages (deploy only runs compose pull && up -d against the file already there). The stage compose files were updated by hand for this deploy, which also resolved the earlier UPLOADS_DIR config drift — both api containers now run with UPLOADS_DIR=/data/uploads and serve uploads from the persistent volume. Per-stage COLLAB_PORT (test 8102, int 8112) is required since both stacks share the VPS.

erified on Test and Int (commit 8316c61, pipeline green — all CI + CD jobs, incl. the new /collab/healthz smoke assertion and Int promotion). - docker compose now includes the collab service on both stages; both dorfteich-{test,int}-collab-1 containers report Up (healthy) — the compose healthcheck hits /healthz (process liveness + DB ping). - https://test.dorfteich.cloud/collab/healthz and https://int.dorfteich.cloud/collab/healthz → 200 {"status":"ok","service":"collab",...,"checks":[{"name":"database","status":"ok"}]} through the reverse proxy (/collab* → 8102/8112, WebSocket upgrade passes through in Caddy). - Structured pino logs (service=collab) emit connection open/close events; a WebSocket handshake is accepted for now — authentication arrives with #34, document persistence with #35. Implementation notes for follow-ups: - apps/collab is built as ESM ("type": "module"), because Hocuspocus v4 depends on the ESM-only crossws. Relative imports use .js extensions. - /healthz is served via the Hocuspocus onRequest hook: write the response, then reject with a falsy reason to stop the hook chain (a truthy reject would crash the request handler). Non-health requests fall through to Hocuspocus. Operational note: the CD pipeline does not sync docker-compose.yml to the stages (deploy only runs compose pull && up -d against the file already there). The stage compose files were updated by hand for this deploy, which also resolved the earlier UPLOADS_DIR config drift — both api containers now run with UPLOADS_DIR=/data/uploads and serve uploads from the persistent volume. Per-stage COLLAB_PORT (test 8102, int 8112) is required since both stacks share the VPS.
Collaborator

Reposting the verification note cleanly under the model account — the earlier comment was pasted manually and dropped its leading character ("erified…").

Verified on Test and Int (commit 8316c61, pipeline green — all CI + CD jobs, incl. the new /collab/healthz smoke assertion and Int promotion).

  • docker compose now includes the collab service on both stages; both dorfteich-{test,int}-collab-1 containers report Up (healthy) — the compose healthcheck hits /healthz (process liveness + DB ping).
  • https://test.dorfteich.cloud/collab/healthz and https://int.dorfteich.cloud/collab/healthz → 200 {"status":"ok","service":"collab",...,"checks":[{"name":"database","status":"ok"}]} through the reverse proxy (/collab* → 8102/8112, WebSocket upgrade passes through in Caddy).
  • Structured pino logs (service=collab) emit connection open/close events; a WebSocket handshake is accepted for now — authentication arrives with #34, document persistence with #35.

Implementation notes for follow-ups:

  • apps/collab is built as ESM ("type": "module"), because Hocuspocus v4 depends on the ESM-only crossws. Relative imports use .js extensions.
  • /healthz is served via the Hocuspocus onRequest hook: write the response, then reject with a falsy reason to stop the hook chain (a truthy reject would crash the request handler). Non-health requests fall through to Hocuspocus.

Operational note: the CD pipeline does not sync docker-compose.yml to the stages (deploy only runs compose pull && up -d against the file already there). The stage compose files were updated by hand for this deploy, which also resolved the earlier UPLOADS_DIR config drift — both api containers now run with UPLOADS_DIR=/data/uploads and serve uploads from the persistent volume. Per-stage COLLAB_PORT (test 8102, int 8112) is required since both stacks share the VPS.

_Reposting the verification note cleanly under the model account — the earlier comment was pasted manually and dropped its leading character ("erified…")._ Verified on Test and Int (commit 8316c61, pipeline green — all CI + CD jobs, incl. the new `/collab/healthz` smoke assertion and Int promotion). - docker compose now includes the collab service on both stages; both `dorfteich-{test,int}-collab-1` containers report Up (healthy) — the compose healthcheck hits `/healthz` (process liveness + DB ping). - https://test.dorfteich.cloud/collab/healthz and https://int.dorfteich.cloud/collab/healthz → 200 `{"status":"ok","service":"collab",...,"checks":[{"name":"database","status":"ok"}]}` through the reverse proxy (`/collab*` → 8102/8112, WebSocket upgrade passes through in Caddy). - Structured pino logs (`service=collab`) emit connection open/close events; a WebSocket handshake is accepted for now — authentication arrives with #34, document persistence with #35. Implementation notes for follow-ups: - `apps/collab` is built as ESM (`"type": "module"`), because Hocuspocus v4 depends on the ESM-only `crossws`. Relative imports use `.js` extensions. - `/healthz` is served via the Hocuspocus `onRequest` hook: write the response, then reject with a falsy reason to stop the hook chain (a truthy reject would crash the request handler). Non-health requests fall through to Hocuspocus. Operational note: the CD pipeline does not sync `docker-compose.yml` to the stages (deploy only runs `compose pull && up -d` against the file already there). The stage compose files were updated by hand for this deploy, which also resolved the earlier `UPLOADS_DIR` config drift — both api containers now run with `UPLOADS_DIR=/data/uploads` and serve uploads from the persistent volume. Per-stage `COLLAB_PORT` (test 8102, int 8112) is required since both stacks share the VPS.
Sign in to join this conversation.
No project
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stwaidele/dorfteich#33
No description provided.