Skip to main content

Module scope

Module scope 

Source
Expand description

RuntimeScope — per-execution caller identity surface for the multi-tenant work tracked in Parslee-ai/car#187.

§What this is

A small value the dispatcher attaches to each Runtime::execute_* invocation so the runtime knows on whose behalf an ActionProposal is being executed. The fields mirror — and are sourced from — the proposal-context surfaces #187 phase 1 and phase 2 already populate:

  • caller_id — typically proposal.context["a2a_caller_verified"].subject when an AuthValidator returns an Identity, else proposal.context["a2a_caller"].caller_id (cooperative-peer hint).
  • tenant_id — verified-tenant claim if present, else the cooperative a2a_caller.tenant_id hint, else None.
  • claims — bag of verified token claims the dispatcher chose to forward (subject is already on caller_id; this carries the surrounding metadata like iss, aud, org_id, etc.).

§What this PR enforces vs. what’s deferred

This first PR of #187 phase 3 is foundation only:

  • Runtime::execute_scoped / execute_scoped_with_cancel accept a &RuntimeScope and record it on the per-execution event log (each ActionInvoked event carries caller_id / tenant_id so downstream audit / log analysis sees who issued what).

  • ✅ The car-a2a dispatcher derives a scope from the verified Identity (when present) and the cooperative a2a_caller metadata, and calls the scoped entry point. Default-deny activates when a non-NoAuth validator is configured but no Identity surfaces (e.g. token validated but subject missing).

  • Memgine queries are NOT yet scoped. Facts, skills, and working-set retrieval still hit the global graph regardless of scope.tenant_id. Tracked as the next PR in #187 phase 3.

  • State keys are NOT yet namespaced. state.get / state.set still live in a flat KV space. Tracked separately; needs careful migration design for existing persisted state.

  • FFI parity is partial. WS dispatches that flow through the car-a2a bridge get scope automatically; the NAPI / PyO3 execute_proposal standalone functions don’t accept a scope parameter yet. Adding that is one of the issue’s acceptance criteria and lands in a follow-up.

Tools and policies that want per-tenant behaviour today can still read proposal.context["a2a_caller_verified"] directly — the phase 1/2 surfaces remain. RuntimeScope is the structured handle the runtime itself uses; tool handlers should keep reading the proposal context.

Structs§

RuntimeScope
Per-execution identity surface (Parslee-ai/car#187 phase 3).