Validate complex/list response type tags against value shape (#376)#411
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code ReviewThis PR extends the fail-loud type/value contradiction check from scalar PLAUSIBLE —
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## v1.0.0-beta.3 #411 +/- ##
=================================================
+ Coverage 73.85% 76.22% +2.37%
=================================================
Files 156 158 +2
Lines 3698 3761 +63
=================================================
+ Hits 2731 2867 +136
+ Misses 967 894 -73
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Code ReviewSummary: Extends the fail-loud type/value contradiction check from scalar tags to complex/list response Strengths
Observations / Minor NotesUnusual guard expected.matches(value) else {
try reportComplexMismatch(value, fieldName: fieldName, declaredType: fieldType.rawValue)
}
Doc-comment length on The doc comment is detailed and accurate, but it's substantially longer than comments elsewhere in the file. CLAUDE.md guidance is one short line max for comments where the WHY is non-obvious. The most critical WHY ("fail-loud to match scalar contradiction treatment") is already captured in the method name and the Test nit
Overall: Correct, well-tested, and closes the issue cleanly. The edge cases (ASSETID, LIST container-only validation, untagged-path unchanged) are all handled thoughtfully. LGTM pending the minor readability notes above. |
) Extends the fail-loud type/value contradiction check (added for #375) from scalar tags to the complex/list response `type` tags. A declared REFERENCE/ASSET/ASSETID/LOCATION/LIST whose decoded value isn't the matching oneOf case now throws ConversionError.typeValueMismatch instead of silently coercing to the value's self-describing shape. - makeTypedComplex (FieldValue+Components.swift) gates on an ExpectedComplexValue mapping, then reuses makeComplexFieldValue so a tagged value converts identically to the same value untagged. ASSETID shares AssetValue with ASSET; LIST is validated at the container level (elements stay lenient, matching the existing list conversion). The response `type` enum carries a single LIST tag, unlike the request's granular *_LIST family. - Untagged responses are unchanged (still value-shape driven), so well-formed responses never start failing — the asset-vs-location oneOf regression stays green. - Flipped complexTypeContradictionStaysLenient to complexTypeContradictionThrows and added complexTypeMatchingValueConverts; updated the CLAUDE.md policy note. Note: #375 (scalar TIMESTAMP write tagging + scalar contradiction validation) was already implemented on v1.0.0-beta.3 (landed via beta.2 #395); this completes the epic's remaining read-path validation work. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4dce57c to
fb40ce6
Compare
Review: #411 — Validate complex/list response type tags against value shapeNicely scoped follow-up to #375 that closes the loop on #376. I traced the logic against the generated Code quality / design
Potential bugs
Performance
Security
Test coverage
CLAUDE.md
Overall: solid, well-tested, and consistent with the established scalar-validation pattern. No blocking issues from me. |
Cover the timestamp path in the demo end-to-end: - Offline: add a "Timestamp Wire Round-Trip" suite asserting the composed request path (String -> FieldType.convertValue -> FieldValue.date -> JSON) emits CloudKit's TIMESTAMP milliseconds, for both ISO-8601 and epoch inputs. - Live: seed a fixed timestamp field in CreateRecordsPhase and assert in LookupRecordsPhase that it reads back as .date with the same value, exercising MistKit's response TIMESTAMP recovery (#376) end-to-end. A whole-millisecond timestamp would otherwise decode as .int64 unless the response type tag is honored. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ReviewReviewed the diff ( Bug:
|
Building MistDemoTests for the wasm cross-compile SIGKILLs the Swift frontend (silent exit 1 mid-compile) once the target's aggregate type-check memory crosses the runner's ceiling. The target already has 65 methods over the -warn-long-expression-type-checking=100 limit (Swift Testing #expect + optional-chained == comparisons), so it sat at the edge; the timestamp round-trip tests were the straw that flipped all 8 wasm jobs at once. Switch the wasm compile from batch mode (~whole file-group per frontend, peak RSS ~= batch) to primary-file mode (one file per frontend, peak RSS ~= one file) via -Xswiftc -disable-batch-mode. Only the wasm code path consumes wasm-swift-flags, so native Linux/other workflows are unaffected. Keeps every test compiling on wasm. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review: #411 — Validate complex/list response type tags against value shapeReviewed the diff (7 files) against Code quality
Potential bugs / issues
PerformanceNo concerns. The added check is O(1) per field (a single enum init + switch), and only runs on the response-decoding path, not the hot request path. SecurityNo concerns. This only tightens validation (fail loud on an internally-inconsistent response) rather than relaxing it, and doesn't touch auth, tokens, or transport code. Test coverage
Minor / out of scope
Overall: a clean, well-scoped, well-tested extension of an already-established pattern. The main actionable item is updating |
The epoch round-trip test compared a Double against the bare integer literal product `1_705_315_800 * 1_000`. On wasm32 `Int` is 32-bit, so that product overflows `Int32.max` at compile time, failing all 8 wasm/wasm-embedded CI jobs (native 64-bit hosts were unaffected). Keep the Int literal on 64-bit and compute the expected milliseconds as a Double under `#if arch(wasm32)`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ReviewSolid, well-scoped change — this is a clean extension of the #375 fail-loud scalar validation to the complex/list response Code quality / correctness
Test coverageGood symmetry: One gap worth flagging
Minor / non-blocking
Security / performanceNo concerns — this is pure validation logic on already-decoded local data, no new I/O, no new attack surface. The added checks make error reporting more precise (throwing with field name + declared type + value) rather than silently mis-typing data, which is a net safety improvement for consumers. Nice work — approve modulo the schema.ckdb gap, which I'd consider a should-fix rather than a blocker since dev-environment tests will pass either way. |
Epic #410. Completes the FieldValue TIMESTAMP-correctness epic.
What
Extends the fail-loud type/value contradiction check (added for #375) from scalar tags to the complex/list response
typetags. A declaredREFERENCE/ASSET/ASSETID/LOCATION/LISTwhose decoded value isn't the matchingoneOfcase now throwsConversionError.typeValueMismatchinstead of silently coercing.makeTypedComplexgates on anExpectedComplexValuemapping, then reusesmakeComplexFieldValueso a tagged value converts identically to the same value untagged.complexTypeContradictionStaysLenient→complexTypeContradictionThrows, addedcomplexTypeMatchingValueConverts, updated the CLAUDE.md policy note.Note on #375
The scalar TIMESTAMP write tagging and scalar contradiction validation #375 describes are already present on
v1.0.0-beta.3(landed via beta.2 #395). This PR is the remaining read-path validation. Recommend closing #375 as already-resolved.Closes #376.
Verification
swift build, fullswift test(539 pass), swift-format + swiftlint--strictall clean.