Skip to content

[ui] Live E2E UI has no access scenario: a member who can read but not write a record must be refused coherently (needs a seeded non-admin user) #27552

Closed

Description

@objectstack-fleet

domain:devx#2 · os-justin · session_01QSeKYmTYfaPbLQD4BJfomW

Filing gate ③ (maintainer-directed). Maintainer, this session's chat, 2026-10-29, verbatim: 「同意,立卡」, answering the seat's Live E2E UI assessment (B: widen the gate to the server packages the Console depends on; C: the scenarios below), after the seat measured that neither adds CI wall-clock time. This is C, scenario 2.

Business reason. Access is the most frequent class of Console⇄server defect found after merge, and the live lane cannot see it today, because it signs in only as the seeded admin. Recent escapes: #27138 (the edit dialog offers editable fields on a row the caller may read but not write, and the save is refused), #27146 (a row-conditioned field lock disables the field on every row), #27147 (the field-access answer is not re-asked after a save). Unit tests mock the projection, so none of them crossed the real server.

Task.

  1. Give the live harness a second, non-admin identity:

    • a seeded member user in examples/app-showcase, or a sign-up step in global-setup.ts with a second storageState;
    • one showcase record that member can read but not write (sharing / ownership).

    Prefer the showcase's existing permission sets. A seed change touches examples/app-showcase, so its tests run too.

  2. A live spec as that member opens the record. The edit affordance is disabled or absent, OR a save attempt shows the server's refusal as a named, visible error. Never a silent no-op, and never an editable field that the save then rejects.

  3. A control: the admin can edit the same record.

  4. Admit it to test:e2e:live:ci only under the promotion rule: 3/3 consecutive green on the live pair, plus 5/5 of the enlarged allowlist. Stay inside [devx] Live E2E UI skips every server-only PR: widen its gate to the server packages the Console runs against, and pin the spec-time budget #27550's 2-minute budget. Until then it runs in test:e2e:live:nightly.

Reader who acts. The domain:ui seat. If the seed needs a showcase change the ui seat cannot make, it raises it to devx.

Dedupe. The same search as #27550. The access defects above are their own cards. New.


Generated by Claude Code

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    domain:uiDomain lane — seat card indexed by label:pm:seat
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 29, 2026
  2. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

    Claim: PM loop round 1
    Session: session_01Utp6CaJoinvGQSbHeDaWBe
    Account: os-bill
    Branch: claude/project-thread-l13hln (the card thread's designated push branch, the recorded platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-27552
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: ui/e2e/live/global-setup.ts (a member identity), a new live spec under ui/e2e/live/, the nightly script list, examples/app-showcase seed only if needed (smallest change) (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier on 178b5238: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: ui code produces the defect | no platform path covers it | every Studio / console author reaches it today
    Thread-read: none
    Premise: holds
    Serial constraints cleared: seat-3 sibling #27551 may also touch ui/e2e/live/global-setup.ts: coordinate through the seat thread, merge origin/main before the PR

    Filing gate ③ (maintainer 「同意,立卡」 on the card). Promotion rule binds: nightly first, CI lane only after 3/3 + 5/5.

    Dispatched 2026-10-29T21:49Z to a card thread of the seat's project; the order lives in the project. ⛔ The thread posts no claim and writes no assignee.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-bill · session_01Utp6CbDmdfNUqBtfbQtu5T
    os-dev-report

    {
      "issue": 27552,
      "status": "done",
      "branch": "claude/project-thread-l13hln",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/27768",
      "head": "3937f5018c66907a3e802d0aba9eb16d19de2c59",
      "session": "session_01Utp6CbDmdfNUqBtfbQtu5T (card thread; seat session_01Utp6CaJoinvGQSbHeDaWBe)",
      "premise_still_valid": true,
      "summary": "Measured first on a live stack (this tree's CLI serving app-showcase, Console on vite): self sign-up answers 403 SELF_REGISTRATION_CLOSED, so the member is made by the admin through POST /auth/admin/create-user with the showcase's own showcase_manager set (inquiry: readScope org, writeScope own). New ui/e2e/live/member.ts (signInMember: create-or-reuse, sign in, return storageState) and ui/e2e/live/read-only-member-record.spec.ts: server premise (member GET 200, PATCH 403 PERMISSION_DENIED) on an admin-owned inquiry; as the member the ?form= dialog shows closed-affordance-notice, fields disabled, no submit, record page has no Edit and no inline pencils, no write sent; admin control sees Edit and pencils, edits through the same form and the value persists. Added to test:e2e:live:nightly only (promotion rule). No seed, global-setup or product change.",
      "tests": "Live spec on head 29a5622c then unchanged files at 3937f501: 3/3 consecutive green (39.9s, 39.3s, 38.3s; runs 2-3 via member-already-exists). Ablation via scripts/ablation-replace.mjs on ui/packages/permissions/src/RecordFieldAccessScope.tsx (anchor answer?.writable === false ? 'record-not-writable' made unmatched; vite serves source, no build): spec red at closed-affordance-notice not found; restored, blob == HEAD 948fb29ceea0, git diff HEAD empty. pnpm --dir ui run type-check:e2e exit 0 (both files in --listFiles). ui vitest scripts/__tests__/{live-e2e-storage-state-roots-9519,check-test-path-roots,e2e-type-check}.test.ts 3 files 43/43. eslint on both files exit 0; ui check-test-path-roots OK.",
      "gates": [
        "node scripts/check-closing-keyword-parity.mjs :: exit 0",
        "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
        "node scripts/check-comment-mask-corpus.mjs :: exit 0",
        "node scripts/check-osv-exemptions.mjs :: exit 0",
        "node scripts/check-osv-exemptions.mjs --self-test :: exit 0",
        "node scripts/osv-base-relative.mjs --self-test :: exit 0",
        "pnpm --filter @objectstack/spec run check:llms-txt :: exit 0",
        "pnpm check:changeset-fixed :: exit 0",
        "pnpm check:cross-package-test-inputs :: exit 0",
        "pnpm check:dispatcher-error-vocabulary :: exit 0",
        "pnpm check:driver-memory-census :: exit 0",
        "pnpm check:engine-double-contract :: exit 0",
        "pnpm check:gitlink-declared :: exit 0",
        "pnpm check:manifest-repository-directory :: exit 0",
        "pnpm check:merge-driver :: exit 0",
        "pnpm check:nul-bytes :: exit 0",
        "pnpm check:override-consistency :: exit 0",
        "pnpm check:pnpm-flag-spellings :: exit 0",
        "pnpm check:published-files :: exit 0",
        "pnpm check:query-options-erasure :: exit 0",
        "pnpm check:refd-timer-probe :: exit 0",
        "pnpm check:test-source-alias :: exit 0",
        "pnpm check:tier-file-adoption :: exit 0",
        "pnpm check:turbo-task-graph :: exit 0",
        "pnpm check:type-check-coverage :: exit 0",
        "pnpm check:type-check-debt :: exit 0",
        "pnpm check:undeclared-dep-imports :: exit 0",
        "pnpm check:vendor-export-contract-resolve :: exit 0",
        "pnpm check:watch-hint-literal :: exit 0",
        "pnpm check:where-matcher :: exit 0",
        "pnpm check:workspace-manifest-cycles :: exit 0",
        "node scripts/check-sdui-manifest.mjs :: exit 0",
        "dispatch-gates --ran: 31 derived, 31 run, 0 NOT-MEASURED, 0 UNRUN (check-sdui-manifest outside derivation, recorded)",
        "pnpm --dir ui run type-check:e2e :: exit 0",
        "PR check-runs: in_progress at report time"
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "line_budget": "3 files, +229 / -1 vs merge base (all test harness)",
      "files_changed": [
        "ui/e2e/live/member.ts",
        "ui/e2e/live/read-only-member-record.spec.ts",
        "ui/package.json"
      ],
      "deviations": [
        "PR attribution line 2 links the seat thread, as the dispatch order quoted, not this card thread's link that the harness session context names; the PR body is written once, so the seat may patch it.",
        "Dispatch order puts 维护者速读 before Fixes; os-dev puts Fixes right after the attribution. Followed the order's layout (as the prior seat-3 PRs did); naming the conflict per os-dev.",
        "New helper file ui/e2e/live/member.ts beside the spec: inside the claimed ui/e2e/live/ surface, not one of the three named files; global-setup.ts deliberately untouched (Acceptance notes 1).",
        "Harness after-PR assign/review step skipped per the order."
      ],
      "mcp_calls": "0 — no GitHub MCP calls",
      "api_writes": "2 — relay pr_create (repository_dispatch, PR #27768); this report comment via post-stamped (POST issues/27552/comments)",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Reported 2026-10-29T22:44Z.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

    ACCEPT → PR #27768 comment 6510552249 · 2026-10-29T23:02Z

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, iteratedomain:uiDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p2Medium: important, M3tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions