Release rehearsal — the work inbox against production data (2026-09-23)
Rehearsal for the release that adds the work inbox (WRK-001…016), the outbound message queue lockdown (AUD-022) and a visa billed by its supplier. Done before the production migrations, as 15-platform-reliability and the 2026-09-19 rehearsal require.
1. What was restored
| Source | GitHub Actions run 35852911414, artifact supabase-backup-20260923T110957Z |
| Checksums | all three verified (roles, schema, data) |
| Target | local stack alhuda-rehearsal, port 59322 |
| Result | 130 public tables, zero schema errors |
Restored per Backup & restore, including Correction 2 from
19 September: the local image's default privileges are revoked before
schema.sql loads, or the copy grants anon and authenticated rights
production does not have. 22 data errors, all in auth tables whose columns
differ between production's auth service and the local one — the same list as
19 September, none of them business data.
The snapshot is five releases behind main. It was taken at 11:09 UTC;
releases #387–#391 merged between 12:07 and 16:53. So anything this rehearsal
reports as "missing in production" may simply post-date the backup. Where that
matters it is said below.
Production carries very little data: 0 bookings, 0 customers, 10 journal entries. This is a system in use for configuration, not yet for trading.
2. What ran
The three migrations this release adds, in filename order, one transaction each,
stopping on the first error — exactly as supabase db push would:
| Migration | Result |
|---|---|
20260926200000_a_visa_is_billed_by_its_supplier.sql |
applied |
20260926220000_work_inbox.sql |
applied |
20260926230000_the_outbound_queue_is_for_senders.sql |
applied |
Then all three again, to prove they are idempotent: no errors, and no duplicated
seed rows (8 work.* permissions, 9 queues, 16 work types, 16 weights, 6
calendar days, 7 channel targets — the same counts as the first pass).
What production gains: 7 Work* tables, the business calendar, the eight
work.* permissions with SUPER_ADMIN holding all of them through the existing
Permission_grant_super_admin trigger, and CommunicationQueue going from one
blanket staff policy to three permission-gated ones with no DELETE for anybody.
3. What broke, and what it means
Nothing in this release. 46 of 52 database suites passed on the production copy. All six failures are pre-existing or artefacts of the snapshot:
| Suite | Why it failed | Is it this release? |
|---|---|---|
access_model.sql |
ACC-049: OPS_MANAGER holds admin.cities.view and admin.locations.view but not admin.view, so it can act in the admin module without being able to open it |
No — passes on a database built from migrations |
journal_write_paths.sql |
FIN-076: bookings.edit not granted to TICKET_MANAGER |
No — same family as above |
lead_keeps_its_passengers.sql |
Lead.passengers does not exist |
No — that migration reached main at 16:53, after the 11:09 snapshot |
incidents.sql |
the fixture cannot insert an Incident without a counter row |
No — test/data collision |
tickets_visa_comms.sql |
duplicate key on CommunicationSetting_key_key |
No — the setting already exists in production |
role_dashboards.sql |
counts differ against real rows | No — also fails on the dev database |
Two of these deserve the owner's attention, and neither is settled by this rehearsal because the snapshot is old:
- Grant coherence. If production still lacks
admin.viewforOPS_MANAGERandbookings.editforTICKET_MANAGER, then an operations manager cannot open the admin pages they hold rights inside, and a ticketing manager cannot edit the bookings they are expected to ticket. Both are documented as granted in PERMISSIONS.md. Deliberately not "fixed" here: a migration that grants permissions on a hunch is permission widening, and if either was revoked on purpose that decision should be found before it is undone. - Whether production has #387–#391's migrations at all. The CLI on this
machine is not authenticated, so
supabase migration listcould not be run. Check it before pushing.
4. Before the push
npx supabase migration list— confirm what Remote is missing. Expect the three above; if it also lists #387–#391's migrations, production's database is behind its frontend and that is the more urgent thing.- Take a fresh backup (
gh workflow run supabase-backup.yml) if the newest is older than the last release. npx supabase db pushapplies in filename order and stops at the first failure. The 19 September rehearsal exists because a back-fill hit the FIN-031 voucher guard and would have stopped halfway.
5. After the push
npx supabase migration list— the three show against Remote.select count(*) from "Permission" where name like 'work.%';→ 8.select polname from pg_policy where polrelid = 'public."CommunicationQueue"'::regclass;→ threecommunications.sendpolicies, and notCommunicationQueue staff only.- Open
/workas a member of staff: the inbox lists your own items, and rows from bookings, incidents, requests, visa enquiries, holds and groups appear read-only with Open links (WRK-001). - A cashier signing in should see the Work inbox in the nav and be unable to claim anything (ACC-044).