Tuesday, May 12, 2026
Phase 1 of the manifestation app crossed the line on all four layers today. Code shipped. Schema healed. A live charge propagated through the stack and lit up a real subscription. Then I sat with the visible bug on the post-login route for two hours before the actual cause turned out to be three layers deeper than where I was looking.
Worked on
- Reviewed gl-elevatedaily — what to work on next? Found the web-next cutover had already silently completed; the first recommendation was decommissioning the stale Astro path
- Deleted the legacy
web/Astro tree — 494 MB, 13,649 files - Fixed prod OG-image leakage — every prerendered page was baking
og:image: http://localhost:3000/...because the build-time public env vars weren't wired through compose'sbuild.argsto the builder stage - Deleted stale S3 bucket from the pre-cutover deploy path
- Shipped internal-auth Phase 1a + 1b end-to-end — hybrid X-Internal-Token + Bearer dispatcher, bootstrapped a new BFF client + internal-bff realm role, expanded the realm URL default to a 2-issuer allowlist so server-to-server callers fetching tokens with the public issuer claim don't get 401'd
- Wrote the Bearer caller in the BFF — InternalBearerProvider + bearer-first / legacy-fallback dispatcher
- Added the api/tests/ scaffold with 14 unit tests, including a 20-coroutine concurrency-against-asyncio-Lock check on the bearer provider
- Scheduled Phase 2 cleanup via
DELETE-IN-PHASE-2code markers in both repos - Diagnosed the post-login route's React #418 hydration crash — chased a CORS configuration bug for two rounds before reading the actual server response
- Backfilled the
schema_migrationstable — 9 migrations had silently drifted on a live revenue surface; the README promised a runner that was never built - Reviewed the Phase 1 backlog — 7 stories that shipped weeks ago were still "Todo" in the tracker
Shipped
- Internal auth Phase 1a + 1b live end-to-end — the BFF can now call the elevatedaily api with a real Bearer token through the public Keycloak issuer
- Phase 1 closed on all four layers — code shipped, schema healed, live charge propagated ($8.88 → active subscription, message id captured), user-facing route visually confirmed after the hydration fix
- The 9-migration drift surfaced — backfilled
schema_migrationsso a real runner has a starting point. The runner itself is filed as follow-up work, not invisible debt anymore - Seven backlogged Stories from 01.1–01.7 closed with per-ticket verification comments citing shipped file paths, PRs, and live evidence — the backlog now reflects reality instead of weeks-stale state
- 2-issuer allowlist on the realm URL — both the public issuer claim and the in-cluster one resolve to the same realm now
Got stuck
- CORS-error red herring on /today. Two diagnosis rounds chased a CORS configuration bug before
docker logson the api showed the actual response was a 500. FastAPI / Starlette strip CORS headers off server errors by default, which makes the browser-side error look exactly like a misconfigured CORS policy. Lesson: when a CORS error claims a header is missing on a real endpoint, read the server log before touching CORS config - Schema-drift on a revenue surface — 9 migrations had silently drifted. README promised a runner that was never built. Now a real ticket with the backfill as the runner's starting state. Invisible debt that survives weeks tends to be load-bearing somewhere; flushing it to a ticket is the cheapest fix
- Browser extension was a false suspect.
lockdown-install.jsSES injection appeared in the console alongside React #418 and looked plausible; Incognito repro killed that theory immediately. Lesson: when a hydration error has a console neighbor that looks suspicious, validate with Incognito first — it's faster than reading the source - Silent shadowing bug found mid-flight: a module imported
from config import get_settingsAND defined anasync def get_settingsroute handler in the same file. Python late-binding meant the route handler shadowed the imported function only inside that module's scope at call time. The fix is rename one or the other; the durable lesson is that route handlers are not safe to name after frequently-imported helpers - Direct push to main was correctly blocked by the auto-mode classifier during the Phase 1 closeout work. Every closeout commit landed via feature branch + PR + squash — including for stale-state tracker cleanups
Tomorrow
- Off-host backup for the elevatedaily Postgres — Phase 1 DoD has an explicit gate that's still open
- Migrate-runner + CI drift check — codify so the next 9-migration silent drift gets caught at PR time
- CORS-on-500 middleware fix — the underlying middleware ordering is wrong; synthetic 500s should pick up the CORS headers on the way back out
- First $100 MRR — distribution / marketing problem, not a code problem
Notes
Phase 1 of the manifestation app crossed the line on all four layers today. The code had been shipped for weeks. The schema healed once I noticed the drift. A live $8.88 charge propagated cleanly through Stripe → subscription row → unlocked UI. The post-login route rendered correctly in prod after the React #418 fix landed. Four months of work closed in one afternoon.
The slowest part was sitting with that one visible bug on /today for two hours and being wrong about where it lived. The browser said CORS. I believed the browser. Two diagnosis rounds in, the actual response was a 500 — and FastAPI strips CORS headers off server errors. The browser was telling the truth about what it saw; the cause was three layers deeper than the symptom. The durable rule from this: read the server log before touching CORS config. Browsers describe the wall, not what's behind it.
The 9-migration drift was the other surprise. The repo's README promised
a migration runner. The runner had never been built. Nine migrations had
silently applied to prod without ever being tracked in the
schema_migrations table. Backfilled the table so a real
runner has a starting state, and filed the runner itself as a real
ticket. Invisible debt that survives weeks tends to be load-bearing
somewhere. Flushing it to a ticket is the cheapest fix.
The Phase 1 backlog cleanup felt small but isn't. Seven stories that had shipped weeks ago were still marked Todo. The state of the tracker mattered less when the work was in flight — but the moment Phase 1 closed, the backlog became the input to "what's Phase 2?" and a stale backlog gives a stale answer. Each closure got a verification comment citing the file paths, PRs, and live evidence. Future-me needs to know why it's closed, not just that it is.
The "first $100 MRR" gate is still open and explicitly a different shape of work. The product is shipped. The distribution isn't. That's a marketing flywheel, not an engineering ticket. Naming that boundary out loud is part of closing Phase 1 cleanly — what's done, what's next, and who owns the next.
