diff --git a/packages/shared/src/validators/secret.test.ts b/packages/shared/src/validators/secret.test.ts index 4c2cfe02901..8c03375d4bd 100644 --- a/packages/shared/src/validators/secret.test.ts +++ b/packages/shared/src/validators/secret.test.ts @@ -63,12 +63,15 @@ describe("secret validators", () => { }); }); - it("requires secret rotation payloads to include new material", () => { - expect(() => rotateSecretSchema.parse({})).toThrow(/requires value or externalRef/); - expect(() => rotateUserSecretValueSchema.parse({})).toThrow(/requires value or externalRef/); + it("requires secret rotation payloads to include rotation input", () => { + expect(() => rotateSecretSchema.parse({})).toThrow(/requires value, externalRef/); + expect(() => rotateUserSecretValueSchema.parse({})).toThrow(/requires value, externalRef/); expect(rotateUserSecretValueSchema.parse({ value: "new-secret" })).toEqual({ value: "new-secret", }); + expect(rotateUserSecretValueSchema.parse({ providerVersionRef: "version-2" })).toEqual({ + providerVersionRef: "version-2", + }); }); it("rejects externalRef on managed secrets", () => { diff --git a/packages/shared/src/validators/secret.ts b/packages/shared/src/validators/secret.ts index 01f75b09f42..bb6bf4e04cf 100644 --- a/packages/shared/src/validators/secret.ts +++ b/packages/shared/src/validators/secret.ts @@ -79,15 +79,25 @@ export const createSecretSchema = z.object({ export type CreateSecret = z.infer; -function requireSecretRotationMaterial( - value: { value?: string | null; externalRef?: string | null }, +function requireSecretRotationInput( + value: { + value?: string | null; + externalRef?: string | null; + providerVersionRef?: string | null; + providerConfigId?: string | null; + }, ctx: z.RefinementCtx, ) { - if (!value.value?.trim() && !value.externalRef?.trim()) { + if ( + !value.value?.trim() && + !value.externalRef?.trim() && + value.providerVersionRef === undefined && + value.providerConfigId === undefined + ) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["value"], - message: "Secret rotation requires value or externalRef", + message: "Secret rotation requires value, externalRef, providerVersionRef, or providerConfigId", }); } } @@ -97,7 +107,7 @@ export const rotateSecretSchema = z.object({ externalRef: z.string().optional().nullable(), providerVersionRef: z.string().optional().nullable(), providerConfigId: z.string().uuid().optional().nullable(), -}).superRefine(requireSecretRotationMaterial); +}).superRefine(requireSecretRotationInput); export type RotateSecret = z.infer; @@ -194,7 +204,7 @@ export const rotateUserSecretValueSchema = z.object({ externalRef: z.string().optional().nullable(), providerVersionRef: z.string().optional().nullable(), providerConfigId: z.string().uuid().optional().nullable(), -}).superRefine(requireSecretRotationMaterial); +}).superRefine(requireSecretRotationInput); export type RotateUserSecretValue = z.infer; diff --git a/server/src/__tests__/secrets-routes.test.ts b/server/src/__tests__/secrets-routes.test.ts index 450dba3a305..fb2be0591a5 100644 --- a/server/src/__tests__/secrets-routes.test.ts +++ b/server/src/__tests__/secrets-routes.test.ts @@ -162,7 +162,7 @@ describe("secret routes", () => { .send({}); expect(res.status).toBe(400); - expect(JSON.stringify(res.body)).toMatch(/requires value or externalRef/); + expect(JSON.stringify(res.body)).toMatch(/requires value, externalRef/); expect(mockSecretService.rotateCurrentUserSecretValue).not.toHaveBeenCalled(); });