Skip to content

Latest commit

 

History

History
109 lines (87 loc) · 5.11 KB

runtime-map.md

File metadata and controls

109 lines (87 loc) · 5.11 KB

Runtime map — who owns which screen

This app is a child runtime: it extends the published platform (bos://dev.everything.near/everything.dev) and overrides only what it changes. Some code is in this repo; some is a remote Module Federation bundle inherited through extends. This page is the authored guide to that split. The facts are generated; the conventions are here.

Generated artifacts (never hand-edit)

Artifact What it is
.bos/generated/runtime-map.json Full inventory: sources, mounts, every composed route with its owner and full path, shadowed claims, unresolved sources
ui/src/lib/runtime-map.gen.ts Typed view: REMOTE_ROUTES, RemotePath, RUNTIME_SOURCES, RUNTIME_MOUNTS, SHADOWED_ROUTES, UNRESOLVED_SOURCES

Both are gitignored and regenerated by pnpm run types:gen (which runs bos types gen first, then scripts/gen-runtime-map.mjs). pnpm run typecheck does this for you. To prove the static model still matches the real composition engine:

pnpm run verify:runtime-map   # runs constructTree over the same manifests and diffs

Remote route manifests are served at <ui.production>/manifest.gen.json — e.g. https://cdn.everything.dev/bundles/dev.everything.near/everything.dev/auth-ui/manifest.gen.json. They are not the plugin manifest (plugin.manifest.json) and not derivable from the MF entry.

Loud by default. If a remote manifest can't be fetched, the generator reports UNRESOLVED and fails — so an upstream route rename breaks typecheck instead of silently shrinking the map. For offline work, set BOS_MAP_ALLOW_UNRESOLVED=1.

Sources in this app

Key Kind Where it lives Source of truth
ui core ui this repo, ui/ local ui/src/routes/
auth auth plugin (server + UI) remote published bundle upstream github.com/NEARBuilders/everything-dev, plugins/auth/
registry, proposals API plugins this repo, plugins/ local contract.ts + index.ts (no UI)

There is no local auth workspace. bos.app.ts's auth block carries only this app's variables/secrets. To change auth behaviour, go upstream; to change an auth screen, claim its path locally (below).

Composition rules

  • Mounts are the only cross-source parenting points. This core ui declares public (_public.tsx, no gate), authenticated (_authenticated.tsx, session gate), and admin (_admin.tsx, admin gate). A plugin route whose id starts _public/… lives under the public mount, and so on.
  • Core ui wins. If a local route claims a path a plugin also claims, the local route wins and the plugin route is skipped (the host logs [Compose] … core ui wins; shadowed route skipped). Plugin-vs-plugin collisions throw — peer ambiguity is a config error.
  • Core-only degrade. Composed plugin paths 404 when the owning plugin isn't composed in. That is by design; it is why the pluginPath() helpers exist.

The three ways to change a screen

  1. Claim the path locally (fastest; no upstream release). Create a route file that claims the same path, e.g. ui/src/routes/_public/login.tsx. Core wins and the plugin's route is shadowed. Verify with pnpm run types:gen — the route should appear as ui-owned in runtime-map.json, and the plugin's claim as shadowed.
  2. Import the whole plugin workspace when you need to change its internals: bos import plugins/auth. This vendors a subtree from upstream so you own it. Heavier; you now maintain it.
  3. Change upstream when the behaviour belongs to everyone: open a PR at github.com/NEARBuilders/everything-dev, it ships in a platform release, then bump the platform: pin in bos.app.ts.
notice / issue in this repo
      → upstream PR (nearbuilders/everything-dev)
      → platform release (changesets)
      → pin bump in bos.app.ts
      → bos deploy

Navigating to plugin-owned paths

Plugin routes are not in the core's registered route tree, so a literal to="/login" does not typecheck. The honest boundary is pluginPath / pluginHref / pluginSearch from @/app (re-exported from everything-dev/ui/auth):

<Link to={pluginPath("/settings")} />

Typed native to for composed paths requires regenerating the route tree's fileRouteTypes in the framework typegen — tracked as everything-dev#345 / #346. Until then, pluginPath stays; do not add an interim typed wrapper (upstream recorded "no interim casts").

Non-navigational uses (prefix matching, label lookup) are typed against RemotePath from ui/src/lib/runtime-map.gen.ts, so an upstream rename fails typecheck.

Known limits

  • Nav labels are runtime-only — they live in route options (staticData.nav), not manifests, so the generated inventory reports nav: null and the live nav is assembled from pluginNav at runtime.
  • Remote search-param schemas are not in manifests — typed search for plugin paths needs a separate manifest story upstream.
  • The union freezes at generation time — runtime tenant UI overrides fall outside it; types there are advisory.