Skip to content

mig: add issuance selection profiles for headless callers - #8041

Merged
danielkov merged 100 commits into
mainfrom
daniel/aim-597-mig-issuance-selection-profiles
Oct 29, 2026
Merged

danielkov merged 100 commits into
mainfrom
daniel/aim-597-mig-issuance-selection-profiles

Conversation

@danielkov

@danielkov danielkov commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

AIM-597 (1 of 2)

Stacked on #8040.

Summary

  • New table issuance_selection_profiles: one profile per user session issuer and headless caller. The caller is either a client (user_session_client_id) or a workload subject (workload_issuer_id + workload_subject). Each is unique among live rows. Application code enforces that exactly one is set; no cross-column CHECK, per the repo's schema rules.
  • Tenancy is pinned with composite foreign keys:
    • (organization_id, project_id) → projects (organization_id, id).
    • (organization_id, workload_issuer_id) → workload_issuers (organization_id, id).
    • (user_session_issuer_id, user_session_client_id) → user_session_clients (user_session_issuer_id, id), so a profile's client always belongs to its issuer.
  • The issuer itself keeps a plain FK, because project-scoped issuers do not always carry organization_id. The next PR's API checks the issuer is the organization's before writing.
  • The client FK needs a new unique index, user_session_clients (user_session_issuer_id, id). Atlas emits it CONCURRENTLY, which makes this migration -- atlas:txmode none. The new table is empty and its constraints are declared inside CREATE TABLE, so there is no PG305/PG306 scan.
  • The profile's choices are upstream_client_selections rows of credential kind issuance_profile that name the profile, so there is no second choices table. In the next PR, issuance copies the choices that still validate onto each new session.
  • Schema, migration, atlas.sum and sqlc models only. Nothing reads or writes the table yet.

Motivation

RFC section 7.7, "Standard grant compatibility": unmodified jwt-bearer clients and workloads can't send per-server choices. Instead, an admin configures a profile scoped to the authenticated client or workload and the target sign-in, and its validated choices are copied onto each issued session.

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 a review from a team as a code owner October 24, 2026 15:44
@changeset-bot

changeset-bot Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dcc7c5c

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

This PR includes changesets to release 1 package
Name Type
server Patch

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-597

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

atlas migrate lint on server/migrations

Status Step Result
1 new migration file detected 20261029221223_issuance-selection-profiles.sql
ERD and visual diff generated View Visualization
Analyze 20261029221223_issuance-selection-profiles.sql
1 reports were found in analysis
Data dependent changes detected
Adding a unique index "user_session_clients_issuer_id_key" on table "user_session_clients" might fail in case columns "user_session_issuer_id", "id" contain duplicate entries (MF101)
Read the full linting report on Atlas Cloud

@github-actions

Copy link
Copy Markdown
Contributor

atlas migrate lint on clickhouse/migrations

Status Step Result
No migration files detected  
ERD and visual diff generated View Visualization
No issues found View Report
Read the full linting report on Atlas Cloud

@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 5 files

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

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

Comment thread server/database/schema.sql Resolved
Comment thread server/database/schema.sql Resolved
Comment thread server/database/schema.sql 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.
… daniel/aim-597-mig-issuance-selection-profiles
The agent gateway does not forward the caller's headers to its servers, so
a key set up with a pass-through credential could not authenticate there.
…reate-and-attach-auth-clients

# Conflicts:
#	server/internal/testenv/queries.sql
…o daniel/aim-596-feat-dashboard-auth-client-setup
…aniel/aim-596-feat-consent-auth-client-picker

# Conflicts:
#	server/internal/mcp/authnchallenge_consent_template_test.go
#	server/internal/mcp/export_test.go
…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
… daniel/aim-597-mig-issuance-selection-profiles

# Conflicts:
#	server/migrations/atlas.sum
…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
… daniel/aim-597-mig-issuance-selection-profiles
@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
… daniel/aim-597-mig-issuance-selection-profiles
Base automatically changed from daniel/aim-596-feat-agent-key-auth-client-choices to main October 29, 2026 22:01
@danielkov
danielkov requested a review from a team as a code owner October 29, 2026 22:01
…suance-selection-profiles

Regenerate the issuance selection profiles migration on top of main (SQL unchanged).
@danielkov
danielkov added this pull request to the merge queue Oct 29, 2026
Merged via the queue into main with commit 5edca0a Oct 29, 2026
49 checks passed
@danielkov
danielkov deleted the daniel/aim-597-mig-issuance-selection-profiles branch October 29, 2026 22:32
@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