- Shipped
- August 27, 2026 at 8:27 PM UTC
- Author
- Kamo
- Commit
- 7f2d383
Triage was silent. Somebody filed a report and then had to keep opening the tab to find out whether anyone had looked at it — which is the same as not being told. applyStatus now reads the status the row held BEFORE the write and hands both halves to the notifier, because the reporter's letter is about the move: told only where it landed, they cannot tell an advance from a reversal. Everything the letter needs is resolved while the transaction is still open — the reporter's address, name and timezone, and the org's domain all hang off LAZY associations — and the send happens after it commits. The two halves cannot be swapped: holding a transaction open across an HTTP round trip pins a database connection for its duration, and on this database a read after a write inside one transaction can abort it outright. Nothing in the after-commit path writes to the database, which is what keeps it clear of the trap where a @Transactional method called from afterCommit silently discards everything it writes. No email for a status set to the value it already held, for a report with no reporter, or when the reporter IS the person who moved it — a platform administrator can file a report and then triage it, and telling them about their own click is how a notification stream teaches people to ignore it. An off-boarded member is not written to either, through the same predicate the missed-message notices use. A failed send is logged and dropped rather than retried. Unlike a missed chat message there is no ledger behind this, because the report itself is the durable record: the status is on screen the moment the reporter looks.