Repository navigation
feat(auth): control schema, local accounts and sign-in sessions (M2a, #92) - #98
Merged
Merged
Conversation
…92) Migration 0004 adds a control schema (name from CONTROL_SCHEMA) with tenants, users, memberships (the four ADR-0003 roles) and sessions. Passwords use stdlib scrypt; session tokens are random, returned once and stored as SHA-256 hashes. POST /api/auth/login, POST /api/auth/logout and GET /api/auth/me; require_session is ready for the data routers (#93, #94) but not applied to them yet. scripts/create_tenant_admin.py creates a tenant and its first admin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YPoXzBSj89ZHgw7nfTmbB
This was referenced Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #92. This is part 1 of 5 of ART Milestone 2 (BR-36; ADR-0003).
What changes
Migration
0004_control_schema. Adds acontrolschema (name set byCONTROL_SCHEMA) with four tables:tenants: the slug is checked as^[a-z][a-z0-9_]{1,40}$.users.memberships: one role per user per tenant, limited touploader,reviewer,tenant_adminorauditor.sessions.Downgrade drops the schema.
api/services/accounts.py.hashlib.scrypt, so there's no new dependency and it works air-gapped.secrets.token_urlsafe(32). The token is returned once, and only its SHA-256 is stored./api/authendpoints.POST /login(tenant, username, password) returns a token,POST /logoutrevokes it, andGET /mereturns the user, tenant and role.What makes a session invalid. Expiry (
SESSION_TTL_HOURS, default 12), logout, deactivating the user, or removing their membership all end a session immediately.require_sessiondependency. Ready for use, but not yet applied to the data routers. M2b: route every request to its tenant's schema (BR-36) #93 (tenant routing) and M2c: role-based authorisation matrix (BR-36) #94 (role matrix) switch them over. Until then the existing API-key gate is unchanged.scripts/create_tenant_admin.py. Creates a tenant and its first admin. It reads the password fromTE_ADMIN_PASSWORDor prompts for it, and requires at least 12 characters.Other changes. CORS now allows the
Authorizationheader.docs/ENV_VARIABLES.mddocuments the two new settings. The migration tests now use a throwaway control schema, so they never drop the live one.Evidence
All runs are against local PostgreSQL 16.
scripts/test_report.py --strict)tests/test_accounts.py+tests/test_migrations.pyscripts/lint.shtenant_admin); a short password is refusedThe login endpoint is covered by the existing global rate limit for writes (20 per minute per client). A per-account lockout isn't included; say if you want it.
Generated by Claude Code