You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Propose identity propagation as a credential, not just as data — completing the identity story that #245 starts on the attribution side. #245 propagates {task_id, user_id, repo, trace_id} so actions are traceable; this RFC makes outbound calls (GitHub, Linear, future Jira/Slack) carry an enforceable per-task, per-repo, short-lived identity via AgentCore Identity Token Vault, so attribution becomes cryptographic rather than advisory.
This is the "Delegation chain propagation" item #245 explicitly defers as out-of-scope follow-up, combined with ROADMAP's "Per-repo GitHub credentials" and "Layered credential derivation."
Drafted by Bonk, reviewed and filed by Laith Al-Saadoon.
Why this is mostly resume, not greenfield
ABCA already runs on AgentCore Runtime, and the identity-propagation plumbing exists end-to-end but is dormant (parked at Phase 2.0a due to a USER_FEDERATION service-side bug; fell back to direct Secrets Manager):
Orchestrator already sets runtimeUserId on InvokeAgentRuntimeCommand — cdk/src/handlers/shared/strategies/agentcore-strategy.ts:56
Orchestrator role already holds bedrock-agentcore:InvokeAgentRuntimeForUser — cdk/src/constructs/task-orchestrator.ts:288-289
Agent already reads the WorkloadAccessToken header and re-injects it across the pipeline thread (the per-thread ContextVar workaround is already solved) — agent/src/server.py:283-310, 387-413
The bedrock-agentcore dep is kept as "vestigial" specifically so this path imports cleanly when resumed — agent/pyproject.toml
Current credential gap
Surface
Today
Risk
GitHub
One shared PAT in Secrets Manager (agent/src/config.py:resolve_github_token)
One token, all repos; no per-user/repo scoping (tracked SECURITY.md limitation)
Linear
Per-workspace OAuth token in SM, manual refresh (linear-oauth-resolver.ts)
Workspace-scoped, not user-scoped; no act-claim audit chain
AgentCore Identity
Parked (Phase 2.0a) — fell back to direct Secrets Manager
Outbound identity collapses to a shared service credential
Why now
The AgentCore deep-dive (v1.2, 2026-05-13) records OBO (ON_BEHALF_OF_TOKEN_EXCHANGE) GA'd April 2026 across 14 regions and re-grounds the oauth2Flow enum against current API refs. The Phase 2.0a blocker was a USER_FEDERATION service bug; the platform side that parked us has materially changed. Phase 0 below re-validates before we commit.
Design
Shared binding key with #245. AgentCore Identity binds tokens to (workload_identity, user_id). user_id MUST be the same IdP-namespaced value #245 standardizes (e.g. cognito+<sub>, avoiding sub collisions across IdPs). One identity, two planes: #245 stamps it in logs/spans; this RFC stamps it in tokens.
Flow selection (deep-dive §12 decision tree):
Integration
Inbound
Downstream
Flow
GitHub (commit/PR as user)
Cognito
github.com (different ecosystem)
USER_FEDERATION (3LO)
Linear
Cognito/webhook
linear.app (different)
USER_FEDERATION (3LO), replacing manual SM refresh
Headless / webhook-no-user
none
n/a
M2M (client_credentials) under a manual workload identity
Future AWS-native downstream
Cognito
same ecosystem
OBO with act-claim delegation
The honest webhook caveat: webhook-triggered tasks (Linear/Slack/GitHub) authenticate the tenant via HMAC, not the user. The real OAuth consent moment is when the agent calls back out. Read-only triage → M2M service account; write-back → gated on fresh per-user consent.
Token Vault providers replace direct Secrets Manager reads: a GithubOauth2 provider (GitHub App → repo-scoped, short-lived, auto-refreshing installation tokens) retires the shared PAT; AtlassianOauth2/SlackOauth2 follow the same pattern as those integrations land.
Delegation chain (the #245 deferral): where downstream can consume it, use OBO delegation mode (actorTokenContent=M2M) so the issued token carries an act claim recording user → orchestrator → agent — per-action accountability, feeding #237's abca.audit.v1correlation block.
Backend-agnostic: per SECURITY.md, SessionRole + agent code already serve both AgentCore and the parked ECS backend. Deep-dive §15 documents the raw-boto3 equivalent for ECS, so the agent keeps a single resolve_<integration>_token() seam regardless of how the WAT arrives.
Phasing
Phase 0 — Re-validate (spike, no prod change). Confirm USER_FEDERATION/OBO works post-GA for our Cognito→GitHub shape in a throwaway provider. Record go/no-go with date + region.
Phase 1 — GitHub via Token Vault (3LO). Stand up GithubOauth2 provider; switch resolve_github_token() to the vault path behind a flag, PAT fallback retained; retire the shared PAT once green. Resolves the SECURITY.md "Shared GitHub PAT" limitation.
Phase 2 — Linear onto the vault. Move per-workspace OAuth to the vault provider; delete manual-refresh code.
Summary
Propose identity propagation as a credential, not just as data — completing the identity story that #245 starts on the attribution side. #245 propagates
{task_id, user_id, repo, trace_id}so actions are traceable; this RFC makes outbound calls (GitHub, Linear, future Jira/Slack) carry an enforceable per-task, per-repo, short-lived identity via AgentCore Identity Token Vault, so attribution becomes cryptographic rather than advisory.This is the "Delegation chain propagation" item #245 explicitly defers as out-of-scope follow-up, combined with ROADMAP's "Per-repo GitHub credentials" and "Layered credential derivation."
Why this is mostly resume, not greenfield
ABCA already runs on AgentCore Runtime, and the identity-propagation plumbing exists end-to-end but is dormant (parked at Phase 2.0a due to a USER_FEDERATION service-side bug; fell back to direct Secrets Manager):
runtimeUserIdonInvokeAgentRuntimeCommand—cdk/src/handlers/shared/strategies/agentcore-strategy.ts:56bedrock-agentcore:InvokeAgentRuntimeForUser—cdk/src/constructs/task-orchestrator.ts:288-289WorkloadAccessTokenheader and re-injects it across the pipeline thread (the per-thread ContextVar workaround is already solved) —agent/src/server.py:283-310, 387-413bedrock-agentcoredep is kept as "vestigial" specifically so this path imports cleanly when resumed —agent/pyproject.tomlCurrent credential gap
agent/src/config.py:resolve_github_token)linear-oauth-resolver.ts)act-claim audit chainWhy now
The AgentCore deep-dive (v1.2, 2026-05-13) records OBO (
ON_BEHALF_OF_TOKEN_EXCHANGE) GA'd April 2026 across 14 regions and re-grounds theoauth2Flowenum against current API refs. The Phase 2.0a blocker was a USER_FEDERATION service bug; the platform side that parked us has materially changed. Phase 0 below re-validates before we commit.Design
Shared binding key with #245. AgentCore Identity binds tokens to
(workload_identity, user_id).user_idMUST be the same IdP-namespaced value #245 standardizes (e.g.cognito+<sub>, avoidingsubcollisions across IdPs). One identity, two planes: #245 stamps it in logs/spans; this RFC stamps it in tokens.Flow selection (deep-dive §12 decision tree):
act-claim delegationThe honest webhook caveat: webhook-triggered tasks (Linear/Slack/GitHub) authenticate the tenant via HMAC, not the user. The real OAuth consent moment is when the agent calls back out. Read-only triage → M2M service account; write-back → gated on fresh per-user consent.
Token Vault providers replace direct Secrets Manager reads: a
GithubOauth2provider (GitHub App → repo-scoped, short-lived, auto-refreshing installation tokens) retires the shared PAT;AtlassianOauth2/SlackOauth2follow the same pattern as those integrations land.Delegation chain (the #245 deferral): where downstream can consume it, use OBO delegation mode (
actorTokenContent=M2M) so the issued token carries anactclaim recordinguser → orchestrator → agent— per-action accountability, feeding #237'sabca.audit.v1correlationblock.Backend-agnostic: per SECURITY.md, SessionRole + agent code already serve both AgentCore and the parked ECS backend. Deep-dive §15 documents the raw-boto3 equivalent for ECS, so the agent keeps a single
resolve_<integration>_token()seam regardless of how the WAT arrives.Phasing
GithubOauth2provider; switchresolve_github_token()to the vault path behind a flag, PAT fallback retained; retire the shared PAT once green. Resolves the SECURITY.md "Shared GitHub PAT" limitation.act-claim where supported; emit the actor chain into RFC: Governance planes — analytics and compliance export #237'scorrelationblock.Acceptance criteria
user_idbinding key matches feat(observability): end-to-end task attribution and cross-plane trace correlation #245's namespaced value exactly (no divergence between log attribution and token binding).WorkloadAccessTokenbridge degrades gracefully if the dep is absent (already true).actchain (Phase 3) is joinable to feat(observability): end-to-end task attribution and cross-plane trace correlation #245trace_idand feeds RFC: Governance planes — analytics and compliance export #237correlation.Out of scope
Open questions
actclaim for user attribution — decide here.GetResourceOauth2Tokenfetches; negligible at current volume, noted for feat: Bedrock cost attribution — session tags, request metadata, and operator FinOps guidance #215 forecasting.Related