§7 verify plugin contract end-to-end vs README (todo §7); cross-checked every contract claim in README/docs/plugin-contract.md/plugins/scheduling against the implementation + shipped reference plugin — the contract holds (derived id/mount, apiVersion+checkApiVersion, gated nav/routes, all RouteResult shapes, ctx.chrome native shell, ctx.verifyCsrf, can()/GuardError, view-resolver including core + own partials, registered icons, upstream-fetch statelessness). Fixed one doc drift: docs/plugin-contract.md reserved-id list named 8 ids but RESERVED_PLUGIN_IDS has 10 — the §5 admin + §6 oauth2 mounts were missing (discovery refuses them, test-covered), so the doc now lists all 10. Docs-only; typecheck + 296 units green.

This commit is contained in:
2026-06-19 15:02:59 +02:00
parent f189f88942
commit 45d9b2ede9
2 changed files with 7 additions and 5 deletions

View File

@@ -43,10 +43,11 @@ anywhere; no uppercase, underscores, dots, or slashes); the host rejects a malfo
at discovery. The id also namespaces the plugin's `views/`, its `/public/<id>/` assets, and (by
convention) its nav/permission tokens.
A handful of ids are **reserved** for the host's own first-party mounts (`auth`, `login`,
`logout`, `public`, `recovery`, `registration`, `settings`, `verification`); since plugin routes
resolve first, a folder claiming one would silently shadow a built-in route, so discovery refuses
it loud (`RESERVED_PLUGIN_IDS`).
A handful of ids are **reserved** for the host's own first-party mounts — the Kratos auth flows
(`auth`, `login`, `logout`, `recovery`, `registration`, `settings`, `verification`), the `admin`
screens, the `oauth2` provider routes, and `public` (static). Since plugin routes resolve first, a
folder claiming one would silently shadow a built-in route, so discovery refuses it loud
(`RESERVED_PLUGIN_IDS`).
Installing a plugin is "drop the folder, restart." Removing one is "delete the folder, restart."
Nothing else references it; the operator stays in control through the central menu override