MOTIR-4243In Review
Mount the Public page room — the registry entry with a `cloudOnly` flag, the page with its guard and off-cloud 404, and the read that returns all three hero fields
Carved out of MOTIR-4171 by the split MOTIR-4205's sizing re-check produced (2026-09-02). The design of record is design/projects/public-page.mock.html + design/projects/design-notes.md § Public page — the room in project settings (MOTIR-4205); this card is the MOUNT — the door, the page and the read — and MOTIR-4171 (blocked by it) builds the room's client island on top.
What to do
- The registry entry —
lib/settings/projectSettingsNav.ts, per the notes' table:id: 'public-page',group: 'access', placed directly aftermembers,href: '/settings/project/public',icon: Globe,labelKey: 'nav.publicPage',permission: 'project:administer'(VERIFIED:publicProjectsService.setPublicOverviewrefuses throughprojectAccessService.assertCanManage, which assertsproject:administer—lib/services/projectAccessService.ts:684; write the evidence comment the other entries carry). The palette action and the totality pairing follow from the entry. - A
cloudOnly?: trueflag onSettingsNavEntryand its filter. The registry filters on permission only; the row must be ABSENT off-cloud (the public surface does not exist there — MOTIR-3908,lib/publicProjects/cloudGate.ts).app/(authed)/layout.tsx:282already resolvespublicProjectsAvailable = isCloud(); thread it toSidebarNavand dropcloudOnlyentries invisibleSettingsNav(andhasVisibleSettingsArea) when it is false. The totality test keeps pairing the route with the entry regardless of the flag. - The page —
app/(authed)/settings/project/public/page.tsx: the members page's shape (getSession→getActiveProject→ the no-projectEmptyState),guardSettingsPage('public-page', ctx)(MOTIR-2469),if (!isCloud()) notFound()(the billing page's precedent,settings/organization/billing/page.tsx:24), the header from the notes (h1 font-serif text-3xlPublic page +settings.publicPage.subtitlewith the project name), and the initial values handed to the island. Until MOTIR-4171 lands the island, the page renders the header alone — an admin-only room for the window between two PRs in one sprint; say so in the PR. - The read —
projectsService.getPublicOverview(lib/services/projectsService.ts~:905) returns the body only. Widen it (or addgetPublicHero) to return{ publicOverviewMd, publicTagline, publicTags }from the project row through the repository, browse-scoped as today; a real-database test covers the null / authored arms. - i18n —
nav.publicPage,publicPage.title,publicPage.subtitlein en and zh (the notes' catalog). The island's ~30 keys are MOTIR-4171's. - Delete the forward-looking guard rows MOTIR-4205 added in
tests/design-asset-addresses.test.ts— the twoKNOWNrows for/settings/project/publicand theKNOWN_PATHSrow for this page file — in the same commit;carries no KNOWN entry that has stopped applyinggoes red otherwise.
Acceptance criteria
- The rail's Access group shows Public page directly under Members & access for a
project:administerholder, withGlobe, active on/settings/project/public— matchingdesign/projects/public-page.mock.htmlPanel A frame ① and Panel B's rail. - A member without
project:administersees no row, and the typed URL is refused by the destination guard (tests/settings/projectSettingsNav.test.ts's access matrix gains the row). - With
MOTIR_CLOUDunset the row is absent (asserted through thecloudOnlyfilter) and the route answers 404 (notFound()), asserted like the billing page's self-host spec. - The route ↔ registry totality test stays green with the new page and entry; the ⌘K palette offers Public page from the registry with no hand-written action.
- The widened read returns all three hero fields, null-safe, and the page passes them to the island as its initial values.
nav.publicPage/publicPage.title/publicPage.subtitleexist inenandzh.- The three forward-looking guard rows are deleted in this commit and
vitest run --config vitest.design.config.tsis green. - Its own tests ship with it; no full-suite and no
--coveragerun locally.
Context refs
motir-core/lib/settings/projectSettingsNav.ts— the registry, its evidence comments,visibleSettingsNav/hasVisibleSettingsAreamotir-core/app/(authed)/layout.tsx:257 / :282 —settingsPermissionsandpublicProjectsAvailablemotir-core/app/(authed)/settings/project/members/page.tsx— the page shape to mirror;_guard.tsx—guardSettingsPagemotir-core/app/(authed)/settings/organization/billing/page.tsx:24— the off-cloudnotFound()precedentmotir-core/lib/services/projectsService.ts~:905getPublicOverview— the read to widenmotir-core/tests/design-asset-addresses.test.ts— the three rows to deletemotir-core/design/projects/design-notes.md§ The entrance — three doors, and the registry entry behind the first- MOTIR-4205 — the design; MOTIR-4171 — the island this mounts