This commit is contained in:
spuhaha18 2026-09-13 12:11:20 +00:00 committed by GitHub
commit d9a3ea1d59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 77 additions and 0 deletions

View File

@ -273,6 +273,82 @@ describeEmbeddedPostgres("agent service secret binding sync", () => {
expect(JSON.stringify(persistedConfig)).not.toContain(literalApiKey);
});
it("converts OpenClaw gateway credential strings into persisted secret refs", async () => {
const companyId = await seedCompany();
const literalAuthToken = `openclaw-token-${randomUUID()}`;
const literalPassword = `openclaw-password-${randomUUID()}`;
const literalDeviceToken = `openclaw-device-token-${randomUUID()}`;
const literalPrivateKeyPem = [
"-----BEGIN PRIVATE KEY-----",
`openclaw-device-key-${randomUUID()}`,
"-----END PRIVATE KEY-----",
].join("\n");
const created = await agentService(db).create(companyId, {
name: "OpenClaw Gateway",
role: "engineer",
status: "idle",
adapterType: "openclaw_gateway",
adapterConfig: {
url: "ws://127.0.0.1:18789",
authToken: literalAuthToken,
password: literalPassword,
deviceToken: literalDeviceToken,
devicePrivateKeyPem: literalPrivateKeyPem,
},
runtimeConfig: {},
spentMonthlyCents: 0,
lastHeartbeatAt: null,
});
const persistedRows = await db
.select()
.from(agents)
.where(eq(agents.id, created.id));
const persistedConfig = persistedRows[0]?.adapterConfig as Record<string, unknown>;
const serializedConfig = JSON.stringify(persistedConfig);
expect(serializedConfig).not.toContain(literalAuthToken);
expect(serializedConfig).not.toContain(literalPassword);
expect(serializedConfig).not.toContain(literalDeviceToken);
expect(serializedConfig).not.toContain(literalPrivateKeyPem);
for (const key of ["authToken", "password", "deviceToken", "devicePrivateKeyPem"]) {
expect(persistedConfig[key]).toMatchObject({
type: "secret_ref",
version: "latest",
});
}
expect(persistedConfig.url).toBe("ws://127.0.0.1:18789");
const bindings = await db
.select()
.from(companySecretBindings)
.where(and(
eq(companySecretBindings.companyId, companyId),
eq(companySecretBindings.targetType, "agent"),
eq(companySecretBindings.targetId, created.id),
));
expect(bindings.map((binding) => binding.configPath).sort()).toEqual([
"authToken",
"devicePrivateKeyPem",
"deviceToken",
"password",
]);
const resolved = await secretService(db).resolveAdapterConfigForRuntime(
companyId,
persistedConfig,
{
consumerType: "agent",
consumerId: created.id,
},
{ adapterType: "openclaw_gateway" },
);
expect(resolved.config.authToken).toBe(literalAuthToken);
expect(resolved.config.password).toBe(literalPassword);
expect(resolved.config.deviceToken).toBe(literalDeviceToken);
expect(resolved.config.devicePrivateKeyPem).toBe(literalPrivateKeyPem);
});
it("replaces agent secret bindings when adapterConfig env changes", async () => {
const companyId = await seedCompany();
const secrets = secretService(db);

View File

@ -105,6 +105,7 @@ const COMING_SOON_SECRET_PROVIDERS: ReadonlySet<SecretProvider> = new Set([
]);
const FALLBACK_ADAPTER_SCHEMA_SECRET_FIELDS: Readonly<Record<string, readonly string[]>> = {
hermes_gateway: ["apiKey"],
openclaw_gateway: ["authToken", "token", "deviceToken", "password", "devicePrivateKeyPem"],
};
const USER_SECRET_DEFINITION_KEY_UNIQUE_CONSTRAINT = "user_secret_definitions_company_key_uq";
const USER_SECRET_VALUE_UNIQUE_CONSTRAINT = "company_secrets_user_definition_owner_uq";