Skip to main content

CI/CD & Developer Tooling

OpenInsure uses a CircleCI-native CI/CD pipeline. GitHub is used exclusively as a version-control host — there is no GitHub Actions integration and no GitHub VCS link in CircleCI. All automated quality enforcement, testing, security scanning, and deployment runs in CircleCI.

caution

CircleCI project slug: circleci/HW2RogsnMHUCC7jGBX9nec/Fuwa3GUWKCGnbJuUY6MJps

When adding environment variables via the CircleCI API use:

POST /api/v2/project/circleci/<org>/<project>/envvar

Not the github/<org>/<repo> path — that returns 404.

Pipeline Overview

The .circleci/config.yml defines five sequential jobs that form the full quality gate:

quick-checks → lint → test → quality-gate → security-scan

(on tag) deploy

Additionally a renovate-deps job runs on a weekly schedule (Monday 06:00 ET) to open dependency update PRs via Renovate.

Job: quick-checks

Fast, cheap validation that runs first to catch obvious problems:

StepCommandPurpose
Type checktsp compile typespec/Validate TypeSpec API spec
Dead codepnpm exec knip --reporter compactDetect unused exports/deps
Workspace invariantspnpm exec sherifVerify pnpm workspace consistency
Unit smokepnpm --filter @openinsure/types testFast type-level sanity check

Job: lint

Code quality and formatting:

StepCommandPurpose
Biomebiome check .Lint + format all TypeScript/TSX
Oxlintpnpm turbo oxlintSecondary linter pass

Job: test

Full test suite with coverage reporting:

pnpm turbo test

Coverage is uploaded to Codecov after every green test run (requires CODECOV_TOKEN env var).

Job: quality-gate

Integration and end-to-end validation:

  • pnpm turbo build — verify all packages build cleanly
  • Database migration dry-run
  • Release smoke tests (scripts/release-smoke.sh)
  • SLO guardrail checks (scripts/check-slo-guardrails.sh)

Job: security-scan

Supply chain and dependency security:

StepToolPurpose
Auditpnpm audit --audit-level=highnpm advisory database
Supply chainSocket.dev CLIDeep package provenance + threat intel

Requires SOCKET_SECURITY_API_KEY env var. Enabled scopes: diff-scans, full-scans, packages, dependencies, triage, threat-feed, security-policy, fixes.

Job: deploy

Triggered on git tags (v*):

wrangler deploy   # All workers in dependency order

Workers deploy in this order: oi-sys-authoi-sys-api → frontends.

Jobs: deploy-finance-portal and deploy-compliance-portal

Each new portal has a dedicated deploy job that runs on master after build, test, lint, and typecheck pass. Both use path-based change detection — they only deploy when files in their respective apps/ directory or shared packages (auth-hooks, config, db, react-query, types, ui) change.

deploy-finance-portal:
steps:
- check-paths:
pattern: '^(apps/finance-portal/|packages/(auth-hooks|config|db|react-query|types|ui)/)'
- run: cd apps/finance-portal && npx opennextjs-cloudflare deploy -- --keep-vars

deploy-compliance-portal:
steps:
- check-paths:
pattern: '^(apps/compliance-portal/|packages/(auth-hooks|config|db|react-query|types|ui)/)'
- run: cd apps/compliance-portal && npx opennextjs-cloudflare deploy -- --keep-vars

Both use --keep-vars so Cloudflare retains existing secrets (FINANCE_JWT_SECRET, COMPLIANCE_JWT_SECRET) set via wrangler secret put.

Developer Tooling

Knip — Dead Code Detection

Knip scans every workspace for unused exports, files, and dependencies.

pnpm knip
# or with compact output:
pnpm exec knip --reporter compact

Knip is configured in knip.json at the repo root. It's advisory in CI (|| true) — findings are surfaced as warnings, not failures, until the initial cleanup pass is complete.

What Knip catches:

  • Exported functions/types that are never imported
  • Dependencies declared in package.json but never used
  • Files that are not reachable from entry points

Sherif — Workspace Invariants

Sherif enforces consistency rules across pnpm workspaces — no syncpack, no custom scripts.

pnpm sherif

What Sherif enforces:

  • All workspace packages that share a dependency use the same version
  • No duplicate package.json fields that conflict across workspaces
  • Package names match their directory structure

Sherif was chosen over Syncpack because Syncpack v13 crashes on Node.js v25+. Sherif is zero-config for pnpm workspaces and works correctly on all Node.js versions.

OpenTofu — Infrastructure as Code

Azure AD resources (the Microsoft SSO app registration for oi-sys-auth) are managed with OpenTofu (the open-source Terraform fork) using the azuread provider.

infra/azure-auth/
├── main.tf # azuread_application, azuread_service_principal
├── variables.tf # tenant_id, client_id, redirect_uris
├── outputs.tf # application_id, client_secret
└── terraform.tfvars # NOT committed — contains Azure credentials

The Azure app registration "OpenInsure Auth" is single-tenant (AzureADMyOrg), restricted to the mhcis.com tenant (ebd58a52-c818-4230-b150-348ae1e17975). Infrastructure changes are applied manually by a platform engineer with Azure Owner rights — there is no automated tofu apply in CI at this time.

# Plan changes
cd infra/azure-auth
tofu init
tofu plan

# Apply (requires Azure credentials in environment)
tofu apply
caution

terraform.tfvars and any .tfstate files contain Azure client secrets and must never be committed to source control. The .gitignore at the repo root excludes *.tfvars and *.tfstate.

Renovate — Automated Dependency Updates

Renovate runs weekly (Monday 06:00 ET) via CircleCI and opens PRs for dependency updates. Requires RENOVATE_TOKEN env var (GitHub PAT with repo scope).

Auto-merge policy (configured in renovate.json):

Update typePolicy
Patch versionsAuto-merge
Security vulnerabilitiesAuto-merge
Next.js / React majorManual review
Cloudflare WorkersManual review
Drizzle ORMManual review
TurboManual review
TanStack (all)Grouped, manual review
@radix-ui/*Grouped, manual review

Internal @openinsure/* packages are excluded from Renovate.

EAS Mobile Deploy

The deploy-mobile CircleCI job triggers on merge to master after all quality gates pass. It runs eas workflow:run .eas/workflows/production.yml which:

  1. Fingerprints native code for iOS and Android
  2. Checks if a compatible build already exists
  3. If native code changed → full EAS build + App Store / Play Store submit
  4. If only JS changed → OTA update to production channel (minutes, no store review)

Required env var: EXPO_CIRCLECI_ACCESS_TOKEN (mapped to EXPO_TOKEN at runtime). Generate at expo.dev → Account Settings → Access Tokens.

Codecov — Coverage Tracking

Coverage reports are uploaded after every passing test run. Reports are uploaded from the test CI job using codecov-action.

To add coverage locally:

pnpm turbo test -- --coverage

Requires CODECOV_TOKEN set in CircleCI project environment variables.

Socket.dev — Supply Chain Security

Socket.dev performs deep analysis of every npm package in the dependency graph — beyond the advisory database. It detects:

  • Typosquatting — packages with names similar to popular ones
  • Malicious code injection — packages that execute code at install time
  • Dependency confusion — private package names published to the public registry
  • Unmaintained packages — packages with no recent activity or abandoned by their author
  • Protestware / env var exfiltration — behavioral analysis of install/postinstall scripts

Required CircleCI Environment Variables

VariablePurposeWhere to get
CLOUDFLARE_API_TOKENWorker deploymentsCloudflare dashboard → API Tokens
FLY_API_TOKENFly.io runners/servicesfly auth token
RENOVATE_TOKENGitHub PAT for Renovate PRsgithub.com/settings/tokens
CODECOV_TOKENCoverage uploadapp.codecov.io
SOCKET_SECURITY_API_KEYSupply chain scansocket.dev dashboard
TURBO_TOKEN + TURBO_TEAMTurbo remote cachevercel.com/account/tokens
PD_VERCEL_TOKENDeploy pushdown.ai to VercelVercel dashboard → pushdown team
DATABASE_URLMigration jobsPlanetScale dashboard (app.planetscale.com)
JWT_SECRETAPI test suite + admin/UW portalGenerate: openssl rand -hex 32
FINANCE_JWT_SECRETFinance portal authwrangler secret put FINANCE_JWT_SECRET --name oi-sys-finance
COMPLIANCE_JWT_SECRETCompliance portal authwrangler secret put COMPLIANCE_JWT_SECRET --name oi-sys-compliance
note

Sanctions API credentials are Worker secrets, not CI env vars. OPENSANCTIONS_API_URL and OPENSANCTIONS_API_KEY are set via wrangler secret put on oi-sys-api. During CI, OPENSANCTIONS_API_URL is intentionally absent — the static SDN fallback activates automatically and all sanctions unit tests pass without a live endpoint.

danger

All CI credentials must be rotated before any production deployment. Dev credentials were set during initial setup. See the PRE-LAUNCH REMINDER note in CLAUDE.md.

Local Quality Gate

Run the same checks locally before pushing:

# Type safety
pnpm exec tsc --noEmit

# Lint + format
biome check --write .

# Dead code audit
pnpm knip

# Workspace invariants
pnpm sherif

# Full test suite
pnpm turbo test

# Build verification
pnpm turbo build

Or run everything at once with the gauntlet script:

pnpm gauntlet

Commit Conventions

Commits follow the Conventional Commits spec, enforced by commitlint:

feat(claims): add reserve change audit trail
fix(billing): correct invoice balance calculation
chore(deps): bump drizzle-orm to 0.45.1

Scopes should match the affected package or app (e.g., api, billing, claims, portal).

Quickstart

Set up a local dev environment from scratch.

Architecture

Understand the edge/origin split and data flow.