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
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;