diff --git a/.env.example b/.env.example index a19fd2d7..fae646b1 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,11 @@ PORT=3000 # (The /mcp limiter keeps a global per-email key as an IP-independent backstop, # but the per-IP and per-IP+email keys rely on a trustworthy X-Forwarded-For.) +# APP_SECRET has a DUAL role: it signs JWTs AND derives the AES-256-GCM key that +# encrypts stored AI-provider credentials (API keys) at rest. CONSEQUENCE: if you +# change APP_SECRET after setup, every stored AI API key becomes undecryptable — +# you must re-enter them in AI settings — and all existing sessions/JWTs are +# invalidated. Choose it ONCE, keep it stable, and back it up alongside your DB. # minimum of 32 characters. Generate one with: openssl rand -hex 32 APP_SECRET=REPLACE_WITH_LONG_SECRET diff --git a/README.md b/README.md index 578790f0..c1689068 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,11 @@ the existing data directory is reused as-is: start the new migrations apply on top of your existing schema (`CREATE EXTENSION vector` plus the `page_embeddings` and AI tables); watch the logs for `Migration "..." executed successfully`. +> ⚠️ **Never change `APP_SECRET` after setup.** It does double duty: it signs JWTs *and* derives the +> AES-256-GCM key that encrypts stored AI-provider credentials (API keys). Rotating it makes every +> saved AI API key undecryptable (you'd have to re-enter them in AI settings) and invalidates all +> existing sessions. Pick it once, keep it stable, and back it up together with your database. + ### Notes - **Back up first.** Take a `pg_dump` before swapping — migrations apply in place, and the diff --git a/README.ru.md b/README.ru.md index 0bd9a5de..0b16ad62 100644 --- a/README.ru.md +++ b/README.ru.md @@ -159,6 +159,12 @@ dump/restore, существующий каталог данных переис новые миграции применяются поверх вашей схемы (`CREATE EXTENSION vector` плюс таблицы `page_embeddings` и AI-таблицы); следите в логах за строками `Migration "..." executed successfully`. +> ⚠️ **Никогда не меняйте `APP_SECRET` после установки.** Он выполняет двойную роль: подписывает JWT +> *и* служит материалом для ключа AES-256-GCM, которым шифруются сохранённые ключи AI-провайдеров +> (API-ключи). Смена секрета сделает все сохранённые AI-ключи нерасшифровываемыми (придётся вводить +> их заново в настройках AI) и инвалидирует все текущие сессии. Задайте его один раз, держите +> неизменным и бэкапьте вместе с базой данных. + ## Возможности