Published in draft, pending legal counsel review, and subject to change.
← All Policies
Powered by Keel · Platform policy

Access Control Policy [DRAFT]

STATUS: DRAFT v1.0 — pending legal counsel review.

Operative for internal use; [DRAFT] will be removed once counsel sign-off is recorded.

Owner: Keel — Engineering

Effective: 2026-05-27 (interim; final effective date confirmed at counsel sign-off)

Review cadence: Annual; access review cadence quarterly (see § 6)

Applies to: All human and service-account access to the Keel fund management platform, its underlying data stores, and its operational tooling.


1. Purpose

This policy defines who can access which systems containing fund and limited-partner data, the workflow for granting and revoking access, and the audit trail required to demonstrate compliance to Plaid auditors and LP-side due diligence reviewers.

2. Principles

1. Least privilege. Every account receives the minimum access required for its function. Broader privileges require documented justification.

2. Separation of duties. No single account holds both data-modification authority and audit-erasure authority. Audit records cannot be edited or deleted by the actor that produced them.

3. Identity provenance. Every action that mutates fund or LP data is attributable to a named human or a documented service account via the AuditEvent model (src/lib/audit.ts).

4. Time-bound access. Temporary access (vendor support, third-party accountant review) is granted with an explicit expiry date and revoked automatically or by checklist.

3. Access Tiers (Roles)

Access is partitioned into the following tiers, mapped to the UserRole enum in prisma/schema.prisma and to platform-side permissions where applicable:

TierApp roleDescription
Fund ManagerADMINFull read-write access to all fund and LP data. Sole tier with destructive-action authority (deactivate fund, soft-delete LP, void capital call).
Operations AdminADMIN (delegated)Day-to-day fund operations: issue capital calls, reconcile wires, send notices, manage prospects. Created by Fund Manager with documented justification.
Accountant ReviewACCOUNTANTRead-only access to K-1 statements + supporting capital-account ledger; edit access only to K-1 review fields. Time-bound by default (60 days per engagement).
Investor (LP)INVESTORRead-only access to that LP's own subscription, capital account, K-1s, call notices, and documents. No access to other LPs' data.
ProspectPROSPECTTime-bound access to subscription booklet, marketing decks, and document checklist for that prospect only. Revoked on conversion or expiry.

Infrastructure-level access (Vercel deployment, Neon database console, Vercel Blob token, GitHub repository) is held only by Fund Manager and the engineering owner. Access to these platform consoles is treated as Fund Manager tier for the purposes of this policy.

4. Access Request Workflow

1. Request. The requester submits a short written request (email or issue) listing: the requestor's name and role, the system(s) and tier requested, the business purpose, and the expected duration.

2. Approval. Fund Manager tier requests require Fund Manager approval. Operations Admin tier requires Fund Manager approval. Accountant Review tier requires Fund Manager approval and engagement letter on file. Investor and Prospect tiers are auto-provisioned through the normal subscription / prospect flow and do not need a manual request.

3. Provisioning. Engineering owner creates the account (or platform user, where applicable), grants the requested role, and records the provisioning event in the engineering log.

4. Notification. Requester is notified of credentials via the platform's standard provisioning flow (magic link / password reset email).

Verbal or undocumented access grants are prohibited.

5. Off-boarding

When a person leaves the organization or no longer requires access:

1. The engineering owner is notified by the Fund Manager within 1 business day.

2. The engineering owner executes the off-boarding checklist within 2 business days:

- Disable the in-app account. Today this is done by setting User.lockedUntil to a far-future date (effectively permanent lockout) and rotating that user's password hash to a random value so credential reuse fails. The Investor or ManagerMember record the User is linked to is soft-deleted via its deactivatedAt field where applicable. (Backlog: add `User.deactivatedAt` as a first-class soft-delete field rather than overloading `lockedUntil` — see Institutional Readiness roadmap.)

- Revoke platform-console access on Vercel, Neon, GitHub, Resend, Anthropic, Anvil, Plaid (where applicable).

- Invalidate any active sessions. NextAuth JWT sessions expire on their own schedule. Automated de-provisioning / modification of access (P3-9): privileged claims (role, admin permission, admin-access, investor/group/prospect linkage) are re-read from the database on a throttled interval (SESSION_CLAIM_REFRESH_MINUTES, default 5) inside the JWT callback (src/lib/auth.ts). When an account is deactivated, deleted, or its role is modified (e.g., a transfer to a different function), the next re-read strips or updates its claims automatically — so a terminated or transferred person loses or has their access changed within minutes, without waiting for token expiry or rotating a global secret. For immediate, total invalidation across all sessions (known compromise / Fund Manager off-boarding), rotate NEXTAUTH_SECRET.

- Rotate any shared secrets the off-boarded account had access to (API keys, deploy tokens, database credentials where individual access was granted).

- Record the off-boarding event in the engineering log with timestamp and the list of systems revoked.

3. The Fund Manager confirms completion at the next quarterly access review.

Automation status (updated 2026-06): In-app access changes are automated — the P3-9 claim re-read above modifies or revokes a deactivated/demoted user's effective access within SESSION_CLAIM_REFRESH_MINUTES of the change, with no manual session purge. The remaining manual steps are platform-console revocation (Vercel/Neon/GitHub/etc.) and shared-secret rotation. Firm-wide automated lifecycle for terminated/transferred employees across all systems (HR-IT / SSO-driven provisioning and de-provisioning) is an organizational IT control attested from the firm's identity infrastructure, complementary to the app-layer automation described here.

6. Periodic Access Review

Every quarter the engineering owner produces an access-review artifact listing:

  • Every active account at each tier with last sign-in date.
  • Every accountant or vendor engagement currently within its time-bound window, with expiry date.
  • Every account that has not signed in for 90+ days (candidate for revocation).
  • Every platform-side console user (Vercel, Neon, GitHub, Resend, Anthropic, Anvil, Plaid).

The Fund Manager reviews the artifact and signs off (digital signature or signed PDF attached to the engineering log). Accounts flagged dormant or no-longer-required are revoked within 5 business days of the review.

7. Audit Trail

Every mutating admin action writes an AuditEvent row capturing: actor user ID, actor email, action name (e.g., Investor.update, CapitalCall.issue), entity type, entity ID, and a JSON payload of the relevant before/after values. The AuditEvent table is append-only at the application layer; no admin role has direct DB access in normal operation. Audit records are retained indefinitely.

Authentication events (sign-in, sign-out, magic-link issuance, password reset) are logged via the NextAuth event hooks. Failed authentication attempts are rate-limited at the request level and counted for anomaly detection.

8. Service Accounts

Service accounts (Vercel Cron jobs, scheduled tasks, webhook handlers) operate with the minimum permissions required and are documented with: account name, purpose, the system they call, the credentials they hold, and the rotation cadence. Service-account credentials are stored as platform secrets, never committed to the repository.

9. Multi-factor Authentication

MFA is required for all Fund Manager and Operations Admin tier accounts on:

  • The platform consoles (Vercel, Neon, GitHub, Resend, Anthropic, Anvil, Plaid).
  • The internal admin app login (status 2026-05: planned, see Plaid attestation roadmap item C11).
  • The investor portal login (status 2026-05: optional, MFA opt-in planned).

Until MFA on the internal app is shipped, all Fund Manager and Operations Admin accounts must sign in from secured devices on networks under their control. This compensating control is documented and reviewed monthly.

10. Roles and Responsibilities

  • Fund Manager: approves access grants at all tiers, signs the quarterly access review, decides exceptions.
  • Engineering owner: provisions and de-provisions accounts, maintains the audit log, produces the quarterly review artifact, files exceptions.

11. Policy Review

Reviewed annually. The access-review process described in § 6 is reviewed each quarter as part of the review artifact itself.


Change history

  • 2026-05-27 — Initial version (v1.0). Authored alongside Plaid attestation work; pairs with the Patch SLA and EOL Software Management policies.