SKILL.md
Schema boundary typing
Use this skill when
- The user wants runtime validation and static typing to agree at an API, storage, or parsing boundary.
- Untrusted input currently flows into application code with weak typing.
- The repository already uses a schema or validator library, or the boundary needs either a simple guard or a reusable schema pattern.
Do not use this skill when
- The boundary is already validated elsewhere and the task is only to reuse an existing type.
- The task is mainly about internal domain modeling rather than input validation at the edge.
Inputs to gather
Required before editing
- The untrusted boundary, such as request input, JSON parsing, or persisted records.
- Any existing schema or validator library already used by the repository.
- The expected validated shape and the code that consumes it.
- Error-handling expectations when validation fails.
Helpful if present
- Existing parsers, decoders, or helper wrappers around the same boundary.
- Tests for invalid payloads.
- Whether the validated type should be derived from the schema or mapped into a separate domain type.
First move
- Find the boundary where untrusted data first enters typed code.
- Reuse the repository's existing schema or validator approach before adding anything new.
- If no shared schema tool exists, decide whether a simple guard is enough or whether the boundary is important enough to justify a reusable schema pattern.
- Define the validation close to the boundary, not deep inside consumers.
Workflow
- Model the external shape with the repository's existing schema or validator tool.
- Parse or validate at the first boundary that can reject bad input cleanly.
- When a simple guard is enough, keep the solution local and do not introduce a full schema dependency.
- When a reusable schema exists or is justified, derive or expose the validated TypeScript type from it when the library supports that pattern.
- Keep unvalidated data as
unknownuntil it passes validation. - Map into a separate domain type only when the repository already distinguishes transport and domain models.
- Update downstream consumers to rely on the validated type instead of re-checking ad hoc.
Guardrails
- Must not claim a precise type for untrusted input without a matching runtime check.
- Must not introduce a new schema library when the repository already has a standard one or when a simple local guard is sufficient.
- Should validate once at the edge and pass the validated type inward.
- Should preserve existing error mapping and boundary behavior.
- Should prefer a simple local guard when the boundary is small, one-off, and unlikely to be shared.
- May keep a separate domain model when transport shapes and internal models differ materially.
Routing boundary
- Route here from
typescript-any-eliminatorwhen replacinganyrequires runtime boundary validation to make types truthful. - After boundary types are stable, route compile-time contract locking to
type-test-authoring.
Validation
Run targeted tests for valid and invalid boundary inputs.
Verify invalid payloads produce the expected failure shape: field errors, result-object errors, or thrown boundary errors that match the repository's convention.
Re-run typecheck after deriving or re-exporting the validated type.
Confirm consumers no longer rely on unvalidated
unknownor ad hoc casts.Keep
references/boundary-validation-scenarios.mdin sync when the repo's error-handling convention, schema library, or transport-to-domain boundary changes.Smoke test:
- should trigger: "Validate this JSON request body at the API edge and export the safe type."
- should not trigger: "Add compile-time tests for this inferred API type." (→
type-test-authoring)
Examples
Beforeconst payload: User = JSON.parse(raw);Afterconst payload = UserSchema.parse(JSON.parse(raw));Failure shape(custom result wrapper when callers branch on success or failure){ ok: false, errors: [ { path: ['body', 'email'], message: 'Invalid email address' }, ], }Beforeexport function readConfig(value: any) { return value.mode; }Afterexport function readConfig(value: unknown) { return ConfigSchema.parse(value).mode; }
Reference files
references/schema-patterns.md- patterns for schema-first validation, derivation, and transport-to-domain boundaries.references/boundary-validation-scenarios.md- compact checklist for success, failure, and error-shape validation at the boundary.