Quickstart
Set up a local dev environment from scratch.
OpenInsure uses GitHub Actions as the sole CI authority (Woodpecker on Hetzner k3s was retired 2026-05-08 alongside the cluster). All automated quality enforcement, testing, security scanning, and deployment runs in workflow files under .github/workflows/.
The .github/workflows/continuous-integration.yml workflow defines the per-PR + master quality gate:
PR → lint → security → workspace-testmaster → lint → security → workspace-test → deploy-matrix → deploy-fan-inScheduled workflows (ci-daily-maintenance.yml, ci-weekly-maintenance.yml, ci-test-health.yml, renovate.yml) run dependency updates, golden-image refreshes, and test-suite health probes.
lintRuns oxfmt --check . and biome check . for formatting and linting.
testRuns the full quality gate:
quick-checksFast, cheap validation that runs first to catch obvious problems:
| Step | Command | Purpose |
|---|---|---|
| Type check | tsp compile typespec/ | Validate TypeSpec API spec |
| Dead code | pnpm exec knip --reporter compact | Detect unused exports/deps |
| Workspace invariants | pnpm exec sherif | Verify pnpm workspace consistency |
| Unit smoke | pnpm --filter @openinsure/types test | Fast type-level sanity check |
lintCode quality and formatting:
| Step | Command | Purpose |
|---|---|---|
| Biome | biome check . | Lint + format all TypeScript/TSX |
| Oxlint | pnpm turbo oxlint | Secondary linter pass |
testFull test suite with coverage reporting:
pnpm turbo testCoverage is uploaded to Codecov after every green test run (requires CODECOV_TOKEN env var).
quality-gateIntegration and end-to-end validation:
pnpm turbo build — verify all packages build cleanlyscripts/release-smoke.sh)scripts/check-slo-guardrails.sh)security-scanSupply chain and dependency security:
| Step | Tool | Purpose |
|---|---|---|
| Audit | pnpm audit --audit-level=high | npm advisory database |
| Supply chain | Socket.dev CLI | Deep 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.
deploy.github/workflows/continuous-integration.yml runs deploy-matrix only when lint, security, and workspace-test jobs all pass.
deployTriggered on git tags (v*):
wrangler deploy # All workers in dependency orderWorkers deploy in this order: oi-sys-auth → oi-sys-api → frontends.
deploy-finance-portal and deploy-compliance-portalEach new portal has a dedicated deploy step 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-varsBoth use --keep-vars so Cloudflare retains existing secrets (FINANCE_JWT_SECRET, COMPLIANCE_JWT_SECRET) set via wrangler secret put.
Knip scans every workspace for unused exports, files, and dependencies.
pnpm knip# or with compact output:pnpm exec knip --reporter compactKnip 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:
package.json but never usedSherif enforces consistency rules across pnpm workspaces — no syncpack, no custom scripts.
pnpm sherifWhat Sherif enforces:
package.json fields that conflict across workspacesSherif 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.
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 credentialsThe 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 changescd infra/azure-authtofu inittofu plan
# Apply (requires Azure credentials in environment)tofu applyRenovate runs weekly (Monday 06:00 ET) via .github/workflows/renovate.yml and opens PRs for dependency updates. Requires RENOVATE_TOKEN env var (GitHub PAT with repo scope).
Auto-merge policy (configured in renovate.json):
| Update type | Policy |
|---|---|
| Patch versions | Auto-merge |
| Security vulnerabilities | Auto-merge |
| Next.js / React major | Manual review |
| Cloudflare Workers | Manual review |
| Drizzle ORM | Manual review |
| Turbo | Manual review |
| TanStack (all) | Grouped, manual review |
@radix-ui/* | Grouped, manual review |
Internal @openinsure/* packages are excluded from Renovate.
The mobile deploy pipeline lives in .github/workflows/continuous-integration.yml (eas-build-tags + eas-update jobs). It runs in parallel with the main pipeline: EAS Update on master push (when mobile-affecting paths change), EAS Build on mobile/v* git tags. It calls eas workflow:run .eas/workflows/production.yml which:
Required env var: EXPO_TOKEN (set via gh secret set EXPO_TOKEN --repo openinsure/openinsure). Generate at expo.dev → Account Settings → Access Tokens.
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 -- --coverageRequires CODECOV_TOKEN set as a GHA repo secret.
Socket.dev performs deep analysis of every npm package in the dependency graph — beyond the advisory database. It detects:
Secrets are managed via gh secret set --repo openinsure/openinsure. See CLAUDE.md and docs/SECRETS_INVENTORY.md for the full list.
| Variable | Purpose | Where to get |
|---|---|---|
cloudflare_api_token | Worker deployments | Cloudflare dashboard → API Tokens |
github_token | Repo write (tag step) | github.com/settings/tokens |
RENOVATE_TOKEN | GitHub PAT for Renovate PRs | github.com/settings/tokens |
CODECOV_TOKEN | Coverage upload | app.codecov.io |
SOCKET_SECURITY_API_KEY | Supply chain scan | socket.dev dashboard |
TURBO_TOKEN + TURBO_TEAM | Turbo remote cache | vercel.com/account/tokens |
DATABASE_URL | Migration jobs | PlanetScale dashboard (app.planetscale.com) |
JWT_SECRET | API test suite + admin/UW portal | Generate: openssl rand -hex 32 |
expo_token | EAS auth (mobile pipeline) | expo.dev → Account Settings → Access Tokens |
slack_webhook_url | Pipeline notifications | Slack app settings |
sentry_auth_token | Release tagging | Sentry → API Keys (project:releases scope) |
Run the same checks locally before pushing:
# Type safetypnpm exec tsc --noEmit
# Lint + formatbiome check --write .
# Dead code auditpnpm knip
# Workspace invariantspnpm sherif
# Full test suitepnpm turbo test
# Build verificationpnpm turbo buildOr run everything at once with the gauntlet script:
pnpm gauntletCommits follow the Conventional Commits spec, enforced by commitlint:
feat(claims): add reserve change audit trailfix(billing): correct invoice balance calculationchore(deps): bump drizzle-orm to 0.45.1Scopes 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.