docs(modules): core offers a contribution, never a slot name
Amends MODULE_API 1.6.0 in place - it has only ever been on edge, the same rule
the eighth and ninth members were given - and it is a correction rather than an
addition.
As first written, the inverted slot direction had core fill three literal
uo.guild.* names. That worked for module-uo and silently did nothing for anyone
else: a module declaring clan.detail under its own id got an empty page and no
error, because "a fill for a slot nobody declared is not an error" is exactly
the rule that makes an unknown name invisible. It also put a module identifier
inside core, in string literals the Sec 5.2 checker masks by construction.
Sec 3.7a now documents declareModuleSlot(id, name, { core }) and the three
contributions core offers - team.activity, team.forum, team.notify - as a
table, with the rules that follow from the direction: the member is optional, a
slot that asks for nothing stays empty, more than one slot may ask for the same
contribution, and asking for one core does not offer THROWS at the declaration
rather than rendering empty forever.
TEAMS.md's two accounts of the inversion (Part 3's supersession note and the
phase 3 amendment) say the same thing.
Also corrects the UI kit's count in Sec 3.4 and Sec 3.7a: Slot made it nine in
phase 3 and three places still said eight.
Found by phase 11 while writing the chapter that teaches this shape to an
audience outside this org.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -830,18 +830,20 @@ named for a *place* and never for a meaning):
|
||||
|
||||
> **Superseded 2026-08-17 (phase 3, org lead).** Both slots are gone, and the DIRECTION is what
|
||||
> changed. They assumed core rendered the Team page; core renders no Team page. The replacement is
|
||||
> `registry.declareModuleSlot(id, name)` — a **module** declares a place on its own page, namespaced
|
||||
> under its own id, and **core** fills it:
|
||||
> `registry.declareModuleSlot(id, name, { core })` — a **module** declares a place on its own page,
|
||||
> namespaced under its own id, naming which of core's contributions goes there, and **core** offers it:
|
||||
>
|
||||
> | Slot | Declared by | Rendered in | Filled by core with | Props |
|
||||
> | --- | --- | --- | --- | --- |
|
||||
> | `uo.guild.detail` | `module-uo` | its guild detail page | the Team activity feed (§4.3) | `{ externalId, moduleId }` |
|
||||
> | `uo.guild.forum` | `module-uo` | the same page, below the feed | the Team forum (Part 5) — added in phase 4 | `{ externalId, moduleId }` |
|
||||
> | `uo.guild.detail` | `module-uo` | its guild detail page | `team.activity` — the Team activity feed (§4.3) | `{ externalId, moduleId }` |
|
||||
> | `uo.guild.forum` | `module-uo` | the same page, below the feed | `team.forum` — the Team forum (Part 5), added in phase 4 | `{ externalId, moduleId }` |
|
||||
>
|
||||
> Core's fills are applied at MOUNT, not eagerly: core's bundle evaluates before every module chunk,
|
||||
> so when core registers a fill the slot does not exist yet. A fill for a slot no installed module
|
||||
> declares is a no-op, not an error — the mirror of an unfilled slot rendering nothing. `Slot` becomes
|
||||
> the eighth member of the shared UI kit so a module renders the place with core's own error boundary,
|
||||
> Core's contributions are applied at MOUNT, not eagerly: core's bundle evaluates before every module
|
||||
> chunk, so when core offers one, no module-declared slot exists yet. A contribution nothing asks for
|
||||
> is a no-op, not an error — the mirror of an unfilled slot rendering nothing. **Core names the
|
||||
> contribution and never the slot** (amended phase 11, inside 1.6.0: as first built it filled the
|
||||
> literal names above, which reached `module-uo` and no other game). `Slot` becomes
|
||||
> the ninth member of the shared UI kit so a module renders the place with core's own error boundary,
|
||||
> which matters here because the thing being contained is CORE's content failing inside the MODULE's
|
||||
> page.
|
||||
>
|
||||
@@ -2535,13 +2537,16 @@ guild called "Admin" cannot put an official-looking page on the site.
|
||||
>
|
||||
> **So the extension slots invert, and that is a new `MODULE_API` §3.7 direction.** `team.overview`
|
||||
> and `team.member.row` assumed core rendered the page. They are replaced by
|
||||
> `registry.declareModuleSlot(id, name)`: a **module** declares a place on its own page, namespaced
|
||||
> under its own id, and **core** fills it. `module-uo` declares `uo.guild.detail`; core fills it with
|
||||
> the activity feed, because only core can resolve whether a viewer is inside the Team and the
|
||||
> public/members split is a security boundary. Core's fills are applied at mount rather than eagerly —
|
||||
> core's bundle evaluates before every module chunk, so at the moment core registers a fill the slot
|
||||
> does not exist yet. `Slot` joins the shared UI kit as its eighth member so the module renders the
|
||||
> place with core's own error boundary.
|
||||
> `registry.declareModuleSlot(id, name, { core })`: a **module** declares a place on its own page,
|
||||
> namespaced under its own id, and names which of core's contributions belongs there. `module-uo`
|
||||
> declares `uo.guild.detail` and asks for `team.activity`; core offers the activity feed, because only
|
||||
> core can resolve whether a viewer is inside the Team and the public/members split is a security
|
||||
> boundary. **Core names the contribution, never the slot** — amended in phase 11, inside 1.6.0, after
|
||||
> the integration kit found that the literal-name version worked for one module and silently did
|
||||
> nothing for any other. Core's contributions are applied at mount rather than eagerly — core's bundle
|
||||
> evaluates before every module chunk, so at the moment core offers one, no module-declared slot exists
|
||||
> yet. `Slot` joins the shared UI kit as its ninth member so the module renders the place with core's
|
||||
> own error boundary.
|
||||
>
|
||||
> **A module names a Team in its own vocabulary**, so `GET /public/teams/by-external/:moduleId/:externalId`
|
||||
> is added: core's row id and slug are core-internal and handing them to a module is how a module ends
|
||||
|
||||
Reference in New Issue
Block a user