Skip to content

Change the host store to allow prefix RRI keys#5470

Open
backspace wants to merge 16 commits into
mainfrom
cs-11730-s3-canonical-store-key
Open

Change the host store to allow prefix RRI keys#5470
backspace wants to merge 16 commits into
mainfrom
cs-11730-s3-canonical-store-key

Conversation

@backspace

@backspace backspace commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

If a mapping exists, the prefix form is the preferred key.

asURL's string branch normalized remote ids to URL form while its document
branch returned data.id verbatim — which is canonical (prefix form for mapped
realms) as served — so the two branches could key the same mapped-realm card
under different spellings. Fold the string branch to the canonical spelling
too: parse through the VN's URL machinery for normalization, then back to
prefix form where a realm mapping exists. The render store's key
normalization gets the same treatment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Preview deployments

Host Test Results

    1 files  ±0      1 suites  ±0   2h 50m 7s ⏱️ - 7m 31s
3 471 tests +2  3 456 ✅ +2  15 💤 ±0  0 ❌ ±0 
3 490 runs  +2  3 475 ✅ +2  15 💤 ±0  0 ❌ ±0 

Results for commit 061552d. ± Comparison against earlier commit d95b506.

Realm Server Test Results

    1 files  ±0      1 suites  ±0   17m 50s ⏱️ +40s
1 845 tests +4  1 845 ✅ +4  0 💤 ±0  0 ❌ ±0 
1 924 runs  +4  1 924 ✅ +4  0 💤 ±0  0 ❌ ±0 

Results for commit c553362. ± Comparison against earlier commit e26b2c8.

The render store's cache-key normalization and its document-load
normalization shared one helper, so folding keys to canonical spelling also
changed the URL that loadCardDocument stamps onto the returned document's id.
Split them: cache keys fold to the canonical spelling; load targets resolve
to the real URL at the fetch boundary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@backspace
backspace marked this pull request as ready for review July 13, 2026 17:24

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d95b506a08

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/host/app/services/store.ts
The store keys mapped-realm instances in prefix form, and addReference
passes those ids to subscribeToRealm -> realm.realmOf. realmOf scanned
its URL-keyed realms with a VirtualNetwork-less RealmPaths, whose
inRealm only matches same-form inputs — so prefix-form ids never
matched, no Matrix subscription was installed, and cards in mapped
realms missed invalidation events. Pass the VirtualNetwork into
RealmPaths so its cross-form matching applies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@backspace
backspace requested a review from a team July 13, 2026 21:54
@habdelra
habdelra requested a review from Copilot July 14, 2026 00:18

Copilot AI 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.

Pull request overview

This PR updates host-side identifier normalization so that, when a realm mapping exists in the VirtualNetwork, the prefix-form RRI becomes the canonical key (instead of URL-form), and related subsystems (render-service cache keying, realm membership checks) align with that.

Changes:

  • Canonicalize remote ids to prefix form (when mapped) in the host store’s asURL() normalization.
  • Align CardStoreWithErrors cache key normalization with the store’s canonical (prefix-preferred) keying.
  • Update RealmService#realmOf() realm membership checks to allow prefix-form ids against URL-keyed realms, and add an integration test covering subscription installation via a prefix-form reference.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
packages/host/tests/integration/store-test.gts Adds an integration test asserting prefix-form references install realm subscriptions.
packages/host/app/services/store.ts Changes asURL() normalization to prefer prefix-form keys for mapped realms.
packages/host/app/services/render-service.ts Adjusts render-service in-memory cache key normalization to match the store’s canonical spelling.
packages/host/app/services/realm.ts Passes VirtualNetwork into RealmPaths so inRealm() can match prefix-form ids against URL-form realms.

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

Comment thread packages/host/app/services/store.ts
Comment thread packages/host/app/services/store.ts
Comment thread packages/host/app/services/render-service.ts
Comment thread packages/host/tests/integration/store-test.gts
backspace and others added 4 commits July 14, 2026 07:36
unsubscribeFromInstance tested realm membership with a bare
id.startsWith(realmURL), but the store now keys mapped-realm instances
and reference counts in prefix form while subscription keys stay
realm-root URLs (realm events route by URL). The prefix-form id never
matched the URL-form realm key, so a mapped realm's Matrix subscription
leaked and its reference scan mis-counted. Resolve each id to URL space
via toURLHref before the comparison, mirroring the cross-form fix on the
subscribe side in realmOf.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
asURL runs on nearly every store operation and resolved ids via
vn.toURL(id).href, allocating a URL per call. toURLHref is the memoized
equivalent — same resolution and throw behavior — so repeat ids become
a Map lookup. Also apply it to the two prefix-resolution read sites that
used the same pattern.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
normalizeKey runs on every render-store cache get/set and normalizeURL
on the load path; both resolved via vn.toURL(id).href, allocating a URL
per call. Swap to the memoized toURLHref, which has identical resolution
and throw behavior, so repeat ids become a Map lookup. normalizeURL
keeps resolving the original id (not the .json-stripped key) so the
loaded document's id is stamped from the fetch-form URL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The realm-subscription lifecycle test installed the subscription and
dropped the reference but never asserted the teardown, so the unsubscribe
realm-membership mismatch went uncaught. Assert the subscription is gone
after the last drop; this fails on a URL-space startsWith against a
prefix-form id and passes with the URL-space comparison.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
backspace and others added 8 commits July 14, 2026 09:19
Enabling teardown of mapped-realm subscriptions (which the store now
keys in prefix form) destabilized acceptance tests: a subscription torn
down on a reference drop stops delivering the realm invalidations a test
awaits, so the test hangs to timeout. The pre-existing behavior leaks the
subscription but keeps invalidations flowing, so restore it here. A safe
teardown needs the subscription lifecycle stabilized separately, not the
key flip plus eager unsubscribe in one step. The toURLHref performance
changes are unaffected and stay.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Realm subscriptions are keyed by realm-root URL (invalidation events route
by URL) while the store keys instances and reference counts in canonical
form (prefix form for mapped realms). Reconciling the two forms on every
reference drop to decide when to unsubscribe races invalidation delivery:
tearing a subscription down as the last reference drops loses updates a
caller is still awaiting, which hung acceptance tests once the prefix-form
keying made the drop path actually fire.

Realms are few and their subscriptions cheap, so stop reference-counting
them: install one on first use and release them all together when the
store resets or is destroyed. unsubscribeFromInstance now only stops
per-instance field-change tracking; a new unsubscribeFromAllRealms runs
from resetState and the destructor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
resetState runs at mid-session boundaries (realm/workspace switch, route
deactivate), not just teardown. Unsubscribing there stops realm
invalidations reaching cards that outlive the reset, hanging any test
that loads a card, crosses a resetState, then waits for an update. Keep
resetState's original behavior (drop the map, leave the subscriptions to
be re-established on next use) and release subscriptions only from the
destructor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Realm subscriptions are no longer torn down when a reference count hits
zero, so this test's post-drop assertion is inverted: the subscription
now persists past the last reference (released only on store destroy).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The session-lifetime subscription change removed the deterministic hang
but regressed invalidation-heavy tests ~2.7x (28s -> 78s): keeping every
realm subscription up means the store processes invalidations it
previously dropped during reference-count churn. Restore the pre-existing
per-reference teardown, which leaves mapped-realm (prefix-keyed)
subscriptions installed for the session as a benign, documented leak. §3
core canonical keying and the toURLHref perf tweaks are unaffected.

The subscription-lifecycle rework (safe teardown + cheaper invalidation
handling) is deferred; see the realm-subscription-lifecycle follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restores the store and render-service identifier keying to exactly the
form that was green (the §3-core state before any PR-feedback commits).
The toURLHref change was a perf suggestion layered on afterward; with the
unsubscribe fix and subscription-lifetime rework already reverted, this
returns the branch to pure §3-core canonical keying on current main.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@backspace

Copy link
Copy Markdown
Contributor Author

re the automated PR feedback, I originally replied with SHAs of fixes, but they were causing CI problems. They’re now recorded for followup in issues 12114 and 12143.

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