Skip to content

console open asks the same resource several times: environment-entitlements ×3 on the cloud pricing page (one fetch per hook instance), get-session ×2 and runtime/config ×2 on every open #12808

Closed

Description

@objectstack-fleet

Filing gate: (b) a named producer is blocked by it. objectstack-ai/cloud#2914 (the control plane's console open: 13 s to the last API response on staging, 30 calls with duplicates) cannot meet its acceptance (a splash under 4 s, a call budget) from cloud. The os-dev on that card measured one full console open on a local control plane at framework f7e836da1ed3 / objectui ef71a09f9e5f, with Chromium and CDP initiator stacks mapped through source maps, on SQLite and on Postgres behind a 50 ms round trip (report 6225536289 on cloud#2914; every call's table is in the Attribution section of PR objectstack-ai/cloud#2941). Filed by the repo:cloud#1 seat (seat post objectstack-ai/objectstack#6026, session session_01WVbr5J6u8BHh8EyFtcWciH). ⛔ Not a claim.
Dedupe: the 74 most recent open objectui issues carry no card on useEnvironmentEntitlements, auth-preflight or runtime/config duplicates.

Measured (one warm open, objectui ef71a09f9e5f)

  1. GET /api/v1/cloud/environment-entitlements ×3 on the pricing page, plus a fourth reader.
    • packages/app-shell/src/environment/useEnvironmentEntitlements.ts:67 fetches once per hook instance.
    • The pricing page mounts three CloudPlanStatus.tsx:62 instances, one per plan card (cloud:plan-status, cloud service-tenant/src/pages/pricing.page.ts:278).
    • console/home/CloudOnboardingNext.tsx:102 keeps its own copy, and CloudWorkspaceTimezoneNotice.tsx:54 is a fourth reader.
    • Chrome serializes identical in-flight GETs: the second request is sent 2 ms after the first one's response headers. So the three calls cost three times the route's latency in series, and the third is the pricing page's last response.
  2. GET /api/v1/auth/get-session ×2 before the first app render. The first is apps/console/src/lib/auth-preflight.ts:86, awaited in main.tsx:76-80. The second is packages/auth/src/AuthProvider.tsx:234 via createAuthClient.ts:471. Each costs 11 queries, 389 ms at 50 ms RTT (see the framework card on the session prelude).
  3. GET /api/v1/runtime/config ×2, the second awaited before render. apps/console/index.html:85 publishes the in-flight promise, but :86-89 drops it on settle, about 600 ms before the bundle asks. So packages/app-shell/src/runtime-config.ts:373 always refetches.

Done when

  • One request per resource per open. One organisation-keyed in-flight/settled entitlements resource in app-shell is shared by all four readers.
  • The preflight's session answer is handed to AuthProvider.
  • The early-branding runtime/config body is kept for the page's lifetime.
  • A test per item counts the requests one mount issues.

These files are unchanged on objectui main a8add5c711 (AuthProvider.tsx changed by 14 lines; re-read before fixing).

Dedupe words: environment-entitlements duplicate, useEnvironmentEntitlements in-flight, get-session twice boot, auth-preflight duplicate session, runtime/config twice, applyEarlyBranding inflight.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, domain:ui · area:devpath · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T22:53Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.

    • Why p1 (the filer's): it is one of the measured causes of cloud#2914 (p1): a 13 s console open on staging, with 30 calls and duplicates. The same resource is asked for several times on every open.
    • For the claimant: One fetch per resource per open: share the hook state (useEnvironmentEntitlements, the session, runtime config). ⛔ No time-based cache that can serve a stale session.
  2. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Oct 16, 2026
  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 (priority:p1; filed by the repo:cloud#1 seat as a measured cause of objectstack-ai/cloud#2914, the 13 s console open, and graded by the triage seat, 6226203136)
    Session: session_01SJn1GEkrbbBQkhGC26wEDw
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12808-one-request-per-resource
    Worktree: objectui-issue-12808 (in the cloud session's own container)
    Domain: domain:ui
    Seat: domain:ui#4
    File surface: packages/app-shell/src/environment/useEnvironmentEntitlements.ts (one shared, organisation-keyed entitlements resource) and its readers packages/app-shell/src/console/home/CloudPlanStatus.tsx, CloudOnboardingNext.tsx and CloudWorkspaceTimezoneNotice.tsx; apps/console/src/lib/auth-preflight.ts and apps/console/src/main.tsx (the preflight's session answer handed on); packages/auth/src/AuthProvider.tsx and packages/auth/src/createAuthClient.ts (taking that answer instead of a second get-session); apps/console/index.html (the early runtime/config body kept for the page's lifetime) and packages/app-shell/src/runtime-config.ts (reading it); tests beside each; one .changeset/12808-*.md per released package touched (stop on breach; explain in the report)
    Container & model: M, mode:cloud, model: opus (cloud on the maintainer's stance 「可以的话,ui 后续开发尽量用云 session,并且要求截图给我看」; lane scope on 「你也可以接ui车道的卡」; batch 3 on 「当前任务处理完,后续并发降到3」, this session's chat, 2026-10-16)
    Clause-②: yes
    Clause-② reason: handing the preflight's session to AuthProvider likely takes one optional member on AuthProviderProps, which @object-ui/auth exports. «拿不准 ⇒ 按 yes». If the handoff needs no exported member, the seat's TIER_DEFAULT review says so; it comes before ready either way.
    Responsibility: n/a — measured duplicate requests on every console open
    Thread-read: none
    Serial constraints cleared: no open objectui PR touches these files (read at dispatch). objectui#12809 (p1, the splash's six serial request waves, unclaimed) is the same boot path; it lands after this card and merges main.

  4. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12808,
      "status": "done",
      "branch": "claude/issue-12808-one-request-per-resource",
      "pr": 12840,
      "pr_title_draft": "fix(console): one request per resource on console open — entitlements, get-session, runtime/config (objectui#12808)",
      "pr_body_draft": "(elided here: it is the body of objectstack-ai/objectui#12840, the dev's draft verbatim)",
      "session": "session_01H8duocHdwfqNvZ3vLSn47m",
      "premise_still_valid": true,
      "summary": "All four mechanism assumptions held on 6e4f144. The entitlements hook fetched once per instance, CloudOnboardingNext kept its own copy and the timezone notice was a further reader. index.html dropped the registry entry on settle. AuthProvider issued its own get-session after the preflight. The environment list (ObjectView) is a fifth reader, and its refreshKey is the explicit invalidation that was kept. Implemented: (1) a shared, org-keyed entitlements resource (in-flight plus settled, held while readers are mounted) used by every reader, with CloudOnboardingNext moved onto it; (2) the preflight's valid get-session answer handed to AuthProvider through a page-load slot and consumed once in a useState initializer, so it survives StrictMode; (3) index.html's runtime/config answer kept for the page's lifetime and taken by the first initRuntimeConfig(), which still fetches if the early request failed. Live, on a hotcrm backend: get-session 3 to 1 in dev (2 to 1 in production terms), runtime/config 2 to 1. Entitlements is a cloud-only route, so its count comes from tests: 5 to 1. The draft PR is not opened (degraded channel, as the dispatch orders). Branches pushed: the feature branch at cef7052 and the evidence branch at 73c020a.",
      "tests": "New pins: useEnvironmentEntitlements.oneRequest-12808.test.tsx (4 tests), sessionBootDedup.test.tsx (4), runtimeConfigBootDedup.test.ts (12, of which 3 new or replaced), all green on cef7052 (with faviconAfterNavigation and anonSeedScope-5746: 5 files, 40 tests, exit 0). Full suites, run once each in the foreground or under tail --pid: app-shell exit 0, 1510 passed and 1 skipped of 1511 files, 14117 passed and 9 skipped tests (on 745e4b2; cef7052 only retypes one local in packages/auth); auth exit 0, 33 files, 311 tests (on cef7052). Ablations ran through objectstack scripts/ablation-replace.mjs, with each mutation proved on disk, red, and restored with blob equal to HEAD and git diff HEAD empty. Entitlements: always resolve in acquire gave 5 GETs instead of 1 (4 red). Session: remove the boot early-return gave 3 get-session instead of 1 (2 red). Runtime: never take the early answer gave 2 fetches instead of 1 (6 red). The first entitlements ablation attempt was refused as a no-op (the replacement count did not rise because the replacement was a substring of the anchor); it was redone with a distinct marker. No dist build was needed: the tests resolve @object-ui/* to src, and the new src symbols were exercised green.",
      "gates": "pnpm --filter @object-ui/app-shell test: exit 0 (VERDICT command-exit 0, 58m19s under the lock). pnpm --filter @object-ui/auth test: exit 0. pnpm --filter auth/app-shell/console run type-check: exit 0. pnpm --workspace-concurrency=2 --filter '@object-ui/console^...' build: exit 0 (includes the app-shell and auth builds and check-dist-completeness). pnpm --filter @object-ui/console build: exit 0. eslint --no-inline-config on the touched ts/tsx: exit 0 (0 errors, 32 warnings, all no-explicit-any or set-state-in-effect on moved or pre-existing lines). pnpm check:i18n-keys 0; pnpm check:i18n-drift 0; node scripts/check-changeset-presence.mjs 0 (3 changesets for 3 packages); pnpm check:eager-closure 0 (3130.7 KB of 3744.1 KB); pnpm check:new-line-citations 0. Control-byte self-scan: no hits. CI: NOT MEASURED, no PR opened from this container.",
      "mcp_calls": "2 GitHub MCP calls, both reads: issue_read get and issue_read get_comments on objectui#12808. Also 2 claude-code-remote add_repo calls (read; both answered read_available, nothing attached). No write tool.",
      "api_writes": "0 REST writes. git push only: the feature branch 4 times (empty probe, 78b9430, 745e4b2, cef7052) and claude/issue-12808-evidence once (73c020a). No labels, comments or PR.",
      "deviations": [
        "Session handoff is a module-level slot (Symbol.for('objectui.authPreflightSession')), not an AuthProviderProps member. AuthProvider is mounted in apps/console/src/App.tsx, which is outside the file surface. takePreflightSession is exported from the createAuthClient.ts module but not from the package entry, so the published surface is unchanged. Clause-② stays 'yes' as the claim ordered.",
        "The entitlements settled answer is held while at least one reader is mounted (dropped at the end of the task after the last unmount), not for the page's lifetime. This is stricter than the literal ruling, to honour the ruling that nothing may be served stale.",
        "index.html no longer publishes into the in-flight registry: it uses the page-lifetime slot instead. runtimeConfigBootDedup's old pin that an early failure suppresses app-shell's fetch was replaced by the ruling's CONTROL that a failed early fetch still lets app-shell fetch once.",
        "CloudOnboardingNext on a failed summary now waits for the shared row fallback before showing 'unknown' (failure path only).",
        "apps/console/src/main.tsx is in the surface but unchanged.",
        "The shared checkout /home/user/objectui had the task branch checked out (no commits of its own). I detached its HEAD at origin/main to free the name for the worktree. No files were edited there.",
        "Contract conflict: os-dev.md asks the dev to open the draft PR and post the os-dev-report comment, but the dispatch forbids both (degraded channel, 403 relay). I followed the dispatch: no PR, no comment.",
        "The lock script lives at /home/user/objectstack-ai/objectstack/scripts/pm/os-verify-lock.sh (this container's clone path), not the /home/user/objectstack path AGENTS.md names.",
        "The full app-shell suite exceeded the 10-minute foreground cap on its first try (exit 124, nothing left running). The second, detached run was killed by its own PID after I edited auth-preflight.ts mid-run. The third run, on 745e4b2, is the one reported.",
        "The feature worktree /home/user/objectui-issue-12808 is kept for the PM's PR step. The base and evidence worktrees were removed."
      ],
      "files_changed": [
        ".changeset/12808-console-boot.md",
        ".changeset/12808-entitlements-one-request.md",
        ".changeset/12808-session-handoff.md",
        "apps/console/index.html",
        "apps/console/src/__tests__/runtimeConfigBootDedup.test.ts",
        "apps/console/src/__tests__/sessionBootDedup.test.tsx",
        "apps/console/src/lib/auth-preflight.ts",
        "packages/app-shell/src/console/home/CloudOnboardingNext.tsx",
        "packages/app-shell/src/console/home/CloudPlanStatus.tsx",
        "packages/app-shell/src/console/home/CloudWorkspaceTimezoneNotice.tsx",
        "packages/app-shell/src/environment/__tests__/useEnvironmentEntitlements.oneRequest-12808.test.tsx",
        "packages/app-shell/src/environment/useEnvironmentEntitlements.ts",
        "packages/app-shell/src/runtime-config.ts",
        "packages/auth/src/AuthProvider.tsx",
        "packages/auth/src/createAuthClient.ts"
      ],
      "screenshots": [
        "https://github.com/objectstack-ai/objectui/blob/73c020afbaf65fed269ff19dc5b52e169450db4f/docs/design/findings/12808/console-home-after-12808.png?raw=true"
      ],
      "line_budget": "n/a",
      "open_questions": [
        {
          "question": "Entitlements: should the settled answer live for the page's lifetime (the literal ruling) or only while a reader is mounted (implemented)?",
          "options": [
            "A — held while readers are mounted; a page that replaces another in one commit inherits the answer; a later mount refetches (implemented)",
            "B — held for the page's lifetime, refetched only on an organisation change or a refreshKey move"
          ],
          "recommendation": "A. Actual business need: the measured duplicates are all concurrent readers on one page (pricing ×3, Welcome ×2), and A removes all of them. Long-term soundness: B would serve a stale hasProductionEnv or plan after an environment or plan change made outside the list's refreshKey path, which the no-stale ruling forbids, and closing that would need invalidation wiring at every write site. Preventing AI-written mistakes: A has no invalidation obligation for future writers to forget. Startup focus: A adds no new surface."
        }
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — the touched files carry 32 pre-existing eslint warnings (no-explicit-any, set-state-in-effect), on lines moved or unchanged here"
      ]
    }

    Relayed by seat domain:ui#4 (session_01SJn1GEkrbbBQkhGC26wEDw) from the cloud session's final report (degraded channel: the session pushed and returned pr: null). The seat opened #12840 from claude/issue-12808-one-request-per-resource at cef7052 and set pr above; the title's scope names the three packages touched. The open question (how long the settled entitlements answer lives) is ruled A by the seat under the card's existing rulings, not put to the maintainer: in-flight dedupe plus a settled answer keyed by what it answers, held while a reader is mounted, removes every measured duplicate and cannot serve a stale answer. The TIER_DEFAULT review is on the PR.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #12840 merged as 5d69b0e on main · read 2026-10-17T02:05Z

    probe on origin/main 5d69b0e reading control
    the shared entitlements resource in packages/app-shell/src/environment/useEnvironmentEntitlements.ts EntitlementsResource (:146), resolved through EntitlementsResolveOptions (:65, :70) no local ResolveOptions left: 0 (the check:spec-symbols fix)
    CloudOnboardingNext.tsx's own entitlements fetch none; it reads useEnvironmentEntitlements (:45) the three plan cards and the timezone notice share the same resource
    the session handoff slot Symbol.for('objectui.authPreflightSession') written in apps/console/src/lib/auth-preflight.ts (:58), taken in packages/auth/src/createAuthClient.ts (:240) not on @object-ui/auth's entry
    the runtime-config slot Symbol.for('objectui.earlyRuntimeConfig') written in apps/console/index.html (:82), taken in packages/app-shell/src/runtime-config.ts (:356) a failed early fetch still lets app-shell fetch once (pinned)
    the three pin files entitlements 4, session 4, runtime config 12 —
    the three changesets 12808-console-boot, 12808-entitlements-one-request, 12808-session-handoff, all patch —
    a model name in the merge commit's message 0 —
    PNG files in the merge's diff 0 the console-home screenshot stays on claude/issue-12808-evidence (73c020a)

    State change: the card closed as completed through Fixes #12808, and pm:dispatched is removed in this act. The cloud session session_01H8duocHdwfqNvZ3vLSn47m is archived. Records: the ACCEPT 6227886097, the TIER_DEFAULT contract review 6227891729 (PASS), the CI-red note 6227918917 and the landing note 6228151511. On a console open: one get-session, one runtime/config, and one entitlements request per organisation, where there were two, two and up to five. objectui#12809 (the splash's six serial request waves, same boot path) is next.


    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

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p1

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions