diff --git a/serverAppConfigs-docs/Dankclaw/Open Notebook.md b/serverAppConfigs-docs/Dankclaw/Open Notebook.md index 1df844f..547fe98 100644 --- a/serverAppConfigs-docs/Dankclaw/Open Notebook.md +++ b/serverAppConfigs-docs/Dankclaw/Open Notebook.md @@ -45,6 +45,8 @@ open-notebook ([lfnovo/open-notebook](https://github.com/lfnovo/open-notebook)) The app's own login stays on behind the chain. It is not redundant: publishing the API on loopback does **not** hide it from this host's other containers, which can dial `open-notebook:5055` by name on `dankclaw_default`. The chain decides *who from outside* gets in; `OPEN_NOTEBOOK_PASSWORD` decides what anything that already reached the port may do. +**Single tenant — there are no user accounts, so this is an admin-side tool.** Upstream ships one global password and nothing else: `PasswordAuthMiddleware` compares `Bearer `, and the SurrealDB schema has no user/account/owner table (verified in the running image, 2026-10-20). One shared password therefore means **one shared workspace** — the guard chain can gate the door but cannot partition the data, and Authentik identity is never consumed. Multi-user is *approved but unbuilt* upstream (issue **#712**, "design phase, targeted post-v2"); OIDC/SSO was declined for now (**#607** closed). Real per-person isolation means **one deployment per person**, not a flag to flip. For that reason the homepage lists open-notebook under **admin**, not as a user-facing app. + ## What the image actually runs One container, three processes under supervisord (`supervisord.conf` upstream): `uvicorn api.main:app --port 5055` (`:12`), the job worker (`:25`), and the Next.js frontend (`:39`). Two consequences the config depends on: diff --git a/shared/homepage/services.json b/shared/homepage/services.json index 229ef15..9414d14 100644 --- a/shared/homepage/services.json +++ b/shared/homepage/services.json @@ -30,9 +30,9 @@ }, { "name": "open-notebook", - "category": "user", + "category": "admin", "section": "AI", - "description": "Podcast generator — notes in, spoken episode out: script written by frank-zealot, voices rendered by frank-tts. Guarded twice: Authentik at the edge, then its own login.", + "description": "Podcast generator — notes in, spoken episode out: script written by frank-archon, voices rendered by frank-tts. Guarded twice: Authentik at the edge, then its own login. Single shared password, no per-user accounts — admin-only.", "url": "http://notebook.franksdank.cloud", "docs": "", "probe": "127.0.0.1:8502", diff --git a/tests/open_notebook.bats b/tests/open_notebook.bats index 87a084f..ee40c98 100755 --- a/tests/open_notebook.bats +++ b/tests/open_notebook.bats @@ -290,7 +290,9 @@ vhost = sys.argv[2] cards = [s for s in data if s["name"] == "open-notebook"] assert len(cards) == 1, f"expected exactly one open-notebook card, got {len(cards)}" card = cards[0] -assert card["category"] == "user" and card["section"] == "AI", card +# category moved to "admin": single shared password, no per-user accounts, so it +# is positioned as an admin-side tool, not a user-facing app (see the vault page). +assert card["category"] == "admin" and card["section"] == "AI", card assert card["probe"] == "127.0.0.1:8502", card["probe"] assert card["method"] == "http" # Deployed and guarded: the card is live and its link is the vhost, so the