CPCana Handbooks Library
All handbooks

Engineers, IT support, and church administrators

CPCana System Handoff Runbook

Accounts, configuration, deployment, and break-glass procedures for whoever runs CPCana next.

Contents

Target Audience: Incoming Software Engineer, Church Administrator, or IT Support Lead.
System: CPCana (CPCana Church & Organizational Workflow Engine)
Deployment: Chesterfield Presbyterian Church (Deployment #1)
Last Updated: October 5, 2026 (checked against the code); §2.4 (outbound email) rewritten October 3, 2026

Section 1

Executive Summary & Tech Stack

CPCana is a dedicated, single-tenant operations and task management system built specifically for church and non-profit ministry operations. It handles task tracking, multi-project workflows, repeating task resets, automated morning email digests, physical facility printouts, child protection compliance, and staff onboarding.

Technology Overview

ComponentTechnologyProvider / Hosting
Application FrameworkNext.js 14 (App Router, Server Actions)Vercel
Language & TypingTypeScript 5.5+ (Strict mode)Node.js 20+
DatabasePostgreSQLNeon (Serverless Postgres)
ORM & MigrationsPrisma ORM 5.22@prisma/adapter-neon
AuthenticationNextAuth.js 4 (Credentials + Emergency HMAC Support)Native in-app
Outbound EmailNodemailer (SMTP)Google Workspace, smtp.gmail.com with an app password (§2.4)
File Attachments@vercel/blobVercel Blob Storage
Styling & UITailwind CSS 3.4Dynamic brand palette
Testing SuiteVitestnpm test; the whole suite must pass before deploying
Section 2

Critical Ownership & Account Transfer Checklist

Before the departing lead departs, the following external platforms must have ownership transferred or administrative co-owners added:

1. Git Repository (GitHub)

  • Current Remotes:
    • origin: https://github.com/jblizard30-wq/CPCana.git
    • church: https://github.com/cpcoffice/CPCana.git
    • central-admin: https://github.com/jblizard30-wq/central-admin.git
    • Confirm which one Vercel deploys from (Project Settings → Git) before transferring anything.
  • Action:
    • Transfer repository ownership from jblizard30-wq to a Church GitHub Organization (e.g., github.com/chesterfieldpres) or a shared church IT account (it@yourchurch.org).
    • GitHub: Repo Settings → General → Danger Zone → Transfer ownership.
    • Ensure at least two technical church leaders or committee members have Admin permissions on the repository.
    • In branch settings, ensure main branch is protected against accidental force-pushes.

2. Deployment & Hosting (Vercel)

  • Project: cpcana
  • Vercel Team: team_Ih9cpCCbR4JmD2KTwuyKbN0V
  • Action:
    • In Vercel: Team Settings → Members, invite church administrator or IT lead as Owner.
    • In Vercel: Team Settings → Billing, confirm that the payment method on file is an official church card.
    • If the GitHub repo is transferred to a new organization, go to Project Settings → Git in Vercel and reconnect to the new repository URL to maintain automatic deployments on push to main.
    • Export all production environment variables into the church's credential vault.

3. Database (Neon Serverless Postgres)

  • Dashboard: console.neon.tech
  • Action:
    • Invite the incoming technical lead or church IT contact to the Neon Project as an Admin / Owner.
    • Switch billing to the church's payment method.
    • Verify access to connection strings (Pooled connection for serverless queries; Direct connection for schema migrations).
    • Note the point-in-time restore (PITR) backup settings in the Neon dashboard.

4. Outbound Email (Google Workspace SMTP)

Status as of October 3, 2026: production has no email settings, so CPCana sends no email at all: no morning digests, no reminders, no setup invites, no password-reset links. In-app notifications still work. The decision is to send through CPC's Google Workspace using an app password on a chespres.org account. It's free and needs no DNS changes, and because Google sends the mail, it passes chespres.org's sender checks.

Who does what

StepWhoAbout
A. Allow 2-Step VerificationGoogle Workspace admin for chespres.org2 min
B. Create the app passwordWhoever can sign in as the sending account3 min
C. Add the settings to Vercel and redeployVercel project owner (Justin Blizard)5 min
D. Send a test emailAny CPCana admin1 min

Step A: Google Workspace admin (admin.google.com)

  1. Pick the sending account. A dedicated account such as cpcana@chespres.org is best: digests don't arrive from one staff member's name, and email keeps working if that person leaves. Creating a new user may use a Workspace license. If that isn't possible, an existing staff account works.
  2. Go to Menu → Security → Authentication → 2-step verification.
  3. On the left, select the organizational unit that contains the sending account (or the top-level organization).
  4. Check Allow users to turn on 2-Step Verification, then Save. Don't change Enforcement.
  5. Check two things that block app passwords:
    • If enforcement is on, its Methods setting must not be Only security key for this account.
    • The account must not be enrolled in Advanced Protection.

Step B: signed in as the sending account

An admin can't create an app password for someone else; it has to be made from the account itself.

  1. Go to myaccount.google.com → Security, and turn on 2-Step Verification.
  2. Go to myaccount.google.com/apppasswords, enter the name CPCana, and click Create.
  3. Copy the 16-character code and save it in the church password manager. Share it with the Vercel project owner through the password manager, never by email or text.

Step C: Vercel project owner (cpcana → Settings → Environment Variables)

Add each of these with the environment set to Production:

VariableValue
SMTP_HOSTsmtp.gmail.com
SMTP_PORT587
SMTP_USERthe sending account's full address, e.g. cpcana@chespres.org
SMTP_PASSWORDthe 16-character code with spaces removed (mark it Sensitive)
EMAIL_FROMCPCana · Chesterfield Presbyterian <cpcana@chespres.org> (same address as SMTP_USER)

Leave SMTP_REQUIRE_TLS unset; with a password present, CPCana already requires an encrypted connection on port 587. Then go to Deployments, open the current production deployment, and choose Redeploy. New variables take effect only after a redeploy.

Step D: test (any CPCana admin)

Sign in to CPCana and go to Settings → Developer → Outbound Email & SMTP. The status should read Configured. Enter your address and click Send Test, which checks the connection and then sends. It should arrive within a minute, from the sending account.

Things to know

  • Daily limit: Google allows the account 2,000 messages a day. A few staff generate a few dozen.
  • From address: it must be the sending account or one of its Gmail Send mail as aliases. Otherwise Gmail replaces it with the account's own address.
  • Password changes: changing the sending account's Google password, or suspending the account, stops CPCana's email. If the password changes, repeat Step B and update SMTP_PASSWORD (then redeploy).
  • Common errors:
    • "Username and Password not accepted": the app password is wrong or was revoked, or 2-Step Verification was turned off.
    • App passwords page missing or unavailable: Step A isn't done for that account, or the account is limited to security keys or enrolled in Advanced Protection.

5. Domain Registrar & DNS

  • Action:
    • Document where the church's domain is registered (e.g., Cloudflare, GoDaddy, Squarespace/Google Domains).
    • Confirm that church IT has credentials to manage DNS records pointing to Vercel (cname.vercel-dns.com or Vercel A records).

6. Credentials Vault

  • All secrets must be recorded in the church's password manager (e.g. 1Password, Bitwarden):
    • GitHub credentials / Deploy keys
    • Vercel login
    • Neon Postgres credentials
    • The sending account's Google app password (§2.4)
    • Production NEXTAUTH_SECRET, CRON_SECRET, HQ_SUPPORT_SECRET
Section 3

Environment Variables Reference

These variables are defined in .env.example and configured in Vercel under Project Settings → Environment Variables:

VariableRequiredDescriptionExample / Notes
DATABASE_URLYesPostgreSQL connection string from Neonpostgresql://user:pass@ep-...neon.tech/cpcana?sslmode=require
NEXTAUTH_SECRETYesEncryption key for session cookiesGenerate via openssl rand -base64 32
NEXTAUTH_URLYesCanonical base URL of the live sitehttps://cpcana.yourchurch.org
CRON_SECRETYesSecures /api/cron/* endpoints against unauthorized triggersGenerate via openssl rand -base64 32
HQ_SUPPORT_SECRETOptional (needed for central-admin support login)Shared HMAC secret for emergency support login from the control plane. Unset disables support login; nothing else depends on itGenerate via openssl rand -base64 32
BLOB_READ_WRITE_TOKENYesVercel Blob access token for task file uploadsCopied from Vercel Storage dashboard tab
ORG_NAMEOptionalDisplay name for the organization"Chesterfield Presbyterian Church"
BRAND_COLOROptionalPrimary hex color (generates 50–950 Tailwind palette)"#003366"
LOGO_URLOptionalURL or relative path to church logo"/logo.png"
NEXT_PUBLIC_HANDBOOKS_URLOptionalBase URL of this deployment's public handbook library. Shows Handbooks & Guides in the sidebar and search, Settings → Help & Handbooks, and the guide links on individual pages. Unset or not an http(s) URL hides all of them. Read at build time, so redeploy after changing ithttps://handbooks.cpcana.app (CPC's library)
EMAIL_FROMNeeded for emailFrom address for notifications; must match SMTP_USER or one of its Gmail aliases (see §2.4)"CPCana · Chesterfield Presbyterian <cpcana@chespres.org>"
SMTP_HOSTNeeded for emailSMTP server hostname. Unset means no email is sent at allsmtp.gmail.com
SMTP_PORTNeeded for emailSMTP port (587 for STARTTLS, 465 for SSL)587
SMTP_USERNeeded for emailThe sending Google Workspace accountcpcana@chespres.org
SMTP_PASSWORDNeeded for emailThat account's 16-character app password (§2.4, Step B)Secret; mark Sensitive
SMTP_REQUIRE_TLSOptionalSTARTTLS is already required whenever a password is set; "false" only for a trusted internal relayLeave unset
CHILD_PROTECTION_CRON_PROJECT_IDNeeded for the compliance sweepProject where the Monday child-protection renewal tasks are filed. Unset means the sweep files nothinga project id
CHILD_PROTECTION_CRON_SECTION_IDOptionalSection in that project for those tasks; defaults to its first section. A section from another project stops the sweepa section id
GOOGLE_CALENDAR_CLIENT_ID / GOOGLE_CALENDAR_CLIENT_SECRET, OUTLOOK_CALENDAR_CLIENT_ID / OUTLOOK_CALENDAR_CLIENT_SECRETOptionalEnable the Settings → Integrations connect buttons (connecting doesn't sync events yet)Leave blank
APP_URL / NEXT_PUBLIC_APP_URLOptionalFallbacks for the base URL in emailed links when NEXTAUTH_URL is unsethttps://cpcana.yourchurch.org
ENABLED_MODULESYes (to show add-on modules)Add-on modules this deployment shows. Unset or empty enables none. An explicit list is frozen — modules added to the code later stay off until it's editedall (recommended), or a subset such as inventory,meetups,raci,xp
Section 4

Deployment & Build Pipeline

Production Deployment Flow

  1. A commit is merged or pushed to the main branch on GitHub.
  2. Vercel automatically detects the commit and triggers a deployment.
  3. The build command executed by Vercel is:
    prisma migrate deploy && next build
    • Important: Any pending Prisma migrations in prisma/migrations are automatically applied to the Neon database before the Next.js app builds.
    • If migrations fail, the deployment is aborted, preventing broken code from hitting production.
    • Preview deployments skip the migration step. For a branch or pull request (Vercel's VERCEL_ENV is preview), the build prints a note and goes straight to next build, because no database is attached to previews (DATABASE_URL is set for Production only). A preview can never change the production database. Everywhere else, including local builds, the command above runs unchanged.

Local Development Setup

To run CPCana locally on a developer machine:

# 1. Clone repository
git clone https://github.com/<org>/CPCana.git
cd CPCana

# 2. Install dependencies
npm install

# 3. Configure environment
cp .env.example .env
# Edit .env with your local or development Postgres connection string

# 4. Run database migrations
npm run prisma:migrate

# 5. Run test suite to verify health
npm test

# 6. Start development server
npm run dev

Verification & Quality Commands

Before deploying any custom changes, always verify:

npm test              # Runs the full Vitest suite
npm run lint          # Next.js ESLint verification
npx tsc --noEmit      # TypeScript strict compiler check
Section 5

Scheduled Background Jobs (Vercel Cron)

CPCana schedules 7 automated jobs via vercel.json. Every cron requires Authorization: Bearer <CRON_SECRET>. Vercel Cron sends it automatically once CRON_SECRET is set; if it's missing, every job returns 401 and nothing runs.

PathSchedule (UTC)Local (Central Time)Purpose
/api/cron/materialize-recurrence0 7 * * *1:00 AM CST / 2:00 AM CDTResets due repeating tasks in place (back to the base To Do column, subtasks unchecked, due date advanced). No copies are created.
/api/cron/purge-trash0 8 * * *2:00 AM CST / 3:00 AM CDTPermanently deletes soft-deleted tasks older than the retention window.
/api/cron/child-protection-renewals0 9 * * 13:00 AM CST / 4:00 AM CDT (Mon)Files one unassigned review task per expiring or lapsed person (at most every 30 days) into CHILD_PROTECTION_CRON_PROJECT_ID. Does nothing if that variable is unset or the child_protection module is off.
/api/cron/automations0 13 * * *7:00 AM CST / 8:00 AM CDTEvaluates due-date-approaching automation rules.
/api/cron/due-date-reminders0 13 * * *7:00 AM CST / 8:00 AM CDTNotifies assignees of tasks due today, due tomorrow, or overdue, plus blocker alerts (in-app, and emailed when their notification settings allow).
/api/cron/digest0 14 * * *8:00 AM CST / 9:00 AM CDTCompiles and sends morning digest emails based on user preferences.
/api/cron/send-reminders0 15 * * *9:00 AM CST / 10:00 AM CDTSends explicit user-scheduled task reminder emails.

Note: All cron handlers are idempotent. If a cron fires twice, conditional atomic claims prevent duplicate emails or duplicate tasks.

Section 6

Church Application Governance & User Administration

Promoting Staff to ADMIN

  1. Go to /admin/users as an existing Admin.
  2. In the staff member's row, change the Role dropdown to Admin. It saves immediately. (You can't change your own role; to change several people at once, tick their rows and use Set role.) Ensure at least two active church staff members hold the Admin role.

Onboarding New Staff or Volunteers

  • There is no public self-signup in production.
  • To add a user: go to User Management (/admin/users) → + New user.
  • Enter their name, church email, and role, leave Send first-time login invitation email with setup link checked, and click Create user. (Unchecked, you must set a temporary password of 8+ characters instead.)
  • A dialog shows their 7-day /set-password?token=... link with a Copy button, for Slack, Teams, or text. The row's Invite button resends it later.

Resetting a Password

  • If a user forgets their password:
    • They can use Forgot password? on the sign-in page (rate-limited via Postgres).
    • An Admin can go to /admin/users, click Reset pass in the user's row, and either set a temporary password (Set manually) or send a 24-hour reset link (Send email link → Send reset email; the link also appears on screen to copy).
Section 7

Break-Glass Troubleshooting Runbook

Issue 1: The application displays a 500 error or "Database connection failed"

  1. Check Neon Postgres status:
    • Log into console.neon.tech.
    • Check if the database instance is in an active state or suspended due to billing/resource limits.
    • Test connecting with npm run prisma:studio locally with the production connection string to verify access.
  2. Check Vercel Function Logs:
    • Open Vercel dashboard → Click the cpcana project → Click Logs.
    • Filter by status 500 to inspect stack traces.

Issue 2: Emails, morning digests, or reminders are not sending

  1. Check Vercel Cron Runs:
    • Go to Vercel → cpcana → Settings → Cron Jobs.
    • Check the status column to see if the cron job succeeded (200 OK) or timed out.
  2. Check the email settings (§2.4):
    • In CPCana, go to Settings → Developer → Outbound Email & SMTP. Disabled / "Not configured (SMTP_HOST is unset)" means SMTP_HOST is missing from Production. Otherwise click Send Test; it checks the connection, then sends.
    • An authentication error usually means the app password was revoked, often because the sending account's Google password changed. Repeat §2.4 Step B, update SMTP_PASSWORD, and redeploy.
    • Check that the sending account hasn't been suspended or hit Google's 2,000-messages-a-day limit.
  3. Verify in-app settings:
    • Check that the user has email notifications turned ON in /settings/notifications.
    • If the user clicked Unsubscribe from all emails in a past message, every email toggle and their digest were switched off. Have them turn the ones they want back on in /settings/notifications.

Issue 3: An important task was deleted by mistake

  1. Go to Admin → All Trash (/admin/trash).
  2. Find the task. Newest deletions are at the top; your browser's Find (⌘/Ctrl+F) helps on a long list.
  3. Click Restore and confirm. The task returns to its original project and section with its tags and custom field values. Its subtasks are separate trash entries (listed as "Parent / Subtask"); restore those too.
  4. Note: If a task has been in the trash longer than the 30-day retention window, it may have been purged by the nightly cleanup cron.
  5. A deleted project is gone for good: it skips the trash. Recovering one means a Neon point-in-time restore (§2.3).

Issue 4: A volunteer cannot access their RSVP or meetup sheet

  1. Volunteer links: guest sign-up uses one shared link per meetup, with no login. If a volunteer lost it, a Manager, Admin, or the meetup's organizer opens the meetup (/meetups/[id]) and clicks Share with Guests to copy a fresh link (good for 30 days).
  2. Volunteer Check-in Sheets: If paper clipboards are needed on Sunday morning, click "Print Check-in Sheet" on the Meetup to generate an instant physical sheet with supervisor sign-off blocks.
Section 8

Cross-Repository Boundary: central-admin (Control Plane)

The repository connects to an optional control plane (central-admin):

  • Support Login: An administrator at central-admin can access CPCana using a signed HMAC token via /support-login. This uses HQ_SUPPORT_SECRET.
  • Health Probing: The /api/health endpoint responds with { status: "ok" } for external uptime monitors.
  • Independence: CPCana functions completely independently of central-admin. All day-to-day church operations, user management, and passwords are fully self-contained.
Section 9

Key Documentation Files in Repository

All team members should be pointed to the following resources in the repository:

  • docs/admin-guide.md — Detailed instructions for Admins (User management, Teams, Automations, Print tools).
  • docs/user-manual.md — Comprehensive user manual for staff and ministry leads.
  • docs/workflow-strategy-guide.md — Ministry playbooks (Guest assimilation, Facilities, Children's ministry).
  • docs/automation-workflow-guide.md — Click-by-click process stages and automation rules.
  • docs/field-cards.md — Printable worksheets: Sunday prep, child-protection requirements, onboarding.
  • docs/handbooks/ — Builds the CPCana Handbooks Library, the copies of these guides staff actually read: claude.ai artifacts for people with a Claude login, and a public copy at https://handbooks.cpcana.app for everyone else (its own Vercel project, cpcana-handbooks, separate from cpcana). CI checks both are current; see its README for republishing. The app links to the public copy through NEXT_PUBLIC_HANDBOOKS_URL (§3), so if that site moves, update the variable and redeploy. src/lib/handbooks.test.ts fails if a guide's id, title, or public flag in library.json, or a heading the app links to, changes without the app's copy in src/lib/handbooks.ts.
  • CLAUDE.md — Architectural invariants for developers modifying the code.