Input Validation Gate¶
Runtime input procedure — instantiates Domain–Codomain Delimitation
A runtime checkpoint at the boundary that tests each incoming case against the input domain, normalizes what it safely can, and refuses or defers the rest before ordinary processing begins.
An Input Validation Gate is the live, per-request enforcement point where the input boundary is actually applied to real traffic. Where a Type Signature or Eligibility Criteria declares the domain, the gate acts on each case as it arrives: it runs the membership check, confirms the preconditions the downstream code assumes, normalizes borderline-but-recoverable inputs into supported form, and turns anything still out of domain away — cleanly, with a defined response — before ordinary processing ever begins. Its distinguishing quality is that it sits at runtime, at the edge, and its job is to guarantee that everything reaching the core is already known-good, so the core never has to defend itself against inputs it wasn't built for.
Example¶
An order-intake API receives a checkout request. The Input Validation Gate runs first: it confirms the precondition that the request carries a valid auth token (rejecting unauthenticated calls outright), checks membership — a shipping country the service actually ships to, a positive quantity, a currency it supports — and where an input is borderline but fixable, it applies a conversion rule: trimming whitespace, upcasing a country code, coercing "12" to the integer 12. A request for a country the service doesn't serve is out of domain; the gate doesn't crash or half-process it — it returns a clear 422 naming the offending field and stops. Only requests that are in-domain, precondition-satisfied, and normalized pass through to the order logic, which can therefore be written as if malformed input does not exist.
How it works¶
The gate is a sequenced checkpoint: check declared preconditions first (auth, required context), then test each field for domain membership, then apply safe conversions to salvage recoverable inputs, and finally either admit the normalized case or hand it to a rejection/deferral response. The ordering matters — normalize before you judge, but never let normalization become guessing. It is deliberately thin and total: it makes an admit/refuse decision on every case and encodes no business logic, so the boundary is enforced in exactly one place rather than smeared through the core.
Tuning parameters¶
- Strict vs. coercive — whether the gate rejects imperfect input or tries to normalize it. Coercion improves the caller's experience but risks silently reshaping a value into something the caller didn't mean.
- Fail-fast vs. accumulate — stop at the first violation, or collect all of them and return them together. Accumulation is kinder to callers; fail-fast is cheaper and leaks less about internals.
- Precondition depth — how much of what the core assumes is actually checked at the gate versus trusted. Deeper checks catch more but add latency to every call.
- Rejection verbosity — how much the refusal explains. Detailed errors help legitimate callers but can hand an attacker a map of the boundary.
When it helps, and when it misleads¶
Its strength is that it collapses the boundary to a single, testable choke point: the core stays simple because everything past the gate is guaranteed in-domain, and out-of-domain cases fail predictably instead of corrupting state deep inside. Its failure modes are over- and under-reach. Over-aggressive coercion is the subtle one — a gate that "helpfully" reshapes borderline input can admit values the caller never intended, quietly enlarging the effective domain; the safe stance is to validate strictly and cross the trust boundary only with values that provably belong.[1] Under-validation is the opposite risk: a gap in the gate lets a malformed or malicious case through to code that assumed it couldn't happen. And a gate that merely rejects without a route for legitimate-but-unsupported cases turns real users away with no recourse — which is why its rejections should feed a Triage Workflow rather than dead-end.
How it implements the components¶
membership_criteria— applies the domain's membership test to each live case, admitting only conforming inputs.safe_rejection_or_deferral_path— defines the clean, predictable response for out-of-domain cases (a typed error, a422, a deferral) rather than a crash or silent mis-handling.conversion_or_adaptation_rule— normalizes recoverable borderline inputs (trimming, coercion, canonicalization) into supported form before the membership test.precondition_statement— checks the conditions the downstream code assumes (auth present, context set) before admitting the case.
It enforces a boundary it does not author — the domain and membership rules come from Type Signature and Eligibility Criteria — and it makes only an admit/refuse decision; the downstream routing of refused cases to referral, escalation, or appeal is Unsupported Case Triage Workflow, and the output side is Output Validation.
Related¶
- Instantiates: Domain–Codomain Delimitation — the gate is where the input boundary meets real traffic.
- Consumes: Type Signature and Eligibility Criteria supply the domain and membership rules the gate applies.
- Sibling mechanisms: Unsupported Case Triage Workflow · Output Validation · Type Signature · Eligibility Criteria · Clinical Indication Criteria · Output Schema · Contract Test Suite · Service Scope Statement · Model Applicability Card · Scope Change Review
References¶
[1] A trust boundary is the line at which data from a less-trusted source enters a more-trusted context; the standard security principle is to validate (and where possible canonicalize) every input at that boundary and never let unchecked data cross it. Over-eager coercion violates the spirit of this by admitting reshaped values the caller never actually supplied. ↩