Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneesstack72

Relationships

#2783 Object-level refinements on globalArguments schemas are not enforced at execution time

Opened by stack72 · 9/30/2026· Shipped 9/30/2026

Description

Follow-up to swamp-club#2766 (PR swamp/#2737). A globalArguments schema that uses .refine() or .superRefine() on the object is now checked field by field during the lenient global-argument check (parseGlobalArgumentsLeniently in src/domain/models/zod_type_coercion.ts), because zod 4 refuses .partial() on refined objects. The field checks and defaults apply, but object-level refinements never run, even when every global argument is resolved.

Before #2737 these schemas crashed on every fully resolved run (fail closed). Now they run with the refinement unchecked (fail open). For a cross-field invariant such as at least one of apiKey or token must be set, a definition with neither now reaches the method.

Steps to reproduce

Model with:

const G = z.object({ apiKey: z.string().optional(), token: z.string().optional() })
  .superRefine((v, ctx) => { if (!v.apiKey && !v.token) ctx.addIssue({ code: 'custom', message: 'apiKey or token required' }); });

Definition with globalArguments: {} and run any method.

  • Expected: Global arguments validation failed: apiKey or token required
  • Actual: the method runs with neither credential.

Suggested direction

When no global argument is unresolved, after the per-field pass also run the full schema over the parsed data and report its object-level (root-path) issues, while still ignoring missing-required-field issues so the lenient contract for ephemeral direct-execution instances holds. Needs a check of how zod 4 orders object refinements against missing-key issues (refinements may be skipped when the object already has issues). Applies to method execution, swamp model validate and direct type execution, which all share the helper.

Raised as a medium finding by the CI adversarial review on PR #2737.

02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 13 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

9/30/2026, 9:30:39 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack729/30/2026, 2:39:39 PM

Sign in to post a ripple.