Skip to content

feat: password auth + session tokens + user invite#18

Merged
ori129 merged 16 commits intomainfrom
feat/password-auth
Mar 15, 2026
Merged

feat: password auth + session tokens + user invite#18
ori129 merged 16 commits intomainfrom
feat/password-auth

Conversation

@ori129
Copy link
Owner

@ori129 ori129 commented Mar 15, 2026

Summary

  • Password auth — system-admin and ai-leader roles now require a bcrypt password to log in; employees remain email-only (internal VPN is the security gate)
  • Server-side sessions — Bearer tokens stored in login_sessions table with 30-day rolling expiry; all API requests inject Authorization: Bearer <token>
  • Two-step loginPOST /auth/check-email returns requires_password without leaking user existence; login screen adapts accordingly
  • ForceChangePassword gatepassword_temp=true blocks access until user sets a permanent password on first login
  • Admin tools — reset-password endpoint generates a one-time temp password; promote-to-leader modal auto-generates temp password before role change
  • User invite — admin can directly invite users by email (no Compliance API import required); privileged roles get a temp password shown once with copy button
  • DB migrations010_add_password (password_hash + password_temp on workspace_users), 011_add_login_sessions (login_sessions table with expiry index)
  • Backend tests — 20 pytest tests (T1–T20) covering all auth endpoints against real PostgreSQL

Pre-Landing Review

2 issues (0 critical, 2 informational):

  • backend/app/routers/users.py (invite endpoint) — read-check-write on email uniqueness without DB unique constraint; two concurrent admin invites for the same email could create duplicates. Low probability (admin-only). Deferred to TODOS.md.
  • backend/tests/test_auth.py — no tests for POST /users/invite. Deferred to TODOS.md.

Eval Results

No prompt-related files changed — evals skipped.

Test plan

  • All backend tests pass (20/20, 0 failures)
  • No frontend test suite — tested manually via Docker

🤖 Generated with Claude Code

ori129 added 8 commits March 15, 2026 22:15
…essions table

Migrations 010 and 011 — extends workspace_users with bcrypt password
columns and creates login_sessions for session-token-based auth.
auth_utils.py wraps bcrypt hash/verify. schemas.py adds LoginResponse,
CheckEmailResponse, ChangePasswordRequest, ResetPasswordResponse, and
password_temp field to WorkspaceUserRead.
…password, reset-password

- register/login now require password for admin/leader; employees remain email-only
- POST /auth/check-email returns requires_password without leaking user existence
- GET /auth/me validates Bearer token, rolls 30-day session expiry
- DELETE /auth/session revokes server-side session on logout
- POST /auth/change-password; skips old-password check for password_temp accounts
- POST /users/{id}/reset-password generates temp password (admin only)
pytest setup with real PostgreSQL test database. Covers register,
login, check-email, /me token validation + rolling expiry, logout,
change-password (normal + temp-skip), and reset-password (admin-only).
…ontext

- types: add password_temp, LoginResponse, CheckEmailResponse
- api/client: inject Authorization header from localStorage session_token
- AuthContext: boot via GET /auth/me, store token on login/register,
  revoke session on logout, expose refreshUser()
…word gate

- RegisterScreen: password + confirm fields with min-8 validation
- LoginScreen: check-email first, show password field only when required
- ForceChangePassword: full-screen blocking modal for password_temp accounts
- App.tsx: gate renders ForceChangePassword before main app when password_temp=true
- Reset Password button per row (admin only, non-employee users)
- Promotes to ai-leader now intercepts dropdown to generate temp password first
- Temp password shown once in modal with copy button
…misc cleanup

README redesigned with screenshots and collapsible API sections.
admin/reset now deletes workshops/categories/sync_logs in FK order.
SECURITY.md contact info updated. TODOS.md added. .gitignore updated.
@ori129 ori129 requested a review from aarbiv as a code owner March 15, 2026 20:16
ori129 added 2 commits March 15, 2026 22:20
- POST /users/invite (system-admin only): creates WorkspaceUser with local-{uuid} id,
  generates temp password for system-admin/ai-leader roles, returns temp_password in response
- InviteUserRequest / InviteUserResponse schemas
- Frontend: InviteUserModal (email + name + role), "Invite User" button in Users panel header
- useInviteUser React Query mutation + InviteUserResponse type
- Employees get email-only login; privileged roles get a temp password shown once with copy button
@ori129 ori129 changed the title feat: password auth with session tokens feat: password auth + session tokens + user invite Mar 15, 2026
ori129 and others added 2 commits March 15, 2026 23:02
…f-strings)

- Remove unused ResetPasswordResponse import from auth.py
- Remove unused instr_len variable in mock_semantic_enricher.py
- Remove f-prefix from two literal strings in pipeline.py
- Remove unused pytest imports from conftest.py and test_auth.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…imports

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ori129 ori129 removed the request for review from aarbiv March 15, 2026 21:08
ori129 and others added 4 commits March 15, 2026 23:09
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auth_deps.py was untracked (never committed) — caused backend container crash
- add pytest-asyncio to CI install so conftest.py imports succeed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tests require a real PostgreSQL with pgvector — add service to backend
job and wire TEST_DATABASE_URL to localhost. Remove the exit-5 bypass
now that the DB is available.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The pgvector/pgvector image has the extension available but it must be
explicitly enabled per-database before the vector type can be used.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ori129 ori129 merged commit 6b1ff7c into main Mar 15, 2026
6 checks passed
@ori129 ori129 deleted the feat/password-auth branch March 15, 2026 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant