The value check enforces type and enum, and declares the rest
A published contract says more than the launch boundary enforces. That is a real distinction and worth stating, so a caller does not read an unenforced keyword as a guarantee.
The rule
- The per-value stage of the launch check enforces exactly two things from a contract fragment:
typeandenum. - Every other published key (
minimum,maximum,minLength,maxLength,pattern, and nestedpropertiesoritems) is declared in the contract and not enforced here, as is atypethat is not a single string. - The top-level required list is the one declared key that is enforced, and it is enforced by the earlier missing-input stage.
- Values are never coerced.
- Every structured type collapses to a single check that the value is a collection.
- The types meaning "any value" waive the type check entirely, matching every value including null and a collection, while still honouring
enum; they are declared no-constraint types, and a boundary that refused what the runtime accepts would give a port's declared type two meanings. enumcompares by identity, so a number and its string spelling are different values.- Violations across several inputs are aggregated into one refusal, and an input with no contract fragment skips the value check.
What it means
A published contract fragment says more than the boundary checks. Past the
required list — enforced earlier, by the stage that checks presence — the
value stage reads exactly two keys: type and enum. minLength,
maxLength, pattern, minimum, nested properties and items are all
published, all declared, and none of them is enforced here. A caller who
violates every one of them at once still gets through this stage.
A type meaning "any value" is not a stricter case of type — it waives the
type check entirely, matching a collection, a scalar or null alike, while
still honouring enum if one is published. Every structured type collapses
to one check: is the value a collection at all. Nothing is coerced, and
enum compares by identity, so a number and its string spelling are
different values. An input with no contract fragment skips the value check
outright, and violations across several inputs are aggregated into one
refusal rather than answered one at a time.
Example
The workflow declares three inputs against three fragments: count against
{"type": "integer"}, direction against
{"type": "string", "enum": ["asc", "desc"]}, and variables against no
type at all.
{ "count": "five" }{ "direction": "up" }{ "variables": { "live_state": "{\"a\":1}" } }A fourth input, code, is published against
{"type": "string", "minLength": 8, "maxLength": 3, "pattern": "^\\d+$", "minimum": 5}
— a fragment no single value could satisfy. It still launches:
{ "code": "abcdef" }Why
Recorded under OPEN-16.