Skip to content

FlowStack V2: setup & onboarding, secrets, monitoring, safe deploys, upgrades, E2E - #11

Open
vtshreeram wants to merge 25 commits into
jacksonkasi1:devfrom
vtshreeram:feat/v2-setup-dx
Open

vtshreeram wants to merge 25 commits into
jacksonkasi1:devfrom
vtshreeram:feat/v2-setup-dx

Conversation

@vtshreeram

@vtshreeram vtshreeram commented Oct 25, 2026 •

Copy link
Copy Markdown

Summary

FlowStack V2: setup and onboarding, secrets, monitoring, quality gates, safe deploys and template upgrades. Built incrementally on dev; existing commands, auth, schema and migrations are preserved.

bun run setup                      # existing script, extended
  toolchain check (Node 24, Bun)
  questions / flags                # name, mode, frontend, integrations, ports
  configure + .flowstack.json v2   # v1 files upgraded in place
  bun install
  scripts/onboard.mjs              # separate process: setup stays dependency-free
    secrets      .env names | Infisical login + access + required names
    database     connectivity
    migrations   applied only with consent (prompt | --migrate)
    doctor       full report
  rerun = resume (reuse earlier choices)
 scripts/
+├── onboard.mjs  doctor.mjs  dev.mjs  secrets.mjs  db.mjs  upgrade.mjs
+├── deploy-preflight.mjs  cloud-run.mjs  secrets-scan.mjs  check-bundle-secrets.mjs
+└── lib/         env manifest, project config, infisical, db status, toolchain
 apps/server/
+├── src/app.ts  instrument.ts  routes/health/       # Sentry, /health/live|ready, request IDs
 └── .deploy/scripts/deploy.sh                        # verify-before-traffic, rollback, audit
+.github/workflows/  deploy.yml  release.yml          # verify.yml extended: secret-scan, actionlint, e2e
+e2e/  tests/*                                        # 14 → 103 tests + Playwright journey
+AGENTS.md  CLAUDE.md→@AGENTS.md  docs/advanced/*

Deploy flow (deploy.sh):

preflight → build :<sha> → deploy revision with NO traffic (tag r-<sha>)
  → /health/ready on tag URL
     fail: tag failed-<sha>, traffic unchanged, report
     pass: move 100% traffic → (--auto-rollback) re-check, restore previous if unhealthy

Follow-up fixes and verification

  • Added direct Infisical runtime loading for Cloud Run using GCP ID Token Auth. Deployment passes public bootstrap identifiers; instances fetch secrets before importing the API. No local secret files or Google Secret Manager are needed in this mode. Existing env-file and Secret Manager modes remain available.
  • Fixed deployment configuration parsing to respect complete YAML sections and their boundaries, and included dependency patches in the Docker build context.
  • Protected existing migration SQL/snapshots and non-append journal changes during template upgrades; preserved executable script permissions and validated upgrade flags before fetching upstream.
  • Preserved injected auth proxy and database options through Turbo's strict development environment, retained the existing runtime log-format setting in Infisical, and redacted credentials inside arrays without crashing on circular log metadata.
  • Installed the pinned secret scanner in every CI job that runs the hook tests, including preset validation and deployment verification.
  • Centralized the production API build with production JSX compilation. The previous build emitted development JSX calls against production React and silently failed to render verification emails. Runtime/API/browser fixtures now use the same build configuration.
  • Ignored generated Google authentication files so CI credentials do not make production deployments appear dirty or enter build contexts.

Validation on the follow-up commits: 113 tests passed, zero failures and zero skips (including real PostgreSQL-wire-protocol, API lifecycle, deployment simulation, runtime injection and Git-hook tests). Lint, type checking, build and staged gitleaks scan passed. Local browser E2E reached the isolated stack but could not launch Chromium because the pinned Playwright version does not support this host's macOS 13. The Linux CI browser journeys passed for all four personal/organization and React/TanStack combinations on the latest head.

GitHub verification on commit e766e9d: all 12 jobs passed, covering shared lint/types/tests/audit, secret scanning, workflow lint, all five preset builds and all four browser journeys. Successful verification run.

Live Infisical/GCP identity configuration, native runtime authentication against real services and a sandbox deployment have not been performed. These are required before enabling the new runtime mode in a deployed environment.

Evidence from the initial implementation

  • Before: 14 tests; bun audit 45 advisories (5 critical) on dev.
    After: 103 tests pass (10 consecutive runs, 0 failures); 0 advisories; 5/5 presets (4 combos + no optional integrations) install, type-check, test, build with sentinel secrets (no bundle leaks), audit; Playwright journey passes for all 4 presets.
  • Bugs found and fixed, each with a regression test:
    • Production API bundle shipped with SQL query logging on (bun build inlined NODE_ENV="development") → logger: false asserted on the built bundle.
    • Behind a load balancer (X-Forwarded-For: client, lb) all clients shared one auth rate-limit bucket → AUTH_TRUSTED_PROXIES; e2e: client B was 429, now 401; forged left-most IP still 429.
    • Sentry v11 collects cookies/bodies/users when dataCollection is unset → all categories set; runtime test with a fake ingest shows no cookie, bearer or query secret sent.
    • Rollback could pick a release that failed verification → failed-* tag excluded (fake-gcloud test: v1 ok, v2 failed, v3 ok, rollback → v1).
    • Migrations 0004/0005 silently skipped by drizzle on DBs migrated to 0003 (out-of-order journal timestamps) → hash-based db:status detects it and db:migrate refuses.
    • Axios read undocumented VITE_API_URL instead of VITE_API_BASE_URL.
    • infisical run passed INFISICAL_TOKEN into the app process → stripped before the app starts.
    • Membership check mutation (removed in auth middleware) makes the org e2e test fail.
  • Not verified live (mocked only): Infisical project access, Sentry delivery to sentry.io, GCP Workload Identity / Cloud Run deploy and rollback.

Merge Danger

Door: two-way

Revertible commit range; no schema changes, no data migrations, no destructive operations. Deploy script keeps the legacy service-account key and env-file paths working (with warnings); Secret Manager and keyless auth are opt-in.

Blast Radius: tooling-wide

Every developer command goes through new scripts (bun run dev → scripts/dev.mjs). Runtime-visible changes: optional R2/Google/email follow TEMPLATE_FEATURES; API now also runs on non-Neon PostgreSQL (Neon unchanged); production logs become JSON. Before relying on deploys: complete GCP/GitHub setup in apps/server/DEPLOYMENT.md and do a sandbox run first.

🤖 Generated with Claude Code

VT Shreeram and others added 21 commits October 25, 2026 01:28
- Root scripts for doctor, dev:local/dev:secrets, db:*, secrets:*, sentry:verify, prepare (husky).
- Dev dependencies: husky, lint-staged, postgres (db status/migrate), pglite-socket (tests).
- Sentry SDK for the TanStack app.
- bun audit: 45 advisories (5 critical) on dev resolved by in-range updates
  (bun audit fix; vitest, shadcn, react-devtools) and a solid-js ^1.9.17 override.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Project name, optional integrations, safe ports, and v1 .flowstack.json
compatibility. Shared libraries for env manifest and project config.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bun run dev uses Infisical when enabled and never falls back silently;
dev:local and dev:secrets choose explicitly. Non-development secrets are
CI-only and always refused in AI agent sessions. Turborepo passes injected
variables to dev tasks; builds hash only public values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hash-based migration status detects migrations drizzle would skip because
of out-of-order journal timestamps. Production migrations are CI-only;
push/drop are blocked outside development.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…logs

- Sentry v11 dataCollection set explicitly (v11 collects everything when
  unset); shared privacy baseline and beforeSend scrubber in @repo/config.
- /health/live and /health/ready (database), request IDs, safe 500s.
- R2 credentials required only when storage is enabled.
- Build with NODE_ENV=production: an unset NODE_ENV made Bun inline
  "development", which enabled SQL query logging in production bundles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both apps: optional Sentry with the shared privacy baseline, root error
boundaries (TanStack also reports SSR errors), development-only
/debug/sentry, source maps only for Sentry uploads and deleted afterwards.
Google, magic link and uploads follow TEMPLATE_FEATURES.
Fix: axios read the undocumented VITE_API_URL instead of VITE_API_BASE_URL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Images tagged by release; candidates deployed with no traffic and
health-checked before promotion; optional auto-rollback; rollback and
status commands; Secret Manager references so values never pass through
the deployer; preflight validation; production deploys CI-only. Legacy
key files and env-file secrets keep working with warnings. Manual,
approval-gated GitHub workflow using Workload Identity Federation and
Infisical OIDC for migrations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds a full-history gitleaks job (pinned, checksum-verified; failure to
install fails the job), actionlint, shellcheck, a minimal-integrations
preset, sentinel-secret builds checked by check-bundle-secrets, a tagged
release workflow and Dependabot for dev.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AGENTS.md is the single source of agent rules (CLAUDE.md imports it,
AGENT.md points to it); removes unrelated WXT/admin examples. New guides
for Infisical, database, Sentry, git hooks, CI/CD and upgrading; quick
start and setup docs match the commands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…udit records

A candidate that failed verification stayed Ready and could later be
selected as the rollback target once a newer release was promoted.
Failed revisions are now marked with a failed-<release> traffic tag (0%
traffic, not deleted) and excluded from rollback selection. Every run can
write a JSON audit record (DEPLOY_REPORT_FILE), uploaded by the workflow.
Actions updated to current majors (auth/setup-gcloud v3, upload-artifact v7).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
infisical run passes its own environment, including INFISICAL_TOKEN, to
the child. A launcher now strips Infisical credentials before the app
starts. Machine identities using Universal Auth exchange client
credentials (read from the environment, never argv) for a short-lived
token; a rejected identity stops before any command runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neon hosts keep the Neon HTTP driver; other hosts use postgres.js
(DATABASE_DRIVER overrides, DATABASE_POOL_MAX sizes the pool). Local,
Docker and Cloud SQL databases now work at runtime, not only for
migrations, so doctor no longer warns about non-Neon hosts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bun run setup now checks Node.js and Bun first, then (after install)
validates secrets (local .env or Infisical with an offer to sign in),
checks database connectivity, applies development migrations only with
consent (prompt, --migrate or --yes), and runs doctor. Reruns offer to
reuse earlier choices and resume. Setup keeps zero third-party imports
so it runs before bun install; onboarding runs as a separate process.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
flowstack:upgrade:check reports what a newer starter release changes,
using .flowstack.json sourceCommit as the merge base: clean updates,
three-way merges, conflicts, deletions, application-owned files (report
only), new migrations (never executed) and dependency changes (majors
flagged, never applied). flowstack:upgrade previews, requires a clean
tree and confirmation, backs up every touched file, writes conflict
proposals instead of overwriting, and records the new version only once
conflicts are resolved (--mark-resolved).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tests/e2e-api.test.ts runs the production API build against real
migrations on an isolated PostgreSQL with a local mail catcher:
registration, email-link verification, sign-out/in, session isolation,
forged/tampered/bearer credentials, cross-site requests, per-user and
per-organization storage authorization, invitations, safe errors and
log redaction. Verified to fail when the membership check is removed.

e2e/ (Playwright) walks the browser journey (protected redirect, sign-up,
verification, onboarding, sign-out, wrong password, sign-in) and runs for
all four presets in CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Setup docs describe the post-install checks, consent for migrations and
resuming; README and AGENTS.md list test:e2e and the upgrade commands;
CI docs add the e2e job to the required checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A port check that never answered could stall doctor indefinitely; it now
reports the port as unavailable after two seconds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Better Auth resolves no client IP from a multi-hop X-Forwarded-For chain
unless the proxies are trusted, so behind Google's load balancer
(client, lb-ip) every client shared one rate-limit bucket: a few failed
sign-ins from anyone limited all users. AUTH_TRUSTED_PROXIES and
AUTH_IP_HEADERS now configure advanced.ipAddress (default unchanged);
deploy preflight warns while unset. E2E tests prove separate buckets and
that a forged left-most address cannot escape a limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7fdc1f7d-a270-4971-a594-10c963289e87

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-25T01:41:45.018089Z
We couldn’t complete this review. Comment @codex review to try again.
7caa685 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant