113 lines
5.6 KiB
Markdown
113 lines
5.6 KiB
Markdown
|
|
# Boundary Identifiers — In-Package Reference
|
||
|
|
|
||
|
|
If you're editing files in this package, you must know which identifier
|
||
|
|
you're touching. Full spec:
|
||
|
|
`WORKSTREAMS/platform-control-plane-freeze/FOUR-ROOTS-DISENTANGLE.md`
|
||
|
|
(working title preserved for grep continuity).
|
||
|
|
|
||
|
|
## The Four Boundary Identifiers
|
||
|
|
|
||
|
|
| Boundary name | What it identifies | Example | Where it crosses boundaries |
|
||
|
|
|---|---|---|---|
|
||
|
|
| **subjectScope** | NATS subject prefix for this Host's actors | `SPACE-HIVECAST` | `data-subject-scope` attr, `bootstrap.subjectScope` JSON field, `IBrowserBootstrapResponse.subjectScope` |
|
||
|
|
| **authority** | Who owns this surface (user/principal) | `test-user-1` | `data-authority` attr, `bootstrap.authority` JSON field, `IBrowserBootstrapResponse.authority` |
|
||
|
|
| **appName** | Which webapp this is | `director` | `data-app-name` attr, `bootstrap.appName` JSON field, `matrix.json:appName` |
|
||
|
|
| **tabRuntimeId** | This browser tab's runtime identity | `test-user-1.DIRECTOR.SESSION-A1B2C3D4` | `data-tab-runtime-id` attr, computed client-side from `authority` + `appName` + session id |
|
||
|
|
|
||
|
|
## The discipline: clear at the boundary, flexible inside
|
||
|
|
|
||
|
|
The names above are required at **interface boundaries** — anywhere code in
|
||
|
|
this package talks to code outside it. That means:
|
||
|
|
|
||
|
|
- HTTP bootstrap response fields
|
||
|
|
- HTML attributes on `<matrix-dsl-host>`
|
||
|
|
- Exported TypeScript interfaces, types, and function signatures
|
||
|
|
- matrix.json fields
|
||
|
|
|
||
|
|
Inside private functions and private fields of this package, local variable
|
||
|
|
names can use whatever feels natural for the surrounding code. The
|
||
|
|
discipline is at the seams.
|
||
|
|
|
||
|
|
## Rules
|
||
|
|
|
||
|
|
1. **Boundary-crossing values use the canonical boundary name.** When you
|
||
|
|
read a value from a config file, HTML attribute, JSON field, or exported
|
||
|
|
interface, you read the canonical name (`subjectScope`, `authority`,
|
||
|
|
`appName`, `tabRuntimeId`). You can rename it as a local variable inside
|
||
|
|
your function if you want; just make sure the boundary read happened
|
||
|
|
under the right name.
|
||
|
|
|
||
|
|
2. **One concept per boundary name.** Never write `setAttribute('root', ...)`
|
||
|
|
in new code. The `root` attribute is ambiguous — it has meant all four
|
||
|
|
identifiers at different times in git history. Pick the specific one.
|
||
|
|
|
||
|
|
3. **No fallbacks.** Per CLAUDE.md "no fallbacks or legacy crutches,"
|
||
|
|
if `appName` is missing from a bootstrap that needs it, **throw**.
|
||
|
|
Do not silently degrade to using `subjectScope` in the `appName` slot —
|
||
|
|
that's the wire-crossing bug this workstream exists to fix.
|
||
|
|
|
||
|
|
4. **Forbidden boundary names** (do not introduce in new code at boundaries):
|
||
|
|
- `root` — meant all four at different times
|
||
|
|
- `realm` — alias of `root`, same problem
|
||
|
|
- `baseRoot` — got passed in as appName but is named after subjectScope
|
||
|
|
- `rootAttr` — generic, ambiguous
|
||
|
|
- `daemonRoot` / `daemonRealm` — pre-Host-Service legacy
|
||
|
|
- `busRoot` / `authorityRoot` / `runtimeRoot` — these were in-flight rename
|
||
|
|
drafts; superseded by `subjectScope` / `authority` / `tabRuntimeId`
|
||
|
|
- `transportRoot` — classify each site; if the value has `.SESSION-XXXX`,
|
||
|
|
the boundary name is `tabRuntimeId`; otherwise it's `subjectScope`
|
||
|
|
- `spaceRoot` — use `authority`
|
||
|
|
- `appRoot` — use `appName` or `tabRuntimeId` depending on which
|
||
|
|
|
||
|
|
5. **Allowed legacy aliases (compat only at boundaries, one release):**
|
||
|
|
- `bootstrap.root` — still emitted for one release; readers must migrate
|
||
|
|
- `bootstrap.platformRoot` — synonym of `subjectScope` during transition
|
||
|
|
- `bootstrap.addressRoot` — synonym of `authority` during transition
|
||
|
|
- `bootstrap.busRoot` / `bootstrap.authorityRoot` / `bootstrap.runtimeRoot` —
|
||
|
|
in-flight rename names from earlier drafts; emit both old and new for
|
||
|
|
one release so any consumer already coded against them keeps working
|
||
|
|
|
||
|
|
## HTML attribute writes are intent-explicit
|
||
|
|
|
||
|
|
When you write attributes during browser bootstrap, write the specific
|
||
|
|
canonical attribute name:
|
||
|
|
|
||
|
|
```ts
|
||
|
|
this.setAttribute('data-subject-scope', subjectScope); // not 'root', not 'realm'
|
||
|
|
this.setAttribute('data-authority', authority);
|
||
|
|
this.setAttribute('data-app-name', appName);
|
||
|
|
this.setAttribute('data-tab-runtime-id', tabRuntimeId);
|
||
|
|
```
|
||
|
|
|
||
|
|
The legacy `root` attribute is still written during the transition release
|
||
|
|
(transport readers in older code path still consume it as `subjectScope` in
|
||
|
|
hosted mode). New code reads `data-subject-scope` instead.
|
||
|
|
|
||
|
|
## Why this exists
|
||
|
|
|
||
|
|
Through git history, "root" has meant all four of these identifiers at
|
||
|
|
different times. `commit d73fc73ee` (May 14, 2026) introduced `busRoot`
|
||
|
|
as a separate bootstrap field when Space-claimed users couldn't load the
|
||
|
|
platform shell. That fix worked for transport, but the HTML attribute
|
||
|
|
`root` is read by THREE consumers expecting THREE different meanings, so
|
||
|
|
writing `busRoot` into it broke tab identity downstream
|
||
|
|
(`tab_realm.ts:generateIdentityTabRoot`, whose `appName` parameter was being
|
||
|
|
fed `busRoot` until this workstream landed).
|
||
|
|
|
||
|
|
The lesson: **at boundaries, names that say what they mean prevent the
|
||
|
|
wire-crossing class of bug.** Internal variable names can stay flexible;
|
||
|
|
the boundary names cannot.
|
||
|
|
|
||
|
|
## Where each identifier comes from
|
||
|
|
|
||
|
|
- **subjectScope** — server-side, derived from `status.transport.root` of
|
||
|
|
whichever Host's gateway answered the HTTP request
|
||
|
|
- **authority** — server-side, the signed-in principal's
|
||
|
|
`primary_authority_root` (or, on Device hosts, the Device's linked
|
||
|
|
authority from `host-auth.json`)
|
||
|
|
- **appName** — server-side, derived from the route's app context
|
||
|
|
(`/apps/director/` → `director`); declared in the package's `matrix.json`
|
||
|
|
- **tabRuntimeId** — client-side, generated as
|
||
|
|
`${authority}.${appName.toUpperCase()}.SESSION-${sessionId}`,
|
||
|
|
persisted in sessionStorage
|