MOTIR-437Done
6.14.7 Project-admin control — set/unset an epic as private (project-admin-gated via 6.4)
Estimate: 40m · Depends on: 6.14.1, 6.14.3
Build the project-admin control to set/unset an epic as private per the 6.14.1 design, over the 6.14.3 flag — the write path that turns epic privacy on and off.
- The service + route (4-layer): a service method
setEpicPrivacy(epicKey, publicChildrenHidden)(the exact name per 6.14.2’s flag) that updates the flag throughworkItemsService(the shipped write authority), validating that the target is an EPIC-kind item (reject otherwise, per 6.14.2) and that the project is the right tenant. Gated to the PROJECT ADMIN — reuse the 6.4 project-admin check (NOT a new permission); a non-admin is rejected (403). One service method = one transaction. APATCH …/work-items/[key]/epic-privacy(or the epic’s settings route) — HTTP-only, typed-error→status. - The UI: the set-private toggle / segmented control on the epic (in the epic’s actions or settings area) per the 6.14.1 design, project-admin-gated (non-admins see it read-only or absent). Inline edits follow the no-whole-tree-refresh rule (a success response is the confirmation — do NOT fan out a router.refresh / revalidate that would revert the cell). Uses ONLY shipped
components/ui/*+--el-*/[data-display-style]tokens.
Stay 4-layer: the route parses + calls the one service method; the service owns the transaction + the epic-kind + admin validation + the workItemsService write; no raw Prisma in the route.
Acceptance criteria
- A project admin can set/unset an epic private via the control; the flag persists through
workItemsService; setting it on a non-epic is rejected; a non-admin is rejected (403) and sees the control read-only/absent (project-admin-gated via the 6.4 check, no new permission). - The toggle reflects the current state and uses the success-response-is-confirmation pattern (no whole-tree refresh on success); the control matches the 6.14.1 design.
- Only
--el-*+[data-display-style]tokens + shippedcomponents/ui/*; 4-layer respected (route → service →workItemsService; no raw Prisma in the route).
Context refs
- 6.14.1 (design asset — required), 6.14.3 (the flag the write sets), 6.14.2 (the epic-only + admin-gated rules).
scripts/plan-seed/data/story-6.4.ts§ 6.4.4 — the project-admin check reused (mirror, do not fork; no new permission).motir-core/lib/services/workItemsService.ts— the write authority the flag update routes through.motir-core/components/ui/*+app/globals.css;motir-core/CLAUDE.md§ 4-layer + § colour/shape tokens + the inline-edit no-whole-tree-refresh rule.