Skip to content

Update serialisation to write RRIs#5148

Draft
backspace wants to merge 10 commits into
mainfrom
serialise-rri-cs-10753
Draft

Update serialisation to write RRIs#5148
backspace wants to merge 10 commits into
mainfrom
serialise-rri-cs-10753

Conversation

@backspace

@backspace backspace commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

RRI handling currently deals with an ambiguity where one could be the https://cardstack.com/base/ style we’re moving away from (or another URL that will remain valid) or @cardstack/whatever-style. The virtual network is used to normalise, and is therefore passed around.

This moves adoptsFrom.module, relationships, and other RRIs to all be in their correct forms, which opens the way to CS-11450 removing the virtual networks everywhere and delaying resolution of non-URL RRIs until the moment of fetch.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Preview deployments

Host Test Results

    1 files  ±0      1 suites  ±0   1h 52m 49s ⏱️ + 4m 29s
3 081 tests ±0  3 058 ✅ ±0  15 💤 ±0  0 ❌ ±0  8 🔥 ±0 
3 100 runs  ±0  3 069 ✅ ±0  15 💤 ±0  8 ❌ ±0  8 🔥 ±0 

Results for commit b332198. ± Comparison against earlier commit cf4044f.

For more details on these errors, see this check.

Realm Server Test Results

    1 files  ±0      1 suites  ±0   11m 18s ⏱️ -41s
1 718 tests ±0  1 689 ✅ +2  0 💤 ±0  29 ❌  - 2 
1 811 runs  ±0  1 782 ✅ +2  0 💤 ±0  29 ❌  - 2 

Results for commit b332198. ± Comparison against earlier commit cf4044f.

For more details on these errors, see this check.

backspace and others added 3 commits June 15, 2026 09:09
Core of the persistence-format migration to RealmResourceIdentifier
(RRI) prefix form. The `@cardstack/base/` realm prefix is already
registered in the VirtualNetwork; this makes the runtime canonicalize
base-realm module identifiers to that prefix form everywhere they are
resolved, compared, or persisted.

- virtual-network.ts `unresolveURL`: chase a URL-shaped input through
  any registered virtual → real URL mapping and retry the realm-prefix
  match, so a virtual-alias URL canonicalizes to its RRI prefix. This
  is what flips `internalKeyFor` (and therefore index keys,
  `adoptsFrom`, `types`, and `deps`) to RRI form for base modules.
- definition-lookup.ts / host realm.ts: normalize both sides of the
  local-realm membership check via `unresolveURL` so an RRI-form (or
  resolved-URL) input still matches a realm keyed by its virtual alias.
- loader.ts: collapse dependency-tracker keys onto a single canonical
  URL form so a base module imported via the virtual alias and the
  same module imported via the RRI prefix don't fragment into two
  tracker entries.
- constants.ts: base code refs (baseRef/baseCardRef/specRef/etc.) move
  to the `@cardstack/base/` prefix form via the new `baseRealmRRI`.
- module-syntax.ts: emit RRI-form imports for new fields, reusing an
  existing equivalent import (URL or RRI) instead of duplicating.
- realm.ts / render routes / index-query engines: canonicalize emitted
  deps, the module-not-found message, and the realm-config adoptsFrom
  check to RRI form.
- realm-server main.ts/worker.ts/create-realm.ts: register the scoped
  `@cardstack/X/` prefix alongside the cardstack.com URL alias and emit
  RRI refs in bootstrapped realm config.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Surfaces that generate source code, hold lint config, or are realm
content now use the `@cardstack/base/` prefix form, matching what the
runtime resolves and persists.

- eslint-plugin-boxel import-utils + missing-card-api-import-config:
  the auto-import rule's configured target modules move to RRI form,
  and the rule treats URL-form and RRI-form base imports as equivalent
  so it merges into an existing import of either form rather than
  emitting a duplicate.
- create-file-modal / edit-field-modal / item-button: generated import
  lines and default code refs emit RRI form.
- base/cards-grid + cards-grid-layout, experiments-realm cards: realm
  content card refs move to RRI form.
- boxel-cli parse, boxel-ui spec generator, software-factory smoke
  scripts, vscode-boxel-tools skills: tooling that emits or asserts
  base code refs moves to RRI form.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Mechanical sweep across the test suites: fixtures and assertions that
referenced base-realm modules in virtual-alias URL form
(`https://cardstack.com/base/X`) now use the RRI prefix form
(`@cardstack/base/X`), matching what the runtime resolves, serializes,
and indexes after the preceding two commits.

Covers card-source fixtures, `meta.adoptsFrom.module` assertions,
`internalKeyFor`/types/deps expectations, deps-endpoint and search
assertions, DOM `data-test-card` selectors, and prompt/error-message
expectations across host, realm-server, ai-bot, matrix, boxel-cli,
eslint-plugin-boxel, software-factory, and runtime-common tests.

TypeScript module specifiers (`from '...'`, `typeof import('...')`) are
intentionally left in URL form: they resolve through pnpm/node and
flipping them breaks the dual-type-identity guarantee.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@backspace backspace force-pushed the serialise-rri-cs-10753 branch from 576bea3 to 448bc0e Compare June 15, 2026 14:30
backspace and others added 7 commits June 15, 2026 10:49
Temporary diagnostic to capture, for a missing contained-field
definition lookup, the computed lookup key, the canonical module URL,
and the definition keys actually present in the loaded module entry.
Used to pin down where the RRI key form diverges between persistence
and lookup. To be reverted once the root cause is fixed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The line-917 (missing-definition-key) diagnostic never fired, so the
CardInfoField FilterRefers throw originates at an earlier branch.
Add the same key/URL/realm logging to the no-context and
no-module-entry / entry-error branches to pin down which one and with
what canonical URL vs. registered realm URLs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
# Conflicts:
#	packages/eslint-plugin-boxel/lib/utils/import-utils.js
The definition lookup canonicalizes a code ref to a module URL that is
then used both as the cache key and as the module-load / prerender
target. For base-realm refs this resolved to the bare real URL
(`http://localhost:4201/base/X`), but the base realm is reachable
in-process only under its virtual-alias URL
(`https://cardstack.com/base/X`) — the alias is what the loader's
mounted handler / origin-matched auth interceptor recognizes. Fetching
the bare real URL bypasses that and fails at the transport ("Failed to
fetch"), which put the base card-api module entry into an error state
and made every contained-field definition lookup during search throw
FilterRefersToNonexistentType (HTTP 500 on _search).

`canonicalURL` now maps the resolved real URL back to its virtual-alias
form when a URL mapping is registered (only base today), so the
module-load target is the fetchable form — matching what the
pre-flip URL-form code path fetched. Realms with no alias map are
served at their real URL and are returned unchanged. Handles both the
RRI-prefix input and an already-resolved real-URL input.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The `missing-card-api-import` config emits the RRI prefix form, so when
the `_lint` endpoint auto-adds a missing base import (e.g. StringField)
it now writes `@cardstack/base/string`. Update the expected output for
the cases that exercise an auto-added import. Imports the source
already declares in URL form stay URL form — the rule merges the new
named specifiers into the existing line via the URL↔RRI equivalence —
so the `card-api` assertion that the prior sweep over-flipped to RRI is
restored to the URL form the merged import actually keeps.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Drops the temporary console.error scaffolding from the FilterRefers
throw sites now that the base module-load root cause is fixed (resolve
to the fetchable virtual-alias form). The throw sites return to their
original form.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both exercise the virtual-network / header-sanitizer boundary, where
the value is and must remain a real URL — the prior fixture sweep
over-flipped them to the RRI prefix form, which is not a valid URL:

- virtual-network-test redirect: addURLMapping's virtual key and the
  handler's Location header are virtual-alias URLs; `new URL('@cardstack/base/')`
  is invalid. Restore `https://cardstack.com/base/`.
- consuming-realm-header sanitizer: `sanitizeConsumingRealmHeader`
  accepts plain http(s) realm URLs and returns null for anything else,
  so an `@cardstack/base/` input correctly returns null. Restore the
  plain https URL the "accepts a plain https realm URL" case intends.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant