Governance - Access Control & Permission Hierarchy
Governance — Access Control & Permission Hierarchy
Trystpilot’s access model is intentionally flat for MVP. The moderation dashboard is the only
admin-gated surface, protected by a single ADMIN_SECRET environment variable checked in the
server component. Known issue: the current implementation fails open — if ADMIN_SECRET is
not set, the dashboard is accessible. This must be patched before public launch.
Permission Hierarchy
graph TD
subgraph "Access Layers"
Public["Public Layer\n(no auth required)"]
AdminLayer["Admin Layer\n(ADMIN_SECRET required)"]
PhaseTwo["Phase 2 Layer\n(session-based moderator auth)"]
end
subgraph "Public Surfaces"
Home["/ (Home)"]
ProfilePage["profile/[alias]"]
Submit["/submit"]
Report["/report"]
Legal["/legal/*"]
Blog["/blog/*"]
APIRead["GET /api/profiles/*"]
end
subgraph "Admin Surfaces"
Mod["/moderation"]
APIModerate["PATCH /api/reviews/[id]/moderate"]
APICreateProfile["POST /api/profiles"]
end
subgraph "Middleware (middleware.ts)"
RateLimit["Rate Limit check"]
SecurityHeaders["Security headers\n(CSP, X-Frame-Options…)"]
AdminCheck["ADMIN_SECRET check\n⚠️ fails open without secret"]
end
Public --> Home & ProfilePage & Submit & Report & Legal & Blog & APIRead
AdminLayer --> Mod & APIModerate & APICreateProfile
All["All requests"] --> RateLimit --> SecurityHeaders
Mod & APIModerate & APICreateProfile --> AdminCheck
Security Hardening Checklist
| Control | Status | Notes |
|---|---|---|
| Admin secret check | ⚠️ Partial | Fails open if ADMIN_SECRET unset |
| Rate limiting | ❌ Broken | In-memory; must migrate to Upstash Redis |
| CAPTCHA on submit | ❌ Not wired | hCaptcha placeholder exists |
| Security headers (CSP, HSTS) | ✅ | Set in middleware.ts |
| PII never stored in plain text | ✅ | Zip = internal; hashed fingerprints only |
| Secrets in env vars only | ✅ | .env.example is canonical reference |
| SQL injection prevention | ✅ | Parameterised queries via pg client |
| XSS prevention | ✅ | React escapes by default; no dangerouslySetInnerHTML |
| Audit logging | ❌ | Not implemented — Phase 2 |