@@ -400,16 +400,44 @@ def auth_context_factory(meta: RequestMetadata) -> ToolContext:
400400 :class:`ToolContext` — agents that want a typed subclass
401401 (e.g. :class:`~adcp.server.AccountAwareToolContext`) should copy
402402 the three-line body and return their own subclass instead.
403+
404+ Also sets ``metadata["adcp.auth_info"]`` to a typed
405+ :class:`~adcp.decisioning.AuthInfo` when the request is
406+ authenticated, so :meth:`~adcp.decisioning.PlatformHandler._extract_auth_info`
407+ surfaces a non-``None`` :attr:`~adcp.decisioning.RequestContext.auth_info`
408+ for bearer flows — the same typed surface signed-request flows already
409+ populate. ``credential`` is ``None`` for bearer flows because inbound
410+ bearer tokens are not for upstream propagation; adopters who need
411+ :class:`~adcp.decisioning.BuyerAgentRegistry` dispatch must supply a
412+ typed credential in a custom ``context_factory`` subclass.
413+
414+ ``adcp.auth_info`` is server-internal and never wire-echoed by the
415+ framework. Do not pass ``ctx.metadata`` wholesale to a JSON serializer
416+ — the ``AuthInfo`` object is not JSON-serializable.
403417 """
418+ principal_identity = current_principal .get ()
404419 principal_metadata = current_principal_metadata .get () or {}
405420 combined_metadata : dict [str , Any ] = {
406421 ** principal_metadata ,
407422 "tool_name" : meta .tool_name ,
408423 "transport" : meta .transport ,
409424 }
425+ if principal_identity is not None :
426+ # Lazy import to keep module-load order safe — decisioning.context
427+ # imports adcp.server.base but not adcp.server.auth, so there is no
428+ # circular dependency, but hoisting this to module level would create
429+ # one if the import graph ever changes. Call-time import matches
430+ # the pattern already used in dispatch._build_request_context.
431+ from adcp .decisioning .context import AuthInfo # noqa: PLC0415
432+
433+ combined_metadata ["adcp.auth_info" ] = AuthInfo (
434+ kind = "bearer" ,
435+ principal = principal_identity ,
436+ credential = None , # explicit None: no synthesis, no DeprecationWarning
437+ )
410438 return ToolContext (
411439 request_id = meta .request_id ,
412- caller_identity = current_principal . get () ,
440+ caller_identity = principal_identity ,
413441 tenant_id = current_tenant .get (),
414442 metadata = combined_metadata ,
415443 )
0 commit comments