docs: users is unique per instance, not globally
The old index was load-bearing because two lookups were unscoped. Both are scoped now and the unscoped helper is gone, so the property that matters is the absence of any unscoped lookup by email. Says so, and documents auth_source hq. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -198,7 +198,14 @@ sitesvc also (re)declares the unique indexes on `users.email` and `orgs.slug` at
|
||||
- **Roles** — `owner`, `admin`, `member`. `/api/settings` and `/api/org/*` require owner or admin.
|
||||
- **Host/org guard** — `APP_ROOT_LABEL` (default `vantage`) defines the app root label. A request to `<slug>.vantage.<tld>` resolves that org from the slug and rejects sessions belonging to a different one. Org lookups are cached for 60s.
|
||||
|
||||
Unique indexes on user email and org slug are a **security property**, not an optimisation: `GetUserByEmail` does an unscoped `FindOne`, so duplicates would let the OIDC cross-org guard compare against an arbitrary user. Same for duplicate settings docs and duplicate ESO token hashes.
|
||||
Unique indexes are a **security property**, not an optimisation. `users` is
|
||||
unique on `(instance_id, email)` — one address is one user *within* an instance,
|
||||
and the same address may hold a user in several instances, because an account's
|
||||
people are projected into each instance they are granted. This is sufficient only
|
||||
because **every lookup by email is scoped by instance**; there is deliberately no
|
||||
unscoped lookup anywhere, and adding one would let the login path return an
|
||||
arbitrary one of several matching users. Instance slug, settings instance and ESO
|
||||
token hash remain globally unique.
|
||||
|
||||
---
|
||||
|
||||
@@ -315,6 +322,7 @@ Notes that are not obvious from the structs:
|
||||
- `assignments.revoked_at: null` means active. Revocation is soft, preserving audit history.
|
||||
- `workflow_runs.steps_snapshot` freezes the resolved steps so editing the library never rewrites history.
|
||||
- `console_sessions.token_consumed_at` is set atomically to enforce one-time use.
|
||||
- `users.auth_source` is `local`, `oidc` or `hq`. An `hq` user was projected from a Vantage HQ account and carries `hq_user_id`; HQ owns its role, password and existence.
|
||||
|
||||
### Migrations
|
||||
|
||||
@@ -426,7 +434,7 @@ Windows: MSI built by CI (WiX), or `installer/setup.ps1` registering the agent a
|
||||
- AES-256-GCM at rest for private keys, key passphrases, vault secrets, OIDC client secrets, RDP/VNC credentials.
|
||||
- Console session tokens are one-time; RDP credentials are consumed on tunnel open.
|
||||
- ESO read token stored as a SHA-256 hash and rotatable.
|
||||
- Unique indexes on user email, org slug, settings org, and ESO token hash are load-bearing for tenant isolation.
|
||||
- Unique indexes on `(instance_id, email)`, instance slug, settings instance and the ESO token hash are load-bearing for tenant isolation. So is the absence of any unscoped lookup by email.
|
||||
- `authorized_keys` written `0600`, owned by root. The agent runs as root because it must.
|
||||
- Every mutating API path writes an audit event.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user