Multi-tenancy: user accounts and per-user vaults #111
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lz/agent-nexus#111
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Exploratory. Nexus is single-operator by design ("There is no user table — a master passphrase unlocks the vault", AGENTS.md). This issue records what actually has to change if that stops being true, so the decision is made deliberately rather than discovered halfway through.
Not a commitment to build it. Prerequisite for internet exposure: #110.
The load-bearing assumption
event.locals.masterKeyis not an identity token — it is the unlocked master key, held in RAM for the duration of a session (hooks.server.ts:17,auth/session.ts:4). Everything sealed under it (connections.encrypted_token,repo_env_vars) is instance-global, decryptable by anyone holding the one passphrase.Multi-tenancy is not "add a user table and a
user_idcolumn". It requires deciding what a tenant owns and re-keying accordingly. The realistic shape is per-user key material: a per-user key wrapped by that user's password-derived key, so a user's secrets are unreadable without their credentials. That is a vault redesign, and it invalidates the currentrotateMasterPassphrase+sealed-columns.test.tscontract.What each subsystem inherits from single-tenancy
/session/dot-claude/is one directory symlinked into every worker, one.credentials.json, one account (AGENTS.md fact #3). Quota is account-global and stored once, last-write-wins (fact #19). Tenants sharing one Anthropic account is almost certainly not what you want, and separating it means per-tenant session volumes — which touches the worker entrypoint, the Config Explorer bind mount, and quota.~/.claudeconfig volume —settings.json,CLAUDE.md,skills/,agents/— is live-shared across the whole fleet. Under multi-tenancy every edit in the Config Explorer is an edit to everyone's agent config./api/auth/lockis global (#110 item 3).preview_bind_interface). One tenant switching tounrestrictedexposes every tenant's previews.Session model
Whatever else changes, sessions need what #108 establishes: sliding idle timeout plus an absolute ceiling, and sliding driven by user-initiated requests rather than background polls. #108 deliberately builds that shape now so it does not need revisiting here.
Sessions also stop being able to live only in a
Map— see #110 item 2. The hard part is not storage, it is that a persisted session without its key is authenticated but locked, so key custody across restarts has to be answered first.Suggested decomposition, if pursued
Steps 3 and 5 are the expensive ones and are where this should be reconsidered.