motir-core: the lesson permission keys — one to view, one to change the library — granted to admin
The catalog entries the rest of the epic gates on. Small, and worth landing alone so the review is only about the permission model.
Add the keys to lib/permissions/catalog.ts with their domain and enforcement, and grant them in lib/permissions/builtinRoles.ts to the admin role — following whatever the existing project:* keys do rather than inventing a shape.
Two keys, not one. Viewing what the planner learned and changing what it applies are different acts with different blast radii: reading is inspection, changing alters what the planner does for everyone on the project. Collapsing them means a role that can look must also be able to change, which forecloses the obvious future case of a member who can read the list.
The second key gates every change to the library, not only retiring. It covers retiring a lesson (MOTIR-3330) and adding one through the add_lesson MCP tool (MOTIR-3361). Both change the standing instructions the planner is given, so both belong behind the same grant; the line worth drawing is read versus change, and a third key splitting add from retire would express a distinction nobody has asked for. Name it accordingly — a key called …:retire acquires the wrong meaning the moment the second caller arrives.
Do not reuse project:administer. It would work today and it hides the distinction the catalog exists to express; a project that later wants a custom role with read-only lesson access would have no key to grant.
Both are project-domain, since a lesson belongs to a project.
Acceptance criteria
- Two keys — one for viewing, one for changing the lesson library — in the catalog with domain and enforcement set consistently with neighbouring
project:*entries. - The change key's name reads as change the library, not retire, since retiring and adding both take it.
- Both granted to the admin built-in role; no other built-in role gains them by default.
- The
viewerrole does NOT gain either, asserted. - Whatever guard test the catalog already has (totality over the key union, role-map coverage) passes with the new members and does not need weakening.
- No route, tool or UI reads them yet — this card adds the vocabulary only.
Context refs
motir-corelib/permissions/catalog.ts—PermissionKey, the domain/enforcement map,project:administer/project:browseas neighbours.motir-corelib/permissions/builtinRoles.ts— the role → key-set map, andviewer's deliberately small set.motir-corelib/permissions/resolve.ts— how a key is checked at a call site.- MOTIR-3345 — the retire mutation that takes the change key.
- MOTIR-3360 — the create seam that takes the same one.