From eba58cc8b481511b5e33a038981d84b749b1925a Mon Sep 17 00:00:00 2001 From: Ravi Tharuma <25951435+RaviTharuma@users.noreply.github.com> Date: Fri, 21 Aug 2026 19:00:23 +0200 Subject: [PATCH] docs(api-keys): unset DEFAULT_RATE_LIMIT_PER_DAY is unlimited (#11017) (#11022) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⭐5 — ENVIRONMENT.md dizia que DEFAULT_RATE_LIMIT_PER_DAY unset = 1000/dia (legado); código e testes desde #2289 tratam unset/vazio como sem cap implícito. Doc-only, guardado por teste de asserção da tabela. Fecha #11017. --- changelog.d/fixes/11017-rate-limit-docs.md | 1 + docs/reference/ENVIRONMENT.md | 2 +- .../apikey-policy-default-rate-limits.test.ts | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 changelog.d/fixes/11017-rate-limit-docs.md diff --git a/changelog.d/fixes/11017-rate-limit-docs.md b/changelog.d/fixes/11017-rate-limit-docs.md new file mode 100644 index 0000000000..fc92469bd6 --- /dev/null +++ b/changelog.d/fixes/11017-rate-limit-docs.md @@ -0,0 +1 @@ +- **docs(api-keys):** document that unset `DEFAULT_RATE_LIMIT_PER_DAY` is unlimited (#2289), not a hidden 1000/day cap ([#11017](https://github.com/diegosouzapw/OmniRoute/issues/11017)) — thanks @RaviTharuma diff --git a/docs/reference/ENVIRONMENT.md b/docs/reference/ENVIRONMENT.md index 5c317383f9..46e0f8cc18 100644 --- a/docs/reference/ENVIRONMENT.md +++ b/docs/reference/ENVIRONMENT.md @@ -198,7 +198,7 @@ OmniRoute uses **SQLite** (via `better-sqlite3`) for all persistence. These vari | `REQUIRE_API_KEY` | `false` | API middleware | When `true`, all `/v1/*` proxy requests must include a valid API key. | | `ALLOW_API_KEY_REVEAL` | `false` | `src/shared/constants/featureFlagDefinitions.ts` | Allows revealing full API key values in the Dashboard UI. Configurable from Dashboard Feature Flags; security risk on shared instances. | | `NO_LOG_API_KEY_IDS` | _(empty)_ | `src/lib/compliance/index.ts` | Comma-separated API key IDs that bypass request logging (GDPR compliance). | -| `DEFAULT_RATE_LIMIT_PER_DAY` | `1000` | `src/shared/utils/apiKeyPolicy.ts` | Fallback per-day request budget applied to API keys whose `rate_limits` column is null. Default (unset/empty/malformed) keeps the legacy 1000/day, 5000/week, 20000/month windows. Set explicitly to `0` to opt out (unlimited). Any positive integer N enables N/day, 5N/week, 20N/month. Zod-validated; invalid values log a warning and use the legacy default. | +| `DEFAULT_RATE_LIMIT_PER_DAY` | _(unset = unlimited)_ | `src/shared/utils/apiKeyPolicy.ts` | Fallback per-day request budget applied to API keys whose `rate_limits` column is null. Unset or empty: no implicit cap (#2289, #11017). `0` is the same (unlimited). Positive integer N enables N/day, 5N/week, 20N/month. Malformed non-empty values fall back to the legacy 1000/day, 5000/week, 20000/month windows. | | `MAX_BODY_SIZE_BYTES` | `10485760` (10 MB) | `src/shared/middleware/bodySizeGuard.ts` | Maximum allowed request body size. Rejects payloads exceeding this limit. | | `OMNIROUTE_CHAT_LARGE_BODY_BYTES` | `262144` (256 KB) | `src/shared/middleware/chatBodyAdmission.ts` | Actual request bodies at or above this threshold require an atomic process-local heavyweight admission lease before JSON parsing. | | `OMNIROUTE_CHAT_HARD_MAX_BODY_BYTES` | `52428800` (50 MB) | `src/shared/middleware/chatBodyAdmission.ts` | Chat-route hard cap enforced against bytes read during bounded ingestion, including requests with missing, invalid, or dishonest `Content-Length`; excess receives `413`. | diff --git a/tests/unit/apikey-policy-default-rate-limits.test.ts b/tests/unit/apikey-policy-default-rate-limits.test.ts index c553a2f041..75c276e7f7 100644 --- a/tests/unit/apikey-policy-default-rate-limits.test.ts +++ b/tests/unit/apikey-policy-default-rate-limits.test.ts @@ -42,6 +42,22 @@ test("buildDefaultRateLimits: unset / empty env disables implicit fallback limit assert.deepEqual(buildDefaultRateLimits(" "), []); }); +test("ENVIRONMENT.md documents unset DEFAULT_RATE_LIMIT_PER_DAY as unlimited (#11017)", () => { + const md = fs.readFileSync(new URL("../../docs/reference/ENVIRONMENT.md", import.meta.url), "utf8"); + const row = md.split("\n").find((line) => line.includes("`DEFAULT_RATE_LIMIT_PER_DAY`")); + assert.ok(row, "ENVIRONMENT.md must document DEFAULT_RATE_LIMIT_PER_DAY"); + assert.match( + row, + /unset|empty|unlimited|no implicit/i, + "live env table must match buildDefaultRateLimits() (#2289)" + ); + assert.doesNotMatch( + row, + /unset\/empty\/malformed\) keeps the legacy 1000/, + "pre-#2289 1000/day default must not remain in the live table" + ); +}); + test("buildDefaultRateLimits: explicit '0' opts out — no fallback rules", async () => { const { buildDefaultRateLimits } = await import("../../src/shared/utils/apiKeyPolicy.ts");