collabmd 0.1.21 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +94 -7
  2. package/bin/collabmd.js +3 -2
  3. package/docker-compose.yml +13 -1
  4. package/package.json +2 -1
  5. package/public/assets/css/style.css +1 -1
  6. package/public/assets/js/chunks/{chunk-HEWVH67U.js → chunk-CYK7KO7W.js} +8 -8
  7. package/public/assets/js/chunks/editor-session-S5AT7BMV.js +22 -0
  8. package/public/assets/js/{excalidraw-editor-TCIH6GJL.js → excalidraw-editor-5YWMGLKF.js} +145 -62
  9. package/public/assets/js/excalidraw-editor.js +1 -1
  10. package/public/assets/js/main.js +503 -182
  11. package/public/index.html +104 -84
  12. package/src/client/application/app-shell/git-feature.js +247 -9
  13. package/src/client/application/app-shell/ui-feature.js +65 -7
  14. package/src/client/application/app-shell/workspace-feature.js +46 -0
  15. package/src/client/application/app-shell-elements.js +2 -0
  16. package/src/client/application/mermaid-preview-hydrator.js +1 -1
  17. package/src/client/application/plantuml-preview-hydrator.js +1 -1
  18. package/src/client/application/workspace-coordinator.js +147 -18
  19. package/src/client/application/workspace-preview-controller.js +34 -0
  20. package/src/client/application/workspace-route-controller.js +104 -0
  21. package/src/client/bootstrap/collabmd-app-shell.js +95 -0
  22. package/src/client/domain/runtime-paths.js +5 -0
  23. package/src/client/excalidraw-editor.js +50 -2
  24. package/src/client/infrastructure/auth-client.js +219 -52
  25. package/src/client/infrastructure/browser-navigation-port.js +20 -0
  26. package/src/client/infrastructure/editor-collaboration-client.js +4 -0
  27. package/src/client/infrastructure/editor-session.js +47 -7
  28. package/src/client/infrastructure/editor-view-adapter.js +122 -58
  29. package/src/client/infrastructure/runtime-config.js +66 -0
  30. package/src/client/presentation/comment-ui-controller.js +82 -26
  31. package/src/client/presentation/comments-panel.js +2 -2
  32. package/src/client/presentation/excalidraw-embed-controller.js +60 -2
  33. package/src/client/presentation/file-history-view-controller.js +806 -0
  34. package/src/client/presentation/git-diff-view-controller.js +718 -121
  35. package/src/client/presentation/git-panel-controller.js +458 -66
  36. package/src/client/presentation/layout-controller.js +1 -1
  37. package/src/client/styles/components/actions.css +89 -0
  38. package/src/client/styles/components/feedback.css +43 -0
  39. package/src/client/styles/components/navigation.css +68 -0
  40. package/src/client/styles/components/scrollbars.css +104 -0
  41. package/src/client/styles/components/states.css +289 -0
  42. package/src/client/styles/components/surfaces.css +155 -0
  43. package/src/client/styles/features/backlinks.css +213 -0
  44. package/src/client/styles/features/collaboration-chat.css +228 -0
  45. package/src/client/styles/features/collaboration-dialogs.css +154 -0
  46. package/src/client/styles/features/collaboration-presence.css +103 -0
  47. package/src/client/styles/features/collaboration-ui.css +3 -0
  48. package/src/client/styles/features/comment-card.css +236 -0
  49. package/src/client/styles/features/comment-markdown.css +127 -0
  50. package/src/client/styles/features/comment-overlays.css +60 -0
  51. package/src/client/styles/features/comments-drawer.css +120 -0
  52. package/src/client/styles/features/comments.css +4 -0
  53. package/src/client/styles/features/diagram-preview.css +227 -0
  54. package/src/client/styles/features/diff-commit.css +268 -0
  55. package/src/client/styles/features/diff-lines.css +160 -0
  56. package/src/client/styles/features/diff-toolbar.css +98 -0
  57. package/src/client/styles/features/diff.css +3 -0
  58. package/src/client/styles/features/embedded-preview.css +218 -0
  59. package/src/client/styles/features/git-branch.css +155 -0
  60. package/src/client/styles/features/git-files.css +105 -0
  61. package/src/client/styles/features/git-history.css +339 -0
  62. package/src/client/styles/features/git.css +3 -0
  63. package/src/client/styles/features/media-lightbox.css +157 -0
  64. package/src/client/styles/features/outline.css +115 -0
  65. package/src/client/styles/features/preview-content.css +3 -0
  66. package/src/client/styles/features/preview-markdown.css +201 -0
  67. package/src/client/styles/features/preview-sidebars.css +2 -0
  68. package/src/client/styles/features/quick-switcher.css +167 -0
  69. package/src/client/styles/foundation/themes.css +347 -0
  70. package/src/client/styles/foundation/tokens.css +66 -0
  71. package/src/client/styles/foundation/utilities.css +36 -0
  72. package/src/client/styles/layout/editor-page.css +203 -0
  73. package/src/client/styles/layout/overlays.css +132 -0
  74. package/src/client/styles/layout/responsive.css +251 -0
  75. package/src/client/styles/layout/shell.css +314 -0
  76. package/src/client/styles/layout/sidebar.css +176 -0
  77. package/src/client/styles/layout/view-modes.css +92 -0
  78. package/src/client/styles/overrides/codemirror.css +53 -0
  79. package/src/client/styles/overrides/highlightjs.css +7 -0
  80. package/src/client/styles/overrides/vendor.css +2 -0
  81. package/src/client/styles/primitives/controls.css +276 -0
  82. package/src/client/styles/style.css +25 -4945
  83. package/src/server/auth/create-auth-service.js +373 -15
  84. package/src/server/auth/session-cookie.js +30 -4
  85. package/src/server/config/env.js +121 -5
  86. package/src/server/create-app-server.js +8 -0
  87. package/src/server/domain/collaboration/collaboration-room.js +90 -47
  88. package/src/server/index.js +3 -1
  89. package/src/server/infrastructure/git/command-runner.js +2 -1
  90. package/src/server/infrastructure/git/git-service.js +48 -2
  91. package/src/server/infrastructure/git/history-service.js +683 -0
  92. package/src/server/infrastructure/git/parsers.js +30 -0
  93. package/src/server/infrastructure/git/responses.js +73 -0
  94. package/src/server/infrastructure/http/create-auth-api-handler.js +30 -2
  95. package/src/server/infrastructure/http/create-git-api-command-handler.js +2 -0
  96. package/src/server/infrastructure/http/create-git-api-handler.js +2 -0
  97. package/src/server/infrastructure/http/create-git-api-query-handler.js +61 -0
  98. package/src/server/infrastructure/http/create-request-handler.js +15 -0
  99. package/public/assets/js/chunks/editor-session-EAUBJCHH.js +0 -22
package/README.md CHANGED
@@ -152,13 +152,14 @@ Then share the printed URL and password with your collaborator. If `cloudflared`
152
152
 
153
153
  - Treat the URL as write access to the vault unless you enable auth
154
154
  - `--auth password` protects `/api/*` and `/ws/*` with a host password and signed session cookie
155
+ - `--auth oidc` signs users in with Google and uses the verified Google name/email as the in-app identity and git commit author
155
156
  - If `cloudflared` is installed, CollabMD may expose the app through a Cloudflare Quick Tunnel unless you pass `--no-tunnel`
156
- - `oidc` is reserved for a future implementation and is not usable yet
157
+ - `--auth oidc` requires a stable `PUBLIC_BASE_URL`; Quick Tunnel URLs are not supported for OIDC
157
158
 
158
159
  ## Current limitations
159
160
 
160
161
  - Single-instance deployment only: collaboration room state is kept in-process and is not shared across replicas
161
- - `oidc` auth is reserved for a future implementation and is not usable yet
162
+ - `oidc` currently supports Google only
162
163
  - Source-anchored comments currently support markdown, Mermaid, and PlantUML text files, but not `.excalidraw`
163
164
  - Windows use is supported via WSL2 rather than native Windows execution
164
165
 
@@ -203,7 +204,7 @@ collabmd [directory] [options]
203
204
  |--------|-------------|---------|
204
205
  | `-p, --port` | Port to listen on | `1234` |
205
206
  | `--host` | Host to bind to | `127.0.0.1` |
206
- | `--auth` | Auth strategy: `none`, `password`, `oidc` (`oidc` is reserved and not yet available) | `none` |
207
+ | `--auth` | Auth strategy: `none`, `password`, `oidc` | `none` |
207
208
  | `--auth-password` | Password for `--auth password` | generated per run |
208
209
  | `--local-plantuml` | Start the bundled local docker-compose PlantUML service | off |
209
210
  | `--no-tunnel` | Don't start Cloudflare Tunnel | tunnel on |
@@ -228,6 +229,12 @@ collabmd --auth password
228
229
  # Require an explicit password
229
230
  collabmd --auth password --auth-password "shared-secret"
230
231
 
232
+ # Use Google OIDC on a stable public domain
233
+ PUBLIC_BASE_URL=https://notes.example.com \
234
+ AUTH_OIDC_CLIENT_ID=your-google-client-id \
235
+ AUTH_OIDC_CLIENT_SECRET=your-google-client-secret \
236
+ collabmd --auth oidc --no-tunnel
237
+
231
238
  # Use the local docker-compose PlantUML service
232
239
  collabmd --local-plantuml
233
240
 
@@ -258,6 +265,39 @@ To disable the tunnel:
258
265
  collabmd --no-tunnel
259
266
  ```
260
267
 
268
+ ### Google OIDC setup
269
+
270
+ `--auth oidc` uses Google OpenID Connect with the authorization code + PKCE flow.
271
+
272
+ For the full Google Cloud Console walkthrough, including where to create the OAuth client and copy the client ID/client secret, see [docs/google-oidc-setup.md](https://github.com/andes90/collabmd/blob/master/docs/google-oidc-setup.md).
273
+
274
+ Required environment variables:
275
+
276
+ ```bash
277
+ PUBLIC_BASE_URL=https://notes.example.com
278
+ AUTH_OIDC_CLIENT_ID=your-google-client-id
279
+ AUTH_OIDC_CLIENT_SECRET=your-google-client-secret
280
+ ```
281
+
282
+ In Google Cloud Console, create a Web application OAuth client and register this redirect URI:
283
+
284
+ ```text
285
+ https://notes.example.com/api/auth/oidc/callback
286
+ ```
287
+
288
+ If you mount the app under a subpath with `BASE_PATH=/collabmd`, the redirect URI becomes:
289
+
290
+ ```text
291
+ https://notes.example.com/collabmd/api/auth/oidc/callback
292
+ ```
293
+
294
+ Notes:
295
+
296
+ - OIDC requires a stable public URL and is not compatible with ephemeral Cloudflare Quick Tunnel URLs
297
+ - After sign-in, the verified Google name/email become the displayed app identity and the default in-app git commit author
298
+ - You can restrict sign-in to exact users with `AUTH_OIDC_ALLOWED_EMAILS` or entire domains with `AUTH_OIDC_ALLOWED_DOMAINS`
299
+ - The CLI disables the tunnel automatically when `--auth oidc` is active
300
+
261
301
  You can also configure the tunnel via environment variables:
262
302
 
263
303
  ```bash
@@ -278,6 +318,26 @@ docker run -p 1234:1234 -v /path/to/vault:/data ghcr.io/andes90/collabmd:latest
278
318
 
279
319
  The container listens on `0.0.0.0:1234` and stores vault files at `/data`.
280
320
 
321
+ ### Kubernetes / Helm
322
+
323
+ CollabMD now includes a Helm chart at [`packaging/helm/collabmd`](./packaging/helm/collabmd).
324
+
325
+ Use it when you want a Kubernetes-native deployment with:
326
+
327
+ - one supported application replica
328
+ - a persistent volume mounted at `/data`
329
+ - optional ingress
330
+ - optional bundled PlantUML
331
+ - secret-backed auth and private git bootstrap settings
332
+
333
+ Quick start:
334
+
335
+ ```bash
336
+ helm install collabmd ./packaging/helm/collabmd
337
+ ```
338
+
339
+ For examples covering ingress, OIDC, PlantUML, and private git bootstrap, see [packaging/helm/collabmd/README.md](./packaging/helm/collabmd/README.md).
340
+
281
341
  To bootstrap `/data` from a private git repository instead, pass the repo URL plus SSH credentials:
282
342
 
283
343
  ```bash
@@ -324,6 +384,24 @@ docker compose up
324
384
 
325
385
  Open `http://localhost:1234`.
326
386
 
387
+ To test Google OIDC locally with the included compose setup, register this redirect URI in Google Cloud Console:
388
+
389
+ ```text
390
+ http://localhost:1234/api/auth/oidc/callback
391
+ ```
392
+
393
+ Then start compose with the OIDC env vars:
394
+
395
+ ```bash
396
+ AUTH_STRATEGY=oidc \
397
+ PUBLIC_BASE_URL=http://localhost:1234 \
398
+ AUTH_OIDC_CLIENT_ID=your-google-client-id \
399
+ AUTH_OIDC_CLIENT_SECRET=your-google-client-secret \
400
+ docker compose up
401
+ ```
402
+
403
+ If you change `COLLABMD_HOST_PORT`, update `PUBLIC_BASE_URL` and the Google redirect URI to match that host port.
404
+
327
405
  By default, compose uses `COLLABMD_IMAGE=ghcr.io/andes90/collabmd:latest`. If you want to test a local image while developing instead:
328
406
 
329
407
  ```bash
@@ -343,9 +421,11 @@ To use an existing vault on your machine instead of `./data/vault`:
343
421
  HOST_VAULT_DIR=/absolute/path/to/vault docker compose up
344
422
  ```
345
423
 
424
+ `HOST_VAULT_DIR` controls the host-side bind mount source. The app uses `COLLABMD_VAULT_DIR` for the in-container vault path and defaults that to `/data` in Docker.
425
+
346
426
  To bootstrap the compose-managed vault from a private repo, set the git env vars in `.env` and keep `HOST_VAULT_DIR` on a persistent host path. For file-based SSH auth, point `COLLABMD_GIT_SSH_PRIVATE_KEY_FILE` and `COLLABMD_GIT_SSH_KNOWN_HOSTS_FILE` at mounted secret paths; for simpler setups, set `COLLABMD_GIT_SSH_PRIVATE_KEY_B64` instead.
347
427
 
348
- If you want the in-app Git commit action to work inside the container, also set `COLLABMD_GIT_USER_NAME` and `COLLABMD_GIT_USER_EMAIL` so CollabMD can configure the checkout identity automatically.
428
+ If you want the in-app Git commit action to work inside the container without OIDC, also set `COLLABMD_GIT_USER_NAME` and `COLLABMD_GIT_USER_EMAIL` so CollabMD can configure the checkout identity automatically. With `AUTH_STRATEGY=oidc`, CollabMD uses the signed-in Google identity for each commit instead.
349
429
 
350
430
  To change the host port:
351
431
 
@@ -381,6 +461,8 @@ Health check: `GET /health`
381
461
  - The app is reachable only from localhost: pass `--host 0.0.0.0` or set `HOST=0.0.0.0` when you intend to expose it on your network
382
462
  - Port `1234` is already in use: pass `--port 3000` or set `PORT` to another free port
383
463
  - Tunnel did not start: install `cloudflared`, or pass `--no-tunnel` to stay local-only
464
+ - `--auth oidc` fails on startup: set `PUBLIC_BASE_URL`, `AUTH_OIDC_CLIENT_ID`, and `AUTH_OIDC_CLIENT_SECRET`, and make sure the Google redirect URI matches `/api/auth/oidc/callback`
465
+ - Google login loops back to the auth screen: verify the configured `PUBLIC_BASE_URL` matches the browser URL and that your reverse proxy forwards HTTPS correctly
384
466
  - `--local-plantuml` fails: make sure Docker is installed and running, or point `PLANTUML_SERVER_URL` at another PlantUML server
385
467
  - Private git bootstrap fails on startup: verify `COLLABMD_GIT_REPO_URL` plus either `COLLABMD_GIT_SSH_PRIVATE_KEY_FILE` or `COLLABMD_GIT_SSH_PRIVATE_KEY_B64`
386
468
  - WSL2 path issues: run CollabMD against a directory inside your Linux filesystem when possible rather than a mounted Windows path
@@ -487,16 +569,21 @@ scripts/
487
569
  | `AUTH_PASSWORD` | Shared password for `AUTH_STRATEGY=password` | generated per run |
488
570
  | `AUTH_SESSION_COOKIE_NAME` | Session cookie name | `collabmd_auth` |
489
571
  | `AUTH_SESSION_SECRET` | Cookie signing secret | generated per run |
572
+ | `PUBLIC_BASE_URL` | Stable public app origin required for `AUTH_STRATEGY=oidc` | |
573
+ | `AUTH_OIDC_CLIENT_ID` | Google OAuth client ID used for `AUTH_STRATEGY=oidc` | |
574
+ | `AUTH_OIDC_CLIENT_SECRET` | Google OAuth client secret used for `AUTH_STRATEGY=oidc` | |
575
+ | `AUTH_OIDC_ALLOWED_EMAILS` | Comma-separated exact email allowlist for `AUTH_STRATEGY=oidc` | |
576
+ | `AUTH_OIDC_ALLOWED_DOMAINS` | Comma-separated email domain allowlist for `AUTH_STRATEGY=oidc` | |
490
577
  | `BASE_PATH` | URL path prefix for subpath deployments | |
491
578
  | `PLANTUML_SERVER_URL` | Upstream PlantUML server base URL used for server-side SVG rendering | `https://www.plantuml.com/plantuml` |
492
- | `COLLABMD_VAULT_DIR` | Vault directory path | current directory |
579
+ | `COLLABMD_VAULT_DIR` | Vault directory path | CLI: current directory, server entrypoint: `data/vault`, Docker: `/data` |
493
580
  | `COLLABMD_GIT_ENABLED` | Enable or disable git integration in the UI and API | `true` |
494
581
  | `COLLABMD_GIT_REPO_URL` | Remote git repository used to bootstrap the vault checkout | |
495
582
  | `COLLABMD_GIT_SSH_PRIVATE_KEY_FILE` | SSH private key file path for remote git auth; preferred over base64 input | |
496
583
  | `COLLABMD_GIT_SSH_PRIVATE_KEY_B64` | Base64-encoded SSH private key used when no key file path is provided | |
497
584
  | `COLLABMD_GIT_SSH_KNOWN_HOSTS_FILE` | Optional `known_hosts` file path for strict SSH host verification | |
498
- | `COLLABMD_GIT_USER_NAME` | Git author/committer name configured for in-app commits in git-backed deployments | |
499
- | `COLLABMD_GIT_USER_EMAIL` | Git author/committer email configured for in-app commits in git-backed deployments | |
585
+ | `COLLABMD_GIT_USER_NAME` | Fallback git author/committer name for in-app commits when OIDC is not active | |
586
+ | `COLLABMD_GIT_USER_EMAIL` | Fallback git author/committer email for in-app commits when OIDC is not active | |
500
587
  | `WS_BASE_PATH` | WebSocket base path | `/ws` |
501
588
  | `PUBLIC_WS_BASE_URL` | Public WebSocket URL override for reverse proxies | |
502
589
  | `HTTP_KEEP_ALIVE_TIMEOUT_MS` | Keep-alive timeout | `5000` |
package/bin/collabmd.js CHANGED
@@ -61,12 +61,14 @@ if (values.help) {
61
61
  process.exit(0);
62
62
  }
63
63
 
64
- const vaultPath = resolve(positionals[0] || '.');
65
64
  const port = parseInt(values.port ?? process.env.PORT ?? '1234', 10) || 1234;
66
65
  const host = values.host || process.env.HOST || '127.0.0.1';
67
66
  const enableTunnel = !values['no-tunnel'];
68
67
  const useLocalPlantUml = values['local-plantuml'];
69
68
 
69
+ const { resolveCliVaultDir, loadConfig } = await import('../src/server/config/env.js');
70
+ const vaultPath = resolveCliVaultDir(positionals);
71
+
70
72
  process.env.COLLABMD_VAULT_DIR = vaultPath;
71
73
  process.env.PORT = String(port);
72
74
  process.env.HOST = host;
@@ -101,7 +103,6 @@ if (useLocalPlantUml) {
101
103
  }
102
104
 
103
105
  const { createAppServer } = await import('../src/server/create-app-server.js');
104
- const { loadConfig } = await import('../src/server/config/env.js');
105
106
  const { prepareConfigForStartup } = await import('../src/server/startup/git-remote-bootstrap.js');
106
107
 
107
108
  const config = loadConfig({ vaultDir: vaultPath });
@@ -6,7 +6,19 @@ services:
6
6
  environment:
7
7
  HOST: 0.0.0.0
8
8
  PORT: 1234
9
+ AUTH_STRATEGY: ${AUTH_STRATEGY:-none}
10
+ AUTH_PASSWORD: ${AUTH_PASSWORD:-}
11
+ AUTH_SESSION_COOKIE_NAME: ${AUTH_SESSION_COOKIE_NAME:-collabmd_auth}
12
+ AUTH_SESSION_SECRET: ${AUTH_SESSION_SECRET:-}
13
+ PUBLIC_BASE_URL: ${PUBLIC_BASE_URL:-http://localhost:1234}
14
+ AUTH_OIDC_CLIENT_ID: ${AUTH_OIDC_CLIENT_ID:-}
15
+ AUTH_OIDC_CLIENT_SECRET: ${AUTH_OIDC_CLIENT_SECRET:-}
16
+ AUTH_OIDC_ALLOWED_EMAILS: ${AUTH_OIDC_ALLOWED_EMAILS:-}
17
+ AUTH_OIDC_ALLOWED_DOMAINS: ${AUTH_OIDC_ALLOWED_DOMAINS:-}
18
+ BASE_PATH: ${BASE_PATH:-}
19
+ PUBLIC_WS_BASE_URL: ${PUBLIC_WS_BASE_URL:-}
9
20
  PLANTUML_SERVER_URL: http://plantuml:8080
21
+ COLLABMD_VAULT_DIR: ${COLLABMD_VAULT_DIR:-/data}
10
22
  COLLABMD_GIT_REPO_URL: ${COLLABMD_GIT_REPO_URL:-}
11
23
  COLLABMD_GIT_SSH_PRIVATE_KEY_FILE: ${COLLABMD_GIT_SSH_PRIVATE_KEY_FILE:-}
12
24
  COLLABMD_GIT_SSH_PRIVATE_KEY_B64: ${COLLABMD_GIT_SSH_PRIVATE_KEY_B64:-}
@@ -25,7 +37,7 @@ services:
25
37
  volumes:
26
38
  - type: bind
27
39
  source: ${HOST_VAULT_DIR:-./data/vault}
28
- target: /data
40
+ target: ${COLLABMD_VAULT_DIR:-/data}
29
41
  # Optional: mount secret files when using file-based SSH auth.
30
42
  # - type: bind
31
43
  # source: ${HOST_SSH_KEY_FILE}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "collabmd",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "type": "module",
5
5
  "description": "Collaborative markdown vault — like Obsidian, but online. Serve any directory of markdown files for realtime collaborative editing.",
6
6
  "repository": {
@@ -71,6 +71,7 @@
71
71
  "lib0": "^0.2.0",
72
72
  "markdown-it": "^14.1.0",
73
73
  "mermaid": "^11.13.0",
74
+ "openid-client": "^6.8.2",
74
75
  "react": "^19.2.0",
75
76
  "react-dom": "^19.2.0",
76
77
  "ws": "^8.0.0",