Access Control Policy
Owner: Ivy, Founder, Koda Digital · Contact: contact-us@kodadigital.ai · Effective: 2026-09-03 · Updated: 2026-09-27
1. Principle
Least privilege, enforced by the platforms' native role systems rather than by convention. Every identity has the minimum role needed; there are no shared accounts or shared credentials.
2. Roles (RBAC)
| Role | Who / what | Granted via | Rights |
|---|---|---|---|
| Operator (Owner) | Ivy — the single human | Google Cloud IAM roles/owner on the Firebase project; Plaid dashboard Owner |
Deploy code, manage secrets, read Firestore, manage Plaid Items |
| Backend service account | Cloud Functions runtime SA | IAM, managed by Firebase | Read/write Firestore; access the Plaid secrets; call Plaid |
| End user (app) | The Operator and invited beta testers, via the app | Their own Firebase Authentication account (email + password + authenticator app) | On their own data only: read balances/transactions; export transactions; link/unlink Items; edit manual assets; sign out all devices; delete their account |
| Plaid | Plaid's systems | Plaid credentials | Serve financial data when the backend asks; no access to Koda data |
No other principal has any access. Firestore security rules deny all client access
(firestore.rules), so the only path to data is through the backend, and the backend admits
only signed-in, MFA-verified users, each confined to their own data tree users/{uid}
(see authentication-and-secrets.md).
3. Granting access
Administrative access (IAM, the Plaid dashboard) is granted only by the Operator, never by sharing credentials, and only after the requester and purpose are recorded in access-review-log.md. As of the effective date it has never been granted to a second person.
- A new app user is someone the Operator has sent the app to. They create their own account in the app, verify their email and enrol an authenticator; the Operator can also add them in the Firebase console. No redeploy or configuration change is involved. An app account is not administrative access: it reaches only the data that account itself linked, never the Operator's or anyone else's.
- A new device for the same person is not a new grant: the person signs in on it with their password and an authenticator code. Devices are reviewed at each access review.
4. Periodic access reviews
Every 6 months (and immediately after any incident or architecture change) the Operator reviews and records in access-review-log.md:
- Google Cloud IAM members and roles on the project (
gcloud projects get-iam-policyor the console). - Plaid dashboard team members and their roles.
- Enabled service accounts and their keys (none should have user-managed keys).
- Secret Manager secret versions (destroy superseded versions).
- GitHub repository collaborators.
- Firebase Authentication users and their enrolled second factors — every account should belong to someone the Operator sent the app to; disable any that doesn't.
- Devices with the app installed and Google account sessions (Google Security Checkup). If any device is unaccounted for, sign out of every device.
5. De-provisioning / modification of access
With a single operator there are no employees to terminate or transfer. All access is tied to identities that can be revoked in one place:
- Removing a Google IAM member instantly revokes Cloud/Firebase/Firestore/Secret Manager access.
- Removing a Plaid dashboard member instantly revokes Plaid access.
- Disabling a Firebase Authentication user in the console refuses all of that person's API requests from every device on their next request. Deleting the user does the same; their stored data remains until removed (see data-retention-and-deletion.md). Users can also delete their own account and data in the app.
- "Sign out of every device" (
POST /revoke-sessions) revokes all sessions at once — the procedure for a lost or replaced phone. - Plaid Items are revoked with
/item/removevia the app's unlink function.
Data is partitioned per user: each account's tokens, cache, manual assets and
history live under users/{uid} (transactions are not on the server at all — they live on the user's phone), and the backend derives that uid only from the verified
sign-in token. A leaving tester is disabled in the Firebase console the same day.
6. Workstation and account hygiene
- Google account: 2-Step Verification with a passkey/security key; recovery options reviewed at each access review.
- The Operator's Koda Finance account: unique password in a password manager, and the authenticator kept outside that password manager, so compromising one store never yields both factors. A lost authenticator (any user's) is reset by the Operator through the Firebase Admin SDK, then re-enrolled.
- Plaid dashboard: MFA enabled.
- Development machine: full-disk encryption, OS auto-updates, screen lock; secrets are stored only in Secret Manager and local gitignored
.env.localfiles.