Skip to content

Pin that a caller's filter and a grant on one path into a list match through one element - #6561

Merged
habdelra merged 3 commits into
mainfrom
cs-13344-policy-a-callers-filter-on-a-list-field-drops-rows-that-a
Oct 6, 2026
Merged

habdelra merged 3 commits into
mainfrom
cs-13344-policy-a-callers-filter-on-a-list-field-drops-rows-that-a

Conversation

@habdelra

@habdelra habdelra commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

In service of the operation-permission policies, which scope a search to what a caller's grants admit by composing the grants into the caller's own query. When a caller's filter and a query grant test the same path into a list, one element of the list has to satisfy both. The index query engine gives each path into a list one shared alias, so in { every: [callerFilter, { any: grants }] } both conditions test the same element. A teacher whose grant is .teacherIds | any(. == actor()) and who searches teacherIds for a colleague therefore finds nothing, not even a classroom that lists them both. Searching for their own id works, and so does searching on any other field.

We're keeping the engine as it is. The limit only removes rows and never adds one. Lifting it would change the shared-alias rule in the query engine, in both adapters and in the client-side matcher, for every search and not only policy-scoped ones. This PR pins the behavior in policy-scoped-search-test.ts. A new Rosters realm there grants a query over classrooms by teacherIds. The tests check three things: searching for the caller's own id finds both classrooms; searching for a colleague finds nothing, through both the federated and the realm's own search, while the realm owner does find the shared classroom; and a filter on another field finds it. A later engine change to this behavior would then have to be deliberate. The school example realm already avoids the pattern (its README says not to filter on the list a grant reads).

No search's SQL changes; the diff is tests only. The limit is written up in the skills rather than in this repo: for a caller writing a search in cardstack/boxel-skills#177 (card-operations-authoring), and for a policy author in cardstack/boxel-skills#174 (realm-policy-authoring §7).

Linear: CS-13344

🤖 Generated with Claude Code

…ust match one element

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-06T14:01:56.548731Z 0daf0f7 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@habdelra habdelra left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code 🤖] This review checked two things. First, whether the documented limit is the one the engine and the policy composition actually produce. Second, whether the new tests would fail if that behavior changed. It did not cover the rest of the test file.

No blocking issues. The limit holds as stated, and the colleague test would go red if the engine ever stopped sharing the alias. That test also covers the realm's own search path.

  1. Doc precision: the rule applies per path, not per list. For a list of links, conditions on different fields of the linked cards are not tied to one element. See the inline comment on the docs/card-operations.md paragraph.

Comment thread docs/card-operations.md Outdated
Comment on lines +814 to +815
The caller's filter and the grants run as one query, and when both test the
same list field, one element of the list must satisfy both. A teacher whose

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code 🤖] Could this say "the same path" instead of "the same list field"? As written it overstates the limit for a list of links. The engine shares one alias per full dotted path (tree_<column>_<fieldPath> in expression.ts), not per list. A linksToMany grant, .students | any(.id == actor()), compiles to students.id. A caller filter on students.grade therefore gets its own alias and is tested against any element, independently of the grant's.

That matters in both directions:

  • A reader told "the same list field" will avoid a students.grade filter that actually works.
  • Worse, they may expect that filter to apply to their own linked entry, the one the grant matched. It doesn't, because the two conditions aren't tied to one element.

Suggested wording: "…and when both test the same path into a list (the list itself, or the same field of the cards it links to), one element must satisfy both. Conditions on different fields of a list's items are each met by any element, not necessarily the same one."

Non-blocking. The test pins the case that's documented correctly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code 🤖] Fixed in 7bfefed. The paragraph now says one element has to satisfy both only when they test the same path into a list (the list itself, or the same field of the cards it links to), and that conditions on different fields of a list's items are each met by any element. This matches tree_${column}_${fieldPath} keying the alias by the full path.

habdelra and others added 2 commits October 6, 2026 10:02
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@habdelra habdelra changed the title Document and pin that a caller's filter and a grant on one list field match through one element Pin that a caller's filter and a grant on one path into a list match through one element Oct 6, 2026
@habdelra
habdelra requested a review from a team October 6, 2026 14:22
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Host Test Results

    1 files      1 suites   1h 14m 18s ⏱️
5 248 tests 5 236 ✅ 12 💤 0 ❌
5 263 runs  5 251 ✅ 12 💤 0 ❌

Results for commit 66a8bdf.

Realm Server Test Results

    1 files    314 suites   1h 54m 19s ⏱️
4 985 tests 4 985 ✅ 0 💤 0 ❌
5 044 runs  5 044 ✅ 0 💤 0 ❌

Results for commit 66a8bdf.

@habdelra
habdelra merged commit 24ad02f into main Oct 6, 2026
74 of 76 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants