Goal
Staff log in with e-mail and password (invite-only). Every user belongs to a company (Better Auth organization), and every tenant-owned query runs inside withTenant under forced row-level security.
Acceptance criteria
Not part of this task
- SSO / Entra ID, magic link, role-admin UI (invite form + seed script only)
Affected areas
src/features/identity/
src/features/tenancy/
src/db/
Test plan
| Criterion |
Check |
| sign-up and login |
integration test |
| cross-tenant read/write |
integration test with two tenants, repository and raw SQL |
| authorize() |
unit test |
Security/Privacy affected?
Yes – authentication, authorization and tenant isolation. Run security-review before ready-for-review.
Epic: #2 · Architecture: docs/decisions/ADR-0001-pilot-architecture.md
Goal
Staff log in with e-mail and password (invite-only). Every user belongs to a company (Better Auth organization), and every tenant-owned query runs inside
withTenantunder forced row-level security.Acceptance criteria
withTenant(companyId, fn)setsapp.company_idtransaction-locally; repositories cannot be called without a tenant contextapp_rwapp_rw, when a row carrying the id of another company is inserted, then RLS rejects itadminandclerk;authorize()denies admin-only actions to clerks@better-auth/drizzle-adapter; built-in rate limit uses database storage; only organization + admin pluginsNot part of this task
Affected areas
src/features/identity/src/features/tenancy/src/db/Test plan
Security/Privacy affected?
Yes – authentication, authorization and tenant isolation. Run
security-reviewbefore ready-for-review.Epic: #2 · Architecture:
docs/decisions/ADR-0001-pilot-architecture.md