Repository navigation
Authenticated data requests issue ~20 DB queries in ~17 sequential legs — per-request auth/session/localization/metadata resolution has no cross-request caching, costing ~1.5s/request on remote Postgres #10757
Description
⚠️ 2026-09-01:重述停放理由。 本卡此前挂pm:blocked,卡体里没有任何Blocked-by:行 —— 停放理由只活在一条评论里(Blocked-by: #11633),而解锁扫描只读 body。本次把理由写进 body,并把标签改为pm:on-hold,因为那个 blocker 的活已经干完了,剩下的是一次测量,不是一个依赖。
Ruled: 6250819728 · 维护者「10757 在本地测试就可以。」 · 2026-10-18 — 原 Restart-when(远程 Postgres 重测)改为本地重测,判据换算见该评论(recorded by the triage seat)
Restart-touch: packages/core/src/security/resolve-authz-context.ts, packages/rest/src/rest-server.ts, packages/plugins/plugin-auth/src/auth-manager.ts
⛔ 原 Blocked-by: #11633 已不成立。 直接读 #11633 的当前状态(⛔ 不取本卡对它的转述):设计 2026-08-24 交付,维护者 2026-08-25 ACCEPT 并裁完四个分叉,卡本身已从 needs-user-decision 转为 tracking 协调父卡;sub_issues_summary = 5 / 5 完成 —— #11966(leg C)、#11967(leg D)、#11968(substrate)、#11969(ADR 转换)、#11971(leg B,授权缓存,即「设计真正要做的那条腿」,2026-08-30T14:44Z 关闭)全部关闭。
⇒ 本卡 2026-08-28 那次巡检问对了问题(「clearing that blocker does not hand this card work — it hands #11633 work」),只是当时最后一个子卡还没关。现在关完了,所以本卡欠的不是等待,是一次读数。
repo:cloud 席,或握有该部署的运维。⛔ 在读数回来之前,不得据仓内任何数字宣称本卡已解决。
Found while root-causing objectstack-ai/cloud#1518 (control plane pays ~1.5s of server time on EVERY authenticated DB-touching request on prod, ~6s on staging, independent of query shape and response size). Traced at cloud's pin 0c24898c. The mechanism is entirely in framework packages, so per cloud's contract-first rule it is filed here rather than worked around in the consumer.
The measurement
Staging (OS_SERVER_TIMING=true) for GET /api/v1/data/sys_user_preference?$top=1:
wall=6674ms server=[parse=0.05ms, db=6240.57ms, serialize=0.06ms, handler=5812.91ms, total=5813.63ms]
handler ≈ total and db ≈ handler — the request is essentially all DB time. db > total is explained by the db mark being a per-query SUM (PerfTiming.count, packages/drivers/driver-sql/src/sql-driver.ts installQueryTiming) over queries that partly overlap (see the parallel settings reads below).
Where the queries come from — one authenticated GET /data/:object?$top=1 issues ~20 queries in ~17 sequential legs
Every leg is a Neon round trip. At the ~50–90ms/query this deployment measures, ~17 sequential legs are the ~1.5s.
A. better-auth getSession — no caching anywhere (5 queries):
sys_session+ 2.sys_user(better-auth core;cookieCacheis not configured — zero grep hits inplugin-auth);sys_user_permission_set, 4.sys_permission_set(FULL list, limit 50), 5.sys_member— thecustomSessionplugin re-derives platform-admin/org roles on EVERYgetSessioncall (packages/plugins/plugin-auth/src/auth-manager.ts~2898–2960).
B. resolveAuthzContext / resolveUserAuthzGrants (8 queries, sequential) (packages/core/src/security/resolve-authz-context.ts ~330–560):
6. sys_member {user_id}; 7. sys_user_position; 8. sys_member {organization_id} (fellow-org, limit 1000); 9. sys_user_permission_set (duplicate of A3); 10. sys_position {name $in}; 11. sys_position_permission_set; 12. sys_permission_set {id $in}; 13. sys_user {id} for ai_seat (duplicate of A2).
C. Localization (3 queries, parallel): resolveLocalizationContext → 3× settings.get('localization', …) → loadRows is uncached by design (#10221 caches only FAILED reads), so 3 sys_setting reads per request.
packages/rest/src/rest-server.ts ~800 documents this whole block as "~16 sequential queries" and memoizes it per request (execCtxMemo) — but nothing caches it ACROSS requests, so every request pays it once.
D. Route handler (5–6 more):
enforceApiAccess→loadObjectItems→getMetaItems('object')ALWAYS queriessys_metadata(1–2: the empty result triggers the alt-type retry) —packages/metadata-protocol/src/protocol.ts~5700;- plugin-security's engine middleware runs
resolvePermissionSetsForContext→dbLoader(sys_permission_set {name $in}) with no cache, and it runs TWICE — once for the find, once for the COUNT (security-plugin.ts~1351); - the data SELECT itself;
findDatarunsengine.count()whenever a limit is present (protocol.ts~8858) — a second data query even for$top=1.
E. Zero-hint observation: the SqlDriver's tenancy auto-scoping itself issues no extra queries — but its INPUTS (accessible_org_ids, org_user_ids) are what B pays for, including the limit-1000 fellow-org read.
Consequences on a real deployment (cloud prod/staging)
- ~1.5s fixed server time per authenticated data request at ZERO concurrency (prod; ~6s staging where per-query RTT is ~300ms).
- Requests being ~100% DB-bound makes the pg pool cap the request-concurrency cap: cloud measured a hard knee exactly past 10 concurrent (= its pool max), median doubling at 20. The Console home fires 27 API calls in one cold load.
Fix directions (each independently valuable, roughly by leverage)
- Session caching: enable better-auth
cookieCache(signed cookie, short TTL) or an in-process TTL cache keyed by session token — removes A entirely on warm requests. customSessionis redundant work on the data path: B re-derives everything A3–A5 derive, more completely. Consider gating the customSession enrichment to the endpoints that need it, or a short per-user TTL cache.- Cross-request TTL cache for
resolveUserAuthzGrantskeyed(userId, tenantId)with write-invalidation or a short TTL.⚠️ This is authz caching leg B: grants cache — coarse invalidation, default TTL=0 (off), expiry-boundary expiry, bypass list #11971's face and it has LANDED — do not rebuild it; measure it. - Batch B's reads: steps 6–13 are ~8 sequential round trips that could be 2–3 batched/joined queries; the duplicates (A2/13, A3/9) are free wins.
- Cache successful localization reads with write-invalidation (the 新环境日志被 sys_setting 'no such table' ERROR 刷屏:本地化读取先于建表,真错误被噪音淹没 #10221 cache deliberately holds failures only; the dogfood analytics-timezone test pins read-after-write — invalidation-on-write satisfies it).
- Cache
getMetaItems'sys_metadataread (short TTL / registry-epoch key), and skip the alt-type retry when the first read returned an empty-but-healthy result set. - Reuse the find's permission-set resolution for its count (same request, same context — the middleware resolves twice today).
$count=falsefast path: honor the existing$countparameter to skip the COUNT for callers that don't needtotal(objectui's cold-load probes mostly don't).
Per-query evidence is directly obtainable on any deployment of current main by an admin: X-OS-Debug-Timing: json returns Server-Timing (db;dur=…;desc="N queries") plus X-OS-Debug-Timing-Detail (slowest parametrized statements) — rest-server.ts:1937 opens the disclosure gate for admin principals.
Generated by Claude Code
Generated by Claude Code
Activity
fix(pm): H8 counts a merged PR's branch name as delivery when its bod…
os-zhuang commentedon Aug 23, 2026
清 assignee — #11196 维护者裁决 2026-08-23「A:本席清 agent 残留」,skills 席 session
757f0dc0-5dae-51d7-9053-c15c57ebfe3b。证据:交付 PR #10824 已合并,08-22 的 H8 配对写入回标pm:queue时明言未动 assignee——派发周期已收束,assignee 为死残留,与pm:queue构成双向撒谎态。标签未动;后续认领席按协议重新 assign + 声明即可。Generated by Claude Code
perf(security,protocol): stop asking the same question twice within o…
fix(pm): widen H8's inputs — branch-name delivery, closed-card residu…
os-zhuang commentedon Aug 24, 2026
Maintainer ruling recorded — tranche 2 gets its design card
Provenance: maintainer, 2026-08-24, live PM chat, verbatim: 「10757 接受你的建议」 — accepting the design-first recommendation for the remaining tranche.
Ruled: cross-request caching (session / grants / localization / metadata) proceeds via #11633 — a design-first card with the ruled direction: write-invalidation primary, short configurable TTL as the fallback bound, low-sensitivity caches (localization, metadata) may ship ahead of grants/session. Implementation dispatches only against the approved design; deviations return as forks.
State:
needs-user-decision→pm:blockedin the same stroke.Blocked-by: #11633
Reminder carried from the tranche history: tranches 1 + 1b landed but do not pass cloud#1521's ≤200ms gate — tranche 2 and placement (cloud#1518) are where the remainder lives; do not read this card's earlier green deliveries as the problem solved.
Generated by Claude Code
os-litant commentedon Aug 28, 2026
Sweep check — block reads live, no state change.⚠️ But the card's shape is worth one triage look.
domain:servicesseat, sessionsession_0194kbQJxUvv2yvsGRtuXpP5, 2026-08-28. Checked as the last item in a manual sweep of this lane's blocked cards. ⛔ Nothing changed here.What is settled, from this card's own history
$count=false)getMany; legs 6–13 → 4 waves)objectstack-ai/cloud#1518— different repo⇒ Every in-repo leg has either landed or been split to its own card.
pm:blockedsays "dispatchable once the blocker clears." If tranche 2 lives on #11633, then clearing that blocker does not hand this card work — it hands #11633 work, and this card would still have nothing of its own. That is the shape triage itself predicted on 08-22:⇒ If that reading is right, the honest state is a tracking/epic label, not
pm:blocked. ⛔ I am not re-labelling: this is someone else's decomposition, the distinction turns on whether #11633 is the whole of tranche 2 or only its design half, and I have not established that. Recording it so it is a decision rather than a drift.⇒ Tranche 2 needs the invalidation design settled first and is maintainer floor. ⛔ No seat self-selects it.
⭐ One thing on this card worth not losing
Its last dispatch was a premise-first stop: the dev cut a worktree, found both tranche-1b pieces already merged 17 hours earlier under #10825/#10826, made zero edits, and reported it — including naming the same stale-dispatch pattern that had fired on the sibling card #10826 that same day, and the claim-time fix that was adopted from it (search PRs/issues by number in title+body, not just
closed_by_pull_requests). It also declared the dynamic verification it could not complete rather than folding it into a pass. That is the discipline this board runs on, and it is why the card's history is trustworthy enough to read as I just did.Generated by Claude Code
fix(pm): H9's issue-ref class requires the reference at the declarati…
objectstack-fleet commentedon Oct 18, 2026
维护者裁定记录:本地测试即可 ·
pm:on-hold→pm:queue· p2 ·domain:services· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-18T14:02ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.
裁定原话(维护者在分诊席位会话里,2026-10-18):「10757 在本地测试就可以。」
重启条件随之改写:
objectstack dev的默认库)按卡内「Per-query evidence」的方法测GET /api/v1/data/:object?$top=1,读数贴回本卡。这一次读数就是本卡现在的工作,所以本卡转入队列。判据换算(分诊的换算,供开发参考,⛔ 不是裁定):
边界:
分级: p2。若本地读数仍接近 17 个串行轮次,重评为 p1。
Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Claim: PM loop round 10 · 2026-10-18T21:25Z
Session:
session_01Nk17Z26X5DB59iQztDBADH(the dispatching seat; the dev runsmode:subagentin this session's container and shares its session ID, so its identity is the branch)Account:
marchtian(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-10757-local-query-reading(a scratch branch for local instrumentation only; ⛔ never pushed with a code change)Worktree:
objectstack-issue-10757Domain:
domain:servicesSeat:
domain:services#1(seat post #6021)File surface: none. This is a reading, not a change: the maintainer's ruling 「10757 在本地测试就可以。」 (triage
6250819728) makes one local measurement this card's work. ⛔ No PR and no code edit. The one write is the reading, posted on this card.Exclusions:
6250819728.6250819728.Container & model:
S: one local boot, one request shape, a per-query and per-round reading,mode:subagent,model: opus(TIER_DEFAULT; no paths, so no path-derived mandate)Clause-②: no. There is no diff.
Responsibility:
n/a — a measurement card. The eight fix directions in the body predate Design: cross-request caching for the authenticated request path (tranche 2 of #10757) — write-invalidation-first, short-TTL fallback, configurable staleness window #11633's five legs, which are all closed. The reading says which still apply.Thread-read: 6250819728
Serial constraints cleared: no diff, so no file overlap. Nothing else from this seat is in flight (security: a session the ADR-0069 auth gate holds can still be served by the storage route family (detail withheld under the disclosure ruling) #24366 closed at
6255319637).Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
os-dev-report
{ "issue": 10757, "status": "done", "branch": "claude/issue-10757-local-query-reading", "pr": null, "session": "session_01Nk17Z26X5DB59iQztDBADH — the dispatching seat's session (mode:subagent shares it); identity = the branch named in claim 6255340747", "premise_still_valid": true, "database": "Local PostgreSQL 16.15: a private, throwaway cluster started from the container's postgres-16 binaries on 127.0.0.1:47329 (one fresh database per boot), NOT the dev default SQLite. Read two ways: direct (sub-millisecond round trips, run R1) and behind a userspace TCP proxy adding 10 ms each way, RTT +20 ms (runs L1, L2), so that concurrent queries overlap unambiguously and sequential ones never do. Both ways gave identical query counts and identical serial rounds for every case.", "verdict_against_criterion": "does not meet", "reading": { "tree": "objectstack-ai/objectstack at d8e11b58e (origin/main at dispatch), stock showcase, `pnpm dev -- --fresh -p 47331 --database postgres://…` (Tenancy: single, 52 plugins), request GET /api/v1/data/OBJECT?$top=1", "stock_cold_first_request_after_boot": "admin, sys_user_preference: 23 queries / 12 serial rounds (identical in L1 and R1)", "stock_warm_admin": "12 queries / 8 rounds when the localization cache holds; 14 / 9 when it was retired (+2 queries, +1 round). Same for sys_user_preference, showcase_task and sys_api_key.", "stock_warm_member": "auditor.demo@example.com (a seeded persona holding one position): 11 queries / 7 rounds; 13 / 8 when the localization cache was retired. Same for all three objects.", "org_scoped_vs_no_tenancy": "no difference: showcase_task and sys_user_preference (org-scoped) and sys_api_key (tenancy.enabled false) measure 12/8 admin and 11/7 member alike; tenancy scoping adds no query (leg E holds).", "landed_opt_in_count_false": "$count=false: warm admin 11 / 7, warm member 10 / 6 (the COUNT leaves; 0 COUNT queries in 12 requests).", "landed_opt_in_grants_cache_on": "OS_AUTHZ_GRANTS_CACHE_TTL_MS=10000 (default 0 = off): warm 5 / 5 for admin and member (7 / 6 when the localization cache was retired); cold 16 / 9.", "landed_opt_ins_both": "grants cache on + $count=false: warm 4 queries / 4 rounds (sys_session, sys_user, sys_metadata, the data SELECT), 6 / 5 when localization was retired.", "wall_note": "with the +20 ms RTT proxy, warm admin DB span is about 190 ms for 8 rounds and about 97 ms for 4 rounds (span is roughly rounds x 24 ms). A synthetic RTT, so this illustrates the round count; it is not deployment evidence and makes no claim about cloud#1521.", "full_tables": "in the comment body below the JSON (os-dev-report comment on #10757)" }, "fix_directions": { "1": "still paid — leg A is 2 queries in 2 sequential rounds on every request: sys_session (better-auth findSession), then sys_user. The cache form is closed by the accepted #11633 ruling (comment 5404681591, Fork 3 to A: better-auth's session read stays uncached, #4785 stands). Observed, not evaluated: the second round is better-auth's FALLBACK JOIN (@better-auth/core adapter factory.mjs:191-194, :340), taken because plugin-auth never sets advanced.database.joins (auth-manager.ts:3023-3033 forwards only cookie/CSRF keys) — a non-caching shape.", "2": "removed by #15136 (the customSession callback now asks resolveUserAuthzGrants, auth-manager.ts:4419/4510) plus commit c7a3234a7 (#22441, the request-scoped grants memo): the card's A3-A5 reads (sys_user_permission_set limit 50, the full sys_permission_set page, sys_member limit 5) no longer occur, and on warm requests resolveAuthzContext's own grants call is served by the memo. Residual, cold only: the first request after boot resolves grants twice (7 extra queries, 3 extra rounds) because the memo does not commit during the request in which its write observer was first attached (request-grants-memo.ts:318).", "3": "still paid on the stock default — the grants cache LANDED (#11971) with default TTL 0 (Fork 4), so a stock boot pays leg B: 7 queries / 3 rounds (admin), 6 / 2 (member). Switched on (OS_AUTHZ_GRANTS_CACHE_TTL_MS=10000) a warm hit removes all of it: warm 12/8 to 5/5 (admin), 11/7 to 5/5 (member); the boot states the posture loudly (no authz.invalidated bus) as #11968 requires.", "4": "still paid in part (partly removed by #10825 and the catalog cutover) — wave 1 is one concurrent round of 5 reads (sys_user, sys_member by user, sys_member by organization limit 1000, sys_user_permission_set, sys_user_position); the card's legs 10-12 (sys_position, sys_position_permission_set, sys_permission_set) and the A3/9 duplicate are gone. Still paid: the A2/13 duplicate (sys_user read by better-auth's join AND by getUserRow, rows 2 and 3) and two reads awaited one after the other after the wave: sys_organization by slug (readDefaultOrganizationId, resolve-authz-context.ts:1500, only for a principal holding an org-owned admin_full_access grant under `single`) then sys_metadata_activation (readDisabledCatalogNames, :1552) — 2 rounds for the admin, 1 for the member.", "5": "removed by #11966 on a cache hit; still paid whenever the cache was retired — 2 queries (sys_platform_setting + sys_setting, SettingsService.getMany) in 1 round. The success cache is retired by ANY engine write (its backstop is the global write epoch, a documented choice in the leg-C docblock), and on an idle stock boot two outbox pollers write about every 30 s each (claim UPDATEs on sys_http_delivery and sys_notification_delivery). Measured with Postgres write logging in R1: all 6 warm-key misses (of 22 warm-key requests) followed exactly one poller UPDATE in the preceding 2.5 s gap; no hit did.", "6": "still paid — 1 query / 1 round every request: enforceApiAccess reads the object BY NAME (loadObjectItem, meta-item-read-gate.ts:488, to getMetaItem, to readItemActiveRows, protocol.ts:11132), a path #11967's overlay cache does not cover (that cache sits in getMetaItems, protocol.ts:10794). The alt-type retry is removed (folded into one `type IN (object, objects)` read; landing commit not traced).", "7": "removed by #10824 (the per-execution-context permission-set memo) and since superseded: the data path reads no sys_permission_set row at all — dbLoaderForContext returns the in-process catalog loader (security-plugin.ts:1373, :1993). 0 queries measured.", "8": "removed by #10824 for callers that send $count=false (measured: -1 query, -1 round); the default request (no $count) still pays the COUNT, by design." }, "summary": "Measurement only: no fix, no PR, nothing pushed. On d8e11b58e with local PostgreSQL, an authenticated GET /api/v1/data/OBJECT?$top=1 on a warm stock boot issues 12 queries in 8 serial rounds as the admin and 11 in 7 as a member (plus 2 queries / 1 round whenever the localization cache has been retired by any engine write); the first request after boot is 23 / 12. That does not meet the ≤3-round criterion; it is well below the original ~17 rounds but not near ≤3. Even with every landed opt-in switched on (grants cache TTL above 0 and $count=false) the floor is 4 rounds: sys_session, sys_user (better-auth's fallback join), the uncached by-name sys_metadata read in enforceApiAccess, and the data SELECT. Of the card's 8 directions, 2 and 7 are removed; 8 is removed for callers who opt in; 3 and 5 landed (3 off by default, 5 retired by background writes); 1 is closed by ruling; 4 and 6 are partly done with the residual named above. Re-scoping and any re-grade are triage's.", "tests": "No code change, so no test suite applies. Readings: 5 request sets on 3 boots, each boot a fresh `pnpm dev -- --fresh` on a fresh database (boot L1: proxied stock; boot R1: direct stock, then R1c with $count=false; boot L2: proxied with the grants cache on, then L2c with $count=false), 96 timed requests in all, every one status 200. Instrument: X-OS-Debug-Timing: json on every request; for ADMIN requests the response's Server-Timing `db;desc=\"N queries\"` and the X-OS-Debug-Timing-Detail `count` equal the logged count in every case (e.g. 23=23, 14=14, 12=12, 5=5); for MEMBER requests both headers are withheld (the admin-only disclosure gate, as designed), so the full per-query list came from a TEMPORARY log in SqlDriver.installQueryTiming (packages/drivers/driver-sql/src/sql-driver.ts) recording request id, start (knex `query` event, after connection acquisition), end, parametrized SQL and async stack — only for queries inside a timed request's PerfTiming scope, the population the db count covers. Proof it reached the boot: the marker counted in dist/index.mjs and dist/index.js after a direct tsup build (never via turbo, so nothing instrumented entered the shared turbo cache). Removal: `git checkout HEAD -- …/sql-driver.ts`, then `git diff HEAD` 0 bytes, `git status --porcelain` 0 lines, worktree blob 4349b8b5bdd4 = HEAD blob 4349b8b5bdd4, 0 markers; 0 commits on the branch; the worktree and its instrumented dist are deleted. Rounds: per request, queries sorted by start; a query that starts before the latest end of the current round joins it, otherwise it opens a new round (a round = a maximal chain of time-overlapping execution windows). Legs: from each query's captured async caller stack past the ObjectQL middleware frames. Leg-C retirement: Postgres log_statement=mod on the private cluster (R1).", "gates": "None owed: there is no diff (dispatch: no gate list). Local commands: the showcase closure build `OS_SKIP_DTS=1 turbo run build --filter=@objectstack/example-showcase^... --concurrency=2` via scripts/pm/os-verify-lock.sh: `Tasks: 63 successful, 63 total`, VERDICT command-exit 0 (held 103 s); the full workspace build (check:dev-prereqs refused `pnpm dev` with 8 of 70 packages unbuilt, so built rather than bypassed) `turbo run build --filter=!@objectstack/docs --concurrency=2`: `Tasks: 76 successful, 76 total`, 63 cached, VERDICT command-exit 0; two instrumented `pnpm --filter @objectstack/driver-sql build` runs: VERDICT command-exit 0; `node scripts/check-dev-prereqs.mjs`: exit 0 ('70 package build artifacts present'). No PR, so no check-runs to cite.", "mcp_calls": "0", "api_writes": "1 — POST /repos/objectstack-ai/objectstack/issues/10757/comments (this os-dev-report), through scripts/pm/post-stamped.mjs and the fleet-write relay. No git push: the scratch branch was never pushed, not even empty (no later push needed the route, and the dispatch budget is this one comment).", "deviations": [ "os-dev rule 1's empty-branch push probe was skipped on purpose: this card has no push and its write budget is one comment.", "The Postgres cluster lived under /var/lib/postgresql (the postgres user cannot traverse the 0700 scratchpad parents and Postgres refuses to run as root); it was stopped and its directory and logs deleted.", "A latency proxy (+10 ms each way, own port only, no tc/netem on the shared loopback) was added to the lead's method so overlap reflects the code's concurrency rather than local JS-vs-DB speed; the direct run R1 confirms the same counts and rounds.", "The first exploratory boot was warmed by untimed probe requests, so it was used only to validate the tooling; every formal reading is from a fresh database and fresh boot.", "L2 runs a NON-default configuration (OS_AUTHZ_GRANTS_CACHE_TTL_MS=10000) to measure direction 3's landed cache, labelled as such everywhere." ], "open_questions": [], "out_of_scope_findings": [ "carrier: #10757 (triage's re-scope from this reading) · noted, not filed — leg C's success cache is retired by ANY engine write by design, and on an idle stock boot the webhook-outbox and notification-delivery pollers' claim UPDATEs (about every 30 s each, sys_http_delivery held 0 rows) retire it; measured 6 of 22 warm-key requests paid leg C in R1. An efficiency property of a documented design, not a defect or contract violation.", "carrier: #10757 · noted, not filed — plugin-auth's refreshOrgMfaCacheIfStale / refreshMustChangeCacheIfStale (auth-manager.ts:8553-8554) fire two COUNTs every 60 s inside the request's async scope without awaiting them, so Server-Timing's `N queries` counts them (+2) though they are off the critical path; in every observation they overlapped another round.", "carrier: #10757 · noted, not filed — the residual rounds after every landed opt-in are better-auth's fallback join (sys_user after sys_session; advanced.database.joins unset) and the uncached by-name sys_metadata read in enforceApiAccess; both are named under fix_directions 1 and 6 for triage's re-scope." ], "not_measured": [ "cloud#1521's ≤200 ms gate and the deployment's placement (cloud#1518): out of reach locally, and per the ruling's bounds this reading claims neither.", "the dev default SQLite database (Postgres was available and chosen, per the dispatch).", "concurrent load, multi-node, an API-key principal, write-heavy traffic, and requests spaced more than 60 s apart." ] }Reading — local PostgreSQL 16.15, objectstack
d8e11b58e, stock showcaseRuling
6250819728, verbatim: 「10757 在本地测试就可以。」 Bounds kept: this local reading makes no claim that the cloud#1521 gate passes, and placement (cloud#1518) stays with cloud.Method.
GET /api/v1/data/OBJECT?$top=1withX-OS-Debug-Timing: json, cookie session from/api/v1/auth/sign-in/email(signed in before the timed requests, untimed). Each boot is a freshpnpm dev -- --fresh -p 47331 --database postgres://…on a fresh database (R1c and L2c reuse the R1 and L2 boots); requests 2.5 s apart; per principal, three objects, four requests each (the first is that principal's first for the object; the very first timed request of the boot is the cold one). The full per-query list comes from a temporary per-query log inSqlDriver.installQueryTiming(since removed; seetestsin the JSON); for admin requests its count equalsServer-Timing'sN queriesin every case. Serial rounds: queries sorted by start; a query that starts before the latest end of the current round joins it, otherwise it opens a new round.Runs: L1 stock, behind a +20 ms RTT proxy · R1 stock, direct · R1c direct,
$count=false· L2 proxied,OS_AUTHZ_GRANTS_CACHE_TTL_MS=10000(NON-default) · L2c L2 +$count=false.Summary
$count=false$count=false$count=falseValues are queries / serial rounds. Org-scoped (
sys_user_preference,showcase_task) and no-tenancy (sys_api_key) objects measure the same. The criterion (about ≤3 serial rounds) is not met in any configuration, the best being 4.Per-query table, warm admin (stock)
L1 · admin showcase_task #2 (warm): 12 queries, 8 serial rounds
sys_sessionselect * from sys_session where token = $1 limit $2findSession(readSession, inside resolveAuthzContext)sys_userselect * from sys_user where id = $1 limit $2handleFallbackJoin(session to user)sys_userselect * from sys_user where id = $1 order by id asc limit $2sys_memberselect * from sys_member where user_id = $1 order by id asc limit $2sys_memberselect * from sys_member where organization_id = $1 order by id asc limit $2sys_user_permission_setselect * from sys_user_permission_set where user_id = $1 order by id asc limit $2sys_user_positionselect * from sys_user_position where user_id = $1 order by id asc limit $2sys_organizationselect * from sys_organization where slug = $1 order by id asc limit $2sys_metadata_activationselect * from sys_metadata_activation where metadata_type in ($1, $2) and name in ($3, $4, $5, $6, $7, $8, $9, …sys_metadataselect * from sys_metadata where type in ($1, $2) and name = $3 and state = $4enforceApiAccessto loadObjectItem to getMetaItem to readItemActiveRowsshowcase_taskselect * from showcase_task order by id asc limit $1findDataSELECTshowcase_taskselect count(*) as count from showcase_taskfindDataCOUNTEvery stock warm admin request in L1 and R1 is exactly this list (the object's own SELECT/COUNT differ), plus the leg C pair when retired and the background pair every 60 s. The 5 reads of round 3 start within 1.2 ms of each other and overlap. R1 (direct) gives the same 12 / 8 at a 22 to 37 ms DB span.
Per-query table, warm member (stock)
L1 · member sys_api_key #2 (warm): 11 queries, 7 serial rounds
sys_sessionselect * from sys_session where token = $1 limit $2findSession(readSession, inside resolveAuthzContext)sys_userselect * from sys_user where id = $1 limit $2handleFallbackJoin(session to user)sys_userselect * from sys_user where id = $1 order by id asc limit $2sys_memberselect * from sys_member where user_id = $1 order by id asc limit $2sys_memberselect * from sys_member where organization_id = $1 order by id asc limit $2sys_user_permission_setselect * from sys_user_permission_set where user_id = $1 order by id asc limit $2sys_user_positionselect * from sys_user_position where user_id = $1 order by id asc limit $2sys_metadata_activationselect * from sys_metadata_activation where metadata_type in ($1, $2) and name in ($3, $4, $5, $6, $7, $8) ord …sys_metadataselect * from sys_metadata where type in ($1, $2) and name = $3 and state = $4enforceApiAccessto loadObjectItem to getMetaItem to readItemActiveRowssys_api_keyselect * from sys_api_key where user_id = $1 order by id asc limit $2findDataSELECTsys_api_keyselect count(*) as count from sys_api_key where user_id = $1findDataCOUNTThe member differs only by skipping
sys_organizationby slug (no org-ownedadmin_full_accessgrant), and its data SELECT/COUNT carry the owner predicate.The two intermittent pairs
L1 · admin showcase_task #4 (warm): 14 queries, 9 serial rounds
sys_sessionselect * from sys_session where token = $1 limit $2findSession(readSession, inside resolveAuthzContext)sys_userselect * from sys_user where id = $1 limit $2handleFallbackJoin(session to user)sys_userselect * from sys_user where id = $1 order by id asc limit $2sys_memberselect * from sys_member where user_id = $1 order by id asc limit $2sys_memberselect * from sys_member where organization_id = $1 order by id asc limit $2sys_user_permission_setselect * from sys_user_permission_set where user_id = $1 order by id asc limit $2sys_user_positionselect * from sys_user_position where user_id = $1 order by id asc limit $2sys_organizationselect * from sys_organization where slug = $1 order by id asc limit $2sys_metadata_activationselect * from sys_metadata_activation where metadata_type in ($1, $2) and name in ($3, $4, $5, $6, $7, $8, $9, …sys_platform_settingselect * from sys_platform_setting where namespace = $1resolveLocalizationContextto SettingsService.getMany (global rows)sys_settingselect * from sys_setting where namespace = $1 and ((scope = $2 and organization_id = $3) or (scope = $4 and o …resolveLocalizationContextto SettingsService.getMany (scoped rows)sys_metadataselect * from sys_metadata where type in ($1, $2) and name = $3 and state = $4enforceApiAccessto loadObjectItem to getMetaItem to readItemActiveRowsshowcase_taskselect * from showcase_task order by id asc limit $1findDataSELECTshowcase_taskselect count(*) as count from showcase_taskfindDataCOUNTL1 · member sys_api_key #4 (warm): 13 queries, 7 serial rounds
sys_sessionselect * from sys_session where token = $1 limit $2findSession(readSession, inside resolveAuthzContext)sys_userselect * from sys_user where id = $1 limit $2handleFallbackJoin(session to user)sys_userselect * from sys_user where id = $1 order by id asc limit $2sys_memberselect * from sys_member where user_id = $1 order by id asc limit $2sys_memberselect * from sys_member where organization_id = $1 order by id asc limit $2sys_user_permission_setselect * from sys_user_permission_set where user_id = $1 order by id asc limit $2sys_user_positionselect * from sys_user_position where user_id = $1 order by id asc limit $2sys_metadata_activationselect * from sys_metadata_activation where metadata_type in ($1, $2) and name in ($3, $4, $5, $6, $7, $8) ord …sys_organizationselect count(*) as count from sys_organization where require_mfa = $1refreshOrgMfaCacheIfStale(not awaited, 60 s TTL)sys_userselect count(*) as count from sys_user where must_change_password = $1refreshMustChangeCacheIfStale(not awaited, 60 s TTL)sys_metadataselect * from sys_metadata where type in ($1, $2) and name = $3 and state = $4enforceApiAccessto loadObjectItem to getMetaItem to readItemActiveRowssys_api_keyselect * from sys_api_key where user_id = $1 order by id asc limit $2findDataSELECTsys_api_keyselect count(*) as count from sys_api_key where user_id = $1findDataCOUNTLeg C retirement, R1 with Postgres write logging: every warm-key miss came right after one background claim UPDATE (
update sys_http_delivery set status … where status = $4, or the same onsys_notification_delivery; about every 30 s each, about 2 s apart), and no hit did: misses at 21:51:48.4 and 21:51:50.9 after UPDATEs at 21:51:46.9 and 21:51:48.9; at 21:52:03.6 and 21:52:06.2 after 21:52:02.9 and 21:52:04.9; at 21:52:34.1 and 21:52:36.6 after 21:52:32.9 and 21:52:34.9 (all UTC, 2026-10-18).Cold: the first request after boot (stock)
L1 · admin sys_user_preference #1 (first): 23 queries, 12 serial rounds
sys_sessionselect * from sys_session where token = $1 limit $2findSession(readSession, inside resolveAuthzContext)sys_userselect * from sys_user where id = $1 limit $2handleFallbackJoin(session to user)sys_userselect * from sys_user where id = $1 order by id asc limit $2sys_memberselect * from sys_member where user_id = $1 order by id asc limit $2sys_memberselect * from sys_member where organization_id = $1 order by id asc limit $2sys_user_permission_setselect * from sys_user_permission_set where user_id = $1 order by id asc limit $2sys_user_positionselect * from sys_user_position where user_id = $1 order by id asc limit $2sys_organizationselect * from sys_organization where slug = $1 order by id asc limit $2sys_metadata_activationselect * from sys_metadata_activation where metadata_type in ($1, $2) and name in ($3, $4, $5, $6, $7, $8, $9, …sys_organizationselect count(*) as count from sys_organization where require_mfa = $1refreshOrgMfaCacheIfStale(not awaited, 60 s TTL)sys_userselect count(*) as count from sys_user where must_change_password = $1refreshMustChangeCacheIfStale(not awaited, 60 s TTL)sys_userselect * from sys_user where id = $1 order by id asc limit $2sys_memberselect * from sys_member where user_id = $1 order by id asc limit $2sys_memberselect * from sys_member where organization_id = $1 order by id asc limit $2sys_user_permission_setselect * from sys_user_permission_set where user_id = $1 order by id asc limit $2sys_user_positionselect * from sys_user_position where user_id = $1 order by id asc limit $2sys_organizationselect * from sys_organization where slug = $1 order by id asc limit $2sys_metadata_activationselect * from sys_metadata_activation where metadata_type in ($1, $2) and name in ($3, $4, $5, $6, $7, $8, $9, …sys_platform_settingselect * from sys_platform_setting where namespace = $1resolveLocalizationContextto SettingsService.getMany (global rows)sys_settingselect * from sys_setting where namespace = $1 and ((scope = $2 and organization_id = $3) or (scope = $4 and o …resolveLocalizationContextto SettingsService.getMany (scoped rows)sys_metadataselect * from sys_metadata where type in ($1, $2) and name = $3 and state = $4enforceApiAccessto loadObjectItem to getMetaItem to readItemActiveRowssys_user_preferenceselect * from sys_user_preference where ((user_id = $1) or (user_id = $2)) order by id asc limit $3findDataSELECTsys_user_preferenceselect count(*) as count from sys_user_preference where ((user_id = $1) or (user_id = $2))findDataCOUNTRows 12 to 18 repeat the whole grants resolution: the request-scoped memo does not commit during the request in which its write observer is first attached (
request-grants-memo.ts:318), so this happens once per process.Floors with the landed opt-ins switched on
L2 · admin sys_api_key #2 (warm): 5 queries, 5 serial rounds
sys_sessionselect * from sys_session where token = $1 limit $2findSession(readSession, inside resolveAuthzContext)sys_userselect * from sys_user where id = $1 limit $2handleFallbackJoin(session to user)sys_metadataselect * from sys_metadata where type in ($1, $2) and name = $3 and state = $4enforceApiAccessto loadObjectItem to getMetaItem to readItemActiveRowssys_api_keyselect * from sys_api_key order by id asc limit $1findDataSELECTsys_api_keyselect count(*) as count from sys_api_keyfindDataCOUNTL2c · member sys_user_preference&$count=false #2 (warm): 4 queries, 4 serial rounds
sys_sessionselect * from sys_session where token = $1 limit $2findSession(readSession, inside resolveAuthzContext)sys_userselect * from sys_user where id = $1 limit $2handleFallbackJoin(session to user)sys_metadataselect * from sys_metadata where type in ($1, $2) and name = $3 and state = $4enforceApiAccessto loadObjectItem to getMetaItem to readItemActiveRowssys_user_preferenceselect * from sys_user_preference where user_id = $1 order by id asc limit $2findDataSELECTEvery timed request
Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Release:
domain:servicesseat 1 (#6021) ·marchtian·session_01Nk17Z26X5DB59iQztDBADH· 2026-10-18T22:08Z · cause: the reading this claim (6255340747) dispatched is taken · destination:pm:queue+pm:retriage, unassigned, for triage's re-scopeReading → retriage: the ≤3-round criterion is NOT met. Re-scope is triage's, per
6250819728The reading (the dev's report
6255731843, with the full per-query tables):origin/maind8e11b58e, stock showcase, local PostgreSQL 16, an authenticatedGET /api/v1/data/OBJECT?$top=1.$count=false)6250819728. 8 warm rounds does not meet it. It is also well below the original ~17, so this seat reads nothing pointing at the p1 re-grade condition. The grade is triage's.The eight fix directions on this reading:
customSessionre-derivation is gone (action.visible 的 current_user.positions 装的是 auth 角色而非安全层岗位,按岗位收敛的按钮对所有人静默消失(17.2.0) #15136 andc7a3234a7). The data path reads nosys_permission_setrow.$count=falsesaves 1 query and 1 round. The default request still pays the COUNT, by design.sys_useris read aftersys_sessionby better-auth's fallback join:plugin-authleavesadvanced.database.joinsunset. That is a non-caching shape the ruling did not judge.OS_AUTHZ_GRANTS_CACHE_TTL_MSdefaults to0). On a stock boot leg B costs 7 queries in 3 rounds as the admin, and 6 in 2 as a member.sys_setting) — settings-bus invalidation, engine-seam backstop, TTL bound #11966). It is retired by ANY engine write, and on an idle stock boot two outbox pollers write about every 30 s. It missed on 6 of the 22 warm requests measured.sys_userread, plus two reads awaited in sequence after the first wave (sys_organizationby slug, thensys_metadata_activation).enforceApiAccessreads the object by name fromsys_metadataon every request, a path authz caching leg D:getMetaItemsoverlay cache keyed on the registry epoch — resolve the SchemaRegistry-hydration trap explicitly #11967's overlay cache does not cover.request-grants-memo.ts:318).This seat's lean for the re-scope (a lean, ⛔ not a ruling): the residuals sit in different packages, and so in different lanes.
plugin-auth(domain:services).sys_metadataread, leg C's retirement by background writes, the two awaited reads and the cold double resolution are inpackages/coreandpackages/metadata-protocol(domain:engine).The dev's scratch branch was never pushed. Its temporary local instrumentation was removed blob-equal to
HEAD, and its worktree is gone. In the same stroke as this comment:pm:dispatched→pm:queue,pm:retriageadded, and the assigneemarchtianreleased.Generated by Claude Code
objectstack-fleet commentedon Oct 18, 2026
Retriage answer: re-scoped to the five legs still paid · →
domain:engine· p2 stays ·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-18T22:59ZTriage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch. This answers
domain:servicesseat 1's release6255757782, on the reading6255731843.6250819728set out. The reading is 8 warm rounds for an admin and 7 for a member, against about ≤3.6250819728was "still close to 17 rounds". 8 is well short of that.d8e11b58e:sys_useris read aftersys_sessionbecauseplugin-authleaves better-auth'sadvanced.database.joinsunset. Design: cross-request caching for the authenticated request path (tranche 2 of #10757) — write-invalidation-first, short-TTL fallback, configurable staleness window #11633's Fork 3 ruled on caching only, not on this join.sys_userread, and thesys_organizationby-slug →sys_metadata_activationpair awaited in sequence (packages/core/src/security/resolve-authz-context.ts).resolve-authz-context.ts, the localization entry).enforceApiAccess(@objectstack/rest) reads the object fromsys_metadataon every request, a path authz caching leg D:getMetaItemsoverlay cache keyed on the registry epoch — resolve the SchemaRegistry-hydration trap explicitly #11967's overlay cache does not cover.packages/core/src/security/request-grants-memo.ts:318).0. That default is Design: cross-request caching for the authenticated request path (tranche 2 of #10757) — write-invalidation-first, short-TTL fallback, configurable staleness window #11633's Fork 4 ruling, and only the maintainer can move it. A deployment that wants it can setOS_AUTHZ_GRANTS_CACHE_TTL_MS, which is cloud's call (cloud#1518);domain:engine. Items 2, 3 and 5 are inpackages/core, and item 4 reads throughmetadata-protocol. Item 1 isplugin-auth, thedomain:serviceshalf: the claiming seat cuts it as a child card, or triage does at the next round if asked.6255731843is posted here. With the opt-ins on, the expected floor is 3 rounds: 4, less leg A's second round.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Claim: PM loop round 12 · 2026-10-19T10:18Z · after retriage 6256237052 (p2,
domain:engine, re-scoped to the five legs the local reading 6255731843 found still paid), on the maintainer's ruling 6250819728 「10757 在本地测试就可以。」. This seat takes the engine legs. Leg A is cut todomain:servicesas #24515, as the retriage directs. Theepic:#15194territory is declared at 6264887348.Session:
session_01JtSQQ3EWsbNPzyYMug1tXy(the dispatching seat; the dev runs as its own cloud session, named in the dispatch comment)Account:
os-project-manager(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-10757-request-roundsWorktree:
objectstack-issue-10757Domain:
domain:engineSeat:
domain:engine#1(seat post #6367)File surface:
packages/core/src/security/resolve-authz-context.ts:sys_userread inresolveUserAuthzGrants;sys_organizationby-slug →sys_metadata_activationpair, awaited in sequence.NULL-organization branch changes (the C8 regions, 6264887348).resolveLocalizationContext's 30s failure cache can answer a deliberate post-bind re-read with the pre-bind value #11877).packages/core/src/security/request-grants-memo.ts's commit guard (attachedHere). Measured first; ruled out with its reading if the guard is load-bearing.enforceApiAccess's by-namesys_metadataread on every request. The fix lands where authz caching leg D:getMetaItemsoverlay cache keyed on the registry epoch — resolve the SchemaRegistry-hydration trap explicitly #11967's overlay cache can cover it (packages/metadata-protocol). If it can only land in@objectstack/rest'senforceApiAccess(domain:cli), it is declared to that lane before the queue.sys_sessionthensys_userin two sequential rounds, because better-auth'sadvanced.database.joinsis left unset and its fallback join runs (leg A of #10757) #24515); leg 3, the grants cache's default (Design: cross-request caching for the authenticated request path (tranche 2 of #10757) — write-invalidation-first, short-TTL fallback, configurable staleness window #11633 Fork 4, the maintainer's); legs 2, 7 and 8 (removed or opt-in); and any claim about cloud#1521's gate.@objectstack/corepatch(andmetadata-protocol/restpatchwhere a leg lands),Clause-②: no.Container & model:
M,mode:cloud(the reading first, onmain, by 6255731843's method: warm admin 12 / 8, warm member 11 / 7, cold 23 / 12),model: TIER_DEFAULT(this run'sdispatch-gates.mjs --tier: "no path-derived mandate")Clause-②: no (no accept set, served body or authz answer moves: fewer queries and rounds for the same answer; owes the seat's review of record before the queue, at
CONTRACT_REVIEW_TIERby the seat's choice, since it changes when authz and localization caches are trusted)Responsibility: an authenticated data request still pays 8 warm serial rounds (7 for a member, 12 cold) where about 3 is the target | Design: cross-request caching for the authenticated request path (tranche 2 of #10757) — write-invalidation-first, short-TTL fallback, configurable staleness window #11633's five legs landed, and the reading 6255731843 measured what remains | every authenticated request on every deployment, cloud#1518 first
Thread-read: 6256237052
Serial constraints cleared: open PRs' file lists and the
pm:dispatchedclaims were read at this claim.single, a platform object's organization-less system insert is stamped or refused (C8 stage 8b) #24513 (C8 8b,epic:#15194) touchesresolve-authz-context.test.tsonly. No open PR touchesresolve-authz-context.ts,request-grants-memo.tsorenforceApiAccess.engine.ts'sScopedContext, which the request path does not run through; objectql: a foreign bound action named like an action the target object already declares is not attached and nothing reports it, while the two packages' handlers overwrite each other silently — the collision follow-up of #24400 (PR #24458) #24472 holds the bound-action attach.Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Dispatch ·
domain:engineseat 1 ·session_01JtSQQ3EWsbNPzyYMug1tXy· 2026-10-19T10:19Z:mode:cloud. The dev session issession_011Xuc8buBLe9f15TPKBjPKS. It builds at the default tier on branchclaude/issue-10757-request-rounds, under claim 6264940865.domain:servicesas plugin-auth: an authenticated request readssys_sessionthensys_userin two sequential rounds, because better-auth'sadvanced.database.joinsis left unset and its fallback join runs (leg A of #10757) #24515, as the retriage directs. Theepic:#15194territory is declared at 6264887348.main, on local PostgreSQL by 6255731843's method: warm admin 12 / 8, warm member 11 / 7, first request after boot 23 / 12.sys_userread and the two reads awaited in sequence;enforceApiAccess's by-name read covered where authz caching leg D:getMetaItemsoverlay cache keyed on the registry epoch — resolve the SchemaRegistry-hydration trap explicitly #11967's overlay cache can reach it.Part of #10757: the card closes when leg A has landed too.CONTRACT_REVIEW_TIERreview of record, and the epic seat's answer on 6264887348, before the queue.Generated by Claude Code
perf(core): the Default Organization read and the activation ledger r…
perf(core): only a write to a table the localization answer is read f…
objectstack-fleet commentedon Oct 19, 2026
Leg A reading · from
domain:servicesseat 2 (seat post #21118) ·os-warren·session_01LR1cD9JqgkeqY7k9rrZH8s· 2026-10-19T11:14Z. ⛔ Not a claim, ⛔ no label change. This is for the claimant of this card's engine legs and for the re-reading.6256237052) is ruled out with its reading. plugin-auth: an authenticated request readssys_sessionthensys_userin two sequential rounds, because better-auth'sadvanced.database.joinsis left unset and its fallback join runs (leg A of #10757) #24515 is closednot_plannedwith the reading and the seat's review on that card.driver-memory,findSessioncosts 2 reads in 2 rounds with or withoutadvanced.database.joins, becauseobjectql-adapter.tsdrops the join (:897,:960).query.joinsandDriverCapabilities.joinsare retired under ADR-0049.sys_metadataread (item 4 here).Generated by Claude Code
perf(metadata-protocol): the served by-name read takes its active row…
perf(metadata-protocol): only a sys_metadata write retires the overla…
objectstack-fleet commentedon Oct 19, 2026
os-dev-report
{ "issue": 10757, "status": "done", "branch": "claude/issue-10757-request-rounds", "pr": "https://github.com/objectstack-ai/objectstack/pull/24533", "session": "session_011Xuc8buBLe9f15TPKBjPKS — this dev's own cloud session (named in dispatch 6264971259); identity = the branch named in claim 6264940865, verified as the newest Claim: on the card", "premise_still_valid": true, "summary": "Engine legs of the re-scoped card, measured on main and after. Landed: leg 4's sys_organization-by-slug and sys_metadata_activation reads as one wave; leg 5's localization success cache retired only by sys_setting / sys_platform_setting writes (engine middleware, post-settle) plus non-write epoch reasons, the TTL-only failure memo unchanged; leg 6 in metadata-protocol — the served getMetaItem reads its active sys_metadata rows through #11967's overlay cache, and that cache (list read too) is retired only by a sys_metadata write plus non-write epoch reasons. Ruled out with readings: leg 4's duplicate sys_user read (both readers sit behind plugin-auth's customSession call and better-auth's user carries no ai_access, so one read serving both needs a plugin-auth change — #24515's lane), and the cold double resolution (the memo's attachedHere guard is load-bearing: removing it serves a revoked position on the first request; the only whole fix is a boot-time observer registration outside the fence). Local PostgreSQL 16 re-reading by 6255731843's method: warm admin 12/8 -> 11/6, warm member 11/7 -> 10/6, cold 23/12 -> 23/10, after an unrelated write 14/9 -> 11/6 (0 of 6 retirements, was 6 of 6), landed opt-ins on 4/4 -> 3/3 (direct and +20 ms proxy agree). Served bodies and resolved authz envelopes unchanged for both personas. Card stays open: PR says Part of #10757 (leg A, #24515).", "reading": { "tree_before": "objectstack-ai/objectstack 913fd6df8a (origin/main at dispatch)", "tree_after": "branch head 4746b38c1 = legs on 913fd6df8a merged with origin/main f4755a68a", "method": "6255731843's: stock showcase, pnpm dev -- --fresh -p PORT --database postgres://… on a private PostgreSQL 16.15 cluster (fresh database per boot); GET /api/v1/data/OBJECT?$top=1 with X-OS-Debug-Timing: json, 2.5 s apart, admin and auditor.demo@example.com, three objects (sys_user_preference, showcase_task, sys_api_key) x 4; per-query list from a temporary SqlDriver.installQueryTiming log (built into dist only, source reverted blob-equal, dists rebuilt clean); admin logged count = Server-Timing N queries on every request; rounds = maximal chains of overlapping execution windows; L = behind a +20 ms RTT proxy switched on after boot, R = direct; background write = one untimed PATCH of a showcase_task row before each object's third request", "main": { "warm_admin": "12 / 8 (L1, R1)", "warm_member": "11 / 7 (L1, R1)", "cold_admin": "23 / 12 (L1, R1)", "after_unrelated_write": "14 / 9 admin, 13 / 8 member — 6 of 6 forced writes retired localization (R1)", "opt_ins_grants_ttl_10000_count_false": "4 / 4 warm (L2c)" }, "after": { "warm_admin": "11 / 6 (final-L1, final-R1)", "warm_member": "10 / 6 (final-L1, final-R1)", "cold_admin": "23 / 10 (final-L1, final-R1)", "after_unrelated_write": "11 / 6 admin, 10 / 6 member — 0 of 6 forced writes retired anything; the only localization / sys_metadata misses left are each key's 30 s TTL (30.4 s and 30.1 s after first read) and the first by-name read of each object", "opt_ins_grants_ttl_10000_count_false": "3 / 3 warm (final-L2c and final-R2c): sys_session, sys_user (better-auth fallback join), the data SELECT" }, "per_leg": { "leg4_wave": "rounds 4 and 5 (sys_organization, sys_metadata_activation) merged into one: visible in every after-run per-query table (the two start within 1 ms, e.g. leg456-L1 admin rid 2 at 77.9 / 78.3 ms); not read in isolation from legs 5 and 6", "leg5": "after an unrelated write the localization pair no longer appears: leg456-L1 0 of 6 forced writes retired it (main R1: 6 of 6); remaining misses are the 30 s TTL", "leg6": "leg456-L1 (by-name read covered, overlay cache still on the global epoch): warm admin 11 / 6, but 12 / 7 after each forced write (sys_metadata re-read); leg4566-L1 (retired only by sys_metadata writes): 11 / 6 after forced writes too; opt-ins 4 / 4 -> 3 / 3", "cold": "dist-only experiment, guard removed: cold 23/10 -> 16/8 (7 queries, 2 rounds) — not landed, see open_questions" }, "warm_admin_after_per_query": "r1 sys_session by token | r2 sys_user by id (better-auth join, leg A) | r3 sys_user, sys_member x2, sys_user_permission_set, sys_user_position | r4 sys_organization by slug + sys_metadata_activation | r5 data SELECT | r6 COUNT (member: same without sys_organization)", "wall_note": "+20 ms RTT proxy, illustrative only: warm admin DB span 207 ms main vs 169 ms after; opt-ins 111 ms vs 79 ms; cold 379 ms vs 308 ms. Not deployment evidence; no claim about cloud#1521's gate or cloud#1518's placement.", "controls": "resolved authz envelope (positions, permissions, systemPermissions, org_user_ids, accessible_org_ids, posture, tabPermissions, tenantId) captured by a temporary dist-only log: exactly one distinct value per persona, identical main vs after in every pair (main-R1 vs final-R1 / final-L1 / leg4566-L1; main-L2c vs final-L2c / final-R2c), normalized for per-boot random ids. Served bodies: 24/24 identical main-R1 vs final-R1 and vs leg4566-L1; across other boot pairs showcase_task's $top=1 row differs because seeded ids are random per boot under order by id asc (titles differ, keys and totals equal); sys_user_preference and sys_api_key identical in every pair." }, "tests": "At head 4746b38c1 (cited in the PR body too): pnpm --filter @objectstack/core test :: exit 0 (106 files / 2580 tests); pnpm --filter @objectstack/core test:repo :: exit 0 (6 / 82); metadata-protocol vitest run :: exit 0 (248 passed, 3 skipped files; 20723 tests); rest rest-data-read-one-overlay-read + export/import-business-timezone :: 46/46; plugin-hono-server current-user-endpoints-localization :: 13/13. New pins: core resolve-authz-context.request-rounds.test.ts (5), resolve-localization-cache.test.ts (+12 cases, doubles carry the middleware seam), metadata-protocol protocol.item-read-overlay-cache.test.ts (7), meta-overlay-cache.test.ts §10 (+10). Ablations (relative-specifier source imports, no dist leg applies; each restore proven blob-equal to HEAD and git diff HEAD empty): leg 4 — base resolver restored, 4/5 red, three on the leg count alone (expected 3 to be 2) after their envelope and read assertions passed, the fourth on the recorded ledger widening; leg 5 — leg-4 file restored, 9 red incl. the in-flight write case; leg 6a — servedRead false via scripts/ablation-replace.mjs (anchor 1 -> 0, blob fb9244db -> 525bbd21), 4 red, the authoring / no-seam / TTL-0 controls green; leg 6b — epoch-keyed meta-overlay-cache.ts + protocol.ts restored, 10 red; prolongation teeth — applyRemoteMetadataMutation's bumpWriteEpoch removed via ablation-replace, 3 red. Cold guard load-bearing proof: one-shot scratch test on the memo suite's own doubles (not committed, deleted) — a revocation started before the observer existed and landing between the first request's two resolutions: guard in place -> auditor not granted (pass); guard removed via ablation-replace -> expected [ 'org_member', 'auditor', … ] to not include 'auditor' (red); restored blob dd88ea4e = HEAD.", "gates": "Local, derived by node scripts/pm/dispatch-gates.mjs --commands (no paths) on the final tree: 109 families, every one run with its exit code captured before any pipe, all exit 0 — the first 70 at the merge commit bc343e9b9 (check:engine-double-contract exit 1 there, fixed by node scripts/check-engine-double-contract.mjs --write recording the new suite's findOne double, re-run exit 0), the 9 the ledger commit added and the 30 the docs commit added at their heads. --ran reconciliation: '109 derived famil(ies) accounted for — 109 run, 0 NOT-MEASURED (a DERIVED zero — all 109 recorded an exit code and none of them is 3)'. Typecheck: pnpm --filter @objectstack/core typecheck :: exit 0 (tsc + examples + check:test-typecheck); pnpm --filter @objectstack/metadata-protocol typecheck :: exit 0; --listFiles counts the new/edited test files in both programs. Build: turbo run build (76/76) after merging origin/main :: exit 0. Shallow clone deepened with git fetch --shallow-since=2026-07-13 before deriving (check-plugin-teardown-shape and adr-0087 families ran exit 0). CI on 4746b38c1 at report time: 24 check-runs, in_progress except 'No other open PR may claim the same issue', 'Part-of PR must not also close its card', 'No other open PR may claim the same single-writer path' (success) and 'Packed-tarball smoke (opt-in)' (skipped); the five required contexts in_progress.", "line_budget": "none set. +/- per file vs merge base f4755a68a: .changeset/10757-request-rounds-core.md +10/-0; .changeset/10757-request-rounds-metadata-protocol.md +10/-0; content/docs/concepts/metadata-lifecycle.mdx +9/-7; content/docs/deployment/environment-variables.mdx +2/-2; packages/core/src/security/resolve-authz-context.request-rounds.test.ts +182/-0; packages/core/src/security/resolve-authz-context.ts +223/-71; packages/core/src/security/resolve-localization-cache.test.ts +189/-59; packages/metadata-protocol/src/meta-overlay-cache.test.ts +154/-15; packages/metadata-protocol/src/meta-overlay-cache.ts +135/-13; packages/metadata-protocol/src/protocol.datasource-delete-prolongation.test.ts +64/-29; packages/metadata-protocol/src/protocol.item-read-overlay-cache.test.ts +189/-0; packages/metadata-protocol/src/protocol.ts +46/-15; scripts/engine-double-contract.pinned.json +5/-0. Total +1218/-211.", "files_changed": [ ".changeset/10757-request-rounds-core.md", ".changeset/10757-request-rounds-metadata-protocol.md", "content/docs/concepts/metadata-lifecycle.mdx", "content/docs/deployment/environment-variables.mdx", "packages/core/src/security/resolve-authz-context.request-rounds.test.ts", "packages/core/src/security/resolve-authz-context.ts", "packages/core/src/security/resolve-localization-cache.test.ts", "packages/metadata-protocol/src/meta-overlay-cache.test.ts", "packages/metadata-protocol/src/meta-overlay-cache.ts", "packages/metadata-protocol/src/protocol.datasource-delete-prolongation.test.ts", "packages/metadata-protocol/src/protocol.item-read-overlay-cache.test.ts", "packages/metadata-protocol/src/protocol.ts", "scripts/engine-double-contract.pinned.json" ], "deviations": [ "Worktree: the shared primary checkout had claude/issue-10757-request-rounds checked out, so the worktree ../objectstack-issue-10757 was cut from origin/main 913fd6df8a under the temporary local branch tmp/issue-10757-request-rounds and pushed to claude/issue-10757-request-rounds (as the dispatch prescribes). The worktree and the temporary local branch are removed.", "File surface widened past the claim's fence, by measurement: (a) leg 6 also narrows #11967's overlay-cache retirement (list read included) from the global write epoch to sys_metadata writes plus non-write epoch reasons — after covering the by-name read, the measured run still re-read sys_metadata after every unrelated write; #11633 §4's accepted leg-D design names 'any engine-seam write to sys_metadata' as the trigger; (b) two hand-written docs pages whose text stated the old 'any engine write retires it' rule (content/docs/deployment/environment-variables.mdx, content/docs/concepts/metadata-lifecycle.mdx); (c) scripts/engine-double-contract.pinned.json, learned by the gate's own --write. Nothing in @objectstack/rest or plugin-auth is touched, and no C8 NULL-organization region is edited (grantAppliesInTenant / grantAnchorsPlatformStanding / the organization read's filter unchanged and pinned).", "Leg 4 parallelization widens the sys_metadata_activation name IN list by the one name admin_full_access in one case (an organization-owned admin_full_access grant that does not anchor); no verdict reads it, envelope unchanged, pinned and stated in the changeset. Recorded here because the dispatch says no predicate changes; the filter shape and the organization read are byte-identical.", "Write budget: git push ran 6 times to the one branch (the empty-branch probe, WIP pushes before long steps per AGENTS.md, the final push); REST writes are the 2 relay strokes. No other write.", "Measurement instrumentation was temporary and dist-only: driver-sql and core sources were edited, built (driver-sql with OS_SKIP_DTS=1, which removed its .d.ts until the clean rebuild) and reverted blob-equal; for core, check-dev-prereqs --stamp was hand-run after the revert so pnpm dev accepted the instrumented dist (the hand-stamp shape that script's header names as unobservable). Both dists were rebuilt clean afterwards (0 markers, .d.ts present, check-dev-prereqs freshness line clean). Nothing instrumented went through turbo or was committed.", "The private PostgreSQL cluster lived under /var/lib/postgresql (the postgres user cannot traverse the scratchpad); stopped and deleted. Three of my early dev servers outlived their runs (my first run script recorded the wrong process-group id); found by the ports I picked and stopped with kill on lsof -ti tcp:PORT.", "PR activity: not subscribed — os-dev.md's dispatch contract overrides the platform's auto-subscribe posture; CI convergence is the PM's.", "The first 70 derived families ran at the merge commit bc343e9b9; the two later commits change only scripts/engine-double-contract.pinned.json and content/docs, whose added families (9 + 30) ran at their heads, and check:engine-double-contract was re-run after the ledger commit. The first 70 were not re-run at 4746b38c1." ], "mcp_calls": "0 — no MCP GitHub tool was called (one ToolSearch loaded the mcp__github__issue_read schema; it was never invoked). Card, comments and PR were read through unauthenticated public REST GETs.", "api_writes": "2 relay strokes as objectstack-fleet[bot] via scripts/pm/with-fleet.sh --via dispatch (each a POST /repos/objectstack-ai/objectstack/dispatches): (1) pr_create — POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/24533/assignees [os-project-manager], read back 13403 bytes sent = stored; (2) comment — POST /repos/objectstack-ai/objectstack/issues/10757/comments (this os-dev-report). Plus git push to claude/issue-10757-request-rounds (not REST).", "open_questions": [ { "question": "Cold leg: should the request-scoped memo's write observer be registered at boot, so the first request after boot stops resolving grants twice (measured 23/10 -> 16/8, once per process)?", "options": [ "A — leave it (this PR): the guard stays, the first request pays 7 queries / 2 rounds more", "B — export a prime from core and call it from a boot seam (plugin-security start or objectql's engine construction); the attaching scope still stores nothing, so the memo's argument stays whole" ], "recommendation": "A. Business need: real but once per process. Long-term: B adds a cross-package boot call whose only job is a one-request saving. AI-safety: neither option can be written wrong silently, since a forgotten prime degrades to today's safe path. Startup focus: a one-time saving does not earn a new seam. Revisit only if cold-start latency is measured as a real cost on cloud." }, { "question": "Leg 4's duplicate sys_user read (better-auth's session-to-user read and resolveUserAuthzGrants' getUserRow in the customSession call): who carries it?", "options": [ "A — #24515's lane (plugin-auth): the customSession callback hands its session user's row to resolveUserAuthzGrants through a core seed added in the same PR; it still needs ai_access, which better-auth's user deliberately omits, so the seed must be the stored row or ai_access must be read there", "B — leave it paid" ], "recommendation": "A, scoped together with leg A's join: both are plugin-auth's reads of sys_user, and adding the core seed without its consumer would be a declared-but-unused option." }, { "question": "Leg 6 also changed what retires #11967's overlay cache for the LIST read (sys_metadata writes plus non-write epoch reasons, not every write). Is that accepted as part of this card?", "options": [ "A — keep (this PR)", "B — split: keep only the by-name coverage, leave the list read on the global epoch" ], "recommendation": "A. It is the trigger #11633 §4's accepted leg-D design names. Without it, the by-name cache this card needs is retired by the outbox pollers and by every data write. The metadata bridge's remote bump still retires it, pinned by the prolongation suite's ablation." } ], "out_of_scope_findings": [ "carrier: #24515 · noted, not filed — the duplicate sys_user read (r2 better-auth join and r3 getUserRow on every authenticated request) needs a plugin-auth seed; dedupe words: getUserRow, customSession, sys_user duplicate, seedUserRow, ai_access", "carrier: none (承接者:无) · noted, not filed — the first request after boot still resolves grants twice (memo observer attached in that request); one-time 7 queries / 2 rounds; ruled load-bearing here; dedupe words: attachedHere, request-grants-memo cold, observer registration boot", "carrier: none (承接者:无) · noted, not filed — packages/rest/src/rest-data-read-one-overlay-read.test.ts's header says 'nothing is kept between requests'; it remains true for its seam-less engine double (the cache declines there) but no longer describes a real engine, where the served by-name read is cached with write-invalidation; Acceptance-notes material only" ], "not_measured": [ "cloud#1521's gate and cloud#1518's placement — out of reach locally; this reading claims neither", "SQLite (the dev default), multi-node, concurrent load, API-key principals", "CI check-runs on 4746b38c1 — in_progress at report time; convergence is the PM's" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
os-dev-report
{ "issue": 10757, "status": "done", "round": "fix round 1 (seat message 2026-10-19T13:13Z, session_01JtSQQ3EWsbNPzyYMug1tXy)", "branch": "claude/issue-10757-request-rounds", "pr": "https://github.com/objectstack-ai/objectstack/pull/24533", "head": "084e79e16 (was 4746b38c1); no merge of origin/main — the PR reads mergeable: true, so there is no conflict", "session": "session_011Xuc8buBLe9f15TPKBjPKS", "premise_still_valid": true, "summary": "Test Core (5/6)'s red was the seat's diagnosis exactly. environment-overlay-five-types.test.ts read getMetaItem (the control, which now fills the by-name overlay cache), then stored the overlay with driver.create('sys_metadata', …), straight past the engine. No middleware saw that write, so the second read served the cached pre-overlay rows. Fixed at the cause: storeEnvironmentRow now inserts the same row shape through engine.insert under a system context. There is still no write door (saveMetaItem) and the control read still comes first. The docblock says why the row goes through the engine. No cache was disabled, no TTL changed and no assertion weakened. The record notes are carried: the docs now say the retirement happens when the write's statement completes and name the transaction window before the commit; the rest pin's 'nothing is kept between requests' header now says why that holds only on its seam-less engine.", "assertion": { "before": "pnpm exec vitest run --maxWorkers=2 src/environment-overlay-five-types.test.ts (packages/objectql, head 4746b38c1) :: exit 1 — 10 failed, both topologies x five types; 'AssertionError: expected 'Packaged' to be 'Environment overlay' // Object.is equality' (:356)", "after": "same command at 084e79e16 :: exit 0 — Tests 26 passed (26)" }, "sweep": "git grep over *.test.ts / *.spec.ts for tests that write sys_metadata, sys_setting or sys_platform_setting straight into a driver: driver/d/entry/settingDriver/wrapped .create/.update/.delete/.execute, raw INSERT/UPDATE/DELETE SQL, knex(table), stores.get(table).set. Only environment-overlay-five-types.test.ts wrote after a read the new caches serve; it is fixed. Unaffected: (1) objectql default-record-page-save-door.test.ts — storeRow runs on a freshly booted engine BEFORE that case's first read, so the cache is empty; (2) runtime metadata-list-ambient-vs-bare-transaction.integration.test.ts — seeded through the driver before the engine exists, then read through MetadataManager's loader, not the protocol's served read; (3) metadata database-loader-21828-one-content-hash.test.ts — the metadata package's loader, not the protocol cache; (4) cli migrate/plan journal-mode, schema-migrate.host-composition and schema-migration-plugins write-guard — driver-write refusal probes with no served read after them; (5) cli secret orphans/rewrap driver-contract — sys_setting rows for the secret tooling, which never call resolveLocalizationContext; (6) service-settings settings-engine-id-fold-wins / settings-secret-rotation — the settings service's own reads, not the localization cache; (7) the cli migrate SQL suites (meta-stored-legacy-organization, preview-read-only, security-catalog-overlays, organization-ownership-apply/plan, permission-set-zero-row, security-catalog-echo-env-kernel) and metadata-protocol migrations/overlay-index — they seed before the stack boots; the one served read among them (meta-stored-legacy-organization :304) comes after the boot.", "tests": "Full suites, as Test Core runs them, each through scripts/pm/os-verify-lock.sh, exit captured from the command: pnpm --filter @objectstack/objectql test :: exit 0 (446 files / 8392 tests); pnpm --filter @objectstack/runtime test :: exit 0 (422 files; 6645 passed, 19 skipped); pnpm --filter @objectstack/rest test :: exit 0 (300 files; 6095 passed, 326 skipped — the suite's own conditional skips, none in a file this round edits beyond one header comment); pnpm --filter @objectstack/plugin-security test :: exit 0 (188 files; 3754 passed, 45 skipped); pnpm --filter @objectstack/service-settings test :: exit 0 (51 / 881); pnpm --filter @objectstack/plugin-hono-server test :: exit 0 (34 / 422); pnpm --filter @objectstack/mcp test :: exit 0 (40 / 479). From the first round, unchanged by this one: core test 106 / 2580 and test:repo 6 / 82, metadata-protocol 248 files / 20723 tests. Typecheck: pnpm --filter @objectstack/objectql typecheck :: exit 0; pnpm --filter @objectstack/rest typecheck :: exit 0. Build: turbo run build 76/76 (all cached) at 4746b38c1 before the fix; this round changes test files and docs only.", "gates": "Families this round's four paths reach (dispatch-gates --commands with those paths), plus the two families the full derivation newly lists (check-engine-split-ratio --days 90 and --self-test): 86 commands run at 084e79e16, every exit code captured before any pipe, all exit 0. Full derivation (no paths): 111 families; --ran over this round's results and the first round's (the other 25 ran at 4746b38c1 or earlier, on paths this round does not touch) gives '111 derived famil(ies) accounted for — 111 run, 0 NOT-MEASURED (a DERIVED zero — all 111 recorded an exit code and none of them is 3)'. CI on 084e79e16: just pushed, in progress; the PR reads mergeable: true.", "files_changed": [ "packages/objectql/src/environment-overlay-five-types.test.ts (+16/-7)", "packages/rest/src/rest-data-read-one-overlay-read.test.ts (+6/-2, header comment only)", "content/docs/deployment/environment-variables.mdx (+1/-1)", "content/docs/concepts/metadata-lifecycle.mdx (+6/-3)" ], "line_budget": "none set; this round +29/-13 over 4 files (above).", "deviations": [ "Record note ② asks the docs to say 'once the write's transaction commits'. Written instead to the mechanism's real point: the retirement happens when the write's STATEMENT completes. That is the commit outside a transaction. Inside an engine transaction it comes before the commit, and a read that lands between the two can keep the pre-commit rows until the next sys_metadata write or the TTL. 'Commits' would have stated a guarantee the middleware does not give. This is the settle-to-commit window of record ①, now named in both docs pages.", "PR body not edited, under os-dev's no-PATCH rule. Owed to the seat's body patch, together with the closing-keyword patch from the previous message: an Acceptance-notes bullet — 'The localization and overlay caches are retired when a watched write's statement completes; inside an engine transaction that precedes the commit, so a read between the two can keep the pre-commit rows until the next watched write or the TTL (the epoch reading this replaced had the same window).'", "Worktree recreated from origin/claude/issue-10757-request-rounds under the temporary local branch tmp/issue-10757-request-rounds (the primary checkout holds the branch name); removed after the push, as before." ], "mcp_calls": "0 MCP GitHub calls this round. 1 claude-code-remote send_message in the previous round, to the seat. Reads this round were public REST GETs.", "api_writes": "This round: 1 git push to claude/issue-10757-request-rounds (4746b38c1 -> 084e79e16), plus 1 relay stroke as objectstack-fleet[bot] (a POST /repos/objectstack-ai/objectstack/dispatches executing POST /repos/objectstack-ai/objectstack/issues/10757/comments — this report). Cumulative: 2 pr_create-and-comment strokes in round 0, this comment, and 7 pushes.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 19, 2026
Landed ·
domain:engineseat 1 ·session_01JtSQQ3EWsbNPzyYMug1tXy· 2026-10-19T15:24ZCONTRACT_REVIEW_TIERrecord 6268067889 PASS on4746b38c1. CI note 6268090803 (Test Core (5/6)), fixed at the cause in fix round 1. Delta note 6269310900 on084e79e16: the record carries. ACCEPT 6270035817. Not governed.gh-readonly-queue/main/pr-24533-*branch remains.origin/main5a871e4e41is onorigin/main. It carries PR #24533's 15 files, +1243 / −220.completedthroughFixes #10757;pm:dispatchedis cleared.What
mainnow holds, per authenticatedGET /api/v1/data/OBJECT?$top=1, by 6255731843's method on local PostgreSQL:sys_settingorsys_platform_setting, plus every non-writeepoch bump. An idle boot's outbox pollers no longer make it miss. A failure entry keeps its TTL-only rule.getMetaItemread, which the REST exposure gate makes on every/datarequest, takes its stored rows from authz caching leg D:getMetaItemsoverlay cache keyed on the registry epoch — resolve the SchemaRegistry-hydration trap explicitly #11967's overlay cache. Onlysys_metadatawrites through the engine retire it.sys_sessionthensys_userin two sequential rounds, because better-auth'sadvanced.database.joinsis left unset and its fallback join runs (leg A of #10757) #24515, closednot_planned);attachedHereguard is load-bearing);sys_userread (plugin-auth's; it saves a query, not a round).Downstream:
main.repo:cloud#2seat is pointed at this landing for cloud#1518 and cloud#1521, with no claim about either.0(Design: cross-request caching for the authenticated request path (tranche 2 of #10757) — write-invalidation-first, short-TTL fallback, configurable staleness window #11633 Fork 4, the maintainer's).The dev session
session_011Xuc8buBLe9f15TPKBjPKSis archived.Generated by Claude Code