Skip to content

recordIdField is not harvested into the grid's $select — "Revoke Session" reports success and revokes nothing #5217

Description

@os-support-ai

Moved from objectstack-ai/objectstack#8018 by the repo:objectui PM seat (session session_01RV6yuVCxymHYE16PL9vQkE) under the maintainer's direct-dispatch authorisation, 2026-08-18, verbatim: 「转」.

Reason: the original's own routing note — "The projection fix lands in objectui (packages/app-shell), not in this repo."

⚠️ This one is a seam card, and the move does not dissolve the seam. The original also says it "may need to be split across the two repos": the general projection gap is objectui's, but the sys_session.revoke_session declaration lives in objectstack's packages/platform-objects, and the interaction with objectstack-ai/objectstack#7823 is live, not hypothetical. If the fix turns out to need a platform-side change, it goes back as a contract-first split with a Blocked-by: — ⛔ it does not get forced into objectui.

Original thread has 5 comments; read them there. Bare references rewritten to full cross-repo form.

Filed by the domain:metadata PM seat on behalf of objectstack-ai/objectstack#7823's dev, which measured this while doing that card's objectui console-SPA check but could not file it — the objectstack-ai org has no Claude GitHub App connection, so cloud dev containers are blocked from the GitHub API.

⚠️ Authored by a PM from the dev's measurements (its own draft could not be relayed). The measurements and file/line anchors below are the dev's; the framing is that PM's.

The defect

A row action declaring recordIdField gets undefined for it, because the grid never projects that column.

  • useConsoleActionRuntime.tsx:322-325 reads rowRecord[action.recordIdField] — a generic read, correct in itself.
  • The grid builds $select from listView columns + id + predicate fields only (ObjectGrid.tsx:677-722, predicate-fields.ts:141-170). recordIdField is not harvested into that projection.
  • So for any action whose recordIdField is not already a listView column, the row object has no such key and the action sends undefined.

Measured instance — sys_session.revoke_session

sys_session declares revoke_session with recordIdField: 'token', and token is in no listView. So the action sends no token, better-auth's revoke-session (session.mjs:441-443) matches nothing, deletes nothing — and still answers { status: true }.

"Revoke Session" reports success and revokes nothing. A security control that silently no-ops while reporting success.

Two things worth separating

  1. The general defect is the projection gap: any recordIdField outside the listView is silently undefined. sys_session is the instance that surfaced it, not the whole of it. ⚠️ Whoever picks this up should enumerate the other declarations rather than fixing the one — a per-action patch leaves the class open.
  2. The silent success is arguably its own defect: an action that identifies no record should not answer { status: true }. That half is server-side and therefore not in this repo — if it is taken, it is an objectstack card.

⚠️ It interacts with objectstack-ai/objectstack#7823 — read this before choosing a fix

That card proposes internal: true on sys_session.token. If it lands, the obvious repair here — "harvest recordIdField into $select" — is foreclosed for this instance, because an internal field is stripped from result rows regardless of projection. The generic projection fix would still be correct for every other recordIdField; sys_session.revoke_session would then need a different mechanism (an action naming the record by id and letting the server resolve the token, for instance).

⚠️ objectstack-ai/objectstack#7823 is currently a design exit awaiting a maintainer ruling, so the interaction is live. ⛔ Do not assume either card's outcome when scoping this one.

Establishment level, stated honestly

The projection gap and the missing harvest are read from code (grep for recordIdField in the projection builders returns nothing; the control grep for sys_session in the same file set returns hits, so the search reaches objectui source). The end-to-end "click Revoke Session, observe nothing revoked" was not run. ⛔ Reproduce before fixing.

⚠️ Line anchors are from 2026-08-12 — re-measure against the current tree.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions