Files
ds-galo/openspec/changes/metadata-managed-jwt-secret/specs/app-secrets/spec.md
T
iu cb272398ce feat(auth): store the token signing secret in the metadata layer
- 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
2026-10-11 10:18:31 +03:00

2.9 KiB

Spec Delta

Purpose

Хранение секретов приложения в слое метаданных с автогенерацией: единый стабильный секрет на инсталляцию без обязательной настройки окружения.

ADDED Requirements

Requirement: Хранение секрета приложения

Слой метаданных SHALL хранить секрет подписи токенов приложения и SHALL возвращать один и тот же секрет при последующих запусках.

Scenario: Первый запуск

  • WHEN секрет ещё не сохранён
  • THEN система генерирует случайный секрет и сохраняет его в слое метаданных

Scenario: Повторный запуск

  • WHEN секрет уже сохранён
  • THEN система использует сохранённый секрет и не генерирует новый

Requirement: Отсутствие ручного секрета

Система SHALL работать без секрета, заданного в окружении, и SHALL не требовать его наличия при старте.

Scenario: Секрет не задан в окружении

  • WHEN переменная секрета не задана
  • THEN система запускается, используя секрет из слоя метаданных

Requirement: Конкурентный первый запуск

При одновременном первом запуске нескольких инстансов на общей базе метаданных система SHALL обеспечивать единый сохранённый секрет для всех инстансов.

Scenario: Гонка первого запуска

  • WHEN два инстанса одновременно обнаруживают отсутствие секрета
  • THEN сохраняется ровно один секрет, и оба инстанса используют его

Requirement: Использование секрета для подписи URL

При отсутствии отдельного секрета подписи URL система SHALL использовать секрет из слоя метаданных.

Scenario: URL_SECRET не задан

  • WHEN отдельный секрет подписи URL не задан
  • THEN подпись URL объектов использует секрет приложения из слоя метаданных

Scenario: URL_SECRET задан

  • WHEN отдельный секрет подписи URL задан
  • THEN он используется независимо от секрета приложения