Переход к самодостаточному локальному запуску: слои хранения и метаданных абстрагированы, добавлены локальные бэкенды, секрет подписи хранится в метаданных.
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`)
- 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
- 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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Что сделано
Переход к самодостаточному локальному запуску: слои хранения и метаданных абстрагированы, добавлены локальные бэкенды, секрет подписи хранится в метаданных.
storage.Backend(Put/Delete/Get/Ping/EnsureBucket/List), отдача медиа всегда через бэкенд по HMAC-подписанному маршруту/api/objects/<key>; добавлен бэкенд локальной ФС (STORAGE_BACKEND=fs,FS_ROOT), S3 отдаётся через rangedGetObject; presigned URL убраны.modernc.org/sqlite,CGO_ENABLED=0) с миграциями и единым контрактным набором тестов (DB_BACKEND=sqlite,SQLITE_PATH).JWT_SECRETбольше не обязателен — секрет хранится вapp_settingsс автогенерацией;URL_SECRETостаётся опциональным оверрайдом.cmd/reconcileдля сверки «хранилище ∖ журнал» (отчёт по умолчанию,--delete,--min-age).DB_BACKEND=sqlite/STORAGE_BACKEND=fs; логирование выбранных бэкендов при старте..env.example,project.md,README.md; openspec-изменения заархивированы и спеки синхронизированы.Проверка
go build ./...sqlite+fs)