Skip to content

rate-limit degraded warning prescribes "Redis via @objectstack/service-cache", but that adapter refuses to start #25329

Closed

Description

@objectstack-fleet

Finding

Raised by the #24740 card thread (session_01XyLjAesp3Fkx794wqMb4hK) as an out-of-scope finding (class a). The domain:devx seat files it on that thread's behalf and has re-read both sites on origin/main.

The warning gives a fix that does not work. When no cache service is registered, the rate-limit store logs this warning (packages/plugins/plugin-auth/src/rate-limit-storage.ts:217-223):

a multi-node deployment needs a shared cache (Redis via @objectstack/service-cache) or each node enforces the limit independently (ADR-0069 D2)

But that package rejects Redis at startup. CacheServicePlugin.init (packages/services/service-cache/src/cache-service-plugin.ts:80-86) throws when adapter === 'redis':

Redis cache adapter is not yet implemented. Use adapter: "memory" or provide a custom ICacheService via ctx.registerService("cache", impl).

So an operator who follows the warning gets a boot failure. The only working path today is a custom ICacheService registered as cache, which the warning does not mention.

Fix options (for triage)

  • (a) Change the warning: point to the working path, a custom shared ICacheService registered as cache, and say that the bundled Redis adapter is not implemented yet. This is a small change in one file.
  • (b) Implement the Redis adapter in service-cache. This is a feature, and the existing warning text becomes correct.

PR #25328 (#24740) already gives the documentation side the current truth: counters live in the kernel cache, which under serve is in-memory and per process. This finding covers only the runtime log line.

Activity

  1. added
    area:identityLogin and identity — sign-up, sessions, organization membership, SSO
    bugSomething isn't working
    domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landed
    and removed on Oct 23, 2026
  2. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · domain:services seat 1 (seat post #6021, project run by the Sales account) · S mechanical card, in-seat subagent · fix option (a), the warning text · 2026-10-23T12:58Z
    Session: session_016g7nYP9wdNx1GDa5XDr7Uy
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-25329-rate-limit-cache-warning
    Worktree: objectstack-issue-25329
    Domain: domain:services
    Seat: domain:services#1
    File surface: packages/plugins/plugin-auth/src/rate-limit-storage.ts (the degraded warning, :218-223), the pins and docs that quote it, and a changeset. Option (b), implementing the Redis adapter, is a feature with no pull and is not taken. ⛔ packages/plugins/plugin-auth/src/auth-manager.ts is off limits (the #25224 split series cuts it serially). Stop on breach; explain in the report.
    Container & model: S 级机械卡, mode:subagent (general-purpose subagent loading .claude/agents/os-dev.md as its role file), model: default tier, effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: plugin-auth's own log line prescribes a remedy that service-cache refuses at boot | the working path (a custom shared ICacheService registered as cache) exists, and the warning omits it | operators of multi-node deployments who follow the warning, today
    Thread-read: none
    Serial constraints cleared: the #25224 PRs touch auth-manager.ts and its split modules, not rate-limit-storage.ts. PR #25328 (#24740, docs side) is checked by the dev for overlap before editing.
    Resume-from: none

  3. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25329,
      "status": "done",
      "branch": "claude/issue-25329-rate-limit-cache-warning",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/25434",
      "session": "session_016g7nYP9wdNx1GDa5XDr7Uy",
      "premise_still_valid": true,
      "summary": "Fix option (a). The degraded warning from createLazyCounterStore (plugin-auth rate-limit-storage.ts) no longer prescribes 'Redis via @objectstack/service-cache'. On origin/main 925fd0772c, CacheServicePlugin.init still throws for adapter 'redis'. The warning now names the path that works: an ICacheService backed by a store every node reaches, registered as the `cache` service (ctx.registerService('cache', impl)). It promises no bundled adapter, so it cannot go stale. The ADR-0069 D2 reference and the degradedImpact suffix are kept. Pins and docs were flipped in the same PR: the runtime inbound-rate-limit.test.ts pin quoted the old remedy and now asserts the new one plus a negative, the otp-send-guard.ts doc comment carried the same claim, and a new plugin-auth pin was added. The worktree is based on origin/main 925fd0772c, not the f0fdd45bbc named in the dispatch, because origin/main had moved. auth-manager.ts and packages/spec are untouched. PR #25328 is merged and edits only three docs files, so there is no overlap.",
      "tests": "Head ff4e36d9cc. Under the verify lock: (1) built @objectstack/runtime^... plus @objectstack/plugin-auth: VERDICT command-exit 0. The new text is in plugin-auth dist/rate-limit-storage.js, and the old text is in zero dist files. (2) pnpm --filter @objectstack/plugin-auth test: Test Files 189 passed (189), Tests 3580 passed, 10 skipped. plugin-auth typecheck exit 0 (check:test-typecheck OK). pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2 src/security/inbound-rate-limit.test.ts: 25/25 passed, run against the rebuilt dist through exports. runtime typecheck exit 0. Whole command: VERDICT command-exit 0. Ablation with scripts/ablation-replace.mjs: src remedy reverted to '(Redis via @objectstack/service-cache)', anchor x1 to x0, blob 109b2dec52 to 4a99750711. rate-limit-storage.test.ts went 1 failed / 19 passed, AssertionError on the new toContain. Restore: blob equal to HEAD 109b2dec52 and git diff HEAD empty. test:repo was not run locally (CI Test Core).",
      "gates": "Local: the derived list (dispatch-gates --commands, 67 commands) ran at ff4e36d9cc, each exit captured before any pipe. 66 exited 0. check:dual-build-cjs-loads exited 3, PREREQUISITE NOT MET: it needs a whole-workspace dist, so it is NOT MEASURED locally. The --ran reconciliation reads '67 derived, 66 run, 0 NOT-MEASURED, 1 UNRUN', and the unrun one is that gate. PR check-runs at ff4e36d9cc: Lint & Repo Gates success, TypeScript Type Check success, Test Core success, Build Core success, Governed Surface Queue Guard success, Check Changeset success. No check run of the 41 has a failure conclusion.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 relay writes: pr_create (repository_dispatch, run 39960683170, which created PR #25434 as draft with assignee os-sales; body read back byte-identical, 3910 bytes) and this os-dev-report comment through post-stamped.mjs. Plus 2 direct git pushes of the branch (empty, then ff4e36d9cc). Labels: none written (none named, and the changeset is present).",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted in PR Acceptance notes, not filed · read-only text drift, no public-door reproduction: README.md:415 says '@objectstack/service-cache — Cache, in-memory and Redis', and content/docs/kernel/services-checklist.mdx:522 and :543 advertise a Redis adapter. services.mdx:130 and cluster.mdx:720 already say it is a skeleton · dedupe words: service-cache Redis adapter README, services-checklist Redis, cache adapter skeleton docs"
      ]
    }
  4. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · 2026-10-23T14:43Z

    reading value
    PR #25434 MERGED through the queue (ACCEPT 6366574572), head ff4e36d9cc
    origin/main carries b3f3298d97

    State: the card was closed by Fixes #25329. pm:dispatched is off and the assignee is cleared.


    Generated by Claude Code

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:identityLogin and identity — sign-up, sessions, organization membership, SSObugSomething isn't workingdomain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landedpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions