Skip to content

Mark a reach warning beside the live grant it names on the policy card - #6437

Merged
habdelra merged 49 commits into
mainfrom
cs-13396-policy-show-a-reach-warning-beside-the-live-grant-its-about
Oct 1, 2026
Merged

habdelra merged 49 commits into
mainfrom
cs-13396-policy-show-a-reach-warning-beside-the-live-grant-its-about

Conversation

@habdelra

@habdelra habdelra commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

In service of CS-13363, which lets a RealmPolicy card show its author which of its grants are in force. #6418 marks each grant live or inactive from the policy's validate answer, and lists every issue the compile recorded. #6415 adds PolicyIssue.severity and the reach warnings, grant-reaches-ungranted-type and render-reaches-ungranted-type, which leave their grant live. Until now the card listed a reach warning only in its Issues section, so an author reading the rules list saw a plain live grant. This PR marks the warning beside the live grant it names.

cardstack/boxel-catalog#777 (same branch name, merged) adds the mark in RealmPolicy's isolated template. A live grant that a severity: 'warning' issue names by its rule and grant positions gets a "warning" pill ("2 warnings" when there are more). The pill sits in a disclosure that opens to the warnings' messages. Liveness is unchanged: it still comes from rules and admitsNothing, so a warning never makes a grant inactive. A warning on a grant that admits nothing isn't marked on that grant, because the grant hands nothing over. The warning stays in the Issues list, and the grant keeps its inactive mark. In the Issues list, a warning carries the same "warning" pill beside its rule and grant, and the hint says that a warning leaves its grant live.

Closed, the mark sits beside the grant it names. Opened, it shows the warning's message:

The warning mark beside a live read grant, and the warning pill on its Issues entry

The warning mark opened to the warning's message

This PR adds two tests to Integration | realm policy, which the manifest's tests.host already lists, and pins the catalog main commit that merged it:

  • A Roster type links to Student cards. The policy has one rule on Roster with a read and an update grant, and grants nothing on Student. Both grants render live. Only the read is marked with a warning. Opening the mark shows its grant-reaches-ungranted-type message, and the Issues list names the issue's rule (Roster) and grant (read) and marks it as a warning.
  • A policy whose only issues leave grants inactive (a delete grant whose predicate doesn't parse, and an unfilterable query) marks those grants inactive, and marks no warning on any grant or issue.

Merges after: cardstack/boxel-catalog#777

🤖 Generated with Claude Code

habdelra and others added 13 commits September 30, 2026 20:16
…granted-type-the-compile-time' into cs-13396-base-6418-and-6415
…nd pin the catalog commit that draws it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-on-realmpolicy-in-boxel-catalog' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…surface-on-the-realmpolicy-card' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…-on-realmpolicy-in-boxel-catalog' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…-on-realmpolicy-in-boxel-catalog' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about

# Conflicts:
#	packages/catalog/test-subset.json
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 1, 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-01T01:48:30.038019Z ad51720 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Preview deployments

Host Test Results

    1 files      1 suites   1h 11m 30s ⏱️
5 206 tests 5 192 ✅ 14 💤 0 ❌
5 221 runs  5 207 ✅ 14 💤 0 ❌

Results for commit 95b1132.

Realm Server Test Results

    1 files    299 suites   2h 28m 37s ⏱️
4 778 tests 4 778 ✅ 0 💤 0 ❌
4 837 runs  4 837 ✅ 0 💤 0 ❌

Results for commit 95b1132.

@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 covered the two new Integration | realm policy tests, checked against what the card's warning mark has to guarantee, and the catalog pin. It did not cover the integration base's own changes.

No blocking issues. The pin is the catalog branch's head commit, and the red Validate catalog test subset check is the expected not-on-main refusal, which clears at the re-pin. There is one coverage gap:

  1. No test pins the 'live' gate in grantWarnings. See the comment on the inactive-only test.

Adjacent, out of scope. This is in the reach check in packages/runtime-common/card-operations/policy.ts, not in this diff. A snapshot-annotated read grant admits nothing, yet two things still count it:

  • reachLane walks it, so the grant records a reach warning even though it hands nothing over.
  • letsCallerRead counts it as making its type readable. So a snapshot read on Student silences the warning on a live Roster read that does hand Students over.

Both functions already exclude the other admits-nothing case, a filterless query, through grant.filter. I traced this through the code but did not run it.

Comment on lines +984 to +994
test('a policy whose issues only leave grants inactive marks no warning', async function (assert) {
await renderPolicyNamed('policies/inactive-only', [
{
targetType: { module: '../classroom', name: 'Classroom' },
grants: [
{ operation: 'read' },
{ operation: 'delete', where: MISTYPED },
{ operation: 'query', where: UNFILTERABLE },
],
},
]);

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 test can't fail on the 'live' gate in grantWarnings, which is what keeps a warning off a grant that admits nothing. Its policy draws no warning-severity issue at all, because Classroom has no links, so it renders the same with or without the gate.

That case can happen. A snapshot-annotated read on Roster compiles with admitsNothing: 'snapshot', but reachLane still walks it, so validate records grant-reaches-ungranted-type on that grant. I traced this through policy.ts and validate.ts but did not run it. A test (or a policy with this grant) pins that a warning never replaces the inactive mark:

{
  targetType: { module: '../roster', name: 'Roster' },
  grants: [{ operation: 'read', where: { bxl: teachesPredicate, snapshot: true } }],
}
// grantStatuses() is ['inactive']; [data-test-policy-grant-inactive] and the
// snapshot note exist; [data-test-policy-grant-warning] does not;
// [data-test-policy-issue="grant-reaches-ungranted-type"] exists.

Keep that last assertion. It shows the policy really draws a warning. If the reach check stops walking admits-nothing grants (see the review body), the test then fails instead of silently no longer testing the gate. This gap belongs in this PR, but it's non-blocking: the gate itself is correct.

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 🤖] Not adding this one, because #6415 is removing the case it relies on. Its author is changing the reach check to walk only grants that can admit something: a query grant needs a filter, and no other grant may carry a snapshot predicate. Under the same rule, a snapshot read stops counting as granting a read of its type, which is the second point in your review body. After that, no compile records a warning on a grant that admits nothing. The suggested policy would then draw no warning, so the test would fail on #6415's next head instead of pinning the gate.

The gate stays as the card's rule: a warning is marked only beside a live grant. No real policy can reach it, and stubbing the validate answer to reach it would test the stub rather than the card. This branch follows #6415's head, so it picks the reach change up when that lands.

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 🤖] That change is on #6415 now (f5f38c0, "Neither walk nor count as readable a grant that admits nothing"), and this PR's base has it as of 5e5052b. A snapshot read on Roster now draws no reach warning, so no compile produces the case the gate guards against.

habdelra and others added 3 commits September 30, 2026 21:58
…g when every issue is inactive

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@habdelra

habdelra commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

[Claude Code 🤖] Refreshed preview, after cardstack/boxel-catalog@d7afd101. Two things changed since the description's images: a warning in the Issues list now carries its own "warning" pill beside its rule and grant, and the Issues hint now says that a warning leaves its grant live. The mark beside the grant is unchanged.

The warning mark beside a live read grant, and the warning pill on its Issues entry

The warning mark opened to the warning's message

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

@richardhjtan richardhjtan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[Claude Code 🤖] The subset pin and the host test match boxel-catalog#777; nothing blocks. Retarget to main and re-pin to #777's merge commit before merging, as described.

…granted-type-the-compile-time' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
@habdelra
habdelra requested a review from a team October 1, 2026 07:26
habdelra and others added 23 commits October 1, 2026 03:31
…a-reach-warning-beside-the-live-grant-its-about
…surface-on-the-realmpolicy-card' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…-on-realmpolicy-in-boxel-catalog' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…-on-realmpolicy-in-boxel-catalog' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about

# Conflicts:
#	packages/catalog/test-subset.json
…surface-on-the-realmpolicy-card' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…-on-realmpolicy-in-boxel-catalog' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…'s branch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-6415

Both parents merged main d681aea and resolved their own conflicts with it, and they merge with each other cleanly. The base takes exactly that merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a-reach-warning-beside-the-live-grant-its-about
…granted-type-the-compile-time' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…-on-realmpolicy-in-boxel-catalog' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about

# Conflicts:
#	packages/catalog/test-subset.json
…-on-realmpolicy-in-boxel-catalog' into cs-13396-base-6418-and-6415
…a-reach-warning-beside-the-live-grant-its-about
…a-reach-warning-beside-the-live-grant-its-about
…granted-type-the-compile-time' into cs-13396-policy-show-a-reach-warning-beside-the-live-grant-its-about
@habdelra
habdelra changed the base branch from cs-13396-base-6418-and-6415 to cs-13103-policy-grant-reaches-ungranted-type-the-compile-time October 1, 2026 15:24
@habdelra
habdelra changed the base branch from cs-13103-policy-grant-reaches-ungranted-type-the-compile-time to main October 1, 2026 17:03
habdelra and others added 3 commits October 1, 2026 13:04
…a-reach-warning-beside-the-live-grant-its-about
…a-reach-warning-beside-the-live-grant-its-about
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@habdelra
habdelra merged commit 16c1379 into main Oct 1, 2026
84 of 87 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