Skip to content

Admin pages: manifest admin_pages[] slot + lazy import + capability-gated routing #228

@tayebmokni

Description

@tayebmokni

Summary

Implement the admin pages slot: the manifests admin_pages array is the single canonical mechanism for plugin-supplied admin pages. The admin shell composes its menu from this array, gates access by the entrys capability field, and lazy-imports the entry ES module when the route is visited.

The SDKs registerMenu/registerAdminRoute calls are sugar that writes into this slot at build time, not a parallel runtime registry. Backward-compat: validator accepts legacy web.admin.menu shape and rewrites it.

Design reference

  • docs/02-plugin-system.md §7.3 (cross-refs doc 05)

Acceptance criteria

  • At plugin Activate, host parses manifest.admin_pages[] and registers each entry in the admin shells page registry: {slug, parent, title, icon, capability, entry, plugin_slug, plugin_version}
  • Admin shell menu composition (lives in admin app — see doc 05) reads from this registry to build the sidebar
  • Route resolution: when admin visits /admin/{plugin_slug}/{page_slug} the hosts admin router serves the layout shell and the pages entry ES module is lazy-imported via the import map
  • Client-side 403: if current user lacks the capability, the admin shell shows a 403 without importing the entry
  • Server-side enforcement: plugin REST endpoints serving the pages data INDEPENDENTLY re-check the capability (defense in depth)
  • Parent nesting: parent: "tools" nests under the core "Tools" menu; parent: "{slug}/{page-slug}" nests under another plugin page
  • Backward-compat: manifest validator accepts legacy web.admin.menu shape and rewrites to admin_pages at install time; emits a deprecation warning to the plugin author
  • Tests: page registered/unregistered across activate/deactivate; capability gate enforced; legacy web.admin.menu rewrite preserves semantics

Dependencies

#45 (lifecycle), #214 (frontend SDK), doc 05 (admin shell)

Complexity

M

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions