Repository navigation
Explore hiding signals instead of hard-deleting them (traceability) #68
Description
Problem
Deleting a signal today is a hard delete, performed by the client: _confirmDeleteSignal in lib/src/widgets/signal_details_screen.dart best-effort deletes the Storage photos, batch-deletes the comments subcollection, then deletes the signal document. Nothing survives.
That is at odds with where the case system is heading (Master Specification §4.5 case ownership history, §4.6 case timeline, §18.7 audit and oversight), and it causes concrete problems now:
- The signal history is destroyed with the signal. The new
eventssubcollection (signal timeline: status/urgency changes with mandatory update notes) is deleted along with everything else, so there is no record that a signal ever existed, or of who changed what. - The reporter can delete individual history entries. Firestore rules allow a comment/event delete by the parent signal's reporter — required for the delete cascade to work at all from the client. An audit trail its own subject can prune is not an audit trail.
- The cascade is client-side and best-effort. If the app is killed mid-delete, subcollection documents are orphaned (Firestore keeps subcollection docs when the parent document is deleted) and nothing ever cleans them up.
- Moderation has nowhere to go. §18.3 wants "hide post" as a moderator action distinct from deletion, and §4.10 wants expiry/archiving with reduced-quality media rather than erasure.
Idea to explore
Replace hard delete with hiding / soft delete:
- A
hidden(ordeletedAt+hiddenBy) field on the signal, with rules excluding hidden signals from client queries, so the document and its history survive. - Move the actual destructive path server-side into a
deleteSignalcallable using an Admin SDK recursive delete, mirroring the existingdeleteAccountcallable. With deletion no longer client-driven,eventscan becomeallow delete: if falseand the tamper hole closes. - Decide the retention story alongside §4.10 (archive after ~6 months, media deleted after 6–12 months) and the GDPR erasure path — soft delete must not become a way to retain personal data indefinitely.
Questions to settle
- Who may hide: reporter only, or reporter + moderator/admin once those roles exist?
- Is a hidden signal still reachable by direct link / share link, or 404?
- Do profile statistics keep counting a hidden case? (§3.5.1 says stats survive case deletion.)
- What actually gets purged, and when — photos first, document later?
- Does the reporter still get a way to truly erase their own content, for GDPR?
Context
Came out of the signal-timeline work (Master Spec §4.6, "Case Timeline"), which introduces the signals/{id}/events subcollection. That change deliberately keeps allow delete: if isParentSignalReporter(...) on events so the existing cascade keeps working, and records the tamper hole as a known gap rather than fixing it — this issue is that fix.
Activity
Give every case a history worth reading
Point the shim at the issue that will remove it
BurningAXE commentedon Aug 22, 2026
Built on
feature/remove-instead-of-delete(unmerged). Worth recording how this landed, because the shape changed from the proposal:hiddenflag was not used. The moderation slice (deployed 2026-08-17→21, after this issue was filed) already answered that question the other way: hiding moves the document tomoderationQuarantine, becausesignalsis world-readable and a flag would hide a signal from the app and from nobody else. Removal follows the same shape, intoremovedSignals.count(), so it measured signals still visible. That moved to a server-writtenpublicProfiles.signalsPosted.commentsrule was a wider hole than theeventsone this issue names: there is no author-delete rule at all, so a reporter can delete anyone's comment on their own signal, unaudited.Functions, rules and indexes are deployed and device-verified. The tamper-hole half is NOT closed yet — narrowing the three delete rules breaks the old client's cascade, so it waits for the app release and is tracked in #73 along with the other rules-gated items.
Replace deleting a signal with removing it
Record the #68 deploy and device verification
Bring the spec and the QA checklist up to date with dev
Merge the spec and QA checklist sync into dev
BurningAXE commentedon Sep 10, 2026
Done