Skip to content

R10 (governance): delegated identity / on-behalf-of downstream authorization (AARM) #319

Description

@initializ-mk

AARM governance requirement R10. Extends the R1–R9 agent-runtime governance framework (umbrella #216) with delegated identity / on-behalf-of authorization. Tracking issue in the #208 (R3) / #210 (R4b) / #215 (R9) convention. Implementing mechanisms are already scoped: #317 (interactive) and #318 (ID-JAG).

Requirement

A downstream tool call executes under the requesting user's delegated identity, not a shared service grant.

Where R9 (least-privilege credentials, #215) scopes what a tool may do, R10 scopes whose authority it acts under. Today an agent's remote-MCP OAuth is a single, process-global, deploy-time grant (storeKey = "mcp_" + name) — every end user shares one identity against the downstream app (Linear, Jira, GitHub…). For a multi-user deployed agent (Slack, or a UI → A2A) that violates least-privilege at the identity layer: there's no per-user authorization, no per-user attribution downstream, and a compromise of the shared grant is a compromise of every user's access.

R10 requires that per-user identity propagate to downstream tool calls — per-user, per-session, on-behalf-of — so the downstream system authorizes and audits the actual requesting user.

  • Type: SHOULD (enterprise-grade; a proposed fourth SHOULD alongside R7/R8/R9).
  • Status: proposed — not yet implemented.

Scope

R10 is the governance requirement; it is satisfied through one seam with a resolver behind it (design-tool-registry.md §18.2) — BearerToken(server, subject, session) — chosen per MCP server by method:. Forge never learns which resolver answered (that opacity is what lets the managed layer swap the backend):

Resolver Layer Applicability
Forge-local — interactive OAuth, ephemeral per-session (#317) Forge (standalone-capable) any public OAuth MCP; universal
Managed broker — vaulted 3LO now → ID-JAG later (initializ/aip/mcp-delegated-identity-broker.md; #318 Forge-side collapses to assertion-forward — the platform picks interactive vs ID-JAG, Forge never learns which) initializ / platform (holds the IdP trust relationship + token custody + consent delivery; §18.1 / §19) vaulted 3LO: real per-user delegation without EMA/XAA; ID-JAG: enterprise-federated end state

Per §19 the Forge-facing axis is type: user | platform (the principal), not a method: — the platform decides interactive-vs-ID-JAG (opaque to Forge), and in managed mode the callback, consent delivery, and token custody are platform-side (the refresh token never touches the agent).

Both preserve per-user isolation and on-behalf-of identity, and share the identity-plumbing + session-store-interface defined in #317's P0. The broker resolver holds the credential and the enterprise trust relationship — it cannot live in the OSS agent framework (§18.1 test 3).

Fit within AARM (R1–R10)

  • Sits next to R4b (STEP_UP / identity assurance of the caller to Forge) and R9 (least-privilege credentials for a tool). R10 completes the identity story: least-privilege identity — the caller's verified identity (which R4b/OIDC already establishes at the A2A edge) is propagated as the authority for the downstream action.
  • Builds directly on existing primitives: the OIDC-verified auth.Identity (raw assertion in hand at forge-core/auth/middleware.go:122), the DEFER park/resume engine (reused for the interactive gate), and the audit stream.

Audit events (planned)

Consistent with the R-series pattern (credential_issued / task_deferred / …):

  • mcp_auth_requested — a tool call needs a per-user token the session lacks; server, subject, strategy (interactive / id-jag).
  • mcp_auth_completed — token acquired for {subject, session, server}; strategy, wait_ms. Never carries token material or the raw assertion.
  • mcp_auth_denied — consent refused / IdP policy denied / grant rejected; server, subject, reason.

Acceptance criteria (requirement-level)

  • Two users in two sessions calling the same MCP tool produce two distinct downstream identities, isolated per session.
  • No per-user MCP token is written to disk on the runtime path; session end drops it.
  • Satisfiable by either mechanism (A or B), selectable per server, with A as the universal fallback.
  • Audit records the acquisition lifecycle without token/assertion material.
  • The pre-R10 shared-grant path (forge mcp login) remains available (opt-in per server) for single-identity/service use.
  • Docs: a docs/security/delegated-identity.md (R10) added to the governance set, cross-linked from the R-series map.

Related

Anchors

.claude/skills/forge.md §12.11 (R1–R10 map — R10 row added), forge-core/auth/{provider.go:46,middleware.go:122} (Identity + raw assertion), forge-core/mcp/oauth_flow.go (BearerToken seam), forge-cli/runtime/defer.go (park/resume reused by the Forge-local resolver's auth-required gate).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestforge-coreAffects the forge-core library (runtime, security, types, llm, mcp, auth)securitySecurity vulnerability fixes

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions