Implement soft-delete (files.deletedAt) on message retraction/expiry, and a background job that hard-deletes storage objects with no remaining message references. Ensure ref-counting across multi-device envelopes — a file is dead only when all referencing messages are gone.
Acceptance criteria:
- Soft-delete immediate; hard-delete via background job
- Object removed from storage only when unreferenced
- Job is idempotent + safe to retry
Implement soft-delete (
files.deletedAt) on message retraction/expiry, and a background job that hard-deletes storage objects with no remaining message references. Ensure ref-counting across multi-device envelopes — a file is dead only when all referencing messages are gone.Acceptance criteria: