Skip to content

[BUG] A2A runtime task-store callbacks lose authenticated user context before task resolution#2465

Description

@erauner12

馃搵 Prerequisites

  • I have searched the existing issues to avoid creating a duplicate
  • By submitting this issue, you agree to follow our Code of Conduct
  • I am using the latest version of the software
  • I have tried to clear cache/cookies or used incognito mode (if ui-related)
  • I can consistently reproduce this issue

馃幆 Affected Service(s)

App Service

馃殾 Impact/Severity

Blocker

馃悰 Bug Description

The Go A2A runtime extracts the authenticated user from inbound x-user-id
request metadata and stores it in CallContext.User, but the call interceptor
returns the original request context without that identity.

Pre-executor task resolution and task-store persistence callbacks obtain the
user from the returned context.Context, not from CallContext.User. Those
callbacks can therefore run without the authenticated request identity and fall
back to the runtime service identity for owner-scoped task access.

This is especially significant for persisted input-required tasks. A later
A2A continuation is a new request and may be handled by a different process, so
each request must reconstruct and propagate its authenticated identity before
stored-task resolution occurs.

馃攧 Steps To Reproduce

  1. On current main, construct an A2A CallContext whose service parameters
    contain a non-empty x-user-id value.
  2. Call UserIDCallInterceptor().Before(...) with that context.
  3. Observe that CallContext.User contains the authenticated user.
  4. Inspect the returned context.Context with auth.UserIDFromContext(...).
  5. Observe that the returned context does not contain the user identity.
  6. Source inspection shows that when the returned context is subsequently passed
    to KAgentTaskStore, ControllerClient.CallContext cannot add x-user-id to
    the owner-scoped controller call.

馃 Expected Behavior

The A2A call interceptor should preserve the authenticated request identity in
both CallContext.User and the returned context.Context.

Pre-executor task resolution and persistence callbacks should therefore access
the authoritative task store using the same authenticated identity as the
current A2A request.

馃摫 Actual Behavior

Only CallContext.User is populated. The returned request context is unchanged,
so auth.UserIDFromContext(returnedCtx) is empty before executor processing.

Task-store callbacks that run before the executor attaches identity can
therefore use the runtime service identity rather than the authenticated A2A
request identity.

馃捇 Environment

  • OS and version: Not environment-specific
  • Kubernetes version/provider: Not applicable to the source-level reproduction
  • Browser: Not applicable
  • Application version: current main inspected at bc92b6850b4e1342fd6b9483961aa163ece94836
  • Affected component: Go ADK A2A runtime and controller-backed task store

馃敡 CLI Bug Report

Not applicable. The issue is deterministically reproduced at the interceptor
and task-store context boundary.

馃攳 Additional Context

The existing components already support the required behavior:

  • controller-v2 carries upstream authentication headers in A2A service parameters;
  • the runtime interceptor reads x-user-id and populates CallContext.User;
  • controller clients emit x-user-id when the user identity is present in their
    input context;
  • task reads and writes are owner-scoped.

The missing connection is preserving the authenticated user in the context
returned by the call interceptor before task resolution and persistence
callbacks execute. This does not require a new identity source, authentication
mode, header, or trust policy.

This issue isolates the current runtime identity-lifecycle defect from the
legacy controller task-query behavior tracked in #2464.

Focused regression coverage should assert that the interceptor populates both
CallContext.User and auth.UserIDFromContext(returnedCtx) from the same
inbound authenticated request.

馃搵 Logs

CallContext.User.Name: <authenticated-user>
auth.UserIDFromContext(returnedCtx): ""

馃摲 Screenshots

No response

馃檵 Are you willing to contribute?

  • I am willing to submit a PR to fix this issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions