Access Control Policy
1. Scope
This policy applies to all systems that store, process, or have access to customer data — production infrastructure (Supabase, Cloudflare, Edge Functions), source control (GitHub), payment processing (Stripe), data aggregation (Plaid), transactional email (Resend), and any administrative consoles required to operate them.
2. Zero Trust Access Architecture
WhaleWatch operates on a zero-trust model: there is no implicit trust granted to any network, device, or service. Every access request is authenticated and authorized on every call. The architecture meets this in the following concrete ways:
- No perimeter trust / no VPN. All systems are SaaS, accessed over the public internet. There is no “inside the network” — every request is treated as untrusted until authenticated.
- Identity-everywhere. Every user-facing request carries a Supabase JWT; every service-to-service call carries a signed service-role JWT or OAuth bearer token over TLS 1.2+.
- Least privilege via RBAC + RLS. Database access is scoped by Supabase role (
anon,authenticated,service_role). User-owned tables enforce Row-Level Security so a request authenticated as user A can never read user B's rows. Theservice_rolekey bypasses RLS and is restricted to server-side Edge Functions only. - Microsegmentation through SaaS isolation. Application code runs in isolated Deno workers (Supabase Edge Functions); database lives in a managed Postgres on a separate Supabase-managed network; the web tier is served from Cloudflare's edge with WAF in front. Each layer authenticates the next.
- MFA on every administrative account. Supabase, Cloudflare, GitHub, Stripe, Plaid (production), and the underlying email account each enforce multi-factor authentication. See the MFA Implementation Evidence exhibit for the current factor inventory.
- Continuous verification. Sessions issued by Supabase Auth expire automatically; refresh tokens are rotated on each use. No long-lived credentials.
- Encryption everywhere. TLS 1.2+ in transit (TLS 1.3 negotiated by default), AES-256 at rest on the database storage layer.
This implementation is consistent with the principles of NIST SP 800-207 (Zero Trust Architecture) — specifically PE-3, AC-2, AC-3, and IA-2 controls — as applied to a small, all-SaaS operation.
3. Roles and Privileges
The following roles exist in our environment:
Privileges are granted using the principle of least privilege. Elevated roles (Production-Admin, DB-Admin) are restricted to the minimum number of personnel required to operate the service.
4. Authentication and Credential Standards
- Strong passwords. Supabase Auth requires minimum complexity and rejects passwords known to be compromised.
- MFA mandatory for all administrative roles. See §2 above.
- No shared accounts. Each administrator uses a unique identity. Service-to-service access uses signed JWTs scoped to a service role, not impersonated user identities.
- Secrets in environment variables only. API keys and service credentials live in Supabase Edge Function secrets and Cloudflare Pages environment variables — never in source control.
- Session expiration and rotation. JWTs expire automatically; refresh tokens rotate on each use.
5. Periodic Access Reviews and Audits
We conduct a documented access review on a quarterly cadence, plus ad-hoc reviews triggered by any of the following events:
- A team member changes role or leaves the organization.
- A subprocessor is added, removed, or experiences a security incident.
- Suspected unauthorized access or anomalous activity in audit logs.
Each review covers, at minimum:
- Active accounts on Supabase, Cloudflare, GitHub, Stripe, Plaid, and Google Workspace / email.
- API keys and service-role tokens currently in use, with last-used timestamp where available.
- Plaid items connected by users, with a sample audit of recent disconnect requests to confirm they were honored on Plaid's side via
/item/remove. - Whether any accounts are dormant (no login in >90 days) and should be removed.
- Whether any granted privilege exceeds the role's documented baseline.
The output of each review is a dated record (PDF or markdown) listing accounts reviewed, decisions taken, and a sign-off. Records are retained for at least three years.
6. Joiner / Mover / Leaver Process
Joiner. A new team member is provisioned with the minimum set of roles required for their function (see §3). Provisioning is logged in the next quarterly access review. MFA enrollment on every system is a precondition before any access is granted.
Mover. When a team member changes role, their existing access is re-evaluated against the new role's baseline. Privileges no longer needed are removed within five business days. The change is recorded in the next access review.
Leaver. When a team member departs (voluntary or involuntary), access is revoked across all systems on the same business day. Specifically:
- Supabase — remove from project members; rotate any service-role keys they had access to.
- Cloudflare — remove from account members.
- GitHub — remove from organization; review and revoke any personal access tokens, deploy keys, or installed apps tied to their identity.
- Stripe — remove from team.
- Plaid Dashboard — remove from team.
- Google Workspace / email — disable account; transfer ownership of any service-account credentials they held.
- Shared secrets — rotate any credentials, API keys, or webhook secrets they had access to within 24 hours.
Each system listed above supports immediate revocation through its own admin UI or API; revocation is therefore automated in the sense that no batch job, manual ticket queue, or downstream sync is required for the change to take effect — the single action in the source system removes access globally for that system.
7. Vendor and Third-Party Access
We do not grant production access to vendors or third parties. Subprocessors (Supabase, Cloudflare, Plaid, Stripe, Resend, etc.) operate their own infrastructure under their own access controls; we hold each to the security commitments published in our Information Security Policy §8. No vendor receives a credential to our systems.
8. Logging, Audit, and Incident Response
- Supabase records every database query, authentication event, and Edge Function invocation in audit logs accessible to administrators.
- Cloudflare records every HTTP request with source IP, path, status, and user agent.
- Authentication failures, privilege escalations, and unusual access patterns are reviewed during the quarterly access review.
- Suspected access-control incidents are escalated to [email protected] and triaged immediately on receipt; full incident-response procedures are documented in Information Security Policy §7.
9. Exceptions
Any deviation from this policy must be approved in writing by the policy owner (operations team), documented with the business justification, time-limited (no standing exceptions), and reviewed at the next quarterly access review.
10. Roles and Responsibilities
- Policy owner. WhaleWatch operations team — accountable for maintaining and enforcing this policy.
- Access review chair. Operations team — runs the quarterly review and produces the sign-off record.
- Incident escalation. Any access-control incident is escalated to [email protected].
11. Review Cadence
This policy is reviewed at least annually, and additionally whenever the organization adds personnel, adds or removes a subprocessor, or experiences an access-control incident.
12. Compliance Mapping
This policy is designed to be consistent with:
- NIST SP 800-207 — Zero Trust Architecture
- NIST SP 800-53 — AC-2 (Account Management), AC-3 (Access Enforcement), AC-6 (Least Privilege), IA-2 (Identification and Authentication)
- SOC 2 Common Criteria CC6.1, CC6.2, CC6.3 (logical and physical access)
- ISO/IEC 27001:2022 Annex A — A.5.15 (access control), A.5.18 (access rights), A.8.2 (privileged access rights)
- PCI DSS v4.0 Requirement 7 (restrict access by business need to know) and 8 (identify users and authenticate access)
13. Contact
For questions about this policy, contact [email protected]. For incidents involving access-control failures, contact [email protected].