feat: local-first storage and metadata backends #3

Merged
iu merged 5 commits from feature/local-fs-storage-backend into develop 2026-10-11 07:44:15 +00:00
Owner

Что сделано

Переход к самодостаточному локальному запуску: слои хранения и метаданных абстрагированы, добавлены локальные бэкенды, секрет подписи хранится в метаданных.

  • storage: интерфейс storage.Backend (Put/Delete/Get/Ping/EnsureBucket/List), отдача медиа всегда через бэкенд по HMAC-подписанному маршруту /api/objects/<key>; добавлен бэкенд локальной ФС (STORAGE_BACKEND=fs, FS_ROOT), S3 отдаётся через ranged GetObject; presigned URL убраны.
  • metadata: интерфейсы репозиториев по доменам; добавлен SQLite-бэкенд (modernc.org/sqlite, CGO_ENABLED=0) с миграциями и единым контрактным набором тестов (DB_BACKEND=sqlite, SQLITE_PATH).
  • secrets: JWT_SECRET больше не обязателен — секрет хранится в app_settings с автогенерацией; URL_SECRET остаётся опциональным оверрайдом.
  • reconcile: maintenance-команда cmd/reconcile для сверки «хранилище ∖ журнал» (отчёт по умолчанию, --delete, --min-age).
  • defaults: по умолчанию DB_BACKEND=sqlite / STORAGE_BACKEND=fs; логирование выбранных бэкендов при старте.
  • Обновлены .env.example, project.md, README.md; openspec-изменения заархивированы и спеки синхронизированы.

Проверка

  • go build ./...
  • контрактные тесты метаданных на обоих бэкендах
  • ручной запуск без внешних сервисов (sqlite + fs)
## Что сделано Переход к самодостаточному локальному запуску: слои хранения и метаданных абстрагированы, добавлены локальные бэкенды, секрет подписи хранится в метаданных. - **storage**: интерфейс `storage.Backend` (Put/Delete/Get/Ping/EnsureBucket/List), отдача медиа всегда через бэкенд по HMAC-подписанному маршруту `/api/objects/<key>`; добавлен бэкенд локальной ФС (`STORAGE_BACKEND=fs`, `FS_ROOT`), S3 отдаётся через ranged `GetObject`; presigned URL убраны. - **metadata**: интерфейсы репозиториев по доменам; добавлен SQLite-бэкенд (`modernc.org/sqlite`, `CGO_ENABLED=0`) с миграциями и единым контрактным набором тестов (`DB_BACKEND=sqlite`, `SQLITE_PATH`). - **secrets**: `JWT_SECRET` больше не обязателен — секрет хранится в `app_settings` с автогенерацией; `URL_SECRET` остаётся опциональным оверрайдом. - **reconcile**: maintenance-команда `cmd/reconcile` для сверки «хранилище ∖ журнал» (отчёт по умолчанию, `--delete`, `--min-age`). - **defaults**: по умолчанию `DB_BACKEND=sqlite` / `STORAGE_BACKEND=fs`; логирование выбранных бэкендов при старте. - Обновлены `.env.example`, `project.md`, `README.md`; openspec-изменения заархивированы и спеки синхронизированы. ## Проверка - `go build ./...` - контрактные тесты метаданных на обоих бэкендах - ручной запуск без внешних сервисов (`sqlite` + `fs`)
iu added 5 commits 2026-10-11 07:41:57 +00:00
- introduce storage.Backend with S3 and local file-system implementations
- deliver all blobs via signed GET/HEAD /api/objects/<key> (Range, Content-Type)
- stream S3 objects through the backend; remove presigned URL path
- share shared HMAC Signer between backends
- remove S3_PUBLIC_URL; rename S3_PRESIGN_TTL to OBJECT_URL_TTL
- make storage label in health dynamic; nginx proxy_buffering off for objects
- pluggable per-domain Repository interfaces; PostgreSQL and SQLite impls
- SQLite on modernc.org/sqlite (WAL, busy_timeout, foreign_keys, immediate tx)
- separate migrations/sqlite and db.MigrateSQLite; store.NewPostgres/NewSQLite
- cmd/reconcile compares object storage with the journal (report, then --delete)
- storage.Backend.List and photos.Repository.AllStorageKeys
- DB_BACKEND/SQLITE_PATH and STORAGE_BACKEND/FS_ROOT selectable; local defaults
  (sqlite ./galo.db, fs ./data)
- Makefile reconcile/reconcile-delete; docs and .env.example updated
- app_settings table (PostgreSQL migration 000010, SQLite 000002)
- internal/settings repository (Get/Set/Ensure) wired into store.Repos
- secret generated with crypto/rand on first start and persisted; reused on restart
- drop required JWT_SECRET from env/config; app.New takes a TokenManager and
  storage.Open takes the resolved secret (URL_SECRET still overrides)
- docs updated
- 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
iu merged commit 29c2594a9b into develop 2026-10-11 07:44:15 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: iu/ds-galo#3