Skip to content

feat(training-agent): mount /<tenant>/mcp-strict-required + mcp-strict-forbidden, route signed_requests at all three#4099

Draft
bokelley wants to merge 1 commit intomainfrom
claude/issue-4096-strict-required-forbidden-routes
Draft

feat(training-agent): mount /<tenant>/mcp-strict-required + mcp-strict-forbidden, route signed_requests at all three#4099
bokelley wants to merge 1 commit intomainfrom
claude/issue-4096-strict-required-forbidden-routes

Conversation

@bokelley
Copy link
Copy Markdown
Contributor

@bokelley bokelley commented May 4, 2026

Closes #4096

Summary

The signed_requests storyboard skips 9 vectors per tenant: 4 are explicit (skipVectors: 007/018/025 + skipRateAbuse for 020) and 5 are capability-incompatible because /<tenant>/mcp-strict advertises covers_content_digest: 'either', causing the grader to skip vectors requiring 'required' or 'forbidden' profiles. The authenticators and capabilities for both new profiles already existed in request-signing.ts — this PR mounts the routes and routes the storyboard runner at all three.

Changes:

  • server/src/training-agent/index.ts: adds lazy auth singletons (_strictRequiredSigningAuth, _strictForbiddenSigningAuth), authenticator builders, requireToken middleware, and route mounts for /<tenant>/mcp-strict-required and /<tenant>/mcp-strict-forbidden per tenant, following the /<tenant>/mcp-strict pattern. Refactors strictMcpHandler into a makeStrictMcpHandler(digestMode?) factory to share transport/error-handling logic across variants without duplication.
  • server/tests/manual/run-storyboards.ts: replaces the single signed_requests → /mcp-strict run with a 3-variant sequential loop. Per-route skipVectors: /mcp-strict keeps 007/018/025; /mcp-strict-required drops 007 (runs and passes); /mcp-strict-forbidden drops 018 (runs and passes).

Coverage lift per tenant:

Route variant Before After
signed_requests (either) 31P/9S unchanged
signed_requests (required) ~31P/4S
signed_requests (forbidden) ~31P/4S
Net per tenant 31P/9S 36P/4S

Across all six tenants: +30 steps recovered.

Non-breaking justification: adds new routes; existing /<tenant>/mcp-strict and /<tenant>/mcp routes are untouched. No schema changes. Changeset is --empty (no protocol spec impact).

Pre-PR review:

  • code-reviewer: approved — correct lazy-auth pattern, factory handler eliminates duplication, skipVectors assignments are sound; digestMode !== undefined guard applied
  • ad-tech-protocol-expert: approved — non-breaking per spec; skipVectors assignments correct per RFC 9421 (007 belongs on required route, 018 on forbidden route); note: vector 027 fixture hardcodes covers_content_digest: 'either' so it grades as capability-incompatible on the two new routes — correct behavior, 027 still runs on /mcp-strict
  • Capability wiring confirmed: selectSigningCapability(ctx) is called at task-handlers.ts:2950 inside handleGetAdcpCapabilities. ctx.digestMode flows through the makeStrictMcpHandler(digestMode) factory correctly — the new routes advertise the right covers_content_digest profile ('required'/'forbidden') in their capabilities response.

Triage-managed PR. This bot does not currently iterate on
review comments or PR conversation threads (only on the source
issue). To unblock:

  • Push fixup commits directly: gh pr checkout <num>
    fix → push.
  • Or re-trigger: comment /triage execute on the source
    issue.

See #3121
for context.

Session: https://claude.ai/code/session_01KnP4sw6wkheGXwHFTWjrFU

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-triaged Issue has been triaged by the Claude Code triage routine. Remove to re-triage.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

training-agent: mount /<tenant>/mcp-strict-required + /<tenant>/mcp-strict-forbidden, route signed_requests storyboard at all three

2 participants