Skip to content

feat: spec-level Postel's-Law tolerant readers#24

Merged
caballeto merged 1 commit into
mainfrom
feat/postel-tolerant-readers
May 11, 2026
Merged

feat: spec-level Postel's-Law tolerant readers#24
caballeto merged 1 commit into
mainfrom
feat/postel-tolerant-readers

Conversation

@caballeto
Copy link
Copy Markdown
Member

Summary

@devhelm/sdk now decodes response-DTO multi-value enums as plain
strings — MonitorDto.type, IncidentDto.status, etc. flow through
the Zod schemas as z.string() and the TS types as string. New
enum values added by the API after this SDK version was built decode
without raising. Request DTOs keep their literal unions for strict
authoring-time validation (still enforced before the wire round-trip).

Implementation

scripts/lib/preprocess.mjs (vendored copy of mono's
@devhelm/openapi-tools) calls relaxResponseEnumsInSpec before the
spec is consumed by openapi-zod-client / openapi-typescript.
Relaxation happens at the spec level, not as a post-processing regex.
The classifier preserves length-1 enums (discriminator tags) so sealed
union dispatch keeps working.

Negative tests around response-DTO enum rejection (test_invalid_status,
test_invalid_channel_type, …) are flipped to assert acceptance, since
that's the new contract. Request-DTO negative tests stay strict.

Cross-surface design: mini/runbooks/api-contract.md § 3.1.

Tests

  • 1321 / 1321 tests pass.
  • npm run lint clean, npm run typecheck clean.

Test plan

  • CI green.
  • Verify in src/generated/api.ts: response DTOs (e.g.
    AlertChannelDto.channelType) emit as plain string; request
    DTOs (e.g. CreateMonitorRequest.type) keep literal unions.

Made with Cursor

Vendored `scripts/lib/preprocess.mjs` is in lockstep with mono's
`@devhelm/openapi-tools` and runs `relaxResponseEnumsInSpec` before
openapi-zod-client + openapi-typescript consume the spec. Response-DTO
multi-value enums collapse to `z.string()` in `schemas.ts` and `string`
in `api.ts` — so `MonitorDto.type` decodes any string, including future
values added by the API after this SDK version was built. Request DTOs
(CreateMonitorRequest.type, etc.) keep their literal unions for strict
client-side validation.

Negative tests around response-DTO enum rejection are flipped to assert
tolerance (Postel's Law). Negative tests around request-DTO enum
rejection are kept as-is.

See `mini/runbooks/api-contract.md` § 3.1 for the cross-surface design.

Coverage: 1321 / 1321 tests pass; lint + tsc clean.
Co-authored-by: Cursor <cursoragent@cursor.com>
@caballeto caballeto merged commit 0f7096d into main May 11, 2026
3 checks passed
@caballeto caballeto deleted the feat/postel-tolerant-readers branch May 11, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant