From 90e9b0a3f400737e3624d003b3acdb4db0815ba6 Mon Sep 17 00:00:00 2001 From: vvzvlad Date: Sat, 20 Jun 2026 18:34:16 +0300 Subject: [PATCH] docs(public-share): document trusted-proxy XFF requirement + cost cap The anonymous public-share AI assistant's per-IP rate limit is only effective behind a trusted reverse proxy that overwrites X-Forwarded-For with the real client IP (the app runs with trustProxy). Document this deployment requirement and the per-workspace cost backstop env var (SHARE_AI_WORKSPACE_MAX_PER_HOUR, default 300) in .env.example. Co-Authored-By: Claude Opus 4.8 --- .env.example | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.env.example b/.env.example index fbd32428..5acc78b8 100644 --- a/.env.example +++ b/.env.example @@ -81,3 +81,24 @@ MCP_DOCMOST_PASSWORD= # Per-embedding-call timeout in milliseconds for the RAG indexer. # A slow/hung embeddings endpoint fails after this and the batch continues. # AI_EMBEDDING_TIMEOUT_MS=120000 + +# --- Anonymous public-share AI assistant --- +# Opt-in per workspace (AI settings -> "public share assistant"; off by default). +# When enabled, anonymous visitors of a published share can ask an AI about that +# share at POST /api/shares/ai/stream. The assistant is read-only and hard-scoped +# to the single share tree, but every call spends real tokens on the workspace +# owner's configured AI provider. +# +# DEPLOYMENT REQUIREMENT: the per-IP rate limit on this endpoint is only +# effective behind a trusted reverse proxy that OVERWRITES (not appends) +# X-Forwarded-For with the real client IP. The app runs with trustProxy, so +# without such a proxy an attacker can rotate X-Forwarded-For to evade the +# per-IP limit. Put this endpoint (and the app) behind a proxy you control that +# sets X-Forwarded-For to the real client IP. +# +# Backstop: a cluster-wide, sliding-window cap per workspace (IP-independent, +# keyed by the server-resolved workspace id) bounds the owner's bill even if the +# per-IP limit is fully evaded. It is a COST backstop, not an access control, +# and FAILS OPEN if Redis is unavailable. Override the hourly cap below +# (default: 300 calls per workspace per rolling hour). +# SHARE_AI_WORKSPACE_MAX_PER_HOUR=300