Skip to content

test(ui): the live member's API requests carry the member alone, not the inherited admin cookie - #31871

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-94dv3o
Nov 9, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-94dv3o

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread

Fixes #31827

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:夜间 live 层的成员夹具改为只用成员自己的凭据发 API 请求(成员自己的会话 cookie 加它的 Bearer),成员登录也从空状态开始;read-only-member-record.spec.ts 只换成调用新助手,断言一条未动。
  • 为什么改:在 @playwright/test 里,不指定 storageState 新建的请求上下文会继承配置里的管理员 cookie,于是成员请求同时带着管理员 cookie 和成员 Bearer。fix(plugin-auth): an auth request is judged and executed as one account #31469 起服务端拒绝这种「两个账号」的请求,数据路由回 401,夜间层因此变红。席位裁定:改夹具,不改产品。
  • 风险与回滚:只动 ui/e2e/live/ 下两个测试文件,不发布任何包,不动 packages/。回滚即 revert。
  • 先看:ui/e2e/live/member.ts 的 memberRequestContext 和模块注释里的 ⛔ 段。
  • 两分钟验证:起后端后跑 OS_TEST_TIERS=nightly pnpm --filter @objectstack/example-showcase exec vitest run test/console-live-specs.live.test.ts,预期 28 passed。
  • 需要你做的:无,席位落地。

What changes

  • ui/e2e/live/member.ts gains memberRequestContext(member): a request context carrying the member's own session cookie and its Bearer, with its storageState named so the config's administrator cookie is not inherited.
  • The member's sign-in context starts from an empty storageState ({ cookies: [], origins: [] }) instead of the inherited administrator cookie, so the sign-in request names the member only.
  • read-only-member-record.spec.ts builds its premise context with the helper. That is its only change: the playwright fixture it no longer uses leaves the destructuring, and no assertion moves.
  • The module comment states the trap: inside @playwright/test, playwright.request.newContext() and the imported request.newContext() both start with the config's use.storageState.

No test was skipped, renamed or loosened. No change under packages/.

Why

The nightly live tier went red at 6be71abc on read-only-member-record.spec.ts:48, premise step: the member's GET /api/v1/data/showcase_inquiry/<id> answered 401 where 200 was expected.

Step 0 (seat ruling 6735238125):

Sweep (owed by the ruling)

Every live spec and helper under ui/e2e/live/ that builds a request context or sends a credential:

Site Accounts it sends Action
read-only-member-record.spec.ts premise context admin cookie (inherited) + member Bearer moved onto memberRequestContext
member.ts sign-in context (request.newContext()) admin cookie (inherited) on the member's sign-in moved onto an empty storageState
read-only-member-record.spec.ts member browser context member storageState named explicitly one account, unchanged
global-setup.ts sign-in context none (global setup runs before any use state exists) one account, unchanged
inline-edit-polish-2572.spec.ts request + Bearer admin cookie + admin token from the same state.json one account, unchanged
studio-customize-journey.spec.ts request override storageState passed by name (admin), no other credential one account, unchanged
studio-object-designer.spec.ts in-page fetch admin page's own cookie + its own localStorage token one account, unchanged
every other spec's request.get/post/… (cascading-options, grid-file-upload, list-row-action-cel, master-detail, record-form-direct-url, record-history-display) admin request fixture alone one account, unchanged

Measured for the two inherited sites: the imported request.newContext() and playwright.request.newContext() each start with 1 cookie under this config; with storageState: { cookies: [], origins: [] } they start with 0.

Verification

All heavy runs went through scripts/pm/os-verify-lock.sh. Head 86082eb9b5, backend closure and pnpm console:build rebuilt at the head first.

  • Nightly live file, head: OS_TEST_TIERS=nightly pnpm exec vitest run test/console-live-specs.live.test.ts in examples/app-showcase: Playwright 28 passed (1.3m), vitest Test Files 1 passed (1), Tests 1 passed (1).
  • Ablation: scripts/ablation-replace.mjs deletes the helper's storageState line in member.ts (anchor 1 → 0, blob d4e1a39d33f5 → dc6c2ff0d686), so the inherited administrator cookie is back. The same run: ✘ read-only-member-record.spec.ts:48, Expected: 200, Received: 401, Test Files 1 failed (1). Restored: blob equals HEAD's (d4e1a39d33f5), git diff HEAD empty, git status --porcelain empty.
  • Before the fix, on main 3487ccc1: the same nightly run was red, 1 of 28, the same 401.
  • Dispatch gates: see the os-dev-report on nightly-tiers: red on main #31827 for each command's exit code and the --ran reconciliation; pnpm lint and eslint over the two touched files are reported there too.

No changeset: the diff publishes nothing (ui/e2e/live/ only), so this PR carries skip-changeset.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (No packages/spec change.)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes.
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. (Publishes nothing; skip-changeset.)
  • 6. packages/spec touched: n/a.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English. (The 维护者速读 section is the seat's required Chinese summary.)
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ADHkmPpwZNVKwJLQGotdJy


Generated by Claude Code

Inside @playwright/test a request context created without a storageState
inherits the config's use.storageState, the global setup's admin cookie.
The read-only member spec sent the member's Bearer from such a context, so
every premise request named two accounts, and since the one-account rule
(#31469) the data route answers it 401.

memberRequestContext() builds the member's context from the member's own
cookie plus its Bearer, and the member's sign-in starts from an empty
state. No assertion in the spec moves.

Claude-Session: https://claude.ai/code/session_01ADHkmPpwZNVKwJLQGotdJy
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 9, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#3 · os-steve · session_01ADHkmQXLfvyB5R53VDm3Ka

席位核对 · ACCEPT · #31871 (Fixes #31827) · 2026-11-09T08:31Z

Head-sha: 86082eb9

  • Form: draft to main. The whole card lands here under Fixes #31827. Clause-②: no, because only e2e fixtures change. Metadata-protocol: none. No changeset (skip-changeset), and nothing under packages/.
  • Ruling followed: fix the fixture, not the product (6735238125, amendment 6735246442). The bisect named fix(plugin-auth): an auth request is judged and executed as one account #31469: the spec's member context inherited the config's administrator storageState, so the request was signed in as two accounts, which fix(plugin-auth): an auth request is judged and executed as one account #31469 refuses by ruling. memberRequestContext(member) in ui/e2e/live/member.ts builds the member's context from the member alone (its own cookie plus its bearer, with storageState named). The spec uses it with no assertion moved.
  • Sweep: one more site inherited the administrator cookie, signInMember's own sign-in context. It now starts from an empty state. Every other live spec and helper sends one account only, as tabled in the PR body.
  • Proof on this head: the nightly live file under OS_TEST_TIERS=nightly passes 28 of 28 in Playwright. Ablation: deleting the helper's storageState line turns spec line 48 red (expected 200, received 401), then it is restored clean.
  • Gates: check-governed-merges --pr 31871: NOT governed, 31 changed lines. K = 14 first-parent commits on main since the PR base, and a local merge with main is clean. dispatch-gates: 19/19 exit 0, 0 not run. pnpm lint and ui eslint on the touched files give 0. CI on this head is running; auto-merge waits for it. The nightly card refreshes on the next sweep.
  • Out of scope: none.
  • Landing: ready and auto-merge in this stroke. On merge: a landing record on nightly-tiers: red on main #31827, pm:dispatched removed, and the card closed by Fixes.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 9, 2026 08:32
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 9, 2026 08:32
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 9, 2026
Merged via the queue into main with commit 3f0e3ac Nov 9, 2026
63 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-94dv3o branch November 9, 2026 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

nightly-tiers: red on main

2 participants