מפתחים
Application hardening
Maintainer reference for Next.js / client-facing hardening that complements DB authz.
Role resolution in the app
- Proxy (
src/proxy.ts): loadsprofiles.rolefor the authenticated user. On profile-fetch timeout, does not treat the user as a trusted teacher — fail closed for privileged routes. - Login / signup / callback: resolve role from
profiles, never fromuser_metadata. - Server actions: prefer
requireUser/requireTeacher/requireTeacherWorkspacefromsrc/lib/auth/guards.ts.
guards.ts is a shared server helper module (not a "use server" actions barrel) so it is not exposed as client-callable actions by itself.
HTTP security headers
Configured in next.config.ts for /:path*:
| Header | Purpose |
|---|---|
Content-Security-Policy | Restrict scripts, frames, connect, media, workers |
X-Content-Type-Options: nosniff | Block MIME sniffing |
X-Frame-Options: DENY | Clickjacking |
Referrer-Policy: strict-origin-when-cross-origin | Limit referrer leakage |
Permissions-Policy | Disable camera, mic, geolocation, payment |
Strict-Transport-Security | Production only |
Also: poweredByHeader: false.
CSP allows known needs (Supabase hosts, fonts, unpkg for pdf.js worker, talmud.dev frames). Tighten further when nonce-based CSP is wired.
Passwords
- UI minimum: 8 characters (
minLength={8}, placeholder «לפחות 8 תווים») - Hebrew error copy aligns with that minimum (
src/lib/utils/auth-errors.ts)
Known gap (not live)
Supabase leaked-password protection (Have I Been Pwned) requires a Pro plan. The project org is on Free — this is not enabled. Enable after upgrading; do not document it as active.
Havruta media uploads
- Private bucket; MIME allowlist on upload (images / audio types enforced in
havruta-mediaactions) - Clients receive signed URLs with TTL 2 hours (
HAVRUTA_SIGNED_URL_TTL_SECinsrc/lib/havruta/signed-media.ts) - Storage policies + app checks prevent arbitrary file types
Server Actions body size
Teacher PDF / page upload payloads can be large; experimental.serverActions.bodySizeLimit is raised to 10mb in next.config.ts for that pipeline — not a general public upload free-for-all.
Checklist for future PRs
- New privileged actions call
requireTeacher/requireTeacherWorkspace(or equivalent) - No new authz based on
user_metadata.role - New storage buckets stay private + MIME-scoped
- CSP updated if new third-party origins are required
- Revisit leaked-password protection when on Pro
