Scope env binding sync deletes

This commit is contained in:
Dotta committed 2026-05-09 16:55:44 -05:00
1 parent 208c5578e3
commit 5ca3a5cfb3
3 files changed
+47 -1

No files matched your search

@@ -205,6 +205,47 @@ describeEmbeddedPostgres("secretService", () => {
expect(JSON.stringify(events)).not.toContain("runtime-secret");
});
it("scopes env binding sync deletes to the env path prefix", async () => {
const companyId = await seedCompany();
const svc = secretService(db);
const runtimeSecret = await svc.create(companyId, {
name: `runtime-ref-${randomUUID()}`,
provider: "local_encrypted",
value: "runtime-secret",
});
const envSecret = await svc.create(companyId, {
name: `env-ref-${randomUUID()}`,
provider: "local_encrypted",
value: "env-secret",
});
await svc.createBinding({
companyId,
secretId: runtimeSecret.id,
targetType: "agent",
targetId: "agent-1",
configPath: "runtime.token",
});
await svc.syncEnvBindingsForTarget(
companyId,
{ targetType: "agent", targetId: "agent-1" },
{
API_KEY: { type: "secret_ref", secretId: envSecret.id, version: "latest" },
},
);
await svc.syncEnvBindingsForTarget(
companyId,
{ targetType: "agent", targetId: "agent-1" },
{},
);
const bindings = await db
.select()
.from(companySecretBindings)
.where(eq(companySecretBindings.targetId, "agent-1"));
expect(bindings.map((binding) => binding.configPath)).toEqual(["runtime.token"]);
});
it("returns resolved secrets even when success metadata writes fail", async () => {
const companyId = await seedCompany();
const svc = secretService(db);
+4
View File
@@ -454,6 +454,10 @@ export function secretRoutes(db: Db) {
return;
}
assertCompanyAccess(req, existing.companyId);
if (existing.status === "deleted") {
res.status(404).json({ error: "Secret not found" });
return;
}
const removed = await svc.remove(id);
if (!removed) {
+2 -1
View File
@@ -1,4 +1,4 @@
import { and, desc, eq, inArray, ne, notInArray, sql } from "drizzle-orm";
import { and, desc, eq, inArray, like, ne, notInArray, sql } from "drizzle-orm";
import type { Db } from "@paperclipai/db";
import {
agents,
@@ -1902,6 +1902,7 @@ export function secretService(db: Db) {
eq(companySecretBindings.companyId, companyId),
eq(companySecretBindings.targetType, target.targetType),
eq(companySecretBindings.targetId, target.targetId),
like(companySecretBindings.configPath, `${pathPrefix}.%`),
),
);
if (refs.length === 0) return;