chore(openspec): archive completed changes and sync main specs

- archive local-fs-storage-backend, sqlite-metadata-backend,
  storage-orphan-reconciliation, metadata-managed-jwt-secret, default-local-backends
- sync specs: storage-backends, metadata-backends, storage-reconciliation,
  app-secrets; update photos/share-links
- defaults reflected in specs: SQLite and local FS
This commit is contained in:
iu
2026-10-11 10:19:44 +03:00
parent cb272398ce
commit 8638d1bbfc
33 changed files with 392 additions and 13 deletions
@@ -0,0 +1,40 @@
# Proposal
## Why
S3-совместимое хранилище (Garage на `s3.localnet`) в проде недоступно извне, поэтому
отдача медиа не может идти напрямую из хранилища в браузер. Нужен слой хранения,
который всегда отдаёт блобы через бэкенд, и локальный бэкенд для инсталляций без S3.
## What Changes
- Ввести интерфейс `storage.Backend`: Put/Delete/Get/Ping/EnsureBucket/Bucket, `URL`
(всегда подписанный URL приложения) и обязательный `ServeObject`.
- Реализовать бэкенд локальной ФС: блобы под корневым каталогом по непрозрачным ключам
`objects/{id}/{role}{ext}`, защита от обхода пути, отдача через `ServeContent`.
- Реализовать отдачу S3 через бэкенд: `ServeObject` тянет объект ranged `GetObject` из
Garage (внутренняя сеть) и стримит браузеру; presigned URL больше не используются.
- Публичный маршрут `/api/objects/<key>` с HMAC-подписью, сроком, Range и Content-Type
обслуживает и авторизованных, и анонимные share-ссылки.
- Ввести `STORAGE_BACKEND=s3|fs` и `FS_ROOT`; убрать `S3_PUBLIC_URL`; переименовать
`S3_PRESIGN_TTL` → `OBJECT_URL_TTL`; дефолт — `s3`.
- Сделать метку хранилища в health динамической.
- Сделать формулировки отдачи файлов нейтральными к бэкенду в спеках `photos` и `share-links`.
## Capabilities
### New Capabilities
- `storage-backends`: выбор и работа объектного хранилища — S3-совместимое (Garage) и локальная ФС; блобы всегда отдаются через бэкенд по подписанному URL, хранилище клиенту не раскрывается.
### Modified Capabilities
- `photos`: получение фото и скачивание не требуют presigned URL и обслуживаются бэкендом (подписанный URL).
- `share-links`: просмотр по ссылке отдаёт подписанный URL, обслуживаемый бэкендом.
## Impact
- `backend/internal/storage` (интерфейс, общий `Signer`, FS-бэкенд, S3-proxy-отдача),
сервисы `photos` и `albums`, `app` (маршрут отдачи, health), `cmd/*`, `config`.
- Удаление presign-пути AWS SDK из `storage`.
- `.env.example`, `project.md`, `deploy/nginx-sse.conf`.
- Спеки `photos`, `share-links`, новая `storage-backends`.
- Не затрагивает слой метаданных.