Appearance
Installation and Deployment Guide
Last updated: July 22, 2026
Choose your deployment model
Hosted CompliAffirmAI
Clients using compliaffirmai.app do not install software. Create an account, confirm the email address, enroll MFA, choose the appropriate plan, and follow the User Guide.
Self-managed reference deployment
The reference production architecture uses:
- Vercel for the React/Vite frontend and FastAPI function;
- Supabase for authentication and PostgreSQL;
- a private S3-compatible bucket for evidence and generated artifacts;
- Stripe for subscriptions and entitlements;
- Resend for transactional email;
- Cloudmersive for malware and active-content scanning;
- an RFC 3161 timestamp provider for optional ledger anchoring; and
- an independent private bucket for backups.
Self-management is an advanced deployment. Your organization owns provider configuration, keys, DNS, backups, incident response, legal notices, access reviews, and ongoing security updates.
Prerequisites
The tested reference toolchain is:
- Git;
- Node.js 24;
- pnpm 10;
- Python 3.12;
- a Vercel account and CLI for the reference hosting path;
- a Supabase project or compatible PostgreSQL and OIDC/JWT design; and
- private S3-compatible object storage.
Use supported vendor versions and pin versions in controlled production environments.
1. Clone and install
powershell
git clone <your-authorized-repository-url> CompliAffirmAI
Set-Location CompliAffirmAI
pnpm install
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".\backend[dev]"On macOS or Linux, activate the virtual environment with:
bash
source .venv/bin/activate
python -m pip install -e "./backend[dev]"2. Configure local environment values
Copy .env.example to .env.local and provide only the values required for your environment.
powershell
Copy-Item .env.example .env.local.env.local, .env, .vercel, and provider credentials must remain untracked. Never place a secret in a VITE_* variable; variables with that prefix can be compiled into browser code.
Essential production categories
| Category | Principal variables | Guidance |
|---|---|---|
| Application | APP_ENV, APP_URL, ALLOWED_ORIGINS_CSV, VITE_APP_URL | Use production and the final HTTPS origin. Limit CORS to approved origins. Vercel also supplies VERCEL_ENV. |
| Browser authentication | VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY | Publishable key only. Never use a service-role key in the browser. |
| Server authentication | AUTH_JWKS_URL, AUTH_ISSUER, AUTH_AUDIENCE, AUTH_ORG_CLAIM, AUTH_USER_CLAIM | Tokens must carry the organization claim used by tenant routes. |
| PostgreSQL | POSTGRES_URL, POSTGRES_SSL | Use a non-superuser, non-bypass-RLS application role. |
| Primary storage | S3_BUCKET, S3_REGION, S3_ENDPOINT, S3_FORCE_PATH_STYLE, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY | Server-only S3-compatible credentials. OBJECT_STORAGE_* aliases are also supported. |
| Malware scanning | CLOUDMERSIVE_API_KEY, CLOUDMERSIVE_API_URL, MALWARE_SCAN_TIMEOUT_SECONDS | Production evidence must fail closed when scanning cannot complete. |
| Billing | STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, approved Product/Price IDs, and STRIPE_PORTAL_CONFIGURATION_ID | Create a dedicated catalog, Portal configuration, and webhook for this application. |
RESEND_API_KEY or EMAIL_API_KEY, EMAIL_FROM, SUPPORT_EMAIL, RESEND_WEBHOOK_SECRET | Use a verified sender domain. | |
| Internal operations | INTERNAL_API_KEY, CRON_SECRET | Generate separate strong random values. Do not reuse provider secrets. |
| Ledger anchoring | RFC3161_TIMESTAMP_PROVIDER_URL | Optional, but required for live external timestamp anchoring. |
| Independent backup | BACKUP_STORAGE_BUCKET, BACKUP_STORAGE_REGION, BACKUP_STORAGE_ENDPOINT, BACKUP_STORAGE_ACCESS_KEY_ID, BACKUP_STORAGE_SECRET_ACCESS_KEY | Use a provider or credential boundary independent from primary storage. |
| Analytics | VITE_GA4_MEASUREMENT_ID, GA4_MEASUREMENT_ID, GA4_API_SECRET | Optional. Honor consent and never send regulated payloads or secrets. |
The full variable list and safe defaults are documented in .env.example. Provider values that identify products, prices, actions, or webhook endpoints are configuration; private keys, API keys, database passwords, refresh tokens, and webhook secrets are secrets.
3. Provision PostgreSQL and Supabase Auth
Fresh database
For a fresh Supabase database, apply the SQL files in backend/db/migrations/ in filename order, beginning with 001_initial_schema.sql. The chain includes the base schema, catalog seed, tenant RLS, support and notification workflows, billing, governance mappings, indexes, and storage-related updates.
Use one migration lineage and record every applied version. Do not blindly apply both backend/db/migrations/ and supabase/migrations/ to the same database: the dated Supabase files mirror production changes and can overlap the numbered lineage.
If you replace Supabase with compatible PostgreSQL and another identity or storage provider, review and adapt the auth.* and storage.* statements before migration. Equivalent user bootstrap, tenant claims, RLS, object lifecycle, and private-bucket controls are required; schema compatibility alone is not a supported security design.
After migration:
- Confirm tenant tables have row-level security enabled and forced.
- Confirm the application role cannot bypass RLS, create roles, or act as superuser.
- Confirm public
anonandauthenticatedtable grants follow the committed least-privilege design. - Run
pnpm check:rlsandpnpm check:schema.
Auth bootstrap
The initial schema installs an auth.users trigger for a Supabase deployment. A new user receives:
- an organization record;
- an application user record;
- an Owner membership; and
- trusted
app_metadata.org_idandapp_metadata.org_roleclaims.
Configure the Auth site URL and allowed redirect URLs for your final HTTPS origin. Configure branded confirmation and password-reset templates, custom SMTP, and TOTP MFA. Do not allow users to choose or edit their trusted organization claim from browser-supplied metadata.
4. Provision private object storage
Create a private bucket, typically compliaffirmai-evidence, with:
- public access disabled;
- a 25 MB object limit (
26,214,400bytes); - browser CORS limited to the application origin and required signed-upload methods;
- server-only S3 credentials; and
- allowed MIME types for PDF, CSV, XLS, XLSX, DOC, DOCX, PNG, JPEG, JSON, and ZIP.
ZIP is required for TRAIGA Cure Binder export. Keep staging, sealed evidence, and artifacts under organization-scoped keys. Do not grant clients direct bucket-list permissions.
Create a separate private backup bucket and credentials for scheduled backups. A backup in the same bucket with the same credential is not an independent recovery boundary.
5. Configure providers
Stripe
Create application-specific Products, recurring Prices, webhook endpoint, and Customer Portal configuration. Put only approved IDs into the allowlist variables. Entitlements activate from verified, idempotent Stripe webhook events, not from a browser redirect.
Email
Verify the sending domain, configure SPF/DKIM as required by the provider, set the sender and support address, configure the signed delivery-status webhook, and test confirmation and password-reset delivery.
Malware scanning
Use a plan that supports the 25 MB application limit. A production upload must remain unavailable when the scanner errors, times out, detects malware, or flags restricted active content.
Ledger timestamping
Configure an RFC 3161 endpoint if your organization requires external timestamp anchors. Validate request and receipt hashes without writing receipt bodies or secrets to logs.
6. Run locally
Frontend-only review
powershell
pnpm devThis is suitable for UI review and frontend tests. Tenant API calls use same-origin /api/* paths, so a complete provider-backed workflow requires the full-stack development server.
Full-stack reference development
Link the repository to a non-production Vercel project, configure development environment values, then run:
powershell
vercel devAlternatively, run FastAPI directly for API development:
powershell
Set-Location backend
uvicorn app.main:app --reloadWhen running frontend and backend on different origins, configure the backend's allowed origin and an appropriate development proxy. Do not weaken production CORS to simplify local development.
7. Verify before deployment
Run the canonical gate from the repository root:
powershell
pnpm check:launch-readyThis covers TypeScript, frontend tests, browser accessibility and workflow tests, backend tests, production build, language, SEO, headers, secret scanning, Git-history scanning, RLS, schema drift, billing configuration, analytics, AI-safety boundaries, and provider-smoke planning.
For a Windows host where pytest cannot access the global temporary directory, point TEMP and TMP to a clean workspace-owned directory for the test process. Do not disable tests to work around the host ACL.
8. Deploy to Vercel
- Create or link a Vercel project.
- Add browser-safe public values and server secrets to the correct environment scopes.
- Confirm
vercel.jsonstill routes/api/v1/*,/api/internal/*,/health, and/readytoapi/index.py. - Confirm the deployment uses the intended Git commit.
- Deploy:
powershell
vercel deploy --prod --yes- Inspect the deployment and confirm it is Ready and aliased to the intended domain.
- Confirm the deployment's Git metadata matches the tested commit SHA.
9. Post-deployment verification
At minimum:
powershell
pnpm smoke:production-core
pnpm smoke:production-auth
pnpm smoke:production-billing
pnpm smoke:production-logs -- --since 30m --allow-emptyAlso verify:
/healthreturns HTTP 200 andstatus: ok;- public and application routes load over HTTPS;
- authenticated tenant access succeeds only with the correct organization claim;
- a cross-tenant request is denied;
- MFA-protected actions reject AAL1 and accept AAL2;
- a benign evidence file completes upload, hash verification, scanning, sealing, and readback;
- generated artifacts download with matching SHA-256 values;
- Cure Binder JSON, PDF, and ZIP downloads work when TRAIGA is entitled;
- billing entitlements arrive from a signed webhook; and
- runtime logs contain no unexpected 5xx or error-level events.
Live smokes can create real provider objects, email, or billing records. Use dedicated smoke tenants and explicit test controls. Never run a charge-producing or externally visible smoke by accident.
10. Updates and rollback
Before an update:
- back up PostgreSQL and object storage;
- review new migrations and provider changes;
- run the complete launch gate;
- deploy the exact tested commit; and
- rerun authenticated production smokes.
If a release is unhealthy, promote the previous known-good Vercel deployment, inspect runtime and provider logs, and verify database compatibility before rolling application code backward. Database migrations require an explicit recovery plan; do not improvise destructive down-migrations in production.
