feat(mcp): content_policy gate on create_idea + dispatch-defense (sub-project C, Phase 2) #53

Merged
janpeter merged 3 commits from feat/copilot-content-policy-mcp into main 2026-06-14 09:26:19 +02:00
Owner

Sub-project C, Phase 2 - wires the AVG content-policy gate into the MCP idea-intake.

What

  • Submodule bump vendor/scrum4me-shared e29f3cd -> 9a0a0bd. mcp was behind (vendored #14); this syncs it to main, bringing #15 (copilot-roles: AccessLevel/CopilotAppUser/ProductMember.role+access) and #16 (content_policy + checker). 41 additive insertions to the generated prisma/schema.prisma, 0 deletions. Baseline after the bump alone: typecheck clean, 805/805.
  • create_idea gate (src/tools/create-idea.ts): after the access check, loads product.content_policy, parseContentPolicy (fail-closed on malformed), checkContentPolicy(title + description); refuses with toolError before any idea is created.
  • Dispatch-defense (src/lib/dispatch/idea-jobs.ts): re-checks the idea content against the product policy before dispatching an IDEA_* job (defense-in-depth for ideas that entered via an ungated path), throwing DispatchError on a hit. Fail-closed.

Tests

6 new (3 create_idea: forbidden refused / no-policy allowed / malformed fail-closed; 3 dispatch-defense: forbidden refused / clean allowed / malformed fail-closed). Full suite: typecheck clean, 811/811.

Notes

  • The checker itself (@shared/content-policy) was reviewed on scrum4me-shared #16 (3 codex + 3 adversarial rounds + 154 schema). This PR only wires it in.
  • Deploy after the live migration (Scrum4Me #83 / Task M2) - the gate READS content_policy, so it must not deploy before the column is live (migrate-first).
  • Workers bump intentionally deferred (no enforcement there).

🤖 Generated with Claude Code

**Sub-project C, Phase 2** - wires the AVG content-policy gate into the MCP idea-intake. ## What - **Submodule bump** `vendor/scrum4me-shared` e29f3cd -> 9a0a0bd. mcp was behind (vendored #14); this syncs it to main, bringing #15 (copilot-roles: AccessLevel/CopilotAppUser/ProductMember.role+access) **and** #16 (content_policy + checker). 41 additive insertions to the generated `prisma/schema.prisma`, 0 deletions. Baseline after the bump alone: typecheck clean, 805/805. - **`create_idea` gate** (`src/tools/create-idea.ts`): after the access check, loads `product.content_policy`, `parseContentPolicy` (fail-closed on malformed), `checkContentPolicy(title + description)`; refuses with `toolError` before any idea is created. - **Dispatch-defense** (`src/lib/dispatch/idea-jobs.ts`): re-checks the idea content against the product policy before dispatching an `IDEA_*` job (defense-in-depth for ideas that entered via an ungated path), throwing `DispatchError` on a hit. Fail-closed. ## Tests 6 new (3 create_idea: forbidden refused / no-policy allowed / malformed fail-closed; 3 dispatch-defense: forbidden refused / clean allowed / malformed fail-closed). Full suite: **typecheck clean, 811/811**. ## Notes - The checker itself (`@shared/content-policy`) was reviewed on scrum4me-shared #16 (3 codex + 3 adversarial rounds + 154 schema). This PR only wires it in. - Deploy after the live migration (Scrum4Me #83 / Task M2) - the gate READS `content_policy`, so it must not deploy before the column is live (migrate-first). - Workers bump intentionally deferred (no enforcement there). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/scrum4me-mcp!53
No description provided.