# 0008 — Photo storage retention is documented but not enforced (yet)

- **Status:** accepted
- **Date:** 2026-05-02
- **Deciders:** martinezsalmeron
- **Tags:** modules, media, storage, compliance

## Context

The new patient photo gallery (issue #55) lets clinics upload arbitrary
intraoral / extraoral / X-ray imagery. At scale (~hundreds of clinics
× hundreds of patients × dozens of photos each, plus three precomputed
thumbnail sizes) storage growth becomes a real cost and a compliance
question.

Today the only storage backend is `LocalStorageBackend` (a Docker
volume). Object lifecycle / glacier-style tiering is not feasible
locally — it's a feature of S3-class backends. A future
`media_s3` module is on the roadmap and will extend `StorageBackend`
without changing the contract.

Building a custom retention loop on local disk now would be premature
infrastructure (cron + tombstones + restore UI) for a feature nobody
needs at the current scale.

## Decision

Document the retention policy here and stop. **No active enforcement
loop, no archival cron, no UI for "moved to cold storage".** Photos
live alongside other documents and are deleted only via the existing
soft-delete (`Document.status='archived'`).

When the `media_s3` module lands:

1. Map "archived" documents to S3 `STANDARD_IA` after 30 days via
   bucket lifecycle rule.
2. Map archived documents older than 1 year to `GLACIER_DEEP`.
3. Patient-level export keeps full quality from the live tier.
4. Hard-delete remains forbidden (legal retention obligations differ
   per jurisdiction; we let clinics move their data, not lose it).

## Consequences

### Good

- Zero infrastructure investment until the cost matters.
- Lifecycle rules ride on S3 native features when we get there — no
  custom cron, no tombstone bookkeeping.
- Policy is captured in writing today so the storage extension
  doesn't have to reinvent it.

### Bad / accepted trade-offs

- Local-disk clinics keep paying for full-quality storage indefinitely.
  Acceptable for v1.
- "Archived" documents on local backend are still served at full
  quality if someone replays a download URL.

## Alternatives considered

- **Implement an archival cron now (local backend).** Rejected:
  premature, and the local backend has no cold tier to move to.
- **Hard-delete after N days.** Rejected: hostile to clinics, opens
  legal exposure.

## How to verify the rule still holds

- `grep "archive_patient_documents" backend/app/modules/media/service.py`
  — soft-delete-only path remains the single archive entry point.
- When the S3 module ships, `docs/modules/media-s3.md` MUST cite this
  ADR and document the lifecycle rules it ships.

## References

- `backend/app/modules/media/storage/base.py` — backend contract
- `backend/app/modules/media/service.py:archive_patient_documents`
- Issue #55
