Skip to content

docs: HARDENING.md and production-readiness.mdx still describe rate limiting as adapter-wired and off, and never name server.security.rateLimit or trustProxy #24740

Open

Description

@objectstack-fleet

Filing gate ③ a task the maintainer set, in the repo:hotcrm seat 2 chat on 2026-10-20 (verbatim): 「docs/HARDENING.md 里的限流配方引用了已经不存在的代码」. Filed by the repo:hotcrm seat 2 (os-support-ai, session session_01KqkTQNLcxVc588eZpJmp1r, seat post objectstack-ai/hotcrm#2180). ⛔ Not a claim. Domain, type and grade are triage's.

A correction to the order's wording, on measurement: the symbols the recipe imports still exist. RateLimiter and DEFAULT_RATE_LIMITS are in packages/runtime/src/security/rate-limit.ts, exported from @objectstack/runtime. What is false is what the two pages say about the runtime, since #4910 wired the built-in limiter. The seat reported this correction to the maintainer when filing.

Reader (who acts): objectstack triage routes it to the owner of docs/ and content/docs/deployment/. It is the docs follow-up #4937 did not reach.

What is false (read on objectstack main 9b2953d62)

docs/HARDENING.md § Rate limiting:

  • "The runtime exposes a token-bucket primitive but does not auto-wire it into the dispatcher plugin … the decision to enable belongs at the adapter layer." False since 「v17」入站 rateLimit 接执行:ApiEndpoint / HttpServer 的 RateLimitConfig 推导为 runtime token bucket 配置,dispatcher 生效(#4686 拆向之一) #4910. createDispatcherPlugin({ rateLimit }) installs the inbound limiter as global middleware from the authored server.security.rateLimit block, and objectstack serve forwards it. rate-limit.ts's own header and packages/runtime/src/index.ts ("The dispatcher plugin wires BOTH automatically") say so.
  • § Trust the proxy or don't: "The dispatcher's default key extractor reads x-forwarded-for[0]". False. resolveRateLimitKey (inbound-rate-limit.ts) keys on the principal first. It reads forwarded headers only under server.trustProxy, and otherwise uses the transport peer.
  • The Hono recipe keys its buckets on x-forwarded-for's first entry, unconditionally. That is the client-influenced key the runtime's own resolver refuses without trustProxy. A reader who copies it gets a weaker limiter than the one the runtime already ships.
  • "For multi-instance deploys, replace the default MemoryStore with a Redis-backed RateLimitStore." The built-in limiter already counts in the kernel cache service (shared when that is Redis), and warns when it falls back to per-process.
  • The page never names server.security.rateLimit or trustProxy, the two keys an operator actually sets. They are documented only in content/docs/references/system/stack-server.mdx.

content/docs/deployment/production-readiness.mdx (published):

  • The defaults table says rate limiting is "Off (opt-in via adapter)".
  • The prose says "Rate limiting is the one piece you wire at the adapter layer … See the HARDENING.md recipes".
  • The go-live checklist says "Rate limit configured at the adapter for /auth/* …".

All three send a reader past the built-in limiter. The published page matters more, because it ships to every operator.

The same HARDENING.md's CORS section ("not opinionated by the runtime") is carried by the CORS card filed alongside this one, not here.

Expected (proposed; triage owns it)

  • Both pages say that rate limiting is built in and off by default. They name server.security.rateLimit with an example budget, server.trustProxy with when to set it, and the shared-cache requirement for multi-node.
  • The adapter recipe is either deleted or kept only as "per-class budgets, which the built-in single bucket does not do", using the runtime's trust rule for its key.
  • The go-live checklist points at the built-in key.

Dedupe (objectstack issues, all states, semantic search)

"HARDENING.md rate limiting recipe stale adapter layer server.security.rateLimit production-readiness docs": 3 hits, all closed.

None covers these two pages.

Dedupe words: HARDENING.md rate limiting stale; production-readiness rate limit adapter; server.security.rateLimit docs; x-forwarded-for recipe.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdocumentationImprovements or additions to documentationdomain:devxpm:queuepriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions