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.
setEpicPrivacy(epicKey, publicChildrenHidden) (the exact name per 6.14.2’s flag) that updates the flag through workItemsService (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. A PATCH …/work-items/[key]/epic-privacy (or the epic’s settings route) — HTTP-only, typed-error→status.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.
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).--el-* + [data-display-style] tokens + shipped components/ui/*; 4-layer respected (route → service → workItemsService; no raw Prisma in the route).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.