diff --git a/README.md b/README.md index b5bcc5a..0940c66 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,11 @@ that must stay cheap should watch the gateway's aggregated `/healthz`. > All state lives in Redis; the process reads only two environment variables and writes > nothing to disk. -One corollary matters for setup: the bootstrap one-shot token is the **password component of -`REDIS_URL`**. The Redis ACL credential is therefore both the application connection -credential and the trust root for bootstrap — keep it private and rotate it as one value. +One corollary matters for setup: the SPA admin credential — and therefore the bootstrap +trust root — is `CONFIG_ENCRYPTION_KEY` itself, the single 32-byte hex value you supply at +startup. It is only compared in constant time, and is never echoed, logged, or stored. The +Redis ACL password, if you have one, authenticates the Redis connection alone and is not +the credential for any HTTP endpoint. ## 5. Where to read more diff --git a/README.zh-CN.md b/README.zh-CN.md index 4e3d536..32bdf5d 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -74,8 +74,7 @@ docker run --env-file .env -p 8080:8080 messageweave:latest > 所有状态都在 Redis 里;进程只读两个环境变量,不写任何磁盘。 -有一条推论与部署直接相关:bootstrap 的一次性 token 就是 **`REDIS_URL` 的密码分量**。因此 -Redis ACL 凭据同时是应用连接凭据与 bootstrap 信任根——请单独保管并按单一值轮换。 +有一条推论与部署直接相关:SPA 管理凭据——也就是 bootstrap 的信任根——就是 `CONFIG_ENCRYPTION_KEY` 本身,即启动时提供的那个 32 字节 hex 值。它只做常数时间比较,绝不回显、记录或落盘。Redis ACL 密码(如有)只认证 Redis 连接本身,不是任何 HTTP 端点的认证凭据。 ## 5. 去哪读更多 diff --git a/docs/reference.md b/docs/reference.md index fd9b183..d3e33d8 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -34,13 +34,14 @@ Conventions used throughout: Notes: -- `config:business:revision` is an **atomic Redis `INCR`**, not a read-modify-write. Hot reload - compares it: the refresh loop only rebuilds the worker when the remote revision exceeds the - cached local value, which is what keeps a single bad poll from turning into a hot retry loop - (notify.rs:627-650). +- `config:business:revision` is an **atomic Redis `INCR`**, not a read-modify-write. Every + request-bearing entry point calls `refresh_business_config` (notify.rs:717), which only + rebuilds the worker when the remote revision exceeds the cached local value + (notify.rs:722-724) — that guard is what keeps a stale or malformed snapshot from turning + into a rebuild loop. - `config:admin_session` carries no TTL metadata beyond the literal `EX 900` passed at write time; the handler reports the same window in its response body as `expires_in: 900` - (notify.rs:700). + (notify.rs:787). - `config:enabled` is consulted as a gate; missing or `false` keeps business processing off. ### 1.2 AI consent @@ -310,9 +311,16 @@ compatibility. Recognised names, unprefixed unless noted: The single prefixed name is `TELEGRAM_CHAT_ID`. Anything else documented as `TELEGRAM_BOT_TOKEN` or similar is a documentation error, not a supported variable. -**Trust root.** The bootstrap one-shot token is the password component of `REDIS_URL` -(main.rs:87-91). The Redis ACL credential is therefore simultaneously the application -connection credential and the trust root for bootstrap. +**Trust root.** The SPA admin credential is `CONFIG_ENCRYPTION_KEY` itself: read at startup +(main.rs:49) and held as `admin_token` (main.rs:95), it is checked in constant time by +`worker_authorized` (notify.rs:445; compare at notify.rs:1135) at the top of both +`POST /api/bootstrap` (notify.rs:604) and `POST /api/admin/session` (notify.rs:774). It is +only compared against the request bearer — never echoed, logged, or stored. The session +issued by `/api/admin/session` is a freshly generated random 32-byte hex token +(notify.rs:778-787), never the credential; only its digest is retained in Redis under +`config:admin_session`. `REDIS_URL` is the Redis connection string alone: an ACL password in +it, if any, authenticates the Redis connection and is not the credential for any HTTP +endpoint. ---