Security & data handling
Last updated 2026-03-25
This page summarizes technical controls reflected in the Openfund codebase and internal engineering documentation. It is provided for transparency and due diligence. For how we collect and use personal information, see the Privacy Policy.
Region and hosting
Production workloads are deployed to AWS Canada (ca-central-1) for data residency aligned with Canadian operations. Infrastructure is defined as code (AWS CDK) under infrastructure/.
Authentication (session cookies)
API authentication uses HTTP-only cookies set by backend Lambdas (not JavaScript-accessible storage). Cookie names and expiries are shared constants in packages/api/src/cookies.ts; sign-in and refresh flows live under backend/lambda/iam/authn/.
Cookie
Purpose
Expiry
of_access_token
API authentication (JWT)
1 hours
of_id_token
User identity claims (JWT)
1 hours
of_refresh_token
Session refresh
30 days
of_mfa_session
Multi-factor authentication step
5 minutes
Identity provider and MFA
User pools are managed in Amazon Cognito. Password policy (minimum length and complexity) and MFA are configured in infrastructure/lib/stacks/authn-stack.ts: SMS-based second factor is supported; MFA is required in production and may be disabled in non-production environments for engineering workflows.
Authorization (API and pages)
Protected HTTP APIs use a layered model documented under docs/000-best-practices/security/three-layer-auth.md:
- API Gateway Lambda authorizer validates the access token cookie and populates request context (see infrastructure/lib/utils/lambda-helpers.ts).
- createHandler in packages/server/src/handler.ts enforces authentication and calls AWS Verified Permissions for allow/deny decisions.
- Cedar policies in infrastructure/authorization/policies/*.cedar describe which principals may perform which actions on which resources.
Routes that are intentionally public are listed in packages/api/src/routes.ts (PUBLIC_APIS); all other API paths expect an authenticated session unless explicitly exempted.
Encryption and secrets
At rest: The Aurora PostgreSQL cluster uses KMS-backed encryption (storageEncrypted: true in infrastructure/lib/stacks/storage-stack.ts). The documents S3 bucket uses KMS bucket encryption. Database credentials are generated and stored in AWS Secrets Manager.
Integration credentials (e.g. LOS integrations) are encrypted with a dedicated KMS key in application code (backend/lambda/los-integrations/_lib/core/credentials.ts).
In transit: Clients use HTTPS to the API and web application; cookies are only sent over encrypted connections in normal browser use.
Audit logging
Security-relevant failures (authentication/authorization) are logged through the shared handler wrapper. Successful business actions are logged by handlers using logAudit in packages/server/src/audit.ts into the audit_events table. Backup retention for the database cluster is configured on the Aurora cluster (see CDK backup.retention in the storage stack).
Frontend and server-side requests
Browser code calls APIs with credentials: "include" so cookies attach automatically. Server Components and Server Actions forward cookies explicitly when calling the API from the Next.js app (apps/web/lib/api/server.ts) so server-side rendering stays authenticated without exposing tokens to client JavaScript.
Code references (non-exhaustive)
packages/api/src/cookies.ts · packages/api/src/routes.ts · packages/server/src/handler.ts · packages/server/src/audit.ts · infrastructure/lib/stacks/storage-stack.ts · infrastructure/lib/stacks/authn-stack.ts · infrastructure/authorization/policies/ · backend/lambda/iam/authn/ · backend/lambda/los-integrations/_lib/core/credentials.ts