Building a Schema-Driven Deploy Gate (And Fixing Silent Data Loss)
Had one of those debugging sessions where you find a small issue and end up rebuilding half your deployment process. Started investigating why Google Analytics fields weren't persisting in our client management system.
Turns out we had a classic silent failure pattern: googleTagId and ga4MeasurementId were being accepted by the API (returned 200 OK), but were getting silently dropped because there were no database columns or field mappings. The data just vanished into the void.
While fixing this, I discovered four more fields with the same issue: notes, domain, custom_domain, and vertical. They were defined in our field allowlists but had no actual database columns. Pre-existing silent failures that nobody had noticed.
This kind of thing drives me crazy, so I decided to build a proper solution instead of just patching the immediate problem.
The Schema-Driven Solution
Built a new validate-schema.js script that defines a single CLIENT_SCHEMA as the source of truth for all 30 fields across our clients and integrations tables. It diffs this schema against the live database via Supabase's Management API and auto-applies ADD COLUMN IF NOT EXISTS migrations for any gaps.
The key insight was replacing all our separately-drifting field lists (adminFields, fieldToColumn, recordToIntegration, etc.) with one canonical schema that drives everything.
Then I wrapped it in a deploy.sh script that gates all deployments - schema validation must pass before wrangler deploy runs. No more silent schema drift.
Small Wins Along the Way
Made PATCH /client/:id return the full updated record instead of just a success message. Now any save handler can verify the round-trip and catch issues immediately.
Also saved an "Autonomous Execution on Input Provision" rule to my global Claude rules. Basically: when someone gives me incomplete context, I should provision what I need rather than asking for clarification. Speeds up the feedback loop.
The Cloudflare/Supabase Token Dance
Ran into a fun environment variable situation. The Cloudflare worker uses SUPABASE_KEY (anon key), but the schema validator needs the management token for DDL operations. Had to set SUPABASE_MANAGEMENT_TOKEN in my local shell since it can't go in the worker secrets.
Note to self: need to rotate that management token since it got exposed in conversation logs.
What's Next
With the schema validation gate in place, I can focus on building out the hook-based state propagation layer that's been sitting in my task board. The foundation feels much more solid now - no more wondering if data is actually persisting or just pretending to.
Sometimes the best debugging sessions are the ones that prevent future debugging sessions.