Q169: saved cloud and custom endpoints refill their form and keep the saved key

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-09 04:02:08 -04:00
1 parent 5cd413ffcf
commit a8fbc08df6
13 files changed
+160 -23

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
import type { DatabaseSync } from "node:sqlite";
import type { ProviderEndpoint } from "../../shared/commands";
import type { AuthBrokerService } from "./auth-broker-service";
import { loadCredential, type ProviderRow } from "./provider-internal";
function savedPayload(db: DatabaseSync, authBroker: AuthBrokerService, orgId: string, providerId: string): Record<string, unknown> | null {
const provider = db.prepare("select * from providers where id = ? and org_id = ?").get(providerId, orgId) as ProviderRow | undefined;
if (!provider) throw new Error("Provider was not found.");
if (provider.auth_type !== "cloud" || !provider.credential_id) return null;
return JSON.parse(loadCredential(authBroker, orgId, provider).secret) as Record<string, unknown>;
}
const text = (value: unknown): string => (typeof value === "string" ? value : "");
/** The saved address, region, project and deployment of a cloud or custom provider, so its form shows what is in use; never the key. */
export function providerEndpoint(db: DatabaseSync, authBroker: AuthBrokerService, orgId: string, providerId: string): ProviderEndpoint | null {
const saved = savedPayload(db, authBroker, orgId, providerId);
return saved ? { baseUrl: text(saved.baseUrl), region: text(saved.region), projectId: text(saved.projectId), deployment: text(saved.deployment) } : null;
}
/** A cloud form that left its key blank asks to keep the saved key; the saved key goes into the new payload. */
export function withSavedSecret(db: DatabaseSync, authBroker: AuthBrokerService, orgId: string, providerId: string, secret: string): string {
const payload = JSON.parse(secret) as Record<string, unknown>;
if (payload.keepSavedSecret !== true) return secret;
const saved = savedPayload(db, authBroker, orgId, providerId);
if (!saved) throw new Error("There is no saved key to keep; enter the key.");
delete payload.keepSavedSecret;
return JSON.stringify({ ...payload, secret: saved.secret });
}
+9 -3
View File
@@ -1,5 +1,6 @@
import type { DatabaseSync } from "node:sqlite";
import type { CancelProviderResponseInput, ListProviderModelsInput, RevokeProviderCredentialInput, SaveProviderCredentialInput, StreamProviderResponseInput, UpdateProviderPolicyInput, SetProviderPricesInput } from "../../shared/commands";
import type { CancelProviderResponseInput, ListProviderModelsInput, ProviderEndpoint, RevokeProviderCredentialInput, SaveProviderCredentialInput, StreamProviderResponseInput, UpdateProviderPolicyInput, SetProviderPricesInput } from "../../shared/commands";
import { providerEndpoint, withSavedSecret } from "./provider-endpoint";
import type { ProviderModelEntry } from "../../shared/provider-models";
import { PROVIDER_AUTH_TYPE, PROVIDER_DATA_POLICY, type ProviderAuthType } from "../../shared/domain";
import type { ProviderStreamRendererEvent } from "../../shared/provider-request-domain";
@@ -97,8 +98,9 @@ export class ProviderService {
const provider = this.db.prepare("select * from providers where id = ? and org_id = ?")
.get(input.providerId, input.orgId) as { provider_key: string; auth_type: ProviderAuthType } | undefined;
if (!provider) throw new Error("Provider was not found.");
const secret = input.secret.trim();
if (!secret) throw new Error("Credential is required.");
const typed = input.secret.trim();
if (!typed) throw new Error("Credential is required.");
const secret = provider.auth_type === "cloud" ? withSavedSecret(this.db, this.authBroker, input.orgId, input.providerId, typed) : typed;
const adapter = requireAdapter(this.adapters, provider.provider_key, provider.auth_type);
adapter.parseAuthProfile(secret);
const catalogEntry = requireCatalogEntry(provider.provider_key);
@@ -130,6 +132,10 @@ export class ProviderService {
});
}
endpoint(orgId: string, providerId: string): ProviderEndpoint | null {
return providerEndpoint(this.db, this.authBroker, orgId, providerId);
}
/** Revokes at the provider where it can, then always disconnects and erases the credential here; a remote failure is reported, not hidden. */
async revokeCredential(input: RevokeProviderCredentialInput): Promise<void> {
const provider = this.db.prepare(`