docs: record the five Phase 8 prerequisites, and report contributions
Bring the living documentation in line with what the five passes actually shipped, and correct the claims they superseded rather than leaving them to mislead: the module UI context is six members, not five; module styling is compiled CSS, not inline objects only; the strict manifest is version 7. Also close a silent failure the new contribution mechanism introduces. A contribution whose target capability nobody provides — or whose provider moved outside its declared range — is not published, and the manifest is valid and the artifact exists, so an operator sees a screen that renders nothing with no error anywhere. `pnpm modules:validate` now lists each declared contribution with its capability and range and says whether a compatible provider is installed, and Doctor's discovery check reports the same per module. Both derive from the publication registry the API serves from, so neither can disagree with what a running platform would actually publish. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ca3f37d5f9
commit
20d5128bad
@@ -69,6 +69,77 @@ protocol-relative, backslash-prefixed, and scheme-bearing values cannot become n
|
||||
Modularity checks keep authentication out of the module UI SDK/context and Dashboard login code out
|
||||
of the separate display bundle.
|
||||
|
||||
Phase 8 adds evidence for the five platform prerequisites.
|
||||
|
||||
**Design tokens and shared elements** (ADR 0039). The token registry's tests prove it is
|
||||
deterministic and enumerable, that every token derives a unique `--ekklesia-*` identifier from its
|
||||
name and carries a label, description, and category, that each status family pairs a colour with a
|
||||
non-colour symbol, and that a duplicate name, an unknown category, an invalid or single-segment name,
|
||||
and a value carrying a declaration terminator, a rule block, a comment, an at-rule, `url(`,
|
||||
`!important`, an escape, a control character, or markup are each rejected — with an error that never
|
||||
echoes the rejected declaration. The elements' tests assert accessible structure (label/hint/error
|
||||
association, icon-button naming, tab roles and arrow-key movement, announced error and loading
|
||||
states), that status never depends on colour alone, that a dialog renders in place rather than
|
||||
portalling out of an isolated root, and — mechanically — that the stylesheet and every component
|
||||
source contain no literal colour, font stack, or theme value and reference only registered tokens.
|
||||
Both packages compile module-shaped source under the exact browser project a module uses, where
|
||||
`process.env` must fail to typecheck, so the browser boundary is measured rather than asserted.
|
||||
|
||||
**Module stylesheets and artifact isolation** (ADR 0040). The builder's tests prove a plain
|
||||
stylesheet is compiled into the declared artifact with no `.css` emitted beside it, that a local
|
||||
`@import` is inlined, and that an unresolved `@import`, a stylesheet declaring an `--ekklesia-*`
|
||||
variable, and a non-CSS dialect are each rejected with their own sanitized code — while a private
|
||||
alias derived from a registered token is accepted. The loader's tests prove every artifact mounts
|
||||
inside an open shadow root, that the artifact receives that root rather than the host's element, that
|
||||
exactly one `<style>` is installed per mount and never accumulates across remounts, that the host's
|
||||
base rules precede the artifact's so a display can override `:host`, that unmount removes the whole
|
||||
root even when the module's cleanup throws, that a failed mount leaves neither DOM nor styles behind,
|
||||
that an environment without Shadow DOM fails closed rather than mounting unisolated, and that an
|
||||
artifact built against the previous ABI is refused with `MODULE_UI_ABI_UNSUPPORTED`. The template's
|
||||
suite builds real React artifacts through the canonical pipeline and asserts the compiled stylesheet
|
||||
travels inside the one declared file.
|
||||
|
||||
**Browser contributions** (ADR 0041). Manifest tests cover namespacing, the single local segment,
|
||||
duplicate ids and artifact paths, collision with an entrypoint, and a contribution targeting a
|
||||
capability its own module provides. Discovery tests prove a contribution artifact inherits the exact
|
||||
path, symlink, containment, extension, and file-kind protections every other compiled entrypoint has,
|
||||
including two contributions linked to one file. Publication tests prove a contribution is published
|
||||
only when another eligible module provides its capability *within the declared range*, that the
|
||||
contributing module never sees its own contribution, that a lookup fails closed on an unknown,
|
||||
mismatched, or non-string identity, and that the published record carries no domain vocabulary at
|
||||
all. Route tests prove the artifact is served byte-for-byte at a URL that cannot select a neighbour,
|
||||
and that an unknown id, another module's id, a traversal, a source map, a wrong version, an absent
|
||||
provider, and an incompatible provider all collapse into one indistinguishable `404`. The loader's
|
||||
tests cover mount, update-without-remount, a renderer that declares no `update`, deterministic and
|
||||
idempotent unmount, a sanitized update failure, and input that is not genuinely JSON — a `Date`, a
|
||||
function, `NaN`, `undefined`, and a cycle — refused *before* anything is imported and without ever
|
||||
echoing the consumer's data. The flagship shell fixture drives the whole relationship: a `signage`
|
||||
module discovers, mounts, updates, and unmounts an `announcements` React renderer with neither module
|
||||
importing the other, the consumer seeing identity but never a URL, the host resolving publication,
|
||||
and a contribution id the server withheld refused without a fetch.
|
||||
|
||||
**Bounded streaming uploads** (ADR 0042). Contract tests pin the two ceilings, that `maxBodyBytes` is
|
||||
checked against the ceiling the declared mode selects, that 32 MiB holds a 25 MiB image and one byte
|
||||
more is refused, and that no mode admits an unbounded body. HTTP tests cover exact-boundary success,
|
||||
a declared `Content-Length` refused before the handler runs, a misleading smaller `Content-Length`
|
||||
that cannot smuggle a megabyte past the limit, a chunked overflow, a `413` that still wins when the
|
||||
handler swallowed the stream error, proof that the body is genuinely not buffered (a handler sees the
|
||||
first chunk before the last is produced), an aborted upload surfacing as an ordinary failure rather
|
||||
than a `413`, an unread body being released, authorization ordering in both directions, and a
|
||||
rejection that names no limit, size, or body content. The live suite uploads a real 25 MiB body over
|
||||
a real socket end to end and proves the server is healthy immediately afterwards.
|
||||
|
||||
**Display offline fallback** (ADR 0043). The worker's caching logic is exercised directly, because it
|
||||
touches no global: first online load, offline reload after one successful visit, a missing uncached
|
||||
artifact failing honestly, contributed-renderer fallback, version upgrade with pruning that keeps
|
||||
every artifact of the current version and never touches another module's, superseded cache
|
||||
generations removed while unrelated ones survive, network-first behaviour picking up rebuilt bytes,
|
||||
and an explicit inventory proving the descriptor, principal, module API, realtime stream, pairing
|
||||
exchange, auth routes, cross-origin signed object URLs, and the worker itself are **never** stored —
|
||||
so a revoked device's refusal is what a reconnected display sees. Page-level tests cover the quiet
|
||||
offline indicator, a cache fallback reported while the browser still claims to be online, automatic
|
||||
re-resolution when the network returns, and a revoked device dropping back to pairing on reconnect.
|
||||
|
||||
`pnpm verify` is intentionally Docker-free. It never plans or applies migrations against a live
|
||||
database.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user