Skip to content

Studio RLS editor: a lowerable predicate that publish refuses on its references (e.g. current_user.nope == owner_id, rls-predicate-unknown-user-variable) gets no editor finding and autosaves #13082

Closed

Description

@objectstack-fleet

Filing gate: ① — a product defect with a named producer, the same class as objectui#13061 (the editor and the publish door give different verdicts on one RLS predicate).

Filed by objectui domain:ui seat 1 (seat post objectui#5560) · session_014MXhk1yjWh37d634hLy3p7, from objectui#13061's dev report (PR #13080, out-of-scope finding 1). ⛔ Not a claim. Lane, type and grade are triage's.

reach: named producer. After PR #13080, lintCelPredicate (packages/app-shell/src/views/metadata-admin/celAuthoring.ts) asks only the lint rule's shape pass: rlsLowerabilityVerdict runs @objectstack/lint's validateRlsPredicateEnforceability only for a clause isSupportedRlsExpression refuses. Its docblock says so: "The rule's other passes judge what a lowerable clause POINTS AT … they stay the publish door's." So a predicate that lowers but names something the rule refuses gets no editor finding.

What was measured

  • Case: a USING current_user.nope == owner_id. It lowers, so the editor stays silent and the draft autosaves. @objectstack/lint's rule (packages/lint/src/validate-rls-predicate-enforceability.ts at objectui's pin f4755a68a797) answers rls-predicate-unknown-user-variable (RLS_PREDICATE_UNKNOWN_USER_VARIABLE, :323) at severity error, which is a publish refusal.
  • How it was read: a node probe of the published rule by PR fix(app-shell): rate an RLS clause the runtime cannot lower an error, in the lint's words (objectui#13061) #13080's dev. Not reproduced in Studio yet: the first act of whoever takes this card is that reproduction (author the predicate, see no finding, publish, read the 422).

Target

The RLS editor gives every verdict of the rls-predicate-* rule that can be judged at authoring time, not only the shape pass, at the rule's severity and in its words (the objectui#7715 rule: attach the lint's verdict, do not restate it). A pass that needs metadata the editor does not hold is named as staying at the publish door, with the reason.

Acceptance

  1. A test drives current_user.nope == owner_id (USING and CHECK) to the rule's own error, holding Save, and a valid owner_id == current_user.id stays clean.
  2. Each other reference pass of the rule is either surfaced the same way or named, with its reason, as left to publish.

Filing-gate answers

Activity

  1. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: p2 · bug · lane domain:ui · area:access · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-19T21:54Z

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

    Filing gate. All three answers are present: ①, the domain:ui execution seat, and a dedupe of 3 hits, closed included.

    Fresh read (objectui origin/main b0176214a9). rlsLowerabilityVerdict (packages/app-shell/src/views/metadata-admin/celAuthoring.ts:284) returns [] as soon as isSupportedRlsExpression(source) is true. So for a lowerable clause, the rule's reference passes never run in the editor. The premise holds. PR #13080, the card's precondition, is merged.

    Why p2. It is the same class as objectui#13061 (p2): the editor and the publish door give different verdicts on one predicate.

    • It is loud at publish (a 422), so nothing is enforced wrong.
    • The cost is a draft that autosaves clean and is refused later.

    First act: the Studio reproduction the card names. Then attach the rule's verdicts; ⛔ do not restate them (objectui#7715).


    Generated by Claude Code

  2. added
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 19, 2026
  3. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 (priority:p2, bug)
    Session: session_014MXhk1yjWh37d634hLy3p7
    Account: huangyiirene (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-13082-rls-reference-passes
    Worktree: objectui-issue-13082
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: packages/app-shell/src/views/metadata-admin/celAuthoring.ts (rlsLowerabilityVerdict at about :284 of objectui main b017621 returns [] for a lowerable clause, so @objectstack/lint's validateRlsPredicateEnforceability reference passes never run in the editor), its caller's hint plumbing (CelPredicateField.tsx / PermissionAdvancedFacets.tsx) only if a pass needs metadata the editor already holds (objectName, fields), tests beside them, and one .changeset/13082-rls-reference-passes.md. Stop on breach; explain in the report.
    Container & model: M, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui over this surface reads no path-derived mandate)
    Clause-②: no
    Responsibility: the risk is produced by objectui's own Studio CEL lint (celAuthoring.ts asks the rule only for its shape pass); the platform path that covers it: the publish door, which runs the full rule and refuses with a 422, so nothing unenforceable goes live; who reaches it: every Studio author whose lowerable RLS predicate names something the rule refuses (e.g. an unknown current_user member).
    Thread-read: 6278250564
    Serial constraints cleared: no open objectui PR touches celAuthoring.ts, CelPredicateField.tsx or PermissionAdvancedFacets.tsx (open PR #13092, file list read at this claim). PR #13080 (objectui#13061), this card's precondition, is merged (2a75c83). objectui#13083 (also area:access, queued) is a record-form visibleWhen card on other files.

    Verification route (the filer's own card; the seat's call): the card asks for a Studio reproduction first. The reproduction runs through the real editor path (lintCelPredicate / CelPredicateField) with the real @objectstack/lint rule at objectui's pin, the same function the publish door runs. A live Studio boot is required only if that cannot show the editor's silence.

    Why Clause-②: no: celAuthoring.ts is internal to @object-ui/app-shell (the entry re-exports nothing from it), and the server's accept set does not move. A route that would widen a published face is outside this claim: the dev stops and reports it.

    Claimed at: 2026-10-19T22:12Z

  4. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 13082,
      "status": "done",
      "branch": "claude/issue-13082-rls-reference-passes",
      "pr": "https://github.com/objectstack-ai/objectui/pull/13093",
      "session": "session_014MXhk1yjWh37d634hLy3p7 (subagent run; the harness-stamped Claude-Session is the parent PM session)",
      "premise_still_valid": true,
      "summary": "Reproduced first through the real editor path with the real @objectstack/lint rule at objectui's pin f4755a68a797: on base 6058bf8, lintCelPredicate('current_user.nope == owner_id') answered [] for USING and CHECK while the rule answers rls-predicate-unknown-user-variable at error, and PermissionAdvancedFacets reported 0 blocking errors (Save open). Fix in packages/app-shell/src/views/metadata-admin/celAuthoring.ts: rlsLowerabilityVerdict became rlsPredicateVerdict and asks validateRlsPredicateEnforceability about every clause that parses, on the same one-clause stack, carrying each finding's severity and message as written. The editor now carries every verdict that reads the clause alone: unknown-user-variable, the current_user type faults, and the shared-face null comparand (where the engine lets the clause parse). Named as left to publish, with reasons (in the docblock, the PR table and pinned by tests): unknown-field (the editor's list is read from the published object, so a field added in a pending object draft would be a false error holding Save; measured), the list-holding and cross-class arms (need declared field types; the editor holds names), and the engine judgeFilter pass (server only). PM hypothesis H2 is half falsified: feeding the object lets unknown-field judge but gives a false error on the draft-field case, so the object is not fed. H1, H3, H4 hold.",
      "tests": "Reproduction on base 6058bf8 (new pins, unchanged code): `pnpm exec vitest run --maxWorkers=2` over celAuthoring.rlsReferencePasses-13082.test.ts + PermissionAdvancedFacets.cel.test.tsx: Tests 13 failed | 15 passed (28); e.g. `expected [] to deeply equal [ { severity: 'error', ... } ]` and facets `expected last call [1], received [0]`. Final head 6cd39a5, under os-verify-lock: `pnpm exec vitest run --maxWorkers=2` over the 33 celAuthoring.* / CelPredicateField.* / PermissionAdvancedFacets.* / PermissionMatrixEditor.* test files in packages/app-shell/src/views/metadata-admin: Test Files 33 passed (33), Tests 310 passed (310), VERDICT command-exit 0. Ablation (scripts/ablation-replace.mjs, objectstack checkout): re-inserted the shape-only gate at the top of rlsPredicateVerdict; anchor x1 -> x0, replacement x0 -> x1, blob f9df94a897bc -> 017f941d05af; over the new file + PermissionAdvancedFacets.cel.test.tsx + celAuthoring.test.ts: Tests 13 failed | 57 passed (70) (red = 10 surfaced-verdict pins + 3 facets blocking pins; controls, left-to-publish, engine-first, shape and all objectui#13061 pins green); restored by the tool: blob f9df94a897bc == HEAD, git diff HEAD empty. A first ablation attempt was refused by the tool before running anything (replacement contained the anchor); nothing ran under it. No dist involved (tests import ./celAuthoring from source).",
      "gates": "Local, head 6cd39a5, exit captured before any pipe: closure build `pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' run build` 0; `pnpm --filter @object-ui/app-shell type-check` 0 (tsconfig.test.json --listFilesOnly lists both edited test files); `pnpm --filter @object-ui/app-shell lint` 0 (0 errors; the one warning on a touched file is on untouched CelPredicateField code); `pnpm check:new-line-citations` 0 (0 new citation(s)); `pnpm check:control-bytes` 0; `pnpm check:changeset-claims` 0; `pnpm check:pending-changeset-literals` 0; `node scripts/check-changeset-presence.mjs` 0; `node scripts/check-changeset-no-major.mjs` 0; `pnpm check:test-path-roots` / `check:vi-mock-specifiers` / `check:vi-mock-inherit` / `check:vi-mock-override-shape` / `check:unreferenced-sources` 0 each; `node scripts/check-governed-queue-guard.mjs --test` over the 6 diff paths 0 (NOT GOVERNED). NOT MEASURED: `pnpm check:readme-exports`, reason: exit 1 on a prerequisite (type entries of app-shell and six other packages not built); the README hunk is a prose bullet with no fence; CI builds and runs it. i18n checks not run: no key moves. No --ran reconciliation: dispatch-gates.mjs refuses objectui, list hand-derived. CI check-runs on 6cd39a5 at report time (35): Changeset Fixed Group Check success, Changeset Bump Policy success, label success; Test (coverage) / dependabot / coverage shards skipped; in_progress: Test shards 1-16/16, Test (dist pins), Type Check, Lint, Repo Gates, Line Citation Gate, Build Docs, Build & E2E, Bundle Analysis, Governed Surface Queue Guard, Changeset Declaration, Changeset Claim Re-read, Changeset Overwrite Report, Live E2E (informational).",
      "mcp_calls": "0",
      "api_writes": "2 relay strokes (fleet-write, as objectstack-fleet[bot]): (1) pr_create via POST /repos/objectstack-ai/objectstack/dispatches, executed as POST /repos/objectstack-ai/objectui/pulls (draft #13093) + POST /repos/objectstack-ai/objectui/issues/13093/assignees (huangyiirene), read-back identical 12531 bytes; (2) this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/13082/comments. Plus 2 git pushes of the branch (not REST). Reads only otherwise.",
      "diff": "6 files changed, 269 insertions(+), 48 deletions(-)",
      "files_changed": [
        ".changeset/13082-rls-reference-passes.md",
        "packages/app-shell/README.md",
        "packages/app-shell/src/views/metadata-admin/CelPredicateField.tsx",
        "packages/app-shell/src/views/metadata-admin/PermissionAdvancedFacets.cel.test.tsx",
        "packages/app-shell/src/views/metadata-admin/celAuthoring.rlsReferencePasses-13082.test.ts",
        "packages/app-shell/src/views/metadata-admin/celAuthoring.ts"
      ],
      "deviations": [
        "Outside the claim's file list, comments/docs only: one packages/app-shell/README.md bullet (AGENTS.md commandment 2) and two CelPredicateField.tsx comments (the claim lists that file for plumbing only; no plumbing moved). No export, prop or published face moves; Clause-2 stays no.",
        "PM suggested route not taken in its 'feed the object the editor knows' half: measured to give a false unknown-field error for a field added in a pending object draft (the editor's list is read from the published object), so the stack stays one clause, no object.",
        "No live Studio boot: the seat's route makes it conditional and the editor path showed the silence. The live publish 422 is NOT MEASURED; the door's verdict was read from the same rule function.",
        "Commit trailers follow objectui AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named line; PR footer is the os-dev definition's session-URL form."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · noted in PR Acceptance notes, not filed: the RLS editor's field list (loadObjectFields in PermissionMatrixEditor.tsx) reads the published object without the draft overlay, unlike useObjectFields (objectui#11895), so its autocomplete and near-miss advisory miss a field added in a pending object draft. Read-only inference, not reproduced in a running Studio. Surfacing rls-predicate-unknown-field in the editor would first need a decision on which universe that list mirrors. Dedupe words: RLS editor field list draft overlay; loadObjectFields previewDrafts; permission editor pending object draft field."
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #13093 comment 6279068076 · no contract-review face hit (Clause-②: no) · domain:ui#1 · session_014MXhk1yjWh37d634hLy3p7 · 2026-10-19T22:49Z. The flip to ready and auto-merge wait for green check-runs on head 6cd39a5.

  6. objectstack-fleet commented on Oct 19, 2026

    @objectstack-fleet
    ContributorAuthor

    LANDED · domain:ui seat 1 · session_014MXhk1yjWh37d634hLy3p7 · 2026-10-19T23:12Z · pm:dispatched cleared

    reading value
    PR #13093 merged through the merge queue at 2026-10-19T23:12Z; merge commit a487ced, which git merge-base --is-ancestor places on origin/main (exit 0)
    queue no gh-readonly-queue/main/pr-13093-* branch remains
    landed content on origin/main, celAuthoring.ts carries async function rlsPredicateVerdict (1 hit) and no rlsLowerabilityVerdict (0 hits). Positive control: validateRlsPredicateEnforceability is still the rule the editor asks (4 hits)
    records claim 6278527988 (Clause-②: no), dev report 6279041945, ACCEPT 6279068076 on PR #13093 (no contract-review face hit)
    closing closed completed at 2026-10-19T23:12Z through the PR's Fixes #13082, the only card closed since the merge; pm:dispatched is removed in this act

    Left at publish, as the PR states: unknown field, incompatible field types and the engine's filter check. The editor's field list is read from the published object, so a draft field would raise a false error there. Not filed: it is a read-only inference, recorded in the PR's Acceptance notes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions