Repository navigation
fix: validate nested tagged union request bodies - #336
petebacondarwin wants to merge 1 commit into
Conversation
commit: |
|
| mean | stddev | min | max | |
|---|---|---|---|---|
| PR | 177.1 ms | 7.7 ms | 163.8 ms | 202.4 ms |
| base | 172.3 ms | 4.2 ms | 167.0 ms | 183.2 ms |
Δ (PR vs base): ↑ +4.8 ms (+2.8%)
Measured with hyperfine on ubuntu-latest (3 warmup runs, 20 timed runs). CI numbers carry ±a few ms of runner jitter; treat small deltas as noise.
|
💬 Approved with comments — No correctness, security or performance problems found. Only an optional test-coverage suggestion for branch detection and a small documentation clarification remain. Findings: 1 info · 1 suggestion The decision is advisory: this comment never approves, blocks or requests changes on the pull request. 🔧 Fix with your agentPaste the following into your coding agent to investigate and fix these issues. 📋 Code Quality: 💬 1 suggestionNo correctness bugs in the generator or the runtime validator. One optional gap in test coverage for branch detection. Recommendation: 💬 Optional Nits
View full reviewTest coverage of branch detection (suggestion)
What was checked
📝 Documentation: 💬 1 infoThe architecture guide does not say how missing branch-specific fields in nested unions are handled. Recommendation: 💬 Optional Nits
View full review
✅ All other checks passed🚀 Release: ✅ LGTMRisk: Low. The 🔒 Security: ✅ LGTMThis change adds validation on the CLI side. It crosses no new trust boundary, and the server is still the final check on request bodies.
This review read the two new 📖 AGENTS.md: ✅ LGTMThe change follows the repository conventions:
⚡ Performance: ✅ LGTMNo performance concerns. Validation runs once per request over small schema fragments. Reviewed commit: |
| @@ -278,13 +278,17 @@ export function dryRun(ctx: Ctx): string[] { | |||
| } | |||
| lines.push(` ? ${parseBodyExpression(ctx)}`); | |||
There was a problem hiding this comment.
--body takes this raw parse path without calling validateBodyUnions; the request path has the same bypass in bodyBypass(). Consequently a body such as {"dataset_scope": {"type": "datasets"}} is still previewed and sent despite missing the selected branch's required IDs. Validate parsed raw bodies too (and apply the same wrapper after parsing in bodyBypass()).
| lines.push(` ? ${parseBodyExpression(ctx)}`); | |
| lines.push( | |
| ` ? ${(op.bodyUnions?.length ?? 0) > 0 && d.hasBodyParams ? `validateBodyUnions(${parseBodyExpression(ctx)}, bodyUnions)` : parseBodyExpression(ctx)}` | |
| ); |
|
🤖 I've done a thorough review of your PR. Adds generated nested tagged-union validation for flagged request bodies.
|
NuroDev
left a comment
There was a problem hiding this comment.
Seems to be some file conflicts that need fixing @petebacondarwin
6ca897b to
db9821d
Compare
|
LGTM |
|
@NuroDev - ready for another review. |
db9821d to
c7ed823
Compare
| for (const field of t.fields) { | ||
| if (!field.readOnly) visit(field.type, [...path, field.wireName], next); | ||
| } | ||
| } else if (t.kind === "intersection") { |
There was a problem hiding this comment.
An untagged outer oneOf can still contain a tagged union that is flattened into flags, but this walk only descends through objects and intersections. For example, if one branch contains scope: oneOf[{ type: "default" }, { type: "datasets", dataset_ids: ... }] and the outer union has no disjoint required selector, bodyUnions() returns no entry, so --scope-type datasets without IDs again reaches the API. Traverse union members too (and add this nesting shape to the fixture).
| } else if (t.kind === "intersection") { | |
| } else if (t.kind === "intersection" || t.kind === "union") { |
|
🤖 I've done a thorough review of your PR. Adds generated validation for nested tagged-union flag bodies.
|
What changes
Nested
oneOfflags can currently assemble bodies that violate the selected branch. For example, priority-intelligence create/update accept--dataset-scope-type datasetswithout IDs, or--dataset-scope-type defaultwith IDs.Preserve nested union branches selected by disjoint required enum values, including schemas without an explicit discriminator, and validate the assembled wire body with cf's existing JSON Schema validator before sending it or showing a dry-run preview. Enforce branch-specific required fields, closed-object rules, and available array
maxItems. Keep complete--bodyinput available for shapes that cannot be supplied as flags.Regenerate the nine affected commands and add a patch changeset. Generic fixtures execute freshly generated create/update builders and handlers, covering optional omission, valid branches, missing/forbidden fields, the 50/51-item boundary, renamed flags, referenced schemas, and explicit/implicit selectors.
Validation
pnpm --filter cf test— 1,700 passed, 6 skipped.pnpm check— generation, dependency build, workspace type checking, lint, and formatting passed.Addresses the cf portion of cloudflare/forge#33. Missing
minItemsand UUID-format metadata remains tracked separately in cloudflare/forge#47.