feat(guilds): a third place on the guild page, and where that page lives
All checks were successful
PR Checks / server-tests (pull_request) Successful in 23s
PR Checks / client-build (pull_request) Successful in 17s
PR Checks / frozen-manifest (pull_request) Successful in 34s

Two lines only core cannot supply for itself.

`uo.guild.header` is a third declared slot, at the top of the page, for core's
per-Team notification control. A third rather than a corner of the feed because a
slot holds one component and the first fill wins: the control is an action ON this
page and the other two are content IN it, and separate slots are what let this
module say so.

`pageUrlTemplate` tells core where a guild page actually is. Teams are a contract
primitive with no core surface — core owns the tables and the access rules, this
module owns the word "guild" and therefore the page — which leaves core unable to
write a link to one. A notification email that cannot take you to the thread it is
about is most of the way to useless. Core substitutes `{externalId}` and does
nothing else with it; a template naming its own host is refused at registration.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-18 14:35:36 -05:00
parent 7ce78e303c
commit c57310c505
4 changed files with 39 additions and 5 deletions

View File

@@ -317,4 +317,18 @@ async function projectRoster(externalId, members, viewer) {
}
}
module.exports = { getTeams, getTeamMembers, getTeamLeaders, projectRoster, boardIsCurrent }
// Where core should point a link at a guild (MODULE_API 1.6.0, TEAMS.md §6.4).
//
// **Core cannot work this out for itself, and it is not supposed to.** Teams are
// a contract primitive with no core surface — this module owns the guild page,
// because core does not own the word "guild" — so the one thing core needs back
// is where the page it does not own actually lives. A notification email that
// cannot link to the thread it is about is most of the way to useless.
//
// A relative path with `{externalId}` substituted, matching `Guild.jsx`'s route
// (`/uo/guilds/:id`). Core does the substitution and nothing else with it; a
// template naming its own host is refused at registration, which is why this is
// data and not a callback.
const pageUrlTemplate = '/uo/guilds/{externalId}'
module.exports = { getTeams, getTeamMembers, getTeamLeaders, projectRoster, boardIsCurrent, pageUrlTemplate }