Skip to content

feat: choose the shared credential an agent key uses per server - #8040

Merged
danielkov merged 90 commits into
mainfrom
daniel/aim-596-feat-agent-key-auth-client-choices
Oct 29, 2026
Merged

danielkov merged 90 commits into
mainfrom
daniel/aim-596-feat-agent-key-auth-client-choices

Conversation

@danielkov

@danielkov danielkov commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

AIM-596 (5 of 5)

Stacked on #8039.

Summary

  • keys.create takes auth_client_choices for agent keys: one {mcp_server_id, auth_client_id?} per server.
    • Each must be a shared credential (service account or static credential) the server offers enabled, or no-auth on a server that needs none.
    • Pass-through credentials are refused and not listed: the agent gateway does not forward the caller's headers to its servers, so the key could not authenticate there.
    • Personal and identity-provider clients are refused: an agent reaches a person's connection only while acting for them.
    • Choices are recorded in the key's creation transaction under a new api_key credential kind keyed by the key's row id. Ordinary keys refuse choices.
  • keys.rotate copies the rotated key's choices to its replacement.
  • Serving (only where upstream_auth_enforced is on):
    • On a direct server the key has a choice for, the key goes through the typed resolver with that choice: the mandatory mcp:auth check, client headers, and service-account tokens. This includes private servers without a sign-in issuer, where the key is resolved after it authenticates.
    • On the agent gateway, members the key has a choice for are served the same way (memberChoices.onlyChosen).
    • Servers the key has no choice for keep today's path, so existing keys and their attachments are unaffected.
  • ResolveAuthClientAccessTokens: a self-owned (service-account) registration is resolved without attachments for any caller, since its token belongs to nobody. People's connections still go through attachments.
  • authClients.listMcpServerChoices: a server's enabled shared credentials (names and types only), for callers who can connect to the server. Legacy keys are refused.
  • Dashboard: both ways of issuing an agent key (the agent setup wizard and Issue a key in an agent's Credentials section) show "Choose which credential this key uses" under each selected remote or tunneled server that offers several shared credentials. Continuing or issuing is blocked, naming the servers, until each is chosen; the offered credentials are read again at issue.
  • Platform MCP / Admin MCP: no change. Neither creates API keys.

Motivation

RFC section 7.7: agent key creation is the interactive moment that establishes a key's choices, so later key use needs no browser consent, and several ready shared credentials need an explicit choice rather than a silent default.

Gutternote review steps

  1. Setup: in a remote server's Settings → Authentication, add two shared static credentials. Turn on upstream_auth_enforced for the organization to see the chosen one served.
  2. Sidebar → Identity → Agents → an agent → Credentials → New key (/<org>/projects/<project>/identities/agent:<id>/credentials?credential=new).
  3. On the servers step, tick that server. A select reading "Choose which credential this key uses" appears under it.
  4. Continue without choosing. It stops with "Choose which credential the key uses on ." Choose one of the two and issue the key.

Administrators can create remote_session, service_account, static_credential
and pass_through auth clients, offer an existing client on another server, and
replace an administrator-created client's headers. The typed resolver treats
administrator-created clients and associations as authoritative instead of
checking them against the server settings that backfilled copies mirror.
Server settings add a credential another server already offers or create a
new one, and a credential's sheet edits and rotates its headers. The static
Authorization identity choice is renamed to a shared credential. Agent pages
edit credential blocks for managers and connection owners.
…o daniel/aim-596-feat-dashboard-auth-client-setup
Where typed auth client resolution is enforced, consent offers each server's
permitted auth clients, preselects the remembered choice or the fixed order,
and records the picked client and its own registration on the new
credential. Gateways offer the choice per member and capture tools through it.
A member added after a credential was issued gets no-auth or its single
ready permitted client recorded atomically the first time it is used, where
typed auth client resolution is enforced. Otherwise it stays unavailable
until the person reconnects to choose.
Agent key creation records an auth client choice per server under a new
api_key credential kind, rotation copies it, and under enforcement the key
is served through those choices on direct servers and agent gateway members.
The key wizard asks for a credential on servers offering several.
@danielkov
danielkov requested review from a team as code owners October 24, 2026 15:40
@changeset-bot

changeset-bot Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fcc00dd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
server Minor
dashboard Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@linear-code

linear-code Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

AIM-596

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed

This PR changes authentication, authorization, or input validation. Ultrareviews find 2.4x more serious bugs than standard reviews. Comment @cubic-dev-ai ultrareview to run one.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread server/internal/mcp/serve_meta.go Resolved
Comment thread server/internal/authclients/choices.go Resolved

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 55 files

Requires human review: Auto-approval blocked because this review re-detected 7 unresolved issues already reported by Cubic.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread server/internal/authclients/choices.go Resolved
Comment thread server/design/keys/design.go Resolved
Comment thread server/design/authclients/design.go Resolved
Comment thread server/design/authclients/design.go Resolved
Bind a registration's issuer to the client's project, refuse empty header
entries, keep stored secrets across '_'/'-' spellings, report members'
choice among several credentials in get_my_mcp_connection_status, map the
post-offer read failure, and cover admin clients and cross-server offers.
…o daniel/aim-596-feat-dashboard-auth-client-setup
…aniel/aim-596-feat-consent-auth-client-picker
Let an agent approval proceed when only the person lacks access, offer
connect and reconnect for identity-provider clients, record no client for a
no-auth server, and let a later no-auth approval clear the remembered client.
…niel/aim-596-feat-gateway-new-member-choices

# Conflicts:
#	server/internal/mcpservers/upstreamclients/queries.sql
…niel/aim-596-feat-agent-key-auth-client-choices
…ctions UI

Keep the full agent policy as the permission editor's baseline so a
credential restriction no longer makes every save report a conflict.
Load every page of credentials, connections and connection blocks;
show connection-owner blocks read-only; reset the block dialogs on
close; refresh the agent policy after a connection block changes.

Keep stored non-secret header values by name when is_secret is
unchanged, keep header descriptions on save, ask for a new value when
a stored header is renamed, and refuse reserved headers while editing.
Say when sign-ins fail to load, describe both shared credential
formats, and point the Platform MCP setup skill at Static credential
for API key and Basic upstreams.
Fail closed when a key's choices cannot be read or name a legacy choice,
decide gateway key choices before the token path, apply the self-held
credential exception to reconnect checks, block issuing when a server's
credentials cannot be loaded, and clear stale picks.
…niel/aim-596-feat-gateway-new-member-choices
…niel/aim-596-feat-agent-key-auth-client-choices

# Conflicts:
#	client/dashboard/src/pages/agents/credentials/CredentialsWizard.tsx
#	server/internal/mcp/serve_meta.go
…o daniel/aim-596-feat-dashboard-auth-client-setup
…aniel/aim-596-feat-consent-auth-client-picker
…niel/aim-596-feat-gateway-new-member-choices
…niel/aim-596-feat-agent-key-auth-client-choices
@blacksmith-sh

This comment has been minimized.

Drops the "New:" prefix, names the reuse option "Existing credential" and
leaves it out when no other server has a credential to share. The upstream
sign-in row now says what probing a remote upstream found.
…aniel/aim-596-feat-consent-auth-client-picker
…niel/aim-596-feat-gateway-new-member-choices
…niel/aim-596-feat-agent-key-auth-client-choices
Base automatically changed from daniel/aim-596-feat-gateway-new-member-choices to main October 29, 2026 16:49

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

@blacksmith-sh

This comment has been minimized.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed against the latest diff

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread server/internal/mcp/serveendpoint.go Resolved
Comment thread server/internal/mcp/serveendpoint.go Resolved
Comment thread server/internal/mcp/serveendpoint.go Resolved

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

@danielkov
danielkov added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit 3c2e97d Oct 29, 2026
54 checks passed
@danielkov
danielkov deleted the daniel/aim-596-feat-agent-key-auth-client-choices branch October 29, 2026 22:01
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants