Skip to content

Define execution scope for protected effects and complete mediation #736

Open

Description

@omwei-org

Context

The EABC/cMCP interoperability profile for order_create maps the existing cMCP mechanisms for:

  • authority binding: Cedar decision + rel: authorized-intent
  • effect correlation: execution_id + rel: observed-effect
  • execution binding: the proposed Execution Action Binding

The remaining EABC dimension is Execution Scope.

For a protected effect such as order_create, the relevant question is not whether an MCP request passed through the cMCP gateway. It is:

For the declared order_create effect domain, how is the set of paths capable of committing that effect identified, declared, and shown to be mediated?

Gap

Current cMCP mechanisms can establish what happened on a mediated execution path, and can correlate the execution with authority and downstream evidence. They do not appear to provide a protocol-level declaration or evidence model for the effect-producing path set itself.

In particular, the following are different claims:

  1. this MCP tool call was authorized;
  2. this execution was correlated to that authorization;
  3. this downstream evidence was observed for that execution;
  4. all paths capable of producing the protected effect are within the declared enforcement boundary.

The first three have existing cMCP homes. The fourth is the open part.

This matters because gateway mediation of MCP traffic does not by itself prove that an application cannot create the same protected effect through another API, service, direct database operation, alternate tool server, privileged process, or other execution path.

Concrete example: order_create

Assume order_create is the protected effect.

A useful execution-scope declaration would need to make it possible to state something equivalent to:

Protected Effect: order_create

Declared effect-producing paths:
  P1 = MCP tool X -> cMCP -> upstream order service
  P2 = ...
  Pn = ...

Enforcement boundary:
  every Pi capable of committing order_create
  must pass the declared authorization/execution gate

The exact representation need not be this syntax. The question is what cMCP should carry, require, or integrate with so that this scope is explicit and independently assessable rather than inferred from the presence of the gateway.

Questions

  1. Does cMCP already have a planned or existing mechanism for declaring an effect domain / execution scope and its effect-producing paths?
  2. If not, should this be represented as a cMCP profile/contract rather than as a runtime field?
  3. What evidence should establish that the declared path set is complete for a protected effect?
  4. How should a verifier distinguish:
    • "this path was mediated",
    • "this effect was observed", and
    • "all paths capable of producing this effect are mediated"?
  5. Is there an existing cMCP issue or design that should own this rather than opening a new mechanism?

Boundary

This issue is not asking cMCP to implement EABC or to claim universal complete mediation.

The immediate goal is to identify whether cMCP has a native representation for Execution Scope, or to define the smallest missing contract needed for an integration profile to make a scoped non-bypassability claim.

The EABC profile currently records Execution Scope as OPEN / NOT CLAIMED until such a mechanism and evidence boundary are identified.

Activity

  1. imran-siddique commented on Oct 8, 2026

    @imran-siddique
    Member

    @omwei-org this belongs with the confinement work. The gateway can only check calls that pass through it, and docs/confinement.md (tracked in #659) is where cMCP states which routes an agent has and what mediates each one; its routes table is the agent-side half of your path set.

    The two halves need different evidence. Agent-side paths can be enforced and tested, as the confinement fixture does by switching each protection off in turn. Paths outside the agent, such as another service writing the orders database, are a deployment claim: carry them as a declared boundary statement, and report coverage as not established unless an independent observer, through observed-effect, shows the boundary held.

    A PR extending the routes table into a declared path set per protected effect, with order_create as the worked case, would be welcome.

  2. omwei-org commented on Oct 9, 2026

    @omwei-org
    ContributorAuthor

    Hi Imran — following up on your suggestion in issue #736 about extending the routes table into a declared path set for each protected effect.

    I prepared PR #740, but it was automatically closed because I haven't been vouched yet. I’ve read the contribution guidelines and am trying to follow the required process, but I haven’t found a working way to request a vouch: the new-issue URL returns 404, and the repository doesn’t appear to have Discussions enabled.

    Could you point me to the right way to request a /vouch so I can submit the contribution through the normal review process?

  3. imran-siddique commented on Oct 11, 2026

    @imran-siddique
    Member

    /vouch @omwei-org

  4. github-actions commented on Oct 11, 2026

    @github-actions
    Contributor

    @omwei-org is vouched by @imran-siddique. Pull requests from that account will not be closed by the vouch check.

  5. added a commit that references this issue on Oct 11, 2026
  6. imran-siddique commented on Oct 11, 2026

    @imran-siddique
    Member

    @omwei-org you are vouched and #740 is reopened. This issue was the conversation the rule asks for. The dead end you hit was ours: the issue chooser sent "Design discussion" to a Discussions page that is switched off on this repository, fixed in #742.

  7. dinakarjs commented on Oct 21, 2026

    @dinakarjs
    Contributor

    Following merged #740 (02a34b3), the concrete next validation target is an effect-specific order fixture, not another path-set declaration.

    Proposed bounded harness: a dedicated synthetic order service writes uniquely identified orders to a disposable database. A separate observer connection reads committed rows after each trial; gateway return values and audit entries are correlation evidence, not the effect oracle. Use a fresh database/trial identifier for each baseline and mutation.

    Acceptance pairs: (P1) approved order commits once / denied tool commits zero; (P2) confined parent cannot reach an alternate order endpoint / removing the network restriction yields an observed committed order; (P3b) repeat through a child process; (P3a) a controlled file-consuming order writer sees no command / removing the selected filesystem restriction produces an observed order. Preserve ambiguous response-loss outcomes by inspecting durable state, rather than assuming a failed response means no commit. Keep logging/sink canary tests separate.

    P4 stays a deployment-side obligation: inventory other database writers, bind each declared control to its path, and independently assess/observe those controls. Even all harness pairs passing would establish only the exercised paths, not completeness of the real deployment inventory.

    Local preflight for this follow-up found neither a Docker executable nor /var/run/docker.sock. No controlled Linux/container run or real order-effect observation was performed. The remaining prerequisites are owner agreement on fixture placement under confinement #659, the selected synthetic service/observer contract, and a suitable controlled Docker host. No infrastructure provisioned and no completeness claim made. Prepared with Codex.

  8. omwei-org commented on Oct 22, 2026

    @omwei-org
    ContributorAuthor

    Thanks, this is the right next step. An effect-specific fixture with an independent observer is a stronger oracle than anything the gateway reports about itself.
    I agree with the shape of the proposal, with a few points to pin down in the fixture contract:
    Observer independence. The observer connection should use its own credentials and a network path outside the confinement under test. Otherwise the confined process could influence what is being observed.
    Positive control for P3a. The file-consuming order writer should be shown to commit an order when the selected filesystem restriction is removed. This is the same mutation logic as P2, and it confirms the test can fail.
    Scope of the claim. If all pairs pass, this is evidence that the exercised paths are closed under the tested confinement. It does not establish commit-point authority or semantic correctness of the order, and it says nothing about paths that were not exercised. I’d record it as path-specific evidence and keep it separate from any general claim.
    P4 stays a deployment-side obligation. Inventory of other database writers, binding each declared control to its path, and independent assessment of those controls cannot be discharged by the harness. I agree with keeping it out of scope and with making no completeness claim.
    Response-loss outcomes. Agreed that these should be resolved by inspecting durable state rather than inferred from the response. I’d suggest recording them as a distinct outcome class instead of folding them into pass/fail.
    On the open prerequisites: fixture placement under confinement (#659) and the synthetic service/observer contract need owner agreement before anything is run. Optional: I can take a first pass at the observer contract if that helps.
    The controlled Docker host is also still missing, so for now this remains a plan with no observed results, which matches how the follow-up describes itself.

  9. a1k7 commented on Oct 30, 2026

    @a1k7

    I built a minimal P1 fixture scaffold locally on macOS to have a working effect oracle ready, since @dinakarjs noted the controlled Docker host was missing.

    What works locally (3 passing tests, Python 3.14, no Docker):

    fixtures/order_service.py — SQLite-backed synthetic order service. create_order(trial_id) writes one row; the DB is disposable per trial.
    fixtures/observer.py — a separate read-only connection (file:...?mode=ro) on the same DB. Own connection, no shared process state.
    tests/unit/test_p1_order_fixture.py — three tests:

    approved call writes one row → observer sees exactly one row for that trial
    denied call writes zero rows → observer sees zero rows for that trial
    observer reads the same row through two independent connections
    What it does NOT do: no cMCP wiring yet. The synthetic service is not called through the /mcp endpoint. That is the part I need the observer contract for — omwei-org's five refinements (own credentials, own network path, positive control per mutation, scope-of-claim, response-loss as a distinct outcome class) determine the shape.

    Two questions before I go further:

    Is the observer contract from @omwei-org still pending, or should I follow whatever shape lands in #659 for the fixture placement?
    For the cMCP side of P1, is the "denied" arm meant to be a 403 POLICY_DENY from Cedar, or a 403 KILL_SWITCH_TRIPPED from the gateway? Both give "zero committed rows" but the acceptance criterion differs, and the test should record the intended denial class as an outcome, not fold both into "no effect."

    Happy to hand the fixture to @omwei-org or extend it to whichever contract they prefer. The three files above are ~90 lines total, so adapting them is cheap.

  10. omwei-org commented on Oct 30, 2026

    @omwei-org
    ContributorAuthor

    Thanks — this is a useful starting point.

    The observer refinements in my #736 comment are still the intended requirements; they are not yet a separate finalized contract. #659 provides the confinement model and route inventory, but it does not fully specify the effect-observer contract.

    One important distinction: the SQLite scaffold validates the effect oracle, but a separate read-only connection alone does not establish observer independence from the confinement under test. We still need independent credentials and an observation path outside that boundary.

    For P1, I would keep both denial cases, but test them separately:

    • POLICY_DENY: Cedar authorization rejection.
    • KILL_SWITCH_TRIPPED: gateway shutdown rejection.

    Both must produce zero committed effects, but the denial reason must remain explicit in the recorded outcome.

    Please keep the current scaffold as the P1 oracle foundation; we should agree on the observer boundary before wiring it into cMCP.

  11. omwei-org commented on Nov 2, 2026

    @omwei-org
    ContributorAuthor

    @a1k7 happy for you to propose the observer boundary, since you already have the P1 oracle working. I’ll review the draft against the requirements below rather than writing it myself.
    Review criteria:

    1. Independence: the observer uses its own credentials and an observation path outside the confinement under test. A read-only connection on the same host/file only validates the oracle, not independence.
    2. Positive control per mutation: every restriction-on case (0 committed) is paired with a restriction-off case (1 committed observed), so the test can demonstrably fail.
    3. Outcome classes: committed / not committed / response-lost (resolved from durable state) as distinct outcomes, not folded into pass/fail. Denial class (POLICY_DENY, KILL_SWITCH_TRIPPED) recorded separately from the effect result.
    4. Claim scope: results are path-specific evidence for the exercised paths only. No completeness claim; P4 stays a deployment-side obligation.
      A short markdown draft in this thread is enough, no code needed yet. Fixture placement under Validate that agent egress cannot bypass configured release controls #659 still needs owner agreement before anything is wired into cMCP.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions