Add provider auth broker profiles

This commit is contained in:
ZacharyZhang-NY committed 2026-05-23 19:23:55 -04:00
1 parent c862cd1319
commit c6be8a4ee4
10 files changed
+370 -37

No files matched your search

@@ -23,7 +23,7 @@ describe("domain services", () => {
const connection = createConnection();
const rows = connection.db.prepare("select version from schema_migrations order by version asc").all() as Array<{ version: number }>;
expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]);
connection.close();
});
@@ -0,0 +1,79 @@
import { randomUUID } from "node:crypto";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { DatabaseSync } from "node:sqlite";
import { describe, expect, test } from "vitest";
import { providerAuthBrokerSchema } from "../../src/main/database/migrations/021-provider-auth-broker";
function createDatabase(): DatabaseSync {
return new DatabaseSync(join(tmpdir(), `agentcompany-auth-broker-migration-${randomUUID()}.db`));
}
describe("provider auth broker migration", () => {
test("backfills active auth profiles from configured credentials", () => {
const db = createDatabase();
db.exec(`
create table schema_migrations(version integer primary key, name text not null, applied_at text not null);
create table organizations(id text primary key);
create table providers(
id text primary key,
org_id text not null,
provider_key text not null,
auth_type text not null,
credential_id text
);
create table credentials(
id text primary key,
org_id text not null,
provider_key text not null,
kind text not null,
ciphertext blob not null,
display_hint text not null,
created_at text not null
);
insert into schema_migrations(version, name, applied_at) values (20, 'rollback_snapshots', datetime('now'));
insert into organizations(id) values ('org_1');
insert into credentials(id, org_id, provider_key, kind, ciphertext, display_hint, created_at)
values ('cred_1', 'org_1', 'openai', 'api_key', x'736563726574', 'sk-liv...ider', '2026-05-23T01:02:03.000Z');
insert into providers(id, org_id, provider_key, auth_type, credential_id)
values ('prov_1', 'org_1', 'openai', 'api_key', 'cred_1');
`);
db.exec(providerAuthBrokerSchema);
const profile = db.prepare(`
select org_id, provider_id, credential_id, provider_key, auth_type,
profile_kind, display_hint, source_type, capability_json, active, created_at
from provider_auth_profiles
`).get() as {
org_id: string;
provider_id: string;
credential_id: string;
provider_key: string;
auth_type: string;
profile_kind: string;
display_hint: string;
source_type: string;
capability_json: string;
active: number;
created_at: string;
};
const migration = db.prepare("select version, name from schema_migrations where version = 21").get();
expect(profile).toMatchObject({
org_id: "org_1",
provider_id: "prov_1",
credential_id: "cred_1",
provider_key: "openai",
auth_type: "api_key",
profile_kind: "api_key",
display_hint: "sk-liv...ider",
source_type: "migrated_credential",
active: 1,
created_at: "2026-05-23T01:02:03.000Z",
});
expect(JSON.parse(profile.capability_json)).toEqual({ providerKey: "openai", authType: "api_key", capabilityTags: [] });
expect(migration).toEqual({ version: 21, name: "provider_auth_broker" });
db.close();
});
});
@@ -41,6 +41,46 @@ describe("provider service", () => {
}
});
test("creates active auth broker profiles during credential rotation", () => {
const connection = createConnection();
const organization = new OrganizationService(connection.db);
const snapshot = new SnapshotService(connection.db);
const providers = new ProviderService(connection.db, providerAdapters, testVault);
let orgId = "";
let openAiProviderId = "";
connection.transaction(() => {
orgId = createOrganization(organization);
openAiProviderId = providerId(connection, orgId, "openai");
providers.saveCredential({ orgId, providerId: openAiProviderId, secret: "sk-live-provider-one", model: "gpt-5.4" });
providers.saveCredential({ orgId, providerId: openAiProviderId, secret: "sk-live-provider-two", model: "gpt-5.4" });
});
const rows = connection.db.prepare(`
select credential_id, display_hint, source_type, capability_json, active
from provider_auth_profiles
where org_id = ? and provider_id = ?
order by active desc, created_at desc
`).all(orgId, openAiProviderId) as Array<{
credential_id: string;
display_hint: string;
source_type: string;
capability_json: string;
active: number;
}>;
const state = snapshot.load();
const activeProfile = state.providerAuthProfiles.find((profile) => profile.providerId === openAiProviderId && profile.active);
const provider = state.providers.find((item) => item.id === openAiProviderId);
expect(rows.map((row) => row.active)).toEqual([1, 0]);
expect(rows[0]).toMatchObject({ display_hint: "sk-liv...-two", source_type: "manual_secret" });
expect(JSON.parse(rows[0].capability_json)).toMatchObject({ providerKey: "openai", capabilityTags: ["responses", "tools", "background"] });
expect(provider?.credentialId).toBe(rows[0].credential_id);
expect(activeProfile?.credentialId).toBe(rows[0].credential_id);
expect(state.auditEvents.some((event) => event.entityType === "provider_auth_profile" && event.action === "created")).toBe(true);
connection.close();
});
test("checks provider health through its adapter", async () => {
const connection = createConnection();
const organization = new OrganizationService(connection.db);