Skip to content

feat(adt-mcp): enforce scoped safe execution#143

Merged
ThePlenkov merged 18 commits into
mainfrom
feat/scoped-safe-execution
Jul 24, 2026
Merged

feat(adt-mcp): enforce scoped safe execution#143
ThePlenkov merged 18 commits into
mainfrom
feat/scoped-safe-execution

Conversation

@ThePlenkov

@ThePlenkov ThePlenkov commented Jul 24, 2026

Copy link
Copy Markdown
Member

User description

Purpose

This PR adds execution-scoped safe execution enforcement for the ADT MCP server, implementing a generic signed adt-execution-v1 policy with strict bounds on tool calls, duration, and result sizes.

Changes

  • adds a generic signed adt-execution-v1 policy with exact destination, resource, tool, operation, and call limits
  • keeps existing invocation policies fully compatible; the extension is additive
  • requires deployment-owned one-shot authorization and terminal outcome hooks for safe execution
  • consumes authorization before SAP I/O, prevents replay, hard-aborts at the signed deadline, and reports one terminal outcome
  • bounds duration, result size, findings, objects, packages, variants, tests, and coverage data
  • limits scoped reads to object tools with exact canonical resource comparison
  • adds adversarial policy, replay, cancellation, concurrency, timeout, result-limit, and outcome tests

Verification

  • focused policy/runtime tests: 46/46 passed
  • invocation auth integration: 6/6 passed
  • ADT server integration: 20/20 passed
  • broker integration: 17/17 passed
  • client cancellation: 3/3 passed
  • adt-mcp and adt-server runtime builds passed
  • ESLint: zero errors
  • Prettier and git diff --check: passed

Summary by cubic

Enforces scoped safe execution in @abapify/adt-mcp using signed adt-execution-v1 policies, with a hard‑cancellable runtime across @abapify/adt-client and @abapify/adt-server. Tightens scope gating, requires objectType for get_object and get_object_structure, hardens ADT session cleanup, and relaxes JWT validation to accept extra claims.

  • New Features

    • Enforces signed adt-execution-v1 policies (destination/resources, allowlisted tools/classes, max tool calls, deadlines, result limits); prevents replay and records one terminal outcome.
    • Tool gating: atc_run and run_unit_tests only under safe_execute; hides safe_execute tools when hooks are missing; deterministic SAP HTTP failures become terminal outcomes; resolves ATC scope URIs before worklist creation; returns a normal MCP error for missing ATC objects; includes program/class alerts in totals.
    • Scope handling: projects only read tools for read scopes; hides run_unit_tests; fail‑closed on empty resourceKeys for both read and safe‑execute; exact canonical comparisons; get_object and get_object_structure now require uppercased objectType and normalize base types.
    • Cancellation/runtime: threads AbortSignal through client and server; runWithAdtAbortSignal is async; preserves session path/CSRF for DELETE; validates and normalizes ADT session paths (blocks dot‑segments), passes URL objects to fetch, and cleans up on failed CSRF acquisition without caching cleanup tokens.
    • Enforcement polish: pre‑reserves maxToolCalls and rolls back on denial; per‑execution counters persist across calls (limits enforced after terminal outcome); deduplicates helpers (extractSafeExecutePolicy, handleSafeExecuteError, safeExecuteLimitResult); exports parseScopedAdtInvocationPolicy, parseSafeExecutePolicy, and related types.
    • Token validation: removes exact‑key checks on JWT payload/header; now validates required alg/kid/typ and trusted claim fields so issuers can add extra claims without breaking policies.
  • Migration

    • Provide consumeExecutionAuthorization, reportExecutionOutcome, and executeWithDeadline via @abapify/adt-server (defaults to executeWithDeadlineAndAbort); without executeWithDeadline, safe execution is denied and safe_execute tools are hidden.
    • Update all get_object and get_object_structure calls to include objectType (e.g. CLAS, PROG).
    • Issue invocation tokens with agentId adt-execution and constraint.kind adt-execution-v1, including resource/tool scope and limits.

Written for commit 89e5490. Summary will update on new commits.

Review in cubic


Generated description

Below is a concise technical summary of the changes proposed in this PR:

graph LR
    subgraph "@abapify/adt-mcp" ["@abapify/adt-mcp"]
    createMcpServer_("createMcpServer"):::modified
    destinationModeServer_("destinationModeServer"):::modified
    parseScopedAdtInvocationPolicy_("parseScopedAdtInvocationPolicy"):::added
    parseSafeExecutePolicy_("parseSafeExecutePolicy"):::added
    registerRunUnitTestsTool_("registerRunUnitTestsTool"):::modified
    extractSafeExecutePolicy_("extractSafeExecutePolicy"):::added
    handleSafeExecuteError_("handleSafeExecuteError"):::added
    registerAtcRunTool_("registerAtcRunTool"):::modified
    createMcpServer_ -- "Pass scoped authorization/outcome/deadline hooks to destinationModeServer." --> destinationModeServer_
    parseScopedAdtInvocationPolicy_ -- "Materializes scoped safeExecutePolicy from constraint for safe execution." --> parseSafeExecutePolicy_
    registerRunUnitTestsTool_ -- "Derives run_unit_tests safePolicy limits from requestAccess.scoped." --> extractSafeExecutePolicy_
    registerRunUnitTestsTool_ -- "Formats known HTTP failures; rethrows nondeterministic under safePolicy." --> handleSafeExecuteError_
    registerAtcRunTool_ -- "Derives atc_run safePolicy limits from requestAccess.scoped constraints." --> extractSafeExecutePolicy_
    registerAtcRunTool_ -- "Handles deterministic ATC failures; propagates unknown outcomes." --> handleSafeExecuteError_
    classDef added stroke:#15AA7A
    classDef removed stroke:#CD5270
    classDef modified stroke:#EDAC4C
    linkStyle default stroke:#CBD5E1,font-size:13px
    end
    subgraph "@abapify/adt-client" ["@abapify/adt-client"]
    SessionManager_initializeCsrf_("SessionManager.initializeCsrf"):::modified
    SessionManager_buildSessionsUrl_("SessionManager.buildSessionsUrl"):::added
    SessionManager_createSecuritySession_("SessionManager.createSecuritySession"):::added
    SessionManager_acquireCsrfToken_("SessionManager.acquireCsrfToken"):::added
    SessionManager_deleteSecuritySession_("SessionManager.deleteSecuritySession"):::added
    SessionManager_deleteSecuritySessionWithFallback_("SessionManager.deleteSecuritySessionWithFallback"):::added
    SessionManager_handleCsrfInitializationError_("SessionManager.handleCsrfInitializationError"):::added
    SessionManager_fetchSecuritySessionCsrfToken_("SessionManager.fetchSecuritySessionCsrfToken"):::added
    SessionManager_initializeCsrf_ -- "Builds trusted sessions URL with optional sap-client/sap-language." --> SessionManager_buildSessionsUrl_
    SessionManager_initializeCsrf_ -- "Creates temporary security session via GET, extracts trusted session path." --> SessionManager_createSecuritySession_
    SessionManager_initializeCsrf_ -- "Acquires CSRF token using x-sap-security-session use, respects abort signal." --> SessionManager_acquireCsrfToken_
    SessionManager_initializeCsrf_ -- "Deletes temporary session with cached CSRF, passes abort signal." --> SessionManager_deleteSecuritySession_
    SessionManager_initializeCsrf_ -- "On failure, performs fallback cleanup using fresh CSRF token." --> SessionManager_deleteSecuritySessionWithFallback_
    SessionManager_initializeCsrf_ -- "Centralizes initialization errors; triggers best-effort session slot cleanup." --> SessionManager_handleCsrfInitializationError_
    SessionManager_deleteSecuritySessionWithFallback_ -- "Fetches fresh cleanup CSRF token, avoiding shared CSRF pollution." --> SessionManager_fetchSecuritySessionCsrfToken_
    SessionManager_fetchSecuritySessionCsrfToken_ -- "Uses fetched token to issue DELETE for temporary session." --> SessionManager_deleteSecuritySession_
    classDef added stroke:#15AA7A
    classDef removed stroke:#CD5270
    classDef modified stroke:#EDAC4C
    linkStyle default stroke:#CBD5E1,font-size:13px
    end
    subgraph "@abapify/adt-server" ["@abapify/adt-server"]
    main_("main"):::modified
    createAdtServerMcpOptions_("createAdtServerMcpOptions"):::modified
    executeWithDeadlineAndAbort_("executeWithDeadlineAndAbort"):::added
    AdtServerMcpRuntimeOptions_("AdtServerMcpRuntimeOptions"):::modified
    ADT_MCP_("ADT_MCP"):::modified
    ADT_CLIENT_("ADT_CLIENT"):::added
    createServerMcpHandler_("createServerMcpHandler"):::modified
    AdtServerMcpOptions_("AdtServerMcpOptions"):::modified
    main_ -- "Passes executeWithDeadlineAndAbort into createAdtServerMcpOptions configuration." --> createAdtServerMcpOptions_
    main_ -- "Supplies execution deadline handler to MCP runtime options." --> executeWithDeadlineAndAbort_
    createAdtServerMcpOptions_ -- "AdtServerMcpRuntimeOptions now includes authorization, outcome, and deadline overrides." --> AdtServerMcpRuntimeOptions_
    createAdtServerMcpOptions_ -- "Defaults executeWithDeadline to executeWithDeadlineAndAbort when absent." --> executeWithDeadlineAndAbort_
    createAdtServerMcpOptions_ -- "ADt-mcp setup now supports safe_execute authorization/outcome integration." --> ADT_MCP_
    executeWithDeadlineAndAbort_ -- "Uses runWithAdtAbortSignal to abort and await deadline enforcement." --> ADT_CLIENT_
    createServerMcpHandler_ -- "createServerMcpHandler forwards safe-execute hooks from AdtServerMcpOptions." --> AdtServerMcpOptions_
    classDef added stroke:#15AA7A
    classDef removed stroke:#CD5270
    classDef modified stroke:#EDAC4C
    linkStyle default stroke:#CBD5E1,font-size:13px
    end
Loading

Enforce execution-scoped safe execution across the ADT MCP flow by adding signed adt-execution-v1 policies, scoped tool/resource validation, and one-shot grant consumption with terminal outcome reporting. Propagate execution abort signals through @abapify/adt-client and @abapify/adt-server, harden ADT session cleanup, and require objectType for get_object.

TopicDetails
Cancellation flow Propagate the execution abort signal through ADT client requests and CSRF/session handling so scoped runs can be cancelled cleanly without leaking cleanup work across concurrent invocations.
Modified files (5)
  • packages/adt-client/src/adapter.ts
  • packages/adt-client/src/cancellation.ts
  • packages/adt-client/src/index.ts
  • packages/adt-client/src/utils/session.ts
  • packages/adt-client/tests/adapter-cancellation.test.ts
Latest Contributors(2)
UserCommitDate
devin-ai-integration[bot]refactor: reduce CodeS...July 24, 2026
petr.plenkov@gmail.comfeat(adt-mcp): enforce...July 24, 2026
Safe execution Enforce signed adt-execution-v1 grants for read and safe-execute tools, including exact resource/tool matching, maxToolCalls, deadlines, result limits, and terminal outcome reporting.
Modified files (21)
  • packages/adt-mcp/README.md
  • packages/adt-mcp/src/index.ts
  • packages/adt-mcp/src/lib/http/invocation.ts
  • packages/adt-mcp/src/lib/http/server.ts
  • packages/adt-mcp/src/lib/server.ts
  • packages/adt-mcp/src/lib/tools/atc-run.ts
  • packages/adt-mcp/src/lib/tools/destination-mode.ts
  • packages/adt-mcp/src/lib/tools/get-object.ts
  • packages/adt-mcp/src/lib/tools/run-unit-tests.ts
  • packages/adt-mcp/src/lib/tools/scope-catalogue.ts
  • packages/adt-mcp/src/lib/tools/utils.ts
  • packages/adt-mcp/tests/adt-execution-policy.test.ts
  • packages/adt-mcp/tests/http-destination-scope.test.ts
  • packages/adt-mcp/tests/safe-execute-enforcement.test.ts
  • packages/adt-mcp/tests/scope-enforcement.test.ts
  • packages/adt-server/src/bin/adt-server.ts
  • packages/adt-server/src/index.ts
  • packages/adt-server/src/mcp-runtime.ts
  • packages/adt-server/src/server.ts
  • packages/adt-server/tests/mcp-runtime.test.ts
  • packages/adt-server/tests/server.test.ts
Latest Contributors(2)
UserCommitDate
devin-ai-integration[bot]fix(adt-mcp, adt-clien...July 24, 2026
petr.plenkov@gmail.comfeat(adt-mcp): enforce...July 24, 2026
Other Other files
Modified files (6)
  • packages/adt-mcp/src/lib/session/changeset.ts
  • packages/adt-mcp/src/lib/tools/changeset-helpers.ts
  • packages/adt-mcp/src/lib/tools/get-frozen-source.ts
  • packages/adt-mcp/src/lib/types.ts
  • packages/adt-mcp/tests/destination-registry.test.ts
  • packages/adt-mcp/tests/integration.test.ts
Latest Contributors(2)
UserCommitDate
devin-ai-integration[bot]fix(review): address r...July 24, 2026
petr.plenkov@gmail.comfix(mcp): bind immutab...July 19, 2026
Review this PR on Baz | Customize your next review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@netlify

netlify Bot commented Jul 24, 2026

Copy link
Copy Markdown

Deploy Preview for adt-cli canceled.

Name Link
🔨 Latest commit 89e5490
🔍 Latest deploy log https://app.netlify.com/projects/adt-cli/deploys/6a637bfdaf4f91000879fe81

@baz-reviewer

baz-reviewer Bot commented Jul 24, 2026

Copy link
Copy Markdown

Merger

Needs Review

PR exceeds the merge-gate context budget (70159 tokens); escalating to a human reviewer.

Commit 89e5490 · Evaluated 2026-07-24 14:57 UTC


Review this PR on Baz | Customize your next review

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds execution-scoped cancellation to the ADT client and introduces scoped MCP authorization for read and safe_execute operations. It validates signed policies, enforces tool and result limits, reports outcomes, and adds deadline-based abort handling to the ADT server runtime.

Changes

Execution safety

Layer / File(s) Summary
Execution-scoped client cancellation
packages/adt-client/src/cancellation.ts, packages/adt-client/src/adapter.ts, packages/adt-client/src/utils/session.ts, packages/adt-client/tests/adapter-cancellation.test.ts
Abort signals are stored per execution, propagated through adapter and CSRF requests, and isolated across concurrent requests.
Scoped policy contracts and validation
packages/adt-mcp/src/lib/http/invocation.ts, packages/adt-mcp/src/lib/http/server.ts, packages/adt-mcp/src/lib/tools/scope-catalogue.ts, packages/adt-mcp/src/lib/types.ts, packages/adt-mcp/tests/adt-execution-policy.test.ts
Signed scoped claims are parsed into validated policies, then applied to tool, resource, operation-class, and coverage checks.
Safe-execute dispatch and tool limits
packages/adt-mcp/src/lib/tools/destination-mode.ts, packages/adt-mcp/src/lib/tools/atc-run.ts, packages/adt-mcp/src/lib/tools/run-unit-tests.ts, packages/adt-mcp/src/lib/tools/utils.ts, packages/adt-mcp/tests/safe-execute-enforcement.test.ts
Safe execution consumes grants, enforces call and output limits, applies ATC/AUnit limits, runs with deadlines, and records outcomes.
Server wiring and deadline runtime
packages/adt-mcp/src/lib/server.ts, packages/adt-server/src/mcp-runtime.ts, packages/adt-server/src/server.ts, packages/adt-server/src/bin/adt-server.ts, packages/adt-server/tests/*
Execution hooks are forwarded through MCP configuration, and runtime configuration enables deadline-triggered abort execution.
Supporting tool behavior and integration tests
packages/adt-mcp/src/lib/tools/get-object.ts, packages/adt-mcp/src/lib/tools/get-frozen-source.ts, packages/adt-mcp/tests/*.test.ts
Object-type filtering, shared scope-denial results, scoped tool visibility, and server integration assertions are updated.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant DestinationMode
  participant AuthorizationHooks
  participant ADTTool
  participant ADTServerRuntime
  MCPClient->>DestinationMode: invoke scoped safe_execute tool
  DestinationMode->>AuthorizationHooks: consumeExecutionAuthorization
  AuthorizationHooks-->>DestinationMode: authorization admitted
  DestinationMode->>ADTServerRuntime: executeWithDeadline
  ADTServerRuntime->>ADTTool: run under abort signal
  ADTTool-->>DestinationMode: result or failure
  DestinationMode->>AuthorizationHooks: reportExecutionOutcome
  DestinationMode-->>MCPClient: controlled result
Loading

Possibly related PRs

  • abapify/adt-cli#141: Both changes modify scoped atc_run dispatch and operation-class enforcement.
  • abapify/adt-cli#142: Both changes modify ADT client cancellation and CSRF request propagation.

Suggested labels: baz: needs review

Suggested reviewers: baz-reviewer

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the PR’s main change: adding scoped safe execution enforcement for ADT MCP.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/scoped-safe-execution

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@amazon-q-developer amazon-q-developer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR successfully implements scoped safe-execute enforcement for ADT operations with comprehensive security controls. The implementation follows security best practices with fail-closed verification, cryptographic signature validation, and atomic grant consumption. The extensive test coverage validates all critical security boundaries including policy enforcement, grant replay prevention, and proper error handling. No blocking issues found - the code is ready for merge.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

@codacy-production

codacy-production Bot commented Jul 24, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 500 complexity · 28 duplication

Metric Results
Complexity 500
Duplication 28

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

gitar-bot[bot]

This comment was marked as resolved.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Enforce execution-scoped safe execution for ADT MCP (signed adt-execution-v1)

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add signed adt-execution-v1 policy parsing for scoped read and safe_execute.
• Enforce one-shot authorization, tool-call quotas, deadlines, and result-size limits.
• Propagate execution abort signals into ADT client fetch/session flows and add coverage tests.
Diagram

graph TD
  jwt["Signed invocation JWT"] --> verifier["Invocation verifier/parser"] --> guard{"Destination-mode guard"}
  guard -->|"safe_execute"| broker[("Broker grant") ] --> deadline["Deadline runtime"] --> tool["ATC/AUnit tool"] --> client["ADT client adapter"] --> sap["SAP ADT server"]
  guard -->|"scoped read"| client --> sap
  tool -->|"report outcome"| broker

  subgraph Legend
    direction LR
    _svc["Service/Module"] ~~~ _dec{"Decision"} ~~~ _db[("Broker/Store")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Pass AbortSignal explicitly through all tool/client APIs
  • ➕ No AsyncLocalStorage dependency; easier to reason about in some runtimes
  • ➕ Signals are visible in types at every boundary
  • ➖ Large signature churn across adapters, session helpers, and tools
  • ➖ Easy for new call sites to forget to thread the signal, weakening guarantees
2. Schema-driven policy validation (e.g., zod/io-ts) instead of exact-key parsing
  • ➕ More declarative, potentially less custom parsing code
  • ➕ Can auto-generate documentation for policy shapes
  • ➖ Harder to enforce exact-key / no-extra-fields semantics without careful configuration
  • ➖ May increase bundle size / runtime cost for hot-path token verification
3. Isolate safe_execute in a separate worker/process per execution
  • ➕ Strongest containment for timeouts/cancellation and resource caps
  • ➕ Avoids relying on cooperative cancellation in the same Node process
  • ➖ Higher operational complexity (IPC, process lifecycle, state handoff)
  • ➖ More latency and significantly more implementation work than current hook-based approach

Recommendation: The PR’s approach is appropriate for a sidecar that must fail-closed: exact-shape parsers prevent policy widening, dispatch-time checks prevent SAP I/O before grant consumption, and AsyncLocalStorage-scoped AbortSignal propagation enables hard cancellation without mutating shared client state. The main tradeoff (ALS reliance) is acceptable given the concurrency isolation benefits; keep tests around concurrent invocations and ensure Node/runtime support for AsyncLocalStorage and AbortSignal behavior.

Files changed (25) +2475 / -74

Enhancement (16) +1333 / -59
adapter.tsPropagate execution-scoped abort signals into ADT fetch and bounded reads +59/-25

Propagate execution-scoped abort signals into ADT fetch and bounded reads

• Adds execution-scoped abort integration by reading an active async-local AbortSignal and wiring it into request() and readTextBounded() fetch calls. Ensures reads can be aborted mid-body and cleans up abort listeners via dispose().

packages/adt-client/src/adapter.ts

cancellation.tsAdd async-local execution abort signal utilities +20/-0

Add async-local execution abort signal utilities

• Introduces AsyncLocalStorage-backed helpers to run operations with an execution-scoped AbortSignal and retrieve the active signal. Enables concurrent executions without mutating shared ADT client state.

packages/adt-client/src/cancellation.ts

index.tsExport execution-scoped cancellation API +1/-0

Export execution-scoped cancellation API

• Re-exports runWithAdtAbortSignal so downstream runtimes can scope cancellation across ADT client calls.

packages/adt-client/src/index.ts

index.tsExport scoped execution policy types/parsers +4/-0

Export scoped execution policy types/parsers

• Exposes parseScopedAdtInvocationPolicy/parseSafeExecutePolicy and related types for consumers and server wiring.

packages/adt-mcp/src/index.ts

invocation.tsImplement adt-execution-v1 parsing with strict, fail-closed validation +427/-7

Implement adt-execution-v1 parsing with strict, fail-closed validation

• Adds a new trusted agentId (adt-execution) and exact parsers for scoped read and safe_execute policies, including tool/resource binding, maxToolCalls, and safe_execute-specific limits and opaque authorization tokens. Hardens token validation by enforcing exact payload/header key sets and rejecting duplicate classes/destinations.

packages/adt-mcp/src/lib/http/invocation.ts

server.tsPlumb scoped access and safe_execute hooks into HTTP MCP handler +144/-0

Plumb scoped access and safe_execute hooks into HTTP MCP handler

• Snapshots scoped access into request access and enforces class alignment between signed claims and scoped policy. Extends destination server context wiring to optionally include grant consumption, outcome reporting, and deadline execution hooks.

packages/adt-mcp/src/lib/http/server.ts

server.tsAdd server options for safe_execute authorization/outcome/deadline hooks +26/-1

Add server options for safe_execute authorization/outcome/deadline hooks

• Extends createMcpServer options to accept deployment-owned consumeExecutionAuthorization/reportExecutionOutcome/executeWithDeadline hooks and forwards them into destination-mode tooling.

packages/adt-mcp/src/lib/server.ts

atc-run.tsEnforce safe_execute ATC limits and rethrow uncertain failures +22/-3

Enforce safe_execute ATC limits and rethrow uncertain failures

• Reads scoped safe_execute policy to cap verdict/findings output and returns a limit error when exceeded. Uses isKnownAdtHttpFailure to normalize deterministic SAP HTTP errors while rethrowing uncertain transport/abort/parsing failures under safe_execute.

packages/adt-mcp/src/lib/tools/atc-run.ts

destination-mode.tsEnforce scoped dispatch: quotas, one-shot grant consumption, deadline and outcome +107/-5

Enforce scoped dispatch: quotas, one-shot grant consumption, deadline and outcome

• Wraps tool handlers to enforce scoped tool allow-list, per-execution maxToolCalls, and safe_execute requirements (consume grant before handler I/O, execute under hard deadline, enforce result byte cap, and record exactly one terminal outcome). Keeps fail-closed behavior when required hooks are absent or reporting fails.

packages/adt-mcp/src/lib/tools/destination-mode.ts

run-unit-tests.tsNormalize coverage flags and enforce safe_execute AUnit/coverage bounds +109/-10

Normalize coverage flags and enforce safe_execute AUnit/coverage bounds

• Canonicalizes coverage options for policy comparison and rejects inconsistent legacy flags. Applies safe_execute policy limits for findings, test classes/methods, programs, and recursive coverage measurement counts, and rethrows uncertain failures under safe_execute while normalizing deterministic SAP HTTP errors.

packages/adt-mcp/src/lib/tools/run-unit-tests.ts

scope-catalogue.tsAdd scoped access model and exact resource comparisons for safe execution +212/-3

Add scoped access model and exact resource comparisons for safe execution

• Introduces McpScopedAccess and extends allow/list/resource checks to enforce exact toolNames, operationClass, and canonical resourceKeys. Adds canonical object-key generation, exact sorted scope comparisons, and safe_execute resource validation for ATC and unit tests (including coverage option canonicalization).

packages/adt-mcp/src/lib/tools/scope-catalogue.ts

utils.tsDifferentiate deterministic SAP HTTP failures from uncertain transport failures +17/-0

Differentiate deterministic SAP HTTP failures from uncertain transport failures

• Adds isKnownAdtHttpFailure to treat completed SAP HTTP error responses as deterministic failures while excluding abort/network/parsing issues whose execution outcome may be unknown.

packages/adt-mcp/src/lib/tools/utils.ts

types.tsDefine ToolContext hooks for safe_execute grant consumption, outcome, and deadlines +37/-0

Define ToolContext hooks for safe_execute grant consumption, outcome, and deadlines

• Adds ToolContext interfaces for atomic grant consumption, terminal outcome reporting, and a hard-cancellable deadline executor that must not return before the operation settles.

packages/adt-mcp/src/lib/types.ts

index.tsExport safe_execute deadline runtime helper +1/-0

Export safe_execute deadline runtime helper

• Re-exports executeWithDeadlineAndAbort for external use and testing.

packages/adt-server/src/index.ts

mcp-runtime.tsImplement hard deadline + abort runtime and safe_execute enablement gate +119/-1

Implement hard deadline + abort runtime and safe_execute enablement gate

• Adds executeWithDeadlineAndAbort to scope an abort signal across async execution and enforce signed maxDurationMs even under timer delays. Introduces ADT_SERVER_MCP_SAFE_EXECUTE_ENABLED gating and requires invocation configuration plus deployment-owned grant/outcome hooks when safe_execute is enabled.

packages/adt-server/src/mcp-runtime.ts

server.tsPlumb safe_execute hooks through server MCP handler creation +28/-4

Plumb safe_execute hooks through server MCP handler creation

• Extends AdtServerMcpOptions and handler wiring to pass consumeExecutionAuthorization/reportExecutionOutcome/executeWithDeadline into MCP tool context when configured.

packages/adt-server/src/server.ts

Bug fix (1) +15 / -1
session.tsMake CSRF/session initialization abort-aware and fail-safe on cancellation +15/-1

Make CSRF/session initialization abort-aware and fail-safe on cancellation

• Threads an optional AbortSignal through session initialization fetches and inserts throwIfAborted checkpoints between steps. Clears session state on abort and avoids swallowing abort-related errors during best-effort session deletion.

packages/adt-client/src/utils/session.ts

Tests (7) +1122 / -13
adapter-cancellation.test.tsAdd tests for execution-scoped cancellation propagation and isolation +139/-0

Add tests for execution-scoped cancellation propagation and isolation

• Verifies the active execution AbortSignal is passed to fetch, aborts response streaming, and prevents follow-on session/write requests after cancellation. Confirms concurrent executions receive isolated signals.

packages/adt-client/tests/adapter-cancellation.test.ts

adt-execution-policy.test.tsAdd unit tests for adt-execution-v1 parsing and fail-closed validation +218/-0

Add unit tests for adt-execution-v1 parsing and fail-closed validation

• Covers exact parsing for read and safe_execute policies (ATC, AUnit, coverage) and rejects drift in classes, tools, ordering/duplicates, and unsupported destination-wide reads.

packages/adt-mcp/tests/adt-execution-policy.test.ts

http-destination-scope.test.tsUpdate destination tool projection expectations for scoped execution +1/-0

Update destination tool projection expectations for scoped execution

• Ensures read-scoped tool listings do not include safe_execute tools such as run_unit_tests.

packages/adt-mcp/tests/http-destination-scope.test.ts

safe-execute-enforcement.test.tsAdd enforcement tests for grant consumption, deadlines, result caps, and outcomes +556/-0

Add enforcement tests for grant consumption, deadlines, result caps, and outcomes

• Validates fail-closed dispatch, no-I/O-before-consume, replay denial, per-execution maxToolCalls, result-size limiting, deterministic vs uncertain failure handling, and single terminal outcome behavior without SAP retries.

packages/adt-mcp/tests/safe-execute-enforcement.test.ts

scope-enforcement.test.tsAdjust scope enforcement tests for safe_execute catalogue changes +8/-2

Adjust scope enforcement tests for safe_execute catalogue changes

• Aligns expectations so run_unit_tests is classified as safe_execute and updates destination-mode tests accordingly.

packages/adt-mcp/tests/scope-enforcement.test.ts

mcp-runtime.test.tsAdd tests for safe_execute runtime defaults, abort behavior, and hook validation +187/-4

Add tests for safe_execute runtime defaults, abort behavior, and hook validation

• Verifies default deadline runtime selection, aborting SAP fetch with settlement waiting, late-settlement rejection, and strict requirement/preservation of deployment-owned hooks when safe_execute is enabled.

packages/adt-server/tests/mcp-runtime.test.ts

server.test.tsUpdate signed MCP mount test for scoped adt-execution-v1 tool listing +13/-7

Update signed MCP mount test for scoped adt-execution-v1 tool listing

• Switches test invocations to the adt-execution agent and validates that only the signed scoped tool is listed.

packages/adt-server/tests/server.test.ts

Other (1) +5 / -1
adt-server.tsWire default safe_execute deadline runtime into ADT server MCP startup +5/-1

Wire default safe_execute deadline runtime into ADT server MCP startup

• Imports and passes executeWithDeadlineAndAbort into createAdtServerMcpOptions so safe_execute can hard-abort SAP I/O by default when enabled.

packages/adt-server/src/bin/adt-server.ts

baz-reviewer[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

…p fake JWT in test

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
@nx-cloud

nx-cloud Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 89e5490

Command Status Duration Result
nx affected -t lint test build e2e-ci --verbose... ✅ Succeeded 1m 8s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-07-24 14:53:26 UTC

…nied / safe-execute limit payloads via utils.ts helpers\n- Track per-execution dispatch counters in destination-mode.ts\n- Include program and class alerts in AUnit resultCounts\n- Add optional objectType to get_object and fail-closed on empty scoped resourceKeys\n- Relax systemSid regex and sort arrays once in snapshotScopedAccess\n- Keep sessionPath/csrfToken for DELETE on cancellation; avoid clearing shared SessionManager state\n- Make runWithAdtAbortSignal async so synchronous abort throws become rejected promises\n- Compose test JWT fixture from segments to avoid scanner match\n- Use shared safeExecuteLimitResult helper in atc-run and run-unit-tests

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
@ThePlenkov

Copy link
Copy Markdown
Member Author

test

gitar-bot[bot]

This comment was marked as resolved.

gitar-bot[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits July 24, 2026 09:57
…alth\n\n- Extract parseHandlerArgs, isScopeAllowed, maxToolCallsReached, incrementCounter, and runSafeExecution helpers in destination-mode.ts\n- Extract buildSessionHeaders and deleteSecuritySession private methods in SessionManager to reduce initializeCsrf nesting\n- Keep abort cleanup behavior unchanged (DELETE session without clearing shared state)

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
…\n- Deduplicate safe-execute payload in run-unit-tests coverage limit path by using safeExecuteLimitResult()\n- Reserve maxToolCalls slots before any awaited work and roll back on denial\n- Evict safe-execute per-execution counter after the terminal outcome is reported\n- Keep fail-closed scope behavior for destination-mode safe and non-safe paths

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
baz-reviewer[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
baz-reviewer[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

- parseSafeExecutePolicy: split into operation-specific helpers to reduce cognitive complexity
- snapshotScopedAccess: use localeCompare in sorted-unique check
- session helpers: add nosemgrep suppressions for ADT URL fetch

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
baz-reviewer[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

…inted-URL rule

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
baz-reviewer[bot]

This comment was marked as resolved.

… session URLs

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
coderabbitai[bot]

This comment was marked as resolved.

baz-reviewer[bot]

This comment was marked as resolved.

- destination-mode: hide safe_execute tools when execution hooks are missing
- server.ts: pass full destination options to tool list projection
- get-object: make objectType required and update README/tests
- session.ts: add positional overload, SSRF session-path validation,
  cleanup on failed CSRF acquisition, avoid caching cleanup CSRF token
- http/server.ts: restore uniqueness check in isSortedUniqueStrings

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
baz-reviewer[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

…ecute helper dedup

- session.ts: normalize sessionPath via new URL() before origin/path checks
  so dot-segments like ../ cannot bypass the sessions-prefix guard
- atc-run.ts & run-unit-tests.ts: share safePolicy extraction and safe-execute
  error handling via extractSafeExecutePolicy / handleSafeExecuteError

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
cubic-dev-ai[bot]

This comment was marked as resolved.

baz-reviewer[bot]

This comment was marked as resolved.

…fe execution

atc_run now catches the 'ATC object is unavailable' error and returns
mcpErrorResult instead of letting handleSafeExecuteError rethrow it, so
destination-mode records a deterministic 'failed' outcome instead of
'outcome_unknown'.

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
gitar-bot[bot]

This comment was marked as resolved.

baz-reviewer[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits July 24, 2026 13:17
…lists

- Introduce AtcObjectUnavailableError and match it with instanceof instead
  of a literal message string.
- Resolve the ATC scope URIs before creating the server-side worklist, so
  a missing-object failure no longer leaves an orphaned worklist behind.
- Return mcpErrorResult for the deterministic not-found case so
  destination-mode records 'failed' rather than 'outcome_unknown'.

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 4 new potential issues.

Open in Devin Review

Comment thread packages/adt-mcp/src/lib/tools/scope-catalogue.ts
Comment thread packages/adt-mcp/src/lib/http/invocation.ts Outdated
Comment thread packages/adt-mcp/src/lib/http/invocation.ts
Comment thread packages/adt-mcp/src/lib/tools/destination-mode.ts
- require objectType in get_object_structure so scoped read can build a canonical key
- parseScopedObjectKeys now rejects empty resourceKeys for read and safe_execute scopes
- remove exact-key checks on JWT payload/protected header; validate only required alg/kid/typ and trusted claim fields, so issuers can add standard/extra claims without breaking existing invocation policies

Co-Authored-By: Petr Plenkov <petr.plenkov@gmail.com>
@gitar-bot

gitar-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

Note

Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime.
Learn more

Code Review ✅ Approved 7 resolved / 7 findings

Enforces signed adt-execution-v1 policies and execution-scoped safe execution across the MCP server, client, and runtime, addressing 7 review findings including concurrency safety, cleanup delays, and error matching.

✅ 7 resolved
Performance: Redundant re-sorting inside .some() validators

📄 packages/adt-mcp/src/lib/http/server.ts:244-257
In snapshotScopedAccess the sorted-order checks recompute [...resourceKeys].sort(...) (and the toolNames equivalent) on every iteration of the .some() callback, giving O(n² log n) work per snapshot. Inputs are capped at 100 resource keys / 2 tool names, so impact is small, but the pattern is wasteful and hard to read. Sort once into a local and compare against it. e.g. const sortedKeys = [...resourceKeys].sort((a,b)=>a.localeCompare(b)); ... resourceKeys.some((k,i)=>k!==sortedKeys[i]).

Performance: Per-execution dispatch counters map is never evicted

📄 packages/adt-mcp/src/lib/tools/destination-mode.ts:273-287 📄 packages/adt-mcp/src/lib/tools/destination-mode.ts:413-427
In destinationModeServer, the counters map is created once for the server lifetime and gains a permanent entry keyed by each unique scoped.executionId (via counters.set in wrapToolHandler), but no entry is ever deleted. For a long-running MCP server every distinct execution leaves a small {admitted} record behind, so memory grows unbounded over time. Consider evicting an execution's counter once its terminal outcome is reported, or using a bounded/TTL cache keyed by executionId.

Edge Case: maxToolCalls admission not concurrency-safe for same executionId

📄 packages/adt-mcp/src/lib/tools/destination-mode.ts:265-279 📄 packages/adt-mcp/src/lib/tools/destination-mode.ts:318-320
In wrapToolHandler the limit check (counter.admitted >= scoped.maxToolCalls) and the increment are separated by await points (e.g. consumeExecutionAuthorization, executeWithDeadline). Two concurrent tool invocations sharing an executionId can both pass the check before either increments, admitting more calls than maxToolCalls permits. For safe_execute the one-shot consumeExecutionAuthorization largely mitigates this, but the non-safe path (lines 273-279) has no such guard. If concurrent dispatch within one execution is possible, reserve the slot by incrementing before the awaited work (and roll back on denial).

Performance: Abort cleanup can delay cancellation by up to ~10s

📄 packages/adt-client/src/utils/session.ts:585-599
In the abort branch of initializeCsrf, when only sessionPath is known, cleanup awaits fetchSecuritySessionCsrfToken and then deleteSecuritySession before re-throwing the abort error. Both calls are invoked without a signal, so each falls back to AbortSignal.timeout(5_000), meaning a deadline-driven abort can block the rejected promise for up to ~10s of sequential network I/O — undercutting the "hard-abort at the signed deadline" guarantee. Consider running this best-effort session cleanup detached (fire-and-forget) or with a tighter combined budget so the abort propagates promptly.

Bug: Sort check switched from localeCompare to default sort ordering

📄 packages/adt-mcp/src/lib/http/server.ts:227-229
The original validator required resourceKeys/toolNames to be sorted via localeCompare, but the new isSortedUniqueStrings compares against the default Array.prototype.sort() (UTF-16 code-unit) ordering. For keys containing $ - / _ :, code-unit order differs from locale order, so a grant sorted by an issuer using localeCompare can now fail validation and be denied. Sort with the same comparator the issuer/spec uses to avoid rejecting otherwise-valid grants. Also note [...values].sort() is re-run on every .every() iteration (O(n² log n)); sort once outside the loop.

...and 2 more resolved from earlier reviews

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

@ThePlenkov
ThePlenkov merged commit b8cf155 into main Jul 24, 2026
15 checks passed
@ThePlenkov
ThePlenkov deleted the feat/scoped-safe-execution branch July 24, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant