Production Roadmap

21 tasks · 11 critical · Enterprise-grade solutions throughout

11 Critical9 High1 Medium

Phase 0 — Foundation

Before writing a line of production code. Set up the scaffolding everything else depends on.

3 tasks

Register domain & configure Cloudflare DNS

Critical1–2 hours

Register ctrlspend.com (or .io), point nameservers to Cloudflare, and configure DNS records for the app subdomain, marketing site, and email. Cloudflare adds enterprise-grade DDoS protection, CDN, and bot management at no cost on the free tier.

Cloudflare DNS + Namecheap/Google Domains

Cloudflare is the enterprise standard for DNS. Every major SaaS runs on it. Free tier covers DDoS protection, CDN, WAF, and analytics. It scales to millions of requests without changing anything.

  1. 1Purchase ctrlspend.com at Namecheap or Google Domains (~$12/year)
  2. 2Create a free Cloudflare account and add the domain
  3. 3Copy Cloudflare nameservers (ns1.cloudflare.com / ns2.cloudflare.com) into your registrar
  4. 4Add CNAME: app.ctrlspend.com → cname.vercel-dns.com (Proxied ON)
  5. 5Add CNAME: www.ctrlspend.com → cname.vercel-dns.com (Proxied ON)
  6. 6Add A record: ctrlspend.com → 76.76.21.21 (Vercel IP) OR set up a Page Rule redirect from root to www
  7. 7Set SSL/TLS mode to "Full (strict)"
  8. 8Enable HSTS under SSL/TLS → Edge Certificates
  9. 9Set security level to "Medium" under Security → Settings
  10. 10Document all records in /docs/infrastructure/dns.md
  11. 11⚠️ TODO: Verify the @ A record for ctrlspend.app is set to grey cloud (DNS only, not proxied) in Cloudflare — currently resolving through Cloudflare proxy IPs instead of Vercel's 76.76.21.21, which may cause SSL cert renewal issues with Vercel over time

Set up GitHub repository with branch protection

Critical30 minutes

Move the codebase to a private GitHub repository with branch protection on main, required PR reviews, and status checks. This is the foundation for all CI/CD and collaboration.

GitHub (private repo) + branch protection rules

GitHub is the industry standard. Enterprise plan adds SAML SSO, audit logs, and advanced security scanning — all needed for SOC 2.

  1. 1Create private GitHub repo: github.com/new → ctrlspend (private)
  2. 2git init (if not already), git remote add origin <url>
  3. 3git push -u origin main
  4. 4Settings → Branches → Add rule for "main": require PR, require status checks, no force push, no deletion
  5. 5Settings → Secrets → Add VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID for CI
  6. 6Add .github/CODEOWNERS file assigning @rickycraib as owner of all files
  7. 7Add .github/pull_request_template.md

Set up Doppler for secrets management

Critical2 hours

Doppler is a secrets manager that syncs environment variables across local dev, staging, and production. It prevents secrets from ever living in .env files, which get committed by accident. Enterprise feature: secret rotation, audit logs, and team access controls.

Doppler

Doppler is SOC 2 Type II certified, supports secret rotation, has granular per-environment access, integrates natively with Vercel, and has an audit trail — all required for enterprise customers and SOC 2 certification.

  1. 1Sign up at doppler.com, create a "ctrlspend" project
  2. 2Create three environments: development, staging, production
  3. 3Add all environment variables (Clerk keys, Supabase URL/keys, Resend API key, Stripe keys, etc.)
  4. 4Install Doppler CLI: brew install dopplerhq/cli/doppler
  5. 5doppler login && doppler setup (in project root)
  6. 6Update package.json: "dev": "doppler run -- next dev" to auto-inject secrets locally
  7. 7In Vercel: Integrations → Doppler → connect and sync production secrets
  8. 8Delete all .env.local files from the repo (secrets now come from Doppler)
  9. 9Add /docs/infrastructure/secrets.md listing all required env vars (keys only, no values)

Phase 1 — Core Infrastructure

Authentication, database, and deployment. Nothing else can be built until these three are solid.

3 tasks

Deploy to Vercel with staging + production environments

Critical2–3 hours

Deploy CtrlSpend to Vercel with two environments: staging (preview branch) and production (main branch). Configure custom domains, environment variables via Doppler integration, and set up preview deployments for every PR.

Vercel Pro

Vercel is SOC 2 Type II compliant, has a 99.99% SLA on Pro/Enterprise, supports Fluid Compute (no cold starts), and has native Next.js optimization. Pro plan is $20/month and required for team features and custom domains.

  1. 1Sign up for Vercel Pro at vercel.com
  2. 2Import GitHub repo → New Project → select ctrlspend
  3. 3Framework preset: Next.js (auto-detected)
  4. 4Connect Doppler integration (Settings → Integrations → Doppler)
  5. 5Add custom domains: app.ctrlspend.com (production), staging.ctrlspend.com (staging branch)
  6. 6Settings → Git → set Production Branch to "main", enable Preview deployments on all other branches
  7. 7Settings → Functions → set default region to US East (iad1)
  8. 8Enable Vercel Analytics under Settings → Analytics
  9. 9Add vercel.json to configure security headers
  10. 10Set up Slack notification webhook for deploy events

Implement Clerk authentication with multi-tenant organizations

Critical1–2 days

Replace the mock login/onboarding with real Clerk authentication. Clerk handles multi-tenant organizations (each customer = one org), Google/Salesforce SSO, MFA, and enterprise SAML — all without building any of it yourself.

Clerk

Clerk is SOC 2 Type II certified, supports SCIM provisioning and SAML SSO (enterprise requirements), has built-in org management for multi-tenancy, and has a generous free tier (10K MAU). It's the fastest path to enterprise-ready auth without building it.

  1. 1npm install @clerk/nextjs
  2. 2Create Clerk application at dashboard.clerk.com
  3. 3Enable Google OAuth and email/password sign-in methods
  4. 4Enable Organizations feature in Clerk dashboard
  5. 5Create roles: admin, member, viewer with permissions
  6. 6Add Clerk keys to Doppler (NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY)
  7. 7Wrap app/layout.tsx with <ClerkProvider>
  8. 8Create middleware.ts to protect all routes except /login, /onboarding, /marketing pages
  9. 9Update login page to use Clerk's useSignIn hook
  10. 10Update onboarding to call clerk.organizations.create() on completion
  11. 11Create /api/webhooks/clerk route for user.created and org.created events
  12. 12Update Sidebar to use useUser() and useOrganization() from Clerk

Set up Supabase database with full schema and RLS

Critical2–3 days

Design and deploy the complete Postgres schema in Supabase with Row Level Security policies so each organization can only see its own data. This is the single most important architectural decision — getting schema right now prevents painful migrations later.

Supabase (Pro plan)

Supabase is SOC 2 Type II compliant, runs on managed Postgres with point-in-time recovery, has built-in Row Level Security for multi-tenancy, supports realtime subscriptions, and has a $25/month Pro plan with 99.9% SLA. It's the enterprise-ready Firebase alternative.

  1. 1Create Supabase project at supabase.com (Pro plan, region: US East)
  2. 2Add Supabase URL and keys to Doppler
  3. 3npm install @supabase/supabase-js @supabase/ssr
  4. 4Write and run the full schema migration (see agent prompt)
  5. 5Enable Row Level Security on all tables
  6. 6Write RLS policies for each table
  7. 7Create Supabase client helpers (server + browser)
  8. 8Connect Clerk webhook to create org/user records on signup
  9. 9Set up database backups (daily snapshots + PITR on Pro)
  10. 10Create a staging Supabase project for non-production testing

Phase 2 — Real Integrations

Replace mock data with live vendor API connections. Start with the two easiest (OpenAI, Anthropic), then tackle Salesforce — the beachhead.

3 tasks

Build encrypted credential storage service

Critical1 day

Before connecting any real APIs, build the system for securely storing vendor API keys and OAuth tokens. Keys must be encrypted at rest using AES-256-GCM. The raw key should NEVER be stored in the database — only the ciphertext. This is an enterprise and SOC 2 requirement.

AES-256-GCM encryption via Node.js crypto + Supabase storage

Encrypting credentials at rest with a key stored in Doppler (not the database) means a database breach exposes no usable secrets. This is the pattern used by all major SaaS vendors and is required for SOC 2 Type II.

  1. 1Generate a 32-byte random ENCRYPTION_KEY and store in Doppler
  2. 2Build /lib/crypto.ts with encrypt(plaintext) and decrypt(ciphertext) functions
  3. 3Store encrypted credentials in integrations.credential_ref column
  4. 4Build /lib/vault.ts with saveCredential(orgId, vendorId, key) and getCredential(orgId, vendorId)
  5. 5Write tests for encrypt/decrypt round-trip
  6. 6Never log decrypted credentials anywhere

Build background sync engine with Trigger.dev

Critical2–3 days

Vendor data needs to sync on a schedule (every 15–60 minutes) and on-demand when a user clicks "Sync now." Trigger.dev provides a durable job queue with retry logic, observability, and scheduling — all hosted without managing infrastructure.

Trigger.dev v3

Trigger.dev is open-source, SOC 2 compliant, supports long-running jobs (up to 1 hour), has built-in retry with exponential backoff, and a full job history UI. It's the enterprise-grade alternative to raw cron jobs or serverless functions that timeout.

  1. 1npm install @trigger.dev/sdk@v3
  2. 2npx trigger.dev@latest init (creates trigger.config.ts and /trigger directory)
  3. 3Create syncVendorJob that accepts { orgId, vendorId } payload
  4. 4Job steps: fetch credential → call vendor API → normalize data → upsert spend_records → update integrations.last_synced_at
  5. 5Create a scheduled trigger: run syncVendorJob every 15 minutes for all connected integrations
  6. 6Create an on-demand trigger called from "Sync now" button API route
  7. 7Deploy: npx trigger.dev@latest deploy

Build Salesforce Agentforce integration (OAuth + Digital Wallet)

Critical3–5 days

The Salesforce integration is the beachhead product. It requires a proper Salesforce Connected App with OAuth 2.0, then pulls from three APIs: Digital Wallet (credit balance), Agentforce Usage (per-agent breakdown), and Setup Audit Trail (change history).

Salesforce Connected App + REST API

Salesforce OAuth is the enterprise-standard auth flow for Salesforce ISVs. Required for AppExchange listing. The Digital Wallet API is the only source of truth for Flex Credit consumption.

  1. 1Create a Salesforce Connected App in a developer org
  2. 2Configure OAuth scopes: api, refresh_token, offline_access
  3. 3Store client_id and client_secret in Doppler
  4. 4Build OAuth callback route: /api/integrations/salesforce/callback
  5. 5Exchange code for access_token + refresh_token, encrypt and store both
  6. 6Build sync functions for Digital Wallet API, Agentforce Events API, Audit Trail
  7. 7Handle token refresh (Salesforce tokens expire every 2 hours)
  8. 8Test with a real Salesforce sandbox org

Phase 3 — Product Layer

Anomaly detection, notifications, billing, error monitoring, and analytics. This is what turns the integration layer into a product.

5 tasks

Build real-time anomaly detection engine

Critical2–3 days

After each sync, compare the latest spend data against a rolling baseline and create cost_events when anomalies are detected. V1 uses statistical thresholds (2x rolling average). V2 can add Claude-powered root cause analysis.

Custom Postgres + Trigger.dev post-sync job

Running anomaly detection in a Trigger.dev job after each sync keeps it decoupled from the sync itself. Postgres window functions handle the rolling average calculation efficiently at scale.

  1. 1Create detect-anomalies Trigger.dev task, triggered after every sync completes
  2. 2Query last 7 days of spend_records for baseline average
  3. 3If today's spend > 2x the 7-day average AND change > $50, create a cost_event
  4. 4Assign severity based on percent change (>500% = critical, >200% = high, >100% = medium)
  5. 5Avoid duplicate events (check if an open event exists for this integration already)
  6. 6After creating event, trigger notifications (next task)

Build email + Slack notification system

High2 days

Send real notifications when anomalies are detected. Two channels: email (Resend) and Slack (incoming webhooks). Also build the weekly spend digest email sent every Monday morning.

Resend (transactional email) + Slack Webhooks

Resend has best-in-class deliverability, React-based email templates, and a generous free tier. Slack webhooks are free and enterprise-standard for operational alerts. Both are production-grade without any infrastructure.

  1. 1npm install resend react @react-email/components
  2. 2Verify ctrlspend.com domain in Resend dashboard
  3. 3Add SPF, DKIM records to Cloudflare (Resend provides these)
  4. 4Create email templates: anomaly alert, weekly digest, welcome, invite
  5. 5Build /lib/notifications/email.ts using Resend SDK
  6. 6Build /lib/notifications/slack.ts using incoming webhooks
  7. 7Create sendAlertTask Trigger.dev job that routes to email/Slack based on alert_rules
  8. 8Set up weekly digest cron: every Monday 8am via Trigger.dev

Implement Stripe billing with usage-based upgrade prompts

High2–3 days

Set up Stripe subscriptions with the four pricing tiers. Use Stripe Customer Portal for plan management. Add upgrade prompts when users hit plan limits (e.g., trying to add a 3rd integration on the free tier).

Stripe + Stripe Customer Portal

Stripe handles payment compliance (PCI DSS Level 1), global payments, subscription management, proration, and invoicing. Stripe Customer Portal removes the need to build any billing UI yourself.

  1. 1Create Stripe account, complete KYC
  2. 2Create 4 products: Starter (free), Growth ($499/mo), Business ($1499/mo), Enterprise (custom)
  3. 3npm install stripe @stripe/stripe-js
  4. 4Build /api/stripe/create-checkout-session route
  5. 5Build /api/stripe/create-portal-session route
  6. 6Build /api/webhooks/stripe route to handle subscription events
  7. 7On checkout.session.completed: update organizations.plan in Supabase
  8. 8Add plan enforcement: check org plan before allowing additional integrations
  9. 9Add upgrade modal component for when users hit plan limits

Set up Sentry for error monitoring and performance

High2–3 hours

Sentry catches unhandled exceptions, performance bottlenecks, and database query issues in production — before users report them. Enterprise feature: issue assignment, team alerts, and integrations with Slack and Linear.

Sentry (Next.js SDK)

Sentry is the industry standard for error monitoring, SOC 2 Type II compliant, and used by 90% of enterprise SaaS. The Next.js SDK auto-instruments API routes, server components, and client-side errors with zero configuration.

  1. 1npx @sentry/wizard@latest -i nextjs
  2. 2This auto-creates sentry.client.config.ts, sentry.server.config.ts, next.config.js instrumentation
  3. 3Add SENTRY_DSN to Doppler
  4. 4Set up Sentry alerts: email + Slack on new issues
  5. 5Configure session replay for debugging UI issues (sample rate 10% in prod)
  6. 6Set up performance monitoring with 10% trace sampling
  7. 7Create Sentry team and assign to relevant projects

Add PostHog product analytics and feature flags

High3–4 hours

Track key user actions (signup, integration connected, anomaly investigated) to understand where users get value and where they drop off. Feature flags allow safe gradual rollouts of new integrations.

PostHog (Cloud)

PostHog is open-source (self-hostable for maximum data privacy, required by some enterprise customers), SOC 2 Type II compliant, GDPR compliant, and combines product analytics + session replay + feature flags in one tool.

  1. 1npm install posthog-js posthog-node
  2. 2Create PostHog project at app.posthog.com
  3. 3Add NEXT_PUBLIC_POSTHOG_KEY to Doppler
  4. 4Create PostHog provider component, wrap app in it
  5. 5Track key events: user_signed_up, integration_connected, anomaly_investigated, upgrade_clicked
  6. 6Create funnels: signup → connect_integration → view_first_insight
  7. 7Create feature flag: salesforce_deep_integration (for controlled Salesforce rollout)

Phase 4 — Marketing & Legal

Everything customers and prospects see before they sign up. Required before any public launch.

2 tasks

Build marketing website at ctrlspend.com

High3–5 days

A standalone marketing site at ctrlspend.com (separate from the app at app.ctrlspend.com). Must communicate the value proposition, capture email leads for the waitlist, and be optimized for SEO. Built with Next.js so it's the same stack.

Next.js on Vercel + Loops for email capture

Same stack as the app = one repo, one deployment, no context-switching. Loops is the modern email marketing platform built for SaaS — better deliverability than Mailchimp and a better UX than HubSpot.

  1. 1Create /marketing directory as a separate Next.js app OR add pages to the same repo under /app/(marketing)/
  2. 2Build: Hero section, Problem section, Solution/Feature sections, Pricing, Social proof placeholder, CTA
  3. 3Integrate Loops for waitlist email capture (POST to Loops API)
  4. 4Add metadata for SEO: OpenGraph tags, Twitter card, structured data
  5. 5Set up Google Search Console verification
  6. 6Create /sitemap.xml and /robots.txt
  7. 7Add Plausible Analytics for privacy-respecting web analytics

Set up legal infrastructure (ToS, Privacy, DPA)

High1–2 days

Enterprise customers will require a Data Processing Agreement before signing. Privacy Policy and Terms of Service are required for launch. Use Docusign or PandaDoc for DPA e-signature workflow.

Termly (policy generation) + PandaDoc (DPA e-signature)

Termly generates GDPR/CCPA-compliant policies that update automatically when laws change ($10/month). PandaDoc handles enterprise DPA signature workflows. These two tools replace $5,000+ in legal fees for launch.

  1. 1Generate Privacy Policy at termly.io (include: data collected, retention periods, GDPR/CCPA rights)
  2. 2Generate Terms of Service covering: payment, acceptable use, data ownership, termination
  3. 3Create a DPA template (Data Processing Agreement) — you process data on behalf of customers
  4. 4Host all three on the marketing site (/privacy, /terms, /dpa)
  5. 5Add "Privacy Policy" and "Terms" links to login/signup forms
  6. 6Set up PandaDoc with DPA template for enterprise prospects
  7. 7Add cookie consent banner (GDPR requirement for EU users)

Phase 5 — Enterprise Readiness

The features enterprise buyers require before signing. Start SOC 2 early — it takes 3–6 months and blocks deals.

3 tasks

Begin SOC 2 Type II certification with Vanta

High1–2 weeks setup, 3–6 months to certification

SOC 2 Type II certification is required by virtually every enterprise customer before they'll sign a contract. Vanta automates 80% of the compliance work by continuously monitoring your infrastructure and generating the audit evidence automatically.

Vanta

Vanta connects to GitHub, AWS, Vercel, Supabase, Google Workspace, and 100+ other tools to auto-collect evidence. It reduces the cost of a SOC 2 audit from $50K+ to ~$15K and cuts preparation time from 6 months to 6 weeks.

  1. 1Sign up at vanta.com (~$800/month, pause until first $10K ARR)
  2. 2Connect all integrations: GitHub, Vercel, Supabase, Clerk, Stripe, Google Workspace
  3. 3Review the 100+ automated controls Vanta checks
  4. 4Address gaps: security training, password manager policy, background checks, incident response plan
  5. 5Create required policies: Information Security Policy, Acceptable Use, Access Control, Incident Response
  6. 6Enable automated employee device monitoring (Vanta agent)
  7. 7Choose a SOC 2 auditor (Vanta partners: Johanson Group, Sensiba, etc.)
  8. 8Begin 90-day observation period

Implement API rate limiting and abuse protection

High4–6 hours

All API routes need rate limiting to prevent abuse and ensure fair usage. Use Upstash Redis for a serverless, globally-distributed rate limiter that works in Vercel's edge runtime.

Upstash Redis + @upstash/ratelimit

Upstash is serverless Redis that works in Vercel edge functions with zero infrastructure management. @upstash/ratelimit implements sliding window and token bucket algorithms in <10 lines of code. Free tier covers 10K requests/day.

  1. 1Create Upstash account and Redis database at console.upstash.com
  2. 2npm install @upstash/redis @upstash/ratelimit
  3. 3Add UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN to Doppler
  4. 4Create /lib/rate-limit.ts with limiter instances for different route types
  5. 5Apply rate limiting in middleware.ts for all /api routes
  6. 6Return 429 with Retry-After header when limit exceeded

Configure enterprise SAML SSO via Clerk

Medium4–6 hours

Enterprise customers require SAML SSO so their employees sign in with their company identity provider (Okta, Azure AD, Google Workspace). Clerk supports per-organization SAML with zero code changes.

Clerk Enterprise (SAML)

Clerk handles all the SAML complexity (XML parsing, assertion validation, IdP metadata) and exposes it through a simple dashboard UI. Upgrading to Clerk Enterprise enables SAML, SCIM provisioning, and advanced org management.

  1. 1Upgrade to Clerk Enterprise plan (required for SAML)
  2. 2In Clerk dashboard: Enterprise Connections → Enable SAML for an org
  3. 3Customer provides their IdP metadata (Okta/Azure AD/Google)
  4. 4Configure attribute mapping: email, first_name, last_name, role
  5. 5Test with a sandbox IdP (Clerk provides one)
  6. 6Document the SAML setup process for customers in /docs/enterprise/sso-setup.md
  7. 7Add "Configure SSO" button in Settings page for admin users

Phase 6 — Launch

The final checklist before going live. Do not skip any item.

2 tasks

Set up uptime monitoring and on-call alerting

High1–2 hours

Continuously monitor app.ctrlspend.com, the API health endpoint, and Supabase connection. Alert via Slack and PagerDuty if anything goes down. Enterprise SLAs require 99.9% uptime monitoring evidence.

Better Uptime (or Checkly)

Better Uptime monitors from 10+ global locations, has beautiful status pages (status.ctrlspend.com) that you can share with enterprise customers, and has a generous free tier. Status pages are an enterprise trust signal.

  1. 1Sign up at betteruptime.com
  2. 2Add monitors: app.ctrlspend.com, app.ctrlspend.com/api/health, staging.ctrlspend.com
  3. 3Set alert contacts: your email + Slack webhook
  4. 4Create public status page at status.ctrlspend.com
  5. 5Link status page from the marketing site footer and Settings page
  6. 6Set up on-call rotation (even if it's just you right now)

Final pre-launch security and quality checklist

Critical1 day

Run through every item before flipping the switch on the first real user. This includes security headers, database backup verification, GDPR compliance, and smoke testing the full user journey.

Manual checklist + automated security scan (Mozilla Observatory)

A missed security header or misconfigured CSP can result in a breach. Mozilla Observatory and securityheaders.com provide free automated security scanning. Fixing issues costs $0 at launch — it costs millions after a breach.