The weekly privacy check has reported DRIFT: could not read messages on every run since 7 Sep. It is a false alarm on the strongest possible result.
Section 3 counted rows in the legacy plaintext messages table. The FlamenetRelay.DropMessages migration removed that table outright on 2026-09-05 15:06, so SELECT count(*) FROM messages now returns relation "messages" does not exist, the count comes back empty, and the check falls into its could not read branch. The table being gone is stronger than the "exists but empty" the check was written to confirm, and it was being reported as drift.
The timeline confirms it: the 4 Sep run said "all properties hold", the migration landed 5 Sep, the 7 Sep run drifted.
This matters beyond the noise. That same 7 Sep report also carried three genuine findings, the test fleet running a different image than production. A report that always contains a failure is a report that stops being read, which is the exact thing this script's own header warns about.
What changed
Absence is now measured with to_regclass rather than inferred from a count that errored. The header's rule is preserved rather than weakened:
table absent, positively confirmed: pass, messages is gone, not merely empty
table present, zero rows: pass, unchanged
table present with rows: drift, unchanged
existence probe returns nothing at all: drift, because a check that cannot run is a failure
The distinction is the point. Silencing the branch would have made an unreachable database look like a clean sweep.
Verification
Run against production:
ok messages is gone, not merely empty
ok group_members empty
messenger privacy check: all properties hold
Mutation tested, both failure branches still fire:
table pointed at envelopes (19 live rows): DRIFT: envelopes has 19 live rows, the plaintext path is back
database container name broken: DRIFT: could not determine whether messages exists, 5 DRIFTED total, no clean sweep
Note: the deployed copy is not this file
Worth recording. The timer runs /srv/prod/monitoring/messenger-privacy-check.sh, which is a separate copy from /srv/prod/messenger/src/Scripts/monitoring/. The deployed copy is still pre-deslop, carrying the emoji, bold-in-comments and em-dashes this repo cleaned up, so it has already drifted from main.
Merging this changes nothing in the weekly report on its own. The /srv/prod/monitoring/ copy has to be updated too.
## Why
The weekly privacy check has reported `DRIFT: could not read messages` on every run since 7 Sep. It is a false alarm on the strongest possible result.
Section 3 counted rows in the legacy plaintext `messages` table. The `FlamenetRelay.DropMessages` migration removed that table outright on **2026-09-05 15:06**, so `SELECT count(*) FROM messages` now returns `relation "messages" does not exist`, the count comes back empty, and the check falls into its `could not read` branch. The table being gone is stronger than the "exists but empty" the check was written to confirm, and it was being reported as drift.
The timeline confirms it: the 4 Sep run said "all properties hold", the migration landed 5 Sep, the 7 Sep run drifted.
This matters beyond the noise. That same 7 Sep report also carried three genuine findings, the test fleet running a different image than production. A report that always contains a failure is a report that stops being read, which is the exact thing this script's own header warns about.
## What changed
Absence is now **measured** with `to_regclass` rather than inferred from a count that errored. The header's rule is preserved rather than weakened:
- table absent, positively confirmed: pass, `messages is gone, not merely empty`
- table present, zero rows: pass, unchanged
- table present with rows: drift, unchanged
- existence probe returns nothing at all: **drift**, because a check that cannot run is a failure
The distinction is the point. Silencing the branch would have made an unreachable database look like a clean sweep.
## Verification
Run against production:
```
ok messages is gone, not merely empty
ok group_members empty
messenger privacy check: all properties hold
```
Mutation tested, both failure branches still fire:
- table pointed at `envelopes` (19 live rows): `DRIFT: envelopes has 19 live rows, the plaintext path is back`
- database container name broken: `DRIFT: could not determine whether messages exists`, 5 DRIFTED total, no clean sweep
## Note: the deployed copy is not this file
Worth recording. The timer runs `/srv/prod/monitoring/messenger-privacy-check.sh`, which is a **separate copy** from `/srv/prod/messenger/src/Scripts/monitoring/`. The deployed copy is still pre-deslop, carrying the emoji, bold-in-comments and em-dashes this repo cleaned up, so it has already drifted from `main`.
Merging this changes nothing in the weekly report on its own. The `/srv/prod/monitoring/` copy has to be updated too.
paulhitt
(Migrated from gitlab.com)
merged commit bbd20df74d into main2026-09-10 11:30:23 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Why
The weekly privacy check has reported
DRIFT: could not read messageson every run since 7 Sep. It is a false alarm on the strongest possible result.Section 3 counted rows in the legacy plaintext
messagestable. TheFlamenetRelay.DropMessagesmigration removed that table outright on 2026-09-05 15:06, soSELECT count(*) FROM messagesnow returnsrelation "messages" does not exist, the count comes back empty, and the check falls into itscould not readbranch. The table being gone is stronger than the "exists but empty" the check was written to confirm, and it was being reported as drift.The timeline confirms it: the 4 Sep run said "all properties hold", the migration landed 5 Sep, the 7 Sep run drifted.
This matters beyond the noise. That same 7 Sep report also carried three genuine findings, the test fleet running a different image than production. A report that always contains a failure is a report that stops being read, which is the exact thing this script's own header warns about.
What changed
Absence is now measured with
to_regclassrather than inferred from a count that errored. The header's rule is preserved rather than weakened:messages is gone, not merely emptyThe distinction is the point. Silencing the branch would have made an unreachable database look like a clean sweep.
Verification
Run against production:
Mutation tested, both failure branches still fire:
envelopes(19 live rows):DRIFT: envelopes has 19 live rows, the plaintext path is backDRIFT: could not determine whether messages exists, 5 DRIFTED total, no clean sweepNote: the deployed copy is not this file
Worth recording. The timer runs
/srv/prod/monitoring/messenger-privacy-check.sh, which is a separate copy from/srv/prod/messenger/src/Scripts/monitoring/. The deployed copy is still pre-deslop, carrying the emoji, bold-in-comments and em-dashes this repo cleaned up, so it has already drifted frommain.Merging this changes nothing in the weekly report on its own. The
/srv/prod/monitoring/copy has to be updated too.