Skip to content

feat(ai): hold MCP tools and chat to what an analyst may do - #2547

Merged
Makisuo merged 6 commits into
observer/enforcementfrom
observer/agents
Nov 13, 2026
Merged

Makisuo merged 6 commits into
observer/enforcementfrom
observer/agents

fix(ai): keep analysts from driving or stopping an investigation's chat

ee977ef
Select commit
Loading
Failed to load commit list.
Maple Review Bot / Maple / review succeeded Nov 13, 2026 in 2m 57s

Confidence 10/10 · No issues found

🟢 Confidence 10/10 · safe to merge. Every refusal reads the role from the resolved tenant and each branch has a test; the ai test shards were cancelled in CI, so those cases are unverified here.
no findings · tests covered · risk high

Adds a role-based analyst gate to MCP tools/list, tools/call and chat turns, and refuses analysts the investigation chat's POST routes. The open McpQueryError issues in registry.ts are in a query path this diff does not touch. Safe to merge.

  • refusesAnalyst/refusalFor refuse an analyst every mutating MCP tool but dashboards and feedback
  • tools/list hides those tools through a second visibility gate; read-only keys keep theirs
  • profileForRoles turns an analyst chat turn's ask rules into deny outside dashboards
  • resolveSession answers an analyst's POST /messages and /abort with a 403

Fixed since the last review

  • ✅ F1 · The observer's tools/list hiding has no test

Production impact

Open errors in the changed files (2)
Issue Service Occurrences File
@maple/mcp/errors/McpQueryError (7 issues) maple-ai 33 apps/ai/src/mcp/tools/registry.ts
@maple/mcp/errors/McpQueryError (3 issues) maple-chat 15 apps/ai/src/mcp/tools/registry.ts

After this merges, Maple checks whether they stop.

Production traffic of the changed files (last 7 days)
File Calls/day Busiest operations
apps/ai/src/mcp/server.ts 1.9k tools/list 1.9k/day, 0.0% err
apps/ai/src/routes/chat-sessions.http.ts 547 GET 300/day, 0.3% err
GET 247/day, 3.1% err
What was checked
  • forAnalyst rewrites rules in place after the * allow, and permission evaluation is last-match-wins (packages/domain/src/permission.ts:58)
  • All seven DASHBOARD_AUTHORING_TOOLS names match registered tools (apps/ai/src/mcp/tools/*-dashboard*.ts); no delete_dashboard tool exists
  • /internal/chat/apply settles a recorded proposal by reference only (apps/ai/src/routes/internal/chat.http.ts:43), so an analyst cannot inject a tool and arguments

ee977ef · Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.