Skip to main content

Legal Documents Deployment Guide

Overview

This guide covers deploying the Legal Documents Management System to various environments (development, staging, production).

Prerequisites

  • Access to production database
  • Admin panel deployed and accessible
  • Clerk authentication configured
  • Backend API running
  • Frontend application deployed

Pre-Deployment Checklist

  • All code reviewed and merged to main branch
  • Tests passing locally
  • Database migration file created
  • Environment variables configured
  • Admin sidebar updated with Legal Docs link
  • API endpoints tested
  • Admin pages tested
  • User flows tested on staging

Database Migration

1. Create Migration File

The migration file should already exist:

packages/database/prisma/migrations/20241212_add_legal_documents/migration.sql

2. Deploy to Environment

Development (local):

cd packages/database
pnpm prisma migrate dev --name add_legal_documents

Staging:

cd packages/database
# Set DATABASE_URL for staging environment
DATABASE_URL="postgresql://..." pnpm prisma migrate deploy

Production:

cd packages/database
# Set DATABASE_URL for production environment
DATABASE_URL="postgresql://..." pnpm prisma migrate deploy

3. Verify Tables Created

-- Check legal_documents table
SELECT * FROM legal_documents LIMIT 1;

-- Check document_acceptances table
SELECT * FROM document_acceptances LIMIT 1;

-- Check indexes
SELECT * FROM information_schema.statistics
WHERE table_name IN ('legal_documents', 'document_acceptances');

Backend Deployment

1. Environment Variables

No new environment variables needed. Uses existing:

  • DATABASE_URL - Already configured
  • CLERK_SECRET_KEY - Already configured

2. Deploy Code

Option A: Docker (AWS ECS/Fargate)

# Build image
docker build -t civstart-backend:latest -f apps/backend/Dockerfile .

# Push to ECR
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin <ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com
docker tag civstart-backend:latest <ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/civstart-backend:latest
docker push <ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/civstart-backend:latest

Option B: Direct Node

cd apps/backend
npm install
npm run build
npm start

3. Verify API Endpoints

# Test GET endpoint
curl https://api.civstart.com/legal/current/terms

# Should return a document or 404 if none published yet

Frontend Deployment

# Vercel auto-deploys from GitHub main branch
# Ensure environment variables set in Vercel dashboard

NEXT_PUBLIC_API_URL=https://api.civstart.com

2. Environment Variables

Add to Vercel dashboard:

NEXT_PUBLIC_API_URL=https://api.civstart.com

3. Test Frontend

  • Navigate to /settings
  • Check "Legal Agreements" section appears
  • Verify "Review" button works
  • Test TermsAcceptanceModal opens

Admin Panel Deployment

1. Vercel Deployment

Same as frontend deployment above.

2. Verify Admin Pages

Navigate to admin panel:

  • /legal - Document list loads
  • /legal/new - Create page loads
  • Click "Create Document" button
  • Form displays correctly
  • All fields render

3. Test Admin Workflow

  1. Create Document:

    Admin → Legal Docs → Create Document
    - Fill form
    - Click Save & Publish
    - Verify in list as Active
  2. View Details:

    Admin → Legal Docs → Click Document
    - See content
    - See analytics
    - Verify buttons available
  3. View Logs:

    Admin → Legal Docs → Acceptances
    - See empty log (no acceptances yet)
    - Verify Export CSV button

Post-Deployment Steps

1. Create Initial Documents

Option A: Via API

# Create Terms of Service v1.0.0
curl -X POST https://api.civstart.com/legal/admin/documents \
-H "Authorization: Bearer ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "terms",
"version": "1.0.0",
"title": "Terms of Service",
"content": "[PASTE YOUR TERMS HERE]",
"effectiveDate": "2024-12-15T00:00:00Z",
"requiresImmediate": true,
"gracePeriodDays": 0
}'

# Publish it
curl -X POST https://api.civstart.com/legal/admin/documents/{ID}/publish \
-H "Authorization: Bearer ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"requiresImmediate": true,
"gracePeriodDays": 0
}'

Option B: Via Admin Panel

  1. Navigate to /legal in admin panel
  2. Click "Create Document"
  3. Fill in Terms of Service details
  4. Click "Save & Publish"
  5. Repeat for Privacy Policy

2. Test User Flow

Create Test User:

  1. Sign up new user in staging
  2. User should see TermsAcceptanceModal
  3. Modal should show fetched content
  4. User checks checkbox and accepts
  5. Verify acceptance recorded in database:
    SELECT * FROM document_acceptances
    WHERE user_id = 'TEST_USER_ID';

3. Verify Settings Page

  1. Test user logs in
  2. Navigate to /settings
  3. Should see "Legal Agreements" section
  4. Should show:
    • Terms: Accepted ✓ Version 1.0.0
    • Privacy: Accepted ✓ Version 1.0.0
  5. "Review" button should open modal

4. Test Admin Features

Export CSV:

  1. Admin → Legal Docs → Acceptances
  2. Click "Export CSV"
  3. Should download terms-acceptance-2024-12-15.csv
  4. Verify headers and data

View Analytics:

  1. Admin → Legal Docs → Click document
  2. Click "Analytics" tab
  3. Should show:
    • Total acceptances
    • Total users
    • Acceptance rate %
    • Recent acceptances table

Monitoring & Verification

Database

-- Check document count
SELECT type, COUNT(*) as count, SUM(CASE WHEN is_active THEN 1 ELSE 0 END) as active
FROM legal_documents
GROUP BY type;

-- Check acceptance count
SELECT type, COUNT(*) as count
FROM document_acceptances da
JOIN legal_documents ld ON da.document_id = ld.id
GROUP BY ld.type;

-- Check for any errors
SELECT * FROM legal_documents WHERE published_at IS NULL;

API Health

# Test public endpoint
curl -v https://api.civstart.com/legal/current/terms

# Test authenticated endpoint
curl -v -H "Authorization: Bearer USER_TOKEN" \
https://api.civstart.com/legal/status

# Test admin endpoint
curl -v -H "Authorization: Bearer ADMIN_TOKEN" \
https://api.civstart.com/legal/admin/documents

Application Logs

Check for errors:

# Backend logs
docker logs CONTAINER_ID | grep -i legal

# Frontend errors
Check browser console on /legal and /settings pages

Rollback Plan

If issues occur:

1. Rollback Frontend

# Vercel: Revert to previous deployment
vercel rollback

# Or redeploy without legal changes
git revert <COMMIT_HASH>
git push

2. Rollback API

# ECS: Revert to previous task definition
aws ecs update-service \
--cluster civstart-production \
--service civstart-backend \
--task-definition civstart-backend:PREVIOUS_VERSION

# Or redeploy without legal changes
git revert <COMMIT_HASH>
# Rebuild and push image

3. Rollback Database

# WARNING: Only if absolutely necessary
# Create backup first!

# Migrate down (if needed)
pnpm prisma migrate resolve --rolled-back 20241212_add_legal_documents

# Or manually delete tables
DROP TABLE document_acceptances;
DROP TABLE legal_documents;

Common Issues & Solutions

Issue: Modal not fetching documents

Solution:

  • Verify API endpoint is running
  • Check CORS headers
  • Check network tab in DevTools
  • Verify API URL in environment variables

Issue: Acceptance not recorded

Solution:

  • Verify user is authenticated
  • Check POST /legal/accept returns 201
  • Verify database migration ran
  • Check user table has new columns

Solution:

  • Verify sidebar component updated
  • Clear browser cache and refresh
  • Check admin.tsx imports ScrollText icon
  • Verify user email in whitelist

Issue: Published document shows as draft

Solution:

  • Check publishedAt field in database
  • Verify publish API call succeeded
  • Check for validation errors in logs
  • Manually update: UPDATE legal_documents SET published_at = NOW() WHERE id = '...';

Performance Optimization

Database Indexes

Verify indexes are created:

SHOW INDEX FROM legal_documents;
SHOW INDEX FROM document_acceptances;

Query Optimization

For large datasets, ensure pagination:

  • Acceptance logs: Default limit 100, max 500
  • Add appropriate WHERE clauses
  • Use indexes on: type, is_active, published_at, user_id

Caching (Optional Future)

Consider Redis caching for:

  • Current active documents (rarely change)
  • User terms status (check once per login)

Security Verification

  • Admin endpoints require authentication
  • Non-admin users cannot access /legal/admin/*
  • Acceptance records include IP address
  • Published documents cannot be edited
  • API rate limiting (if applicable)
  • CORS properly configured

Communication Checklist

Before going live to production:

  • Notify team of deployment
  • Update status page
  • Send welcome email to users explaining new requirement
  • Schedule support team training
  • Create FAQ for common questions
  • Set up monitoring for acceptance rates

Go-Live Timeline

1-2 Weeks Before

  • Complete all testing
  • Brief support team
  • Create user communication

1 Day Before

  • Final verification on staging
  • Backup production database
  • Notify stakeholders

Deployment Day

  • Deploy database migration
  • Deploy backend
  • Deploy frontend
  • Deploy admin panel
  • Create initial documents
  • Monitor error logs
  • Check acceptance rates

After Deployment

  • Monitor for errors
  • Check user feedback
  • Follow up with support
  • Update documentation
  • Plan next iterations

Rollout Strategy

  • Deploy everything at once
  • Create all documents
  • All users see modal on next login
  • Requires clear communication

Option 2: Phased

  • Deploy code without publishing documents
  • Create documents but don't publish
  • Publish on scheduled date
  • Users notified in advance

Option 3: Gradual

  • Deploy to 10% of users first
  • Monitor acceptance rates
  • Gradually increase to 100%
  • Requires feature flags