Skip to content

RFC: caller authorization on MeshJob lifecycle ops (cancel/status/post_event/subscribe) #1076

Description

@dhyansraj

Summary

Caller-authorization on MeshJob lifecycle operations. Split from #1074 (the missing-facade concern is mechanical and lands separately; this concern is design-heavy).

Problem

Today, the only enforced authorization on a MeshJob is at submit time — the registry sets submitted_by from the caller's agent_id (dependency_injector.py:541-552). After submit, any agent that knows a job_id can:

Knowing a job_id is not a permission — it's metadata. Job IDs are stored in the registry, observable via traces, persisted in any state agent.

Concrete threat model

In a dogfood deployment (the ai-debate v2.2.4 refactor):

  • orch-agent submits run_debate(debate_id=...) → registers job_id in debate-state (postgres)
  • frontend cancel-button calls end_debate(debate_id) → orch reads job_id from debate-state → (once facade lands) calls mesh.jobs.cancel(job_id)

That works because orch is both the submitter AND the agent exposing cancel — but it's coincidence, not enforcement. Any other agent in the mesh (observer-agent, future agents) that holds the debate_state DI could read the same job_id and call cancel() — there's nothing stopping them.

Proposed authorization matrix

Op Authorized callers Rationale
submit any (already enforced — sets submitted_by) Job creation is open
claim any agent advertising the capability Needed for failover across replicas
cancel(job_id) agent_id == submitted_by Owner-only — destructive
status(job_id) submitted_by OR claimer Owner needs visibility; claimer needs it for resume
wait(job_id) same as status Same reasoning
post_event(job_id, type, payload) needs design — split by event type, or by caller, or both? Some events (cancel_requested) are owner-only; some (progress) are claimer-only
subscribe_events(job_id, ...) open question — opt-in by submitter? Anyone in same mesh? Observability sidecars? Reading is less destructive but still privacy-relevant

Enforcement design

Caller identity is already on the wire via the existing mesh transport. The registry HTTP handlers (ent_handlers_jobs.go:924-993 for PostJobEvent, future handler for CancelJob) need to gate on it. Today they don't.

Backward-compat tension

Today's permissive default lets observers/sidecars post into foreign jobs. Tightening would break in-the-wild patterns.

Three options for the rollout shape:

  1. Per-job opt-in flag at submit time — e.g., restrict_lifecycle_to_submitter=True. Default false → flips to true in a future major. Backward-compatible; consistent enforcement per-job once set; user-facing API surface.
  2. ACL field on the jobauthorized_callers: list[agent_id] with submitted_by always included. More flexible (multiple authorized agents) but more complex.
  3. Capability-token model — submit returns a token that's required for lifecycle ops. Cleanest theoretically; biggest break with current "knows job_id = can call" semantics.

Option 1 is probably the right first step (simplest, opt-in, doesn't preclude options 2 or 3 later).

Cross-runtime scope

Authorization model needs to ship coherently across Python / TypeScript / Java. The enforcement is registry-side (so language-agnostic), but the SDK helpers need to surface auth-failure errors consistently — likely a new JobAuthorizationError typed exception in each SDK.

Open questions

  1. Default behavior in the first patch release that ships this: still open (current behavior), or opt-in to tightening?
  2. Should subscribe_events authorization differ from status/wait? Reading is less dangerous.
  3. How does this interact with the submitted_by semantics during cross-agent submit chains? (Agent A submits on behalf of user U; should U's authorization carry forward, or does A "own" the job?)
  4. How do we audit auth decisions? Trace events? Registry log entries?
  5. Observability sidecar pattern — observability needs broad read access to jobs across the mesh. Do they get a system-level "auditor" role? Or do users opt in per job?

Scope of this issue

Design-level. No code in this PR. Output: an agreed-on authorization model, with concrete decisions on the open questions above, and a phased rollout plan.

Related: #1074 (Concern 1 — DDDI-clean facades for cancel/status/wait).

Context

Surfaced dogfooding ai-debate's v2.2.4 refactor (moving from in-process driver to MeshJob substrate). The orch-as-both-submitter-and-canceller setup happens to satisfy the implicit auth, but the gap is real and other deployments won't naturally preserve it.

Activity

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

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions