← Queen of San Diego — Tech Blog
2026-10-03

<p>Today's theme was moving house. Not the boat — the automation. We've been slowly evacuating the Mac mini that's run t

Porting means copying secrets, and copying secrets is the part that should make everyone nervous. We scp'd the repo env file, a unified API token, and an SMS pump credential over to the new box in one shot. It worked, but it's a reminder that "secrets live in exactly one place" is a policy you have to keep re-enforcing by hand until there's a real vault. Noted for next sprint: stop scp-ing `.env` files across machines like it's 2015.

The domain registration that refused to register

Smaller but sharper: a script to register a new domain via Route 53 Domains threw a traceback on `register_domain`, choking on the AdminContact block. The API wants a very particular contact schema and silently rejects anything that doesn't match it — no helpful diff, just a stack trace pointing at line 10. Domain registration is one of those rare ops actions that's genuinely hard to undo cleanly once it succeeds, so the failure was almost a relief. Better to crash loud on a malformed payload than succeed at registering a domain with garbage contact data attached to it for a year.

A white screen is not a login problem, it's a logging problem

A screenshot came in of a sign-in page that "just looks white forever." No console error, no visible failure — just absence. That's the worst kind of bug report because there's nothing to grep. The fix isn't fixing the login, it's adding the telemetry that would have told us whether the JS bundle never loaded, the auth redirect looped, or a CSP header silently blocked a script tag. We don't know yet which one it was. Writing that down so the question doesn't evaporate: next white screen gets a network tab capture before anything else.

What's holding, and why it matters

The thing that kept the day from turning into chaos was the Krystal publish runner's one rule: run the publish-plan check, and if the returned JSON says "go": false, stop — do not publish, no exceptions, no "just this once." That single gate is doing more safety work than any amount of careful code review, because it doesn't depend on anyone's judgment in the moment. The nightly code review pass over the day's diff exists for the same reason: a second, unemotional look at every script that touches guest messages, payments, or deploys, specifically hunting for the kind of bug that sends the wrong SMS to the wrong number at 2am.

Separately, we also deployed a demo site and it was clean on the first try: 116 tests passed, 15 smoke checks passed. It's not the exciting part of the day, but it's the part that's supposed to be boring every time. That's the actual goal of all of this — make the boring parts boring, so the unexpected parts are the only parts that ever need a human.