Skip to content

feat(web): consolidate canonical URN model — component entity + componentUrn#10

Merged
odenirdev merged 1 commit into
mainfrom
feat/canonical-consolidation
Jul 5, 2026
Merged

feat(web): consolidate canonical URN model — component entity + componentUrn#10
odenirdev merged 1 commit into
mainfrom
feat/canonical-consolidation

Conversation

@odenirdev

Copy link
Copy Markdown
Contributor

What

Closes the BASE / CANONICAL MODEL DATA PATTERN MVP task — consolidates the
web-side canonical identity (URN) model. The closed Entity union now covers all
four engine entities, and the model exposes both stored and type-level
identity factories. Interface + factory, no classes — a urn stays a plain string
across the RSC boundary.

DONE criteria

Criterion Status
Entity = page | site-setting | plugin | component urn.ts
buildUrn / componentUrn with tests urn.test.ts (6 tests)
No call site widened to plain string blockKey now returns Urn<string>
Wire/CMS contract untouched (urn never sent/stored by press-cms) ✅ zero packages/cms change

Changes

  • Entity gains component (additive — the ThemeName "additive, not breaking"
    precedent) → urn:component:{uid}.
  • New pure componentUrn(uid) factory (exported from the package root) + tests.
  • blockKey return type tightened stringUrn<string>: the COMPUTED
    per-instance key keeps its urn brand while staying a valid React key. This
    closes the one remaining "widened to string" call site and aligns code with the
    docs.
  • BlockRenderer's unknown-component dev warning now cites the canonical
    urn:component:… form (+ regression test).
  • Removed the now-redundant docs/superpowers/plans/2026-07-04-canonical-urn.md
    CLAUDE.md ("Canonical identity (URNs)") is the living reference.

Three identity classes (each wired to a real consumer)

  • STORED (Canonical<E>): Page (urn:page:{documentId}),
    ResolvedPressConfig (urn:site-setting:default), PressPlugin
    (urn:plugin:{id}).
  • TYPE-level (componentUrn): BlockRenderer unknown-component warning.
  • COMPUTED (blockKey): dynamic-zone React keys — urn:{__component}:{id},
    never stored.

Not in this PR (deliberately separate)

The working branch also carries two unrelated frontiers kept out of this commit to
keep concerns separate: the engine plugin content-type and the cookie-consent
findings. Those ship on their own.

Verification

  • pnpm --filter @ogs-tech/press-web test213/213
  • pnpm --filter @ogs-tech/press-web typecheck → clean ✅

🤖 Generated with Claude Code

…ponentUrn

Close the BASE/CANONICAL identity task. The closed `Entity` union now covers
all four engine entities and the model exposes both stored and type-level
identity factories.

- `Entity` gains `component` (additive, ThemeName precedent) → `urn:component:{uid}`
- add pure `componentUrn(uid)` factory + tests (`buildUrn` already covered)
- `blockKey` now returns `Urn<string>` (was plain `string`): the COMPUTED
  identity keeps its brand while staying a valid React key — no call site
  widened to plain string
- BlockRenderer's unknown-component dev warning cites the canonical
  `urn:component:…` form (+ test)
- drop the now-redundant canonical-urn plan doc (CLAUDE.md is the living ref)
- wire/CMS contract untouched: a urn is never sent or stored by press-cms

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@odenirdev
odenirdev merged commit 260d8ea into main Jul 5, 2026
1 check passed
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