All checks were successful
CD / Build and push images (push) Successful in 2m45s
CI / Lint, typecheck, test (push) Successful in 1m56s
CI / Auth e2e pack (push) Successful in 2m1s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 9s
CD / Smoke tests against Test (push) Successful in 1m9s
CD / Promote to Int (push) Successful in 12s
The api mints a short-lived (60 s) HS256 JWT per page open after an interim
permission check; the collab server authenticates every connection with it
(ADR 0003/0007 — the only JWTs in the system).
- packages/shared: browser-safe token schema/types in `collab-token`, and the
Node `crypto` sign/verify in `token-crypto` behind its own subpath export
(`@dorfteich/shared/token-crypto`) so the web bundle never pulls in
`node:crypto`. Only HS256 is produced/accepted; the signature is checked in
constant time before any untrusted field is read.
- api: `GET /pages/:id/collab-token` (auth-required) returns
{token, mode, expiresInSeconds}; `mode` is rw/ro via the interim access
service; issuance is logged at debug level without the token value.
- collab: `onAuthenticate` verifies the token, checks the pageId matches the
document name, stores {userId, mode} context, and enforces `ro` via
Hocuspocus' read-only connection flag. Hocuspocus' own signal handling is
disabled so index.ts remains the single shutdown owner.
- Shared COLLAB_TOKEN_SECRET env for api + collab (compose, dev overlay,
.env.example, stage docs); a dev default keeps native dev/test/CI running.
Tests: shared token round-trip/rejection; api endpoint e2e (auth required,
claims, 404 for non-members/unknown ids); collab integration via
HocuspocusProvider (valid token connects; expired/tampered/mismatched-page/
wrong-secret rejected; read-only writes dropped, verified with two clients).
Closes #34
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
31 lines
755 B
JSON
31 lines
755 B
JSON
{
|
|
"name": "@dorfteich/collab",
|
|
"version": "0.0.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"description": "Dorfteich collaboration server (Yjs/Hocuspocus)",
|
|
"license": "MIT",
|
|
"main": "dist/index.js",
|
|
"scripts": {
|
|
"build": "tsc -p tsconfig.json",
|
|
"start": "node dist/index.js",
|
|
"start:dev": "tsx watch src/index.ts",
|
|
"typecheck": "tsc --noEmit",
|
|
"test": "vitest run --passWithNoTests"
|
|
},
|
|
"dependencies": {
|
|
"@dorfteich/shared": "workspace:*",
|
|
"@hocuspocus/server": "^4.3.0",
|
|
"pg": "^8.16.0",
|
|
"pino": "^9.6.0"
|
|
},
|
|
"devDependencies": {
|
|
"@hocuspocus/provider": "^4.3.0",
|
|
"@types/node": "^26.1.0",
|
|
"@types/pg": "^8.11.0",
|
|
"tsx": "^4.19.0",
|
|
"vitest": "^3.0.0",
|
|
"yjs": "^13.6.0"
|
|
}
|
|
}
|