Forty-five thousand orders vanished and nothing broke.
That's the insidious part. The Supabase backup restore had silently set is_hidden = 1 on every order in the database. The pages still loaded. The queries still ran. The schema was intact. But the default filter — where is_hidden = 0 — excluded 99% of the data. The leads page showed a handful of records. The quotes page showed almost nothing. It looked like a slow week, not a catastrophe.
The restore had also wiped the migrations table, which meant the stage column didn't exist as far as Laravel was concerned. The leads and quotes pages broke with a column-not-found error — the visible symptom that led to the invisible one. Running migrations on both environments fixed the schema. Checking the actual record count revealed the real problem: forty-five thousand orders, all hidden, all technically present but filtered out of every view.
One UPDATE statement on production. One Redis cache clear. The data came back.
With the crisis resolved, the session built what had originally been planned: a Properties index page. Lazy-loading DataTable with column filters — address, city, zip, customer name. Stats sidebar on desktop showing property counts and coverage metrics. Horizontal stat chips on mobile. A migration that generates property records from existing customer addresses and links them back through orders, so that every customer's service history connects to a physical location on a map.
Redis got split between environments — beta on database 0, production on database 1, with different cache prefixes. This matters because php artisan cache:clear on beta had been nuking production's cache. Two applications sharing one Redis instance with no isolation. The kind of configuration that works until it doesn't, and when it doesn't, cached authentication tokens evaporate and logged-in users get silently logged out on the other site.
JWT verification had been failing because the signing secret in the environment file wasn't the one Supabase was actually using. Found the real one through the Supabase Management API's PostgREST endpoint. Not documented anywhere obvious. The kind of credential that lives in one specific API response and nowhere else.
Six stale local branches got pruned. The SAM training export schedule got re-enabled. The blog got synced. The kind of housekeeping that feels like procrastination but is actually hygiene.
The takeaway lives in the hidden orders. A filter that returns zero results is an error you notice immediately. A filter that returns some results — just not all of them — is an error you live with for days before someone asks why the numbers look low. Always check the full WHERE clause after a data restoration. The schema can be perfect and the data can be present and the application can still be lying to you through omission.