Skip to content

Add RealmService.contains for cross-form membership checks#4628

Open
backspace wants to merge 5 commits intomainfrom
@cardstack/base-realm-membership-cs-10982
Open

Add RealmService.contains for cross-form membership checks#4628
backspace wants to merge 5 commits intomainfrom
@cardstack/base-realm-membership-cs-10982

Conversation

@backspace
Copy link
Copy Markdown
Contributor

@backspace backspace commented May 1, 2026

This was split off #4539, although it’s so small it could have been included!

Substring-prefix checks like card.id.startsWith(realm) only work when both sides are in the same form (URL vs registered prefix). After RRI migration, IDs may be prefix-form while realm URLs are URL-form (or vice versa), silently breaking those checks.

contains resolves both sides to URL form via cardIdToURL before delegating to RealmPaths.inRealm, so cross-form comparisons work as long as the prefix is registered.

Sweeps the two known callers in search.ts and workspace.gts.

Substring-prefix checks like `card.id.startsWith(realm)` only work
when both sides are in the same form (URL vs registered prefix).
After RRI migration, IDs may be prefix-form while realm URLs are
URL-form (or vice versa), silently breaking those checks.

`contains` resolves both sides to URL form via `cardIdToURL` before
delegating to `RealmPaths.inRealm`, so cross-form comparisons work
as long as the prefix is registered.

Sweeps the two known callers in `search.ts` and `workspace.gts`.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

Preview deployments

Host Test Results

    1 files  ±0      1 suites  ±0   1h 57m 22s ⏱️ - 2m 52s
2 565 tests +3  2 550 ✅ +3  15 💤 ±0  0 ❌ ±0 
2 584 runs  +3  2 569 ✅ +3  15 💤 ±0  0 ❌ ±0 

Results for commit 50bf89b. ± Comparison against earlier commit 558a060.

Realm Server Test Results

    1 files  ± 0      1 suites  ±0   16m 57s ⏱️ -19s
1 248 tests +36  1 248 ✅ +36  0 💤 ±0  0 ❌ ±0 
1 326 runs  +42  1 326 ✅ +42  0 💤 ±0  0 ❌ ±0 

Results for commit 50bf89b. ± Comparison against earlier commit 558a060.

@backspace backspace marked this pull request as ready for review May 1, 2026 23:17
@habdelra habdelra requested a review from Copilot May 4, 2026 15:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a reliable realm-membership helper on the Host-side RealmService to avoid incorrect startsWith() realm checks when identifiers may be in mixed forms (URL-form vs registered-prefix form) after the RRI migration.

Changes:

  • Added RealmService.contains(realm, resource) that normalizes both inputs to URL-form via cardIdToURL() and then uses RealmPaths.inRealm().
  • Updated SearchResource.instancesByRealm to use realm.contains() instead of card.id.startsWith(realm).
  • Updated workspace deletion “active workspace” detection to use realm.contains() for open card IDs.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/host/app/services/realm.ts Adds RealmService.contains() for cross-form realm membership checks (URL/prefix).
packages/host/app/resources/search.ts Switches realm grouping logic to use realm.contains() instead of string prefix checks.
packages/host/app/components/operator-mode/workspace-chooser/workspace.gts Uses realm.contains() when checking if any open card belongs to the workspace realm.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/host/app/services/realm.ts Outdated
backspace and others added 2 commits May 4, 2026 09:09
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@backspace backspace requested a review from a team May 5, 2026 16:33
Comment thread packages/host/app/services/realm.ts Outdated
// (and vice versa) as long as the prefix is registered in `prefixMappings`.
// Returns `false` if either side fails to resolve, including when a
// non-URL-like string does not match a registered prefix exactly.
contains(realm: string | URL, resource: string | URL): boolean {
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.

Is there a named type we should use here?

} catch {
return false;
}
return new RealmPaths(new URL(realmHref)).inRealm(rri(resourceHref));
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.

Isn't there a util that can do this with with RRIs?

backspace added 2 commits May 5, 2026 18:31
Per review: use the existing branded types in the helper signature
so intent is documented through the type system. Callers cast their
unbranded strings via `ri()` / `rri()` for now; tightening the source
types of `availableRealmURLs`, `Workspace.args.realmURL`, and
`CardDef.id` is tracked separately.
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.

3 participants