fix(api): lenient response decoder (round-3 P0)#22
Merged
Conversation
mono#369 adds MonitorStatus enum (UP/DOWN/DEGRADED/PAUSED/UNKNOWN) and IncidentFilterParamsSeverity (DOWN/DEGRADED), which causes oapi-codegen to namespace-qualify previously-unique enum constants: - generated.Email → generated.EmailChannelConfigChannelTypeEmail - generated.Down → generated.TriggerRuleSeverityDown - generated.Degraded → generated.TriggerRuleSeverityDegraded It also makes managedBy nullable on Create/Update DTOs (now *string pointer), and adds managedBy to Create/Update Status Page, Resource Group, and Alert Channel DTOs. Changes: - Refresh spec + regenerate types - Update enum constant references to qualified names - Wrap CreateMonitorRequest.ManagedBy in pointer (and similar for status page, resource group, alert channel) — provider continues to hardcode TERRAFORM for attribution - Allow-list new managed_by fields in schema-vs-DTO audit - Update monitor unit test for pointer ManagedBy Co-authored-by: Cursor <cursoragent@cursor.com>
The strict decoder (`json.Decoder.DisallowUnknownFields`) made every released provider version one accidental API field away from a hard break. Round-3 DevEx caught this in production: the API added `currentStatus` to the monitor response and every `terraform apply` against prod failed with `decoding response (POST /api/v1/monitors): json: unknown field "currentStatus"`. Worse, the monitor was created server-side before the decoder rejected the response, leaving an orphan with no Terraform state record. Switch to a lenient decoder that silently ignores unknown fields and logs them at WARN via tflog, so: - Additive API changes never brick old provider versions again. - Operators running with TF_LOG=warn still see the drift signal that strict decoding used to surface as a hard error. - The orphan-leak symptom goes away as a side-effect: the original failure path (POST succeeds → decode fails → state is not written) no longer triggers, because decode now succeeds. Drift visibility is preserved by walking the body's top-level keys after decode and emitting `tflog.Warn` for any key that isn't on the target struct's json tags. The helper unwraps `SingleValueResponse[T]` and `TableResponse[T]` envelopes so warnings name the user-facing DTO fields rather than the wire wrapper. Tests: - TestCreate_LenientDecode_TolerantOfNewResponseFields — the round-3 reproducer, now green. - TestCreate_LenientDecode_StillRejectsMalformedJSON — keeps the contract honest for actually-broken responses. - TestJsonFieldNames_EnvelopeUnwrap — drift-warn helper unwraps the envelope correctly. - TestLogUnknownTopLevelKeys_PicksUpDrift — sanity-checks the helper on the failure mode that bit us. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Round-3 DevEx caught a production-blocking bug: the API added `currentStatus` to the monitor response and the provider's strict decoder rejected every `terraform apply` with `decoding response (POST /api/v1/monitors): json: unknown field "currentStatus"`. Worse, the monitor was created server-side before the decoder rejected the response, leaving orphans with no Terraform state record.
This PR switches the response decoder from strict (`DisallowUnknownFields`) to lenient with drift logging, eliminating the entire class of "new API field bricks every old provider release" failure mode.
What changed
Tests
Full suite green locally: `go test ./...` → 4 packages pass.
Test plan
Made with Cursor