fix(admin-web): align provider surface with backend and ADR-0024

The org-admin provider page was a stale prototype wired to a removed
singular /provider-connection endpoint. It contradicted the pinned
invariants in several ways:

- It documented a process-env fallback for platform-managed credentials,
  but ADR-0024 / Spec.System.Organization pins the resolver fail-closed
  with no process-global key fallback.
- It exposed a BYOK<->PLATFORM_MANAGED mode toggle to org admins, but
  ADR-0021 makes platform-managed connections platform-admin owned; the
  org-side API (requireByokActor) rejects mutating them.
- It modeled one connection per org, while OrganizationProviderConnection
  is keyed by (org, providerId) and the backend exposes a list plus a
  per-providerId BYOK rotation.
- Its HTTP contract (/provider-connection, {baseUrl, hasAuthToken}) did
  not match the real backend (/provider-connections + /:providerId,
  {status, activeVersion, keyId}).
- It dangled a pointer to role/model pages that do not exist in the SPA;
  roles/skills are managed via the CLI.

Rewrite the page to list connections, show status/version/keyId, and
rotate BYOK credentials per providerId with baseUrl + authToken (+ optional
anthropicApiKey) as the backend requires. Platform-managed rows render
read-only. Drop the fallback copy and the dangling pointer. Replace the
singular ProviderConnection API client with providerConnections /
rotateProviderConnection and remove the now-unused PROVIDER_MODES constant.
This commit is contained in:
2026-07-13 23:46:15 +08:00
parent 3ae0cc3e60
commit 8d2e0cb2c6
3 changed files with 132 additions and 100 deletions
+16 -7
View File
@@ -145,12 +145,13 @@ export interface SessionSummary {
updatedAt: string;
}
export interface ProviderConnection {
organizationId: string;
export interface ProviderConnectionRow {
id: string;
providerId: string;
mode: 'BYOK' | 'PLATFORM_MANAGED';
baseUrl: string | null;
hasAuthToken: boolean;
status: 'DRAFT' | 'ACTIVE' | 'DISABLED';
activeVersion: number | null;
keyId: string | null;
createdAt: string;
updatedAt: string;
}
@@ -248,7 +249,15 @@ export const api = {
return get(`${orgBase(slug)}/usage${qs ? `?${qs}` : ''}`) as Promise<UsageReport>;
},
provider: (slug: string) => get(`${orgBase(slug)}/provider-connection`) as Promise<ProviderConnection>,
setProvider: (slug: string, body: { mode: string; providerId?: string; baseUrl?: string | null; authToken?: string | null }) =>
put(`${orgBase(slug)}/provider-connection`, body) as Promise<ProviderConnection>
providerConnections: (slug: string) =>
get(`${orgBase(slug)}/provider-connections`) as Promise<{ connections: ProviderConnectionRow[] }>,
rotateProviderConnection: (
slug: string,
providerId: string,
body: { baseUrl: string; authToken: string; anthropicApiKey?: string },
) =>
put(
`${orgBase(slug)}/provider-connections/${encodeURIComponent(providerId)}`,
body,
) as Promise<ProviderConnectionRow>
};