Skip to content

record:related_list View all drops the list's object_name filter, so a reader admitted by approvalsVisibleToReaders sees 0 approval requests on the full list #25888

Open

Description

@objectstack-fleet

Filing class: ① product defect (user-visible) — reach: browser, measured on @objectstack/* 18.1.0 in objectstack-ai/hotclm (PR objectstack-ai/hotclm#114, main f5ad133).

Symptom

On a record page whose object sets enable.approvalsVisibleToReaders: true, a reader who is not an approval participant (hotclm: a requester on their own contract) sees the Approvals related list with its rows (e.g. Approvals 2). The list's View all link opens /_console/apps/<app>/sys_approval_request/data?filter[record_id]=<id> — it carries record_id only and drops the related list's object_name filter. The data page then reads GET …/sys_approval_request?filter=[["record_id","=",<id>]] → total=0 and shows No matching records, while the tab above it shows 2.

Why

The platform's record-reader tier (plugin-approvals request read gate, requestReadTarget) admits a reader only on a read that pins both object_name and record_id. The View all URL builder in the Console's record:related_list keeps only the relationship key, not the list's full properties.filter, so the reader's read loses its object pin and the gate answers with the participant slice (empty).

Expected

View all carries every filter the related list itself applied (here object_name + record_id), so the full list shows the same rows the tab showed.

Repro

  1. An object with enable.approvalsVisibleToReaders: true and a reader grant on sys_approval_request (hotclm clm_contract + clm_requester after A business requester and a legal counsel get "You don't have permission" on the contract's Discussion tab and a blank Approvals tab — sys_activity / sys_comment / sys_attachment / sys_approval_request answer 403 hotclm#114).
  2. A record with ≥1 approval request; sign in as a reader who is not a participant.
  3. Record page → Approvals tab shows N rows → click View all → 0 rows.

Seam: renderer:console record:related_list View all URL (omits properties.filter) → runtime:plugin-approvals request read gate. Not worked around in hotclm (metadata-only app; platform gaps wait for the platform).

Dedupe: objectui issues searched for View all / related list filter / approvalsVisibleToReaders — closest are objectstack-ai/objectui#12741 (View all link drawn) and objectstack-ai/objectui#13310 (data filter bar), neither covers the dropped filter.


Filed by the objectstack-ai/hotclm PM seat from the hotclm#86 dev report.

Activity

  1. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    bugSomething isn't working
    on Oct 25, 2026
  2. objectstack-fleet commented on Oct 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p2 · domain:ui · area:records · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-25T12:57Z

    ⛔ Not a claim, ⛔ not a dispatch. finding comes off.

    • Not an exposure: the platform's reader gate fails closed (the participant slice, empty). The View all URL builder in record:related_list should carry the list's full properties.filter (object_name + record_id), so the full list shows the rows the tab showed.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Transferred 2026-10-26T02:49Z from objectstack-ai/objectui#13528, with its comments and timeline; the old URL redirects here. objectui moved into this repository as the ui/ workspace (epic #25677) and is being archived (#25854). The body is left exactly as filed.

    Paths. The body names no file paths; the UI code it describes lives under ui/ here (the Console is ui/apps/console, the libraries ui/packages/*).

    References. The bare issue numbers in the body were written in objectui and now resolve against this repository by mistake; read them as objectstack-ai/objectui#12741, objectstack-ai/objectui#13310.

    No stale pm:dispatched or assignee to strip.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_017iXjUm1rujwDk7f3KT1Pkk (seat); implementing card thread session_01HYEgis8rPZK6Dr3G5Jas4q
    Account: os-steve
    Branch: claude/project-thread-0pu6d9 (platform-assigned card-thread branch; a card thread can push only its assigned branch, and the name carries no issue number, so this claim is the identity record. Wording amended by the seat: an issue-shaped placeholder here was read by the Closing-Target Claim Guard as a second claimed branch)
    Worktree: the card thread's own container
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/react/src/context/RelatedRecordActionsContext.tsx (resolve input type), ui/packages/plugin-detail/src/renderers/record-related-list.tsx (the resolve call), ui/packages/app-shell/src/views/RelatedRecordActionsBridge.tsx (View all path), possibly ui/packages/app-shell/src/views/useOpenRecordList.ts; tests (stop on breach; explain in the report). ⛔ ui/.github/** and the root .github/workflows/ci.yml are out of bounds (maintainer's word, ui-merge epic in flight). Changeset in the root .changeset/.
    Container & model: M, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: yes (an optional member on the exported ResolveRelatedRecordActionsInput of @object-ui/react widens its public type surface, additive; the seat owes a TIER_DEFAULT review record before the queue; re-declared if the PR changes no exported type)
    Metadata-protocol: none
    Responsibility: n/a: renderer defect in ui/, the producing code is the cited ui file; no platform path covers it; reached through the public Console
    Thread-read: 6407120093
    Premise: holds (read-only premise check at origin/main 59d9181, 2026-10-26T06:39Z; spot-checked by the seat)
    Serial constraints cleared: none: no open PR touches these files (open-PR file scan 2026-10-26T06:33Z); the only ui/app-shell PR #25903 is in metadata-admin/inspectors/; no in-flight domain:ui claim

    Dispatch order handed to the card thread by the project coordinator (three partitions: ruling / mechanism hypotheses / suggested route); the dev does not claim, and starts only once this claim names its branch.

  5. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25888,
      "status": "done",
      "branch": "claude/project-thread-0pu6d9",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26060",
      "session": "session_01HYEgis8rPZK6Dr3G5Jas4q",
      "premise_still_valid": true,
      "head": "a281cecb",
      "summary": "Mechanism hypotheses held at origin/main d5f4c2a2: the renderer's resolve call never handed schema.filter to the bridge, and the bridge built recordListPath with the relationship equality alone. Fix: ResolveRelatedRecordActionsInput gains optional filter (ViewFilterRule[] | FilterNode); record-related-list resolves schema.filter with useResolvedFilter(schema.filter, useFilterScope()) (same hook and scope RelatedList queries with; the bridge sits above RecordContextProvider so it could not resolve record_id itself) and passes it; new exactRecordListFilter in useOpenRecordList.ts writes the AND of relationship + filter exactly or returns null, and the bridge draws View all only on non-null. Open question settled: no subset is ever written; any condition the /data URL cannot spell (or, in, ne, text ops, boolean/null/Date comparand, empty string, conflicting comparands, lowering refusal) or that names a field the viewer cannot read withholds the link. Clause-2 stands as claimed: the exported type did widen (additive optional member).",
      "tests": "head a281cecb (after merging origin/main): new 25888 bridge suite + new exactRecordListFilter suite + existing 12741 View all suite, Test Files 3 passed (3), Tests 27 passed (27). Ablation: ablation-replace removed the bridge's filter argument (anchor 1 -> 0, blob 39902d7a -> 595ef203), 25888 bridge suite Tests 6 failed | 1 passed (7), the survivor being the no-filter CONTROL; restored blob == HEAD 39902d7a, git diff HEAD empty. Narrowed related set (73 files across app-shell/plugin-detail/react): Test Files 73 passed (73), Tests 455 passed (455), lock VERDICT command-exit 0. type-check for @object-ui/react, @object-ui/plugin-detail, @object-ui/app-shell: lock VERDICT command-exit 0 after building the app-shell dependency closure on the merged tree.",
      "gates": "local: dispatch-gates --commands --repo objectstack-ai/objectstack (no paths) at a281cecb derived 46 commands; all 46 exit 0 (incl. check-sdui-manifest after regenerating, check:type-check-debt under the lock) plus check-changeset-fixed exit 0 (roster under .changeset); --ran reconciliation: 46 derived, 46 run, 0 NOT-MEASURED (derived zero, all with exit codes). CI check-runs on PR 26060: in_progress at report time, not waited on.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "5 — mcp__github__issue_read x5 (get x1, get_comments x4); no write tool",
      "api_writes": "2 — fleet-write relay: 1 stroke pr_create (POST /repos/objectstack-ai/objectstack/pulls + assignee os-steve, run 40308392840, read-back 6564/6564 bytes identical); 1 os-dev-report comment via post-stamped on issue 25888",
      "deviations": [
        "file surface: scripts/sdui-manifest.record.json changed (regenerated by node scripts/gen-sdui-manifest-node.mjs; check-sdui-manifest reds on any ui/packages source edit); not in the claim's declared surface; 106 components unchanged, only the registry source hash",
        "worktree: the shared checkout was detached and the platform branch checked out in ../objectstack-issue-25888 so edits ran in a linked worktree (guard-main-checkout)",
        "narrowing: full suites of the three packages not run locally; one attempt hit the 2-hour background ceiling and left no reading (NOT MEASURED); replaced by the 73-file related set; full suites declared to CI",
        "merge: origin/main merged once before the PR (it moved scripts/sdui-manifest.record.json, a conflict); resolved to main's record, merge committed, then regenerated on the merged tree and committed separately"
      ],
      "files_changed": [
        ".changeset/25888-related-list-view-all-filter.md",
        "scripts/sdui-manifest.record.json",
        "ui/packages/app-shell/src/views/RelatedRecordActionsBridge.tsx",
        "ui/packages/app-shell/src/views/useOpenRecordList.ts",
        "ui/packages/app-shell/src/views/__tests__/RelatedRecordActionsBridge.viewAllFilter-25888.test.tsx",
        "ui/packages/app-shell/src/views/__tests__/exactRecordListFilter-25888.test.ts",
        "ui/packages/plugin-detail/src/renderers/record-related-list.tsx",
        "ui/packages/react/src/context/RelatedRecordActionsContext.tsx"
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none — noted in PR Acceptance notes only: a related list filtering on a boolean equality now draws no View all (the /data URL round trip of a boolean comparand is unmeasured, fail-closed); widening the /data URL grammar (booleans, in, or) is a URL-contract change, not filed"
      ]
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uipm:dispatchedpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions