From bca206d794bd7c1edb608820ff8612fa5ce45638 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 23 Aug 2026 10:29:24 -0700 Subject: [PATCH] fix(gateway): rate-limit cron mutations (#128287) Co-authored-by: Amp --- src/gateway/methods/core-descriptors.ts | 8 ++++---- src/gateway/server-methods-list.test.ts | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/gateway/methods/core-descriptors.ts b/src/gateway/methods/core-descriptors.ts index d1522c0032c1..8247aa5ee0ad 100644 --- a/src/gateway/methods/core-descriptors.ts +++ b/src/gateway/methods/core-descriptors.ts @@ -342,10 +342,10 @@ const CORE_GATEWAY_METHOD_SPECS = [ ["cron.status", "cron", "operator.read", "<=2026.7"], ["cron.scratch.get", "cron", "operator.admin", "2026.7"], ["cron.scratch.set", "cron", "operator.admin", "2026.7"], - ["cron.add", "cron", "operator.admin", "<=2026.7"], - ["cron.update", "cron", "operator.admin", "<=2026.7"], - ["cron.remove", "cron", "operator.admin", "<=2026.7"], - ["cron.run", "cron", "operator.admin", "<=2026.7"], + ["cron.add", "cron", "operator.admin", "<=2026.7", { controlPlaneWrite: true }], + ["cron.update", "cron", "operator.admin", "<=2026.7", { controlPlaneWrite: true }], + ["cron.remove", "cron", "operator.admin", "<=2026.7", { controlPlaneWrite: true }], + ["cron.run", "cron", "operator.admin", "<=2026.7", { controlPlaneWrite: true }], ["cron.runs", "cron", "operator.read", "<=2026.7"], ["gateway.identity.get", "system", "operator.read", "<=2026.7"], // Deprecated read-only compatibility preview; new restart flows request the diff --git a/src/gateway/server-methods-list.test.ts b/src/gateway/server-methods-list.test.ts index 60fb283f6757..dabe6b289074 100644 --- a/src/gateway/server-methods-list.test.ts +++ b/src/gateway/server-methods-list.test.ts @@ -203,6 +203,23 @@ describe("listGatewayMethods", () => { expect(descriptor?.controlPlaneWrite).toBeUndefined(); }); + it("classifies cron mutations as control-plane writes", () => { + const descriptors = createCoreGatewayMethodDescriptors(coreGatewayHandlers); + + for (const method of ["cron.add", "cron.update", "cron.remove", "cron.run"]) { + expect(descriptors.find((descriptor) => descriptor.name === method)).toMatchObject({ + name: method, + scope: "operator.admin", + controlPlaneWrite: true, + }); + } + for (const method of ["cron.get", "cron.list", "cron.status", "cron.runs"]) { + expect( + descriptors.find((descriptor) => descriptor.name === method)?.controlPlaneWrite, + ).toBeUndefined(); + } + }); + it("does not advertise hidden core handlers", () => { const methods = listGatewayMethods(); expect(methods).not.toContain("node.runnerInventory.update");