STET

agent_patch

runs/2026-02-27__21-30-28__gpt-5-4/flux-pr-3712/flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/agent-logs/agent.patch

11312 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/README.md b/app/README.md
index ad93ca2..277aa6f 100644
--- a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/README.md
+++ b/app/README.md
@@ -790,6 +790,7 @@ z.string().date(); // ISO date format (YYYY-MM-DD)
 z.string().time(); // ISO time format (HH:mm:ss[.SSSSSS])
 z.string().duration(); // ISO 8601 duration
 z.string().base64();
+z.string().base64url();
 ```
 
 > Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions that can be used in conjunction with [Refinements](#refine).
diff --git a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/deno/lib/README.md b/app/deno/lib/README.md
index aeaf25d..73f6efd 100644
--- a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/deno/lib/README.md
+++ b/app/deno/lib/README.md
@@ -800,6 +800,7 @@ z.string().date(); // ISO date format (YYYY-MM-DD)
 z.string().time(); // ISO time format (HH:mm:ss[.SSSSSS])
 z.string().duration(); // ISO 8601 duration
 z.string().base64();
+z.string().base64url();
 ```
 
 > Check out [validator.js](https://github.com/validatorjs/validator.js) for a bunch of other useful string validation functions that can be used in conjunction with [Refinements](#refine).
diff --git a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/deno/lib/ZodError.ts b/app/deno/lib/ZodError.ts
index 21ad657..0809033 100644
--- a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/deno/lib/ZodError.ts
+++ b/app/deno/lib/ZodError.ts
@@ -105,6 +105,7 @@ export type StringValidation =
   | "ip"
   | "cidr"
   | "base64"
+  | "base64url"
   | { includes: string; position?: number }
   | { startsWith: string }
   | { endsWith: string };
diff --git a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/deno/lib/__tests__/string.test.ts b/app/deno/lib/__tests__/string.test.ts
index 3c059f0..77f726d 100644
--- a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/deno/lib/__tests__/string.test.ts
+++ b/app/deno/lib/__tests__/string.test.ts
@@ -200,6 +200,52 @@ test("base64 validations", () => {
   }
 });
 
+test("base64url validations", () => {
+  const validBase64urlStrings = [
+    "SGVsbG8gV29ybGQ=",
+    "SGVsbG8gV29ybGQ",
+    "Pz8_Pw==",
+    "Pz8_Pw",
+    "LS0tX18=",
+    "LS0tX18",
+    "",
+  ];
+
+  for (const str of validBase64urlStrings) {
+    expect(str + z.string().base64url().safeParse(str).success).toBe(
+      str + "true"
+    );
+  }
+
+  const invalidBase64urlStrings = [
+    "SGVsbG8gV29ybGQ+",
+    "Pz8/Pw==",
+    "12345",
+    "SGVsbG8gV29ybGQ===",
+    "!LS0tX18",
+  ];
+
+  for (const str of invalidBase64urlStrings) {
+    expect(str + z.string().base64url().safeParse(str).success).toBe(
+      str + "false"
+    );
+  }
+});
+
+test("base64 and base64url flags stay distinct", () => {
+  const base64Schema = z.string().base64();
+  const base64urlSchema = z.string().base64url();
+
+  expect(base64Schema.isBase64).toBe(true);
+  expect((base64Schema as typeof base64Schema & { isBase64url?: boolean }).isBase64url).toBe(false);
+  expect(base64urlSchema.isBase64).toBe(false);
+  expect(base64urlSchema.isBase64url).toBe(true);
+  expect(base64Schema.safeParse("Pz8/Pw==").success).toBe(true);
+  expect(base64Schema.safeParse("Pz8_Pw==").success).toBe(false);
+  expect(base64urlSchema.safeParse("Pz8_Pw==").success).toBe(true);
+  expect(base64urlSchema.safeParse("Pz8/Pw==").success).toBe(false);
+});
+
 test("url validations", () => {
   const url = z.string().url();
   url.parse("http://google.com");
diff --git a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/deno/lib/types.ts b/app/deno/lib/types.ts
index 42d2606..033a4fa 100644
--- a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/deno/lib/types.ts
+++ b/app/deno/lib/types.ts
@@ -566,7 +566,8 @@ export type ZodStringCheck =
   | { kind: "duration"; message?: string }
   | { kind: "ip"; version?: IpVersion; message?: string }
   | { kind: "cidr"; version?: IpVersion; message?: string }
-  | { kind: "base64"; message?: string };
+  | { kind: "base64"; message?: string }
+  | { kind: "base64url"; message?: string };
 
 export interface ZodStringDef extends ZodTypeDef {
   checks: ZodStringCheck[];
@@ -622,6 +623,8 @@ const ipv6CidrRegex =
 // https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript
 const base64Regex =
   /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
+const base64urlRegex =
+  /^([0-9a-zA-Z_-]{4})*(([0-9a-zA-Z_-]{2}(==)?)|([0-9a-zA-Z_-]{3}=?))?$/;
 
 // simple
 // const dateRegexSource = `\\d{4}-\\d{2}-\\d{2}`;
@@ -969,6 +972,16 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
           });
           status.dirty();
         }
+      } else if (check.kind === "base64url") {
+        if (!base64urlRegex.test(input.data)) {
+          ctx = this._getOrReturnCtx(input, ctx);
+          addIssueToContext(ctx, {
+            validation: "base64url",
+            code: ZodIssueCode.invalid_string,
+            message: check.message,
+          });
+          status.dirty();
+        }
       } else {
         util.assertNever(check);
       }
@@ -1027,6 +1040,12 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
   base64(message?: errorUtil.ErrMessage) {
     return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) });
   }
+  base64url(message?: errorUtil.ErrMessage) {
+    return this._addCheck({
+      kind: "base64url",
+      ...errorUtil.errToObj(message),
+    });
+  }
 
   ip(options?: string | { version?: IpVersion; message?: string }) {
     return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) });
@@ -1235,6 +1254,9 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
   get isBase64() {
     return !!this._def.checks.find((ch) => ch.kind === "base64");
   }
+  get isBase64url() {
+    return !!this._def.checks.find((ch) => ch.kind === "base64url");
+  }
 
   get minLength() {
     let min: number | null = null;
diff --git a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/ZodError.ts b/app/src/ZodError.ts
index 6e0da79..1511c41 100644
--- a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/ZodError.ts
+++ b/app/src/ZodError.ts
@@ -105,6 +105,7 @@ export type StringValidation =
   | "ip"
   | "cidr"
   | "base64"
+  | "base64url"
   | { includes: string; position?: number }
   | { startsWith: string }
   | { endsWith: string };
diff --git a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/__tests__/string.test.ts b/app/src/__tests__/string.test.ts
index ef51900..9f0b5d9 100644
--- a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/__tests__/string.test.ts
+++ b/app/src/__tests__/string.test.ts
@@ -199,6 +199,52 @@ test("base64 validations", () => {
   }
 });
 
+test("base64url validations", () => {
+  const validBase64urlStrings = [
+    "SGVsbG8gV29ybGQ=", // "Hello World"
+    "SGVsbG8gV29ybGQ", // unpadded "Hello World"
+    "Pz8_Pw==", // "????" in base64url
+    "Pz8_Pw", // unpadded
+    "LS0tX18=", // "---__" in base64url
+    "LS0tX18", // unpadded
+    "", // Empty string is technically valid
+  ];
+
+  for (const str of validBase64urlStrings) {
+    expect(str + z.string().base64url().safeParse(str).success).toBe(
+      str + "true"
+    );
+  }
+
+  const invalidBase64urlStrings = [
+    "SGVsbG8gV29ybGQ+", // base64-only character
+    "Pz8/Pw==", // base64 slash
+    "12345", // invalid length
+    "SGVsbG8gV29ybGQ===", // invalid padding
+    "!LS0tX18", // invalid character
+  ];
+
+  for (const str of invalidBase64urlStrings) {
+    expect(str + z.string().base64url().safeParse(str).success).toBe(
+      str + "false"
+    );
+  }
+});
+
+test("base64 and base64url flags stay distinct", () => {
+  const base64Schema = z.string().base64();
+  const base64urlSchema = z.string().base64url();
+
+  expect(base64Schema.isBase64).toBe(true);
+  expect((base64Schema as typeof base64Schema & { isBase64url?: boolean }).isBase64url).toBe(false);
+  expect(base64urlSchema.isBase64).toBe(false);
+  expect(base64urlSchema.isBase64url).toBe(true);
+  expect(base64Schema.safeParse("Pz8/Pw==").success).toBe(true);
+  expect(base64Schema.safeParse("Pz8_Pw==").success).toBe(false);
+  expect(base64urlSchema.safeParse("Pz8_Pw==").success).toBe(true);
+  expect(base64urlSchema.safeParse("Pz8/Pw==").success).toBe(false);
+});
+
 test("url validations", () => {
   const url = z.string().url();
   url.parse("http://google.com");
diff --git a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/types.ts b/app/src/types.ts
index df298ae..c994b44 100644
--- a/tmp/agent-patch-flux-pr-3712.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/types.ts
+++ b/app/src/types.ts
@@ -566,7 +566,8 @@ export type ZodStringCheck =
   | { kind: "duration"; message?: string }
   | { kind: "ip"; version?: IpVersion; message?: string }
   | { kind: "cidr"; version?: IpVersion; message?: string }
-  | { kind: "base64"; message?: string };
+  | { kind: "base64"; message?: string }
+  | { kind: "base64url"; message?: string };
 
 export interface ZodStringDef extends ZodTypeDef {
   checks: ZodStringCheck[];
@@ -622,6 +623,8 @@ const ipv6CidrRegex =
 // https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript
 const base64Regex =
   /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
+const base64urlRegex =
+  /^([0-9a-zA-Z_-]{4})*(([0-9a-zA-Z_-]{2}(==)?)|([0-9a-zA-Z_-]{3}=?))?$/;
 
 // simple
 // const dateRegexSource = `\\d{4}-\\d{2}-\\d{2}`;
@@ -969,6 +972,16 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
           });
           status.dirty();
         }
+      } else if (check.kind === "base64url") {
+        if (!base64urlRegex.test(input.data)) {
+          ctx = this._getOrReturnCtx(input, ctx);
+          addIssueToContext(ctx, {
+            validation: "base64url",
+            code: ZodIssueCode.invalid_string,
+            message: check.message,
+          });
+          status.dirty();
+        }
       } else {
         util.assertNever(check);
       }
@@ -1027,6 +1040,12 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
   base64(message?: errorUtil.ErrMessage) {
     return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) });
   }
+  base64url(message?: errorUtil.ErrMessage) {
+    return this._addCheck({
+      kind: "base64url",
+      ...errorUtil.errToObj(message),
+    });
+  }
 
   ip(options?: string | { version?: IpVersion; message?: string }) {
     return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) });
@@ -1235,6 +1254,9 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
   get isBase64() {
     return !!this._def.checks.find((ch) => ch.kind === "base64");
   }
+  get isBase64url() {
+    return !!this._def.checks.find((ch) => ch.kind === "base64url");
+  }
 
   get minLength() {
     let min: number | null = null;