Harden for production: auth, error handling, UI cleanup#2
Conversation
- Delete design-exploration mockups (Departure Board, Terminal, Schematic) and the design-picker Home page — all carried mock data. - Page1 → Directory: talent directory backed by GET /roles, mock task counts and activity log removed. - Page4 → Status: hired-employee health backed by GET /agents, mock channel decoration removed. - Add ProtectedRoute guard, RootRedirect, and a root ErrorBoundary. - Trim DockNav to real routes; / redirects by auth state. - Move the hardcoded ngrok host out of vite.config into ALLOWED_HOSTS env. - Replace raw error text in the Signal Feed with friendly messages. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Root .gitignore: ignore .vscode/, add trailing newline. - app/.gitignore: normalize node_modules/ entry. - CLAUDE.md: rewritten guidance; backend test count now 97. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Authentication
- Real password login: bcrypt-hashed passwords (migration 003), 8-72
char policy. Signup and login both require a password.
- Login returns a single generic error for unknown email vs. bad
password, so the endpoint can't enumerate accounts.
- /users locked down: GET/DELETE /users/{id} now require auth and only
expose the caller's own record; the unauthenticated user-list
endpoint is removed.
- Missing API key returns 401 instead of 422.
OAuth
- Signed, 10-minute-expiry state tokens (app/utils/oauth_state.py).
The user API key no longer travels to Slack/Google/GitHub or their
logs; state doubles as CSRF protection.
Error handling & hardening
- Global exception handlers: internal errors are logged server-side
but clients only see a generic message; upstream httpx failures map
to 502. Structured logging configured.
- Rate limiting via slowapi: signup 10/hour, login 10/minute.
- CORS tightened — env-driven origins, narrowed methods/headers,
dropped the stale localhost:3000 default.
- gateway.send_email no longer reports success on a 4xx/5xx response.
Schema
- migrations/schema.sql: consolidated idempotent snapshot for fresh
Supabase databases (001 + 002 + 003).
Frontend
- Login page gains a password field; api.ts signup/login updated.
Tests: 97 passing (was 78). New deps: bcrypt, slowapi.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
@claude do a review |
|
Claude finished @michaelzwang13's task in 3m 43s —— View job Review —
|
1. Password length was validated in characters, not bytes, so a long multi-byte password could exceed bcrypt's 72-byte limit and be silently truncated into a collision. Passwords are now SHA-256'd and base64-encoded before bcrypt — a fixed 44-byte, null-free input — so length no longer matters. test_passwords.py covers the case. 2. The OAuth start endpoints took the API key as a URL query param, leaking it into backend/proxy access logs and browser history. They now authenticate via the X-Api-Key header and return the consent URL as JSON; the frontend's startOAuth() fetches it and redirects. The key never appears in a URL. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Production-hardening pass over the hackathon build. No new product features — tightens security, error handling, and the frontend surface.
Frontend — UI consolidation & guards (
3902fab)Page1 → Directory: talent directory backed by realGET /roles; mock task counts and activity log removed.Page4 → Status: hired-employee health backed by realGET /agents; mock decoration removed.ProtectedRouteguards,RootRedirect, and a rootErrorBoundary.DockNavto real routes; raw error text replaced with friendly messages.vite.config.tsinto anALLOWED_HOSTSenv var.Backend — auth & API hardening (
0eaea02)003), 8–72 char policy. Login returns one generic error for unknown-email vs. bad-password (no account enumeration)./userslocked down:GET/DELETE /users/{id}require auth + self-ownership; the unauthenticated user-list endpoint is removed.state: 10-min-expiry HMAC tokens — the API key no longer travels to Slack/Google/GitHub or their logs.httpxfailures map to502. Structured logging added.slowapi): signup10/hour, login10/minute.gateway.send_emailno longer reports success on a 4xx/5xx response.migrations/schema.sql: consolidated idempotent snapshot for fresh databases.Testing
/userslockdown, and OAuth state).tscbuild andeslintclean.New dependencies
bcrypt,slowapi(backend).Migration required
Run
backend/migrations/schema.sql(or003_add_password.sqlon an existing DB) in the Supabase SQL Editor — addsusers.password_hash.Still to come (not in this PR)
🤖 Generated with Claude Code