Access Control Policy
Owner: Backend Lead / Admin Last Edited: March 26, 2026 Last Reviewed: March 26, 2026
1. Access Layers
Prism has three distinct access layers:
| Layer | System | Controls |
|---|---|---|
| User authentication | Clerk | SSO, MFA, session management |
| User authorization | Clerk org permissions → backend scopes | What an authenticated user can do |
| Service-to-service | Prism API keys | Scoped, expiring, per-org machine tokens |
| Infrastructure | GitHub, Supabase/RDS, Redis, Cloudflare, monitoring | Admin access to production systems |
2. Clerk Roles and Scope Mapping
Org roles
| Clerk org role | Who it is for | Backend scopes granted |
|---|---|---|
admin | Org owners and operators | All scopes including api_keys:manage, audit:read |
member | Standard users | buildings:read, comps:read, comps:write, tims:read, tims:write, reports:read, reports:write |
read_only | Read-only stakeholders | buildings:read, comps:read, tims:read, reports:read |
The canonical scope list is defined in go-backend/internal/domain/auth.go. The mapping from Clerk org_permissions to backend scopes is normalized in go-backend/internal/middleware/auth.go.
STRICT_CLERK_SCOPES=true must be set in production. When strict mode is on, a missing or empty org_permissions claim is treated as zero-scope (deny-by-default), not a fallback grant.
Infrastructure roles
| System | Role | Who holds it |
|---|---|---|
| GitHub | Owner / Admin | Engineering lead only |
| GitHub | Write | Active engineers |
| Infisical | Admin | Backend lead / Ops lead only |
| Infisical | Member (read-only prod) | Active engineers (when dev environment is set up) |
| Supabase / RDS | DB owner | Backend lead only (break-glass) |
| Supabase / RDS | App role (prism_app) | API process only — no SUPERUSER, no BYPASSRLS |
| Redis | Admin | Backend lead only |
| Cloudflare | Admin | Ops lead only |
| Sentry | Admin | Backend lead only |
| Sentry | Member | Active engineers |
| Render | Admin | Ops lead only |
| Clerk Dashboard | Admin | Backend lead only |
3. MFA and SSO Requirements
MFA must be enforced for all accounts that have access to production systems:
- GitHub: require MFA for all org members (GitHub org settings → Authentication security)
- Clerk Dashboard: enable MFA on the Clerk admin account
- Supabase / cloud DB console: MFA enforced
- Cloudflare: MFA enforced
- Sentry: MFA enforced
- Render: MFA enforced
Single sign-on (SSO) is enforced for end users via Clerk. There is no direct username/password login to the Prism application.
4. Joiner Process (New Team Member)
- Add to GitHub org with appropriate role (Write for engineers, Read for stakeholders).
- Create Clerk account and assign to the correct Prism org with the correct role.
- Provision access to any infrastructure systems (Supabase console, Cloudflare, monitoring) based on their role.
- Do not share personal credentials. Each person gets their own account.
- Record the provisioning date.
5. Mover Process (Role Change)
- Update Clerk org role to the new role.
- Update GitHub org role if it changed.
- Update infrastructure access if it changed.
- Verify old permissions are removed and new ones are active.
- Record the change date.
6. Leaver Process (Off-boarding)
This must be completed on the day of departure, not deferred.
- Clerk: remove user from all Prism orgs in the Clerk dashboard.
- GitHub: remove from the GitHub org or revoke write access.
- Infrastructure: revoke access to Supabase/RDS console, Cloudflare, Sentry, Render.
- Prism API keys: revoke any API keys issued to the departing person or their services.
- Infisical: revoke access to the Infisical project.
- Slack webhooks / other integrations: rotate if the person had access to webhook URLs.
- Shared credentials: rotate any shared secrets the person had access to.
- Record the off-boarding date.
7. Access Review Cadence
A formal access review must be conducted monthly.
Monthly access review checklist:
- Export active Clerk org members and verify each has the correct role.
- Check GitHub org members — remove anyone no longer on the team.
- Review Prism API key list (
GET /api/v1/api-keys) for each org — revoke stale or unrecognized keys. - Review Infisical project members — remove anyone no longer on the team.
- Review infrastructure access (Supabase, Cloudflare, Sentry, Render) — remove stale accounts.
- Confirm MFA is still enforced on all systems.
- Record completion and any changes made.
Store access review records in docs/audit/access-reviews/.
8. API Key Policy
- API keys are org-scoped and must be created with the minimum set of scopes required.
- Keys must have an expiration date set (
expires_in_days). - Keys are stored hashed in the database — the plaintext key is only shown once at creation.
- Keys can be revoked at any time via
DELETE /api/v1/api-keys/{id}(requiresapi_keys:managescope). - Do not put API keys in frontend code, browser environments, or version control.
9. Related Docs
go-backend/internal/domain/auth.go— canonical scope definitionsgo-backend/internal/middleware/auth.go— scope normalization logicdocs/backend/account-profile-onboarding-guide.md— Clerk claim expectations and role setupdocs/security/secrets-management.md— secret rotation including API keysdocs/security/incident-response.md— compromised account response