Access Control Policy
Who can reach production and consumer financial data, how that is enforced, and how it is checked. This is the access control section of Bifold's information security policy, expanded. Bifold is a single-developer operation on managed infrastructure, so the controls lean on the platform boundary rather than on process between people.
1. Scope
Covers every system that can reach consumer financial data: the Supabase project (Postgres database, authentication, edge functions, project secrets), the source repository, the Plaid dashboard, the Apple developer account, the Vercel project serving the public site, and the development machine.
2. Principles
- Deny by default. Access is granted only where a task requires it, never pre-emptively.
- Least privilege. Each role holds the narrowest set of rights that lets it do its job.
- No shared accounts. Every console login is an individually owned, named account. No credential is shared with anyone, ever.
- Enforced at the data layer. Authorization is a property of the database, not of application code that could be bypassed.
3. Human access to production
One person holds administrative access: Eeshan Kulkarni, owner and sole developer. There are no employees, contractors or third parties with standing access.
- Multi-factor authentication is required on every console that can reach production or consumer data - the Supabase dashboard, the source repository, the Plaid dashboard, the Apple developer account and Vercel. An account without MFA does not get production access.
- Console credentials are unique per service, generated and stored in a password manager, and never reused.
- Direct database access is through the platform console only. There is no shared database superuser credential in circulation and no standing production shell.
4. Consumer access to their own data
- Identity: Sign in with Apple. Bifold operates no password of its own, so there is no consumer password to leak, reset or reuse. Apple requires two-factor authentication on every Apple ID.
- Step-up before a bank connection: Face ID, Touch ID or the device passcode is required immediately before Plaid Link is surfaced, on every path into it - first run, adding another bank, and repairing an existing one. All three factors are bound to the device and cannot be phished. A device with none of them set up is refused rather than let through.
- Bank credentials are never held. Bank usernames, passwords and one-time codes are entered into Plaid's own interface. They do not reach Bifold's client or its servers at any point.
5. Authorization model
Roles, and what each may reach:
| Role | Who or what holds it | Reach |
|---|---|---|
anon | An unauthenticated client | Nothing. No user table is readable. |
authenticated | A signed-in consumer's session | Only rows whose owner matches the session's user id, enforced by row-level security on every user table. Cannot be widened by any application query. |
service_role | Server-side edge functions only | Full data access. The key exists only as a managed secret in the server environment; it is not in the app binary, the repository or any committed file. |
The Plaid access token boundary. Tokens live in a dedicated table with row-level security enabled and no policies defined at all, with grants explicitly revoked from both anon and authenticated. The effect is that no consumer session of any kind can read a Plaid access token, whatever the application does; only server-side functions running as the service role can. The app never receives a token.
6. Non-human authentication
- Edge functions authenticate to the database with a service-role JWT, over TLS.
- The scheduled sync job authenticates to its function with a bearer secret held in the database's secret store, never in code.
- Inbound webhooks from Plaid are verified by ES256 signature against Plaid's published verification key, with the request body hash and issue time both checked. Unsigned or stale requests are rejected.
- Every one of these credentials is rotatable independently, and rotation is the first containment step in the incident response procedure.
7. Provisioning and removal
- New access is granted only after the requester is subject to this policy, with MFA enrolled before the first login.
- Access is removed the same day it is no longer needed. For a person that means removing the console account; for a machine credential it means revoking and rotating the secret.
- A consumer removes their own access at any time: disconnecting a bank deletes its stored access token immediately, and deleting the account from within the app disconnects every bank at Plaid and erases all of that consumer's data.
8. Access review
Reviewed at least quarterly, and immediately after any change in who holds access. Each review walks the same four consoles, confirms the member list is exactly the intended one, and revokes stale machine credentials and personal access tokens.
| Date | Scope reviewed | Outcome |
|---|---|---|
| 9 September 2026 | Supabase organization members, source repository collaborators and personal access tokens, Plaid dashboard team, App Store Connect users | Sole owner only on all four; no additional members, no stale machine credentials. MFA confirmed enrolled on each. |
9. Exceptions
There are none in force. Any future exception must be written down with the compensating control and an expiry date, and is revisited at the next quarterly review.