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:

  1. Google Cloud IAM members and roles on the project (gcloud projects get-iam-policy or the console).
  2. Plaid dashboard team members and their roles.
  3. Enabled service accounts and their keys (none should have user-managed keys).
  4. Secret Manager secret versions (destroy superseded versions).
  5. GitHub repository collaborators.
  6. 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.
  7. 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/remove via 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.local files.