§7 review checkpoint (todo §7); ran the architecture + product reviewers on the whole project and addressed findings, no Critical from either. Made permissions honest + decoupled the host from the plugin: new pure seedRoles + bootstrap discoverPlugins() seeds the demo admin admin(/ADMIN_ROLES) ∪ every discovered plugin's declared tokens, dropped the hardcoded scheduling:* from compose ADMIN_ROLES (clean-clone unchanged); docs now state a route/nav permission is a coarse role granted as Keto Role:<token>#members. Added src/plugin-api.ts — the stable author barrel the reference plugin now imports from instead of deep src/* (the contract boundary in code). Made per-plugin CSS usable: shell styles slot + plugins/scheduling/public/scheduling.css linked from the views. Reference now demonstrates hooks.onBoot validating SCHEDULING_UPSTREAM fail-loud (assertHttpUrl). Build ctx.chrome at most once per request (memoized). Doc honesty: fixed the false visual.spec coverage comment, softened the "every plugin ships a Playwright test" claim (authed flow = §8), added an Upstream contract block to the plugin README. Added LICENSE (MIT). Stability-reviewer APPROVE, no Critical/High; addressed both Low nits. typecheck + 301 units green. Deferred: internal route-table (M1)→§9, safeUrl()→§9, data-table empty-state + success-flash→§8/polish, apiVersion-literal enforcement (prose), permission→requireRole rename (future minor).

This commit is contained in:
2026-06-19 15:31:53 +02:00
parent 45d9b2ede9
commit 4e97fb619e
20 changed files with 214 additions and 50 deletions

View File

@@ -124,7 +124,7 @@ test("unknown routes serve the 404 page (a real user-facing flow, covered end-to
// The reference plugin (plugins/scheduling) ships discovered in the image. Its nav + routes are
// permission-gated, so an anonymous visitor never sees or reaches them (the authenticated list/form
// flow is covered by the full-stack suites). Side-effect-free.
// flow needs cross-host login infra — deferred to the §8 full E2E, todo line 121). Side-effect-free.
test("the reference plugin is permission-gated: anonymous → 403, hidden from the dashboard nav", async ({ page }) => {
const res = await page.goto("/scheduling/shifts");
expect(res?.status()).toBe(403);