# description
Versioned schema for the public-draft preflight_action open standard v0. Defines the request, policy, response, error-envelope, and record objects; a document validates at the root if it is any of these five shapes, so standalone policy documents and shipped 400 ErrorResponse bodies validate directly. Decision support only: a producer never executes, signs, routes funds, takes custody, or gives advice; verdicts are evidence statements, never instructions, and 'clear' is never a recommendation. Conservative defaults are normative: unknown/unverified token -> caution, missing data -> unsupported, never a guess. The response definition deliberately keeps preflight-additive fields optional so every shipped check_swap response body (openapi/routescore.v1.yaml CheckSwapResponse) validates as a valid subset instance; producer-side requiredness on the preflight_action surface is normative prose in preflight_action.v0.md section 11.1. Response and record objects are open (unknown fields tolerated) for additive v0.x versioning; the policy object is closed so a mistyped constraint can never be silently ignored. See preflight_action.v0.md for full semantics, the consolidation decisions (ROU-679 / ROU-707 / ROU-714), and the reserved-field convention.

# $defs.verdict.description
Advisory evidence verdict, identical to the shipped check_swap SwapVerdict. Closed enum, frozen for all of v0.x. 'clear' = no caution-level findings among the checks that ran (never a recommendation or endorsement); 'caution' = at least one finding or a defaulted unknown; 'unsupported' = cannot evaluate (out of coverage or missing data), returned with HTTP 422 as a full response body. Never an instruction to execute or refrain.

# $defs.actionType.description
Kind of proposed action. Coverage varies by implementation; an unimplemented action_type MUST yield verdict 'unsupported', never a guess.

# $defs.actorType.description
Declared (not verified) actor kind. Producers make no identity claims. Closed enum, frozen for v0.x.

# $defs.scoreState.description
Gap state of the evidence itself (shipped ScoreState / GAP_STATE_DOCTRINE vocabulary). Independent axis from the verdict: 'clear' with 'partial' is legal and means no findings on incomplete evidence.

# $defs.sourceFreshnessState.description
Freshness state of a data source (shipped SourceFreshnessState). Distinct enum from scoreState; deliberately not merged.

# $defs.confidenceBand.description
Confidence interval around the result when calibrated; nulls plus a label such as 'not_calibrated' otherwise. Shipped ConfidenceBand.

# $defs.commercialDisclosure.description
Producer's own no-pay-to-rank disclosure. Caller-supplied disclosure is always ignored. Shipped CommercialDisclosure.

# $defs.trustEnvelope.description
Full nested trust envelope, attached to every body (success and error) in addition to the flattened top-level copies. Shipped TrustEnvelope.

# $defs.trustEnvelope.properties.caveats.description
At least one caveat is always present (decision-support boundary — preflight_action.v0.md section 7.3).

# $defs.chainView.description
Chain support view. Field names are camelCase verbatim from the shipped CheckSwapChain contract (see preflight_action.v0.md section 12.6).

# $defs.routeView.description
Modeled route view, verbatim from the shipped CheckSwapRoute contract. All figures are modeled, point-in-time model outputs.

# $defs.routeView.properties.modeledRouteLeakBps.description
Modeled route leak / execution-risk component in bps; not a public-mempool MEV claim.

# $defs.routeView.properties.publicMempoolMevBps.description
Public-mempool MEV component in bps when observable; null for sequencer-ordered, private-intent, or batch routes (unknown is stated, never assumed).

# $defs.tokenSafetyView.description
Registry-recognition view, verbatim from the shipped TokenSafetyView contract. Recognition asserts presence in a registry only — never sellability, rights, redemption, custody, liquidity, or investment-quality verification. There is no positive-assurance flag.

# $defs.policyDecision.description
Shipped PolicyDecision, unchanged. This is the caller's own declared policy speaking about the caller's own rules — advisory, never the producer's verdict and never an instruction to execute. A 'warn' or 'block' policy decision means the response verdict MUST NOT be 'clear'.

# $defs.policyViolation.description
One policy rule violation, most severe first in the array. Aligned with the shipped PolicyReason shape.

# $defs.policyViolation.properties.code.description
Stable machine code, e.g. 'assets.not_allowed' or 'notional.exceeds_max'. Open vocabulary within v0.x.

# $defs.policyViolation.properties.rule.description
Rule family. Known values: the shipped set (venues, bridges, chains, route_size, budget, freshness, confidence, quality, score_state, manual_review, safe_default) plus preflight additions (assets, notional, slippage, token_recognition, approval_threshold) and reserved families (basis, reference_staleness, market_regime). Open vocabulary within v0.x.

# $defs.policyResult.description
Result of evaluating the caller-declared policy. Aligned with the shipped PolicyEvaluation; 'applied_safe_default' is the verbatim shipped field name. not_evaluated_fields MUST list every reserved or data-starved rule that could not run — an unevaluated rule is surfaced, never treated as satisfied.

# $defs.policyResult.properties.not_evaluated_fields.description
Policy field names that were accepted but not evaluated (reserved fields, or rules missing required data).

# $defs.structuredCaveat.description
Severity-bearing caveat (Agent-First rule 3). Every 'warning' entry MUST also appear as a flat string in the trust-envelope caveats[] so envelope-only consumers still see it.

# $defs.preflightPolicy.description
routescore.preflight_policy.v0 — flat caller-declared constraint grammar. CLOSED object: unknown fields MUST be rejected with HTTP 400 'invalid_policy' so a mistyped constraint can never be silently ignored. Fields marked 'status: reserved' are accepted but NOT evaluated in v0 (the basis monitor is not shipped — ROU-710/715/720); producers MUST surface them via policy_result.not_evaluated_fields plus a caveat, and MUST NOT treat them as satisfied. Maps onto the shipped routescore.agent_policy.v1 grammar per preflight_action.v0.md section 12.4.

# $defs.preflightPolicy.properties.allowed_chains.description
Chain-id allowlist. Non-empty means closed-by-default: any chain not listed is a violation.

# $defs.preflightPolicy.properties.allowed_assets.description
Asset allowlist (addresses preferred over symbols). Non-empty means closed-by-default.

# $defs.preflightPolicy.properties.max_slippage_bps.description
Violation when modeled slippage exceeds this. If slippage was not modeled the rule is not evaluated — surfaced, never assumed satisfied.

# $defs.preflightPolicy.properties.token_recognition_required.description
When true, token_safety.state other than 'recognized' is a violation. Registry recognition only.

# $defs.preflightPolicy.properties.source_freshness_floor.description
Maximum tolerated source age in seconds (mirrors shipped freshnessFloor.maxAgeSeconds). Violation when any consulted source is older or freshness is unknown/unavailable.

# $defs.preflightPolicy.properties.approval_threshold_usd.description
At or above this notional the response MUST set required_human_approval: true. Advisory: the caller's own software enforces the approval.

# $defs.preflightPolicy.properties.max_basis_bps.description
status: reserved — accepted but NOT evaluated in v0. Tokenized-asset vs reference-price basis ceiling; activates in a v0.x additive revision once the basis monitor ships (ROU-710/715/720).

# $defs.preflightPolicy.properties.max_reference_staleness_seconds.description
status: reserved — accepted but NOT evaluated in v0. Reference-price staleness ceiling in seconds (renamed from ROU-714's max_reference_staleness for unit explicitness).

# $defs.preflightPolicy.properties.block_when_market_closed.description
status: reserved — accepted but NOT evaluated in v0. Off-hours regime rule for tokenized assets tracking market-hours reference prices. The resulting policy decision remains advisory; the producer never blocks anything itself.

# $defs.preflightPolicy.properties.require_can_sell_observed.description
status: reserved — accepted but NOT evaluated in v0 (ROU-721). When it activates: a response-side can_sell state other than 'observed_at_T' is a violation. can_sell is point-in-time only, never forward-looking, and always carries its defeat-ability caveat in-band — the self-removing token class observed on Robinhood Chain (Relay Protocol disclosure, 2026-07-09) can pass a quote-time sell probe and still remove balances afterwards.

# $defs.preflightPolicy.properties.require_privilege_surface_scan.description
status: reserved — accepted but NOT evaluated in v0 (ROU-721). When it activates: a response-side token_privilege_surface state of 'not_evaluated' is a violation. Static privilege-surface observation (mint authority, blacklist/whitelist, trading pause, transfer taxes, upgradeable proxy, owner privileges) reports observed/not_evaluated states only — never an all-clear.

# $defs.preflightPolicy.properties.block_when_fill_path_curation_unknown.description
status: reserved — accepted but NOT evaluated in v0 (ROU-721). When it activates: an unknown fill-path curation state (a venue-operated, mutable block/verify list inside the route's fill path) is a violation. The resulting policy decision remains advisory; the producer never blocks anything itself.

# $defs.preflightActionRequest.description
preflight_action request. Strict superset of the shipped CheckSwapRequest: every shipped check_swap request is a valid instance with action_type defaulting to 'swap'. Producers MAY ignore unknown top-level fields, except inside 'policy' (closed) and except the named forbidden spellings of preflight_action.v0.md sections 5 and 12.6: bare 'notional' is forbidden outright (unit-less; 'false' property schema below), and an alias/canonical value mismatch (token_in vs asset_in, token_out vs asset_out) MUST be rejected with HTTP 400 — that mismatch rule is enforced by producer behavior and conformance tests only, because JSON Schema cannot compare the values of two fields.

# $defs.preflightActionRequest.properties.chain_id.description
Chain ID. 4663 = Robinhood Chain (modeled support level).

# $defs.preflightActionRequest.properties.asset_in.description
Input asset address or symbol. Canonical name for the shipped alias token_in.

# $defs.preflightActionRequest.properties.asset_out.description
Output asset address or symbol. Canonical name for the shipped alias token_out. The output side is the one checked for registry recognition (shipped behavior).

# $defs.preflightActionRequest.properties.token_in.description
Deprecated alias of asset_in, retained verbatim from the shipped check_swap contract. If both alias and canonical field are present with different values the producer MUST return HTTP 400 invalid_input.

# $defs.preflightActionRequest.properties.token_out.description
Deprecated alias of asset_out, retained verbatim from the shipped check_swap contract. Same mismatch rule as token_in.

# $defs.preflightActionRequest.properties.notional_usd.description
Action size in USD. Required and must be positive (shipped bounds). The unit-less 'notional' spelling from the pivot memo is rejected as underspecified — forbidden via the 'false' property schema on 'notional'.

# $defs.preflightActionRequest.properties.route.description
Route id, e.g. uniswap-v3-005 or uniswap-v3-rho. A route on the wrong chain MUST NOT be silently scored (shipped route_chain_mismatch behavior).

# $defs.preflightActionRequest.properties.slippage_allowance_bps.description
Per-request intent; distinct from the policy constraint max_slippage_bps.

# $defs.preflightActionRequest.properties.policy_id.description
Reference to a stored or built-in policy. Mutually exclusive with 'policy'. Unknown id -> HTTP 400 unknown_policy.

# $defs.preflightActionRequest.properties.evidence_context.description
Caller-supplied context for the record. MUST NOT contain wallet addresses, ENS names, emails, or any identity; producers redact identity before evaluation and logging (shipped guardrail precedent).

# $defs.preflightActionResponse.description
preflight_action response. The required set equals the shipped CheckSwapResponse (core result + flattened trust envelope + nested trust), so every shipped check_swap response body validates as a subset instance. The additive preflight fields (schema, action_type, actor_type, policy_result, policy_violations, structured_caveats, relay_to_user, required_human_approval, evidence_bundle_id) are optional HERE but REQUIRED from producers implementing the preflight_action surface — see preflight_action.v0.md sections 7 and 12.5. Open object: consumers MUST tolerate unknown fields (additive v0.x versioning).

# $defs.preflightActionResponse.properties.methodology_version.description
Evaluation-methodology identifier, present in every response. Orthogonal to the spec version.

# $defs.preflightActionResponse.properties.caveats.description
Flat verbatim caveat sentences (trust envelope, shipped). At least one caveat is always present (decision-support boundary); minItems enforces the floor.

# $defs.preflightActionResponse.properties.policy_violations.description
Violations of the caller-declared policy, most severe first. Empty when a policy ran clean; MAY be omitted only when no policy was supplied.

# $defs.preflightActionResponse.properties.relay_to_user.description
One pre-written sentence the agent consumer MUST quote verbatim in its final user-facing answer. Authored by the producer from verdict + highest-severity caveat + score_state; itself subject to the claims-boundary vocabulary scan.

# $defs.preflightActionResponse.properties.required_human_approval.description
True when the policy's approval_threshold_usd was met/exceeded or the approval rule could not be evaluated (conservative default); false only when a policy ran and no approval rule tripped; null/absent when no policy was supplied. Advisory — the caller's own software enforces approval.

# $defs.preflightActionResponse.properties.evidence_bundle_id.description
Id of the persisted evidence record/bundle. Null on keyless/anonymous calls — persistence is the key-gated capability, never the verdict.

# $defs.preflightActionResponse.$comment
Two schema-encoded boundaries. (1) No-calldata boundary (preflight_action.v0.md section 13, Out of scope): the property names calldata, tx, transaction, signature, and signed_payload are forbidden via 'false' property schemas — a response never carries execution or signing material; the object stays otherwise open for additive v0.x fields. (2) Verdict/policy coupling (sections 7.1 / 12.1), encoded in the if/then below: when the caller-declared policy evaluates to 'warn' or 'block', the verdict MUST NOT be 'clear'.

# $defs.errorResponse.description
Gateway error envelope (shipped ErrorResponse): used for HTTP 400/401/403/429/500. NOT used for verdict 'unsupported', which returns HTTP 422 with a full preflightActionResponse body. Carries the trust envelope like every other body.

# $defs.referencePriceEvidence.description
Basis-regime gap-state evidence for tokenized assets (ROU-715; additive, optional in this schema for subset compatibility — the reference implementation emits it on every evaluated response). Tokenized assets can trade on-chain around the clock while their reference instruments trade in defined market sessions, so token/reference basis and reference-price staleness are recurring observable quantities for that asset class. Until the basis monitor ships (ROU-710/720) this field reports honest gap states only: state 'unavailable' when a tokenized-asset reference relationship is recognized but unobserved, 'unsupported' when none is recognized (registry recognition only). Freshness, staleness, and basis values are never guessed. Policy-usable via the reserved hooks max_basis_bps / max_reference_staleness_seconds / block_when_market_closed.

# $defs.referencePriceEvidence.properties.freshness.description
Reference-price freshness reading. Always 'unknown' (recognized tokenized asset, no source wired) or 'unsupported' (not applicable) until observations ship.

# $defs.referencePriceEvidence.properties.as_of.description
Observation timestamp (ISO-8601). Null until an observation source ships.

# $defs.referencePriceEvidence.properties.staleness_seconds.description
Observed reference-price age in seconds. Null until observations ship.

# $defs.marketRegimeEvidence.description
Reference-market open/closed regime evidence (ROU-715; additive, optional in this schema for subset compatibility — the reference implementation emits it on every evaluated response). The regime is reported as 'unknown' until a market-hours observation source ships (ROU-710/720); it is never derived from a guess. state semantics match referencePriceEvidence.state.

# $defs.marketRegimeEvidence.properties.regime.description
Reference-market regime flag. Always 'unknown' today.

# $defs.marketRegimeEvidence.properties.as_of.description
Observation timestamp (ISO-8601). Null until an observation source ships.

# $defs.preflightRecord.description
routescore.preflight_record.v0 (consolidates ROU-707's working title preflight_record.v1; renumbered so the record version tracks the spec version). The persisted form of a preflight response: response-superset by construction — the full response object nests VERBATIM under 'response', no field is forked, renamed, or duplicated. Read-only evidence: no calldata, no transaction payloads, no signing material, ever. This schema enforces the canonical execution-material property names only at the response TOP level ('false' property schemas); producers MUST additionally reject execution-material keys at ANY depth with normalized key matching (lowercase, '_'/'-' stripped) per preflight_action.v0.md section 9 — producer/conformance-test-enforced, not schema-enforced. Hash recipe identical to routescore.evidence_bundle.v0 / routescore.attested_artifact.v2: remove record_id, recorded_at, and integrity, sort object keys recursively (arrays keep order), serialize with ECMAScript JSON.stringify (canonical JSON is PINNED to ECMAScript serialization semantics — number rendering, string escaping, no whitespace, no Unicode normalization; non-JavaScript verifiers must reproduce them or use the reference verifier canonicalize()/contentHash() in the reference implementation's src/lib/attestation.ts), SHA-256 the UTF-8 bytes; must equal integrity.output_hash. record_id and recorded_at are both excluded so the hash identifies the evidence content, not the storage row.

# $defs.preflightRecord.properties.request.description
Optional identity-redacted echo of the evaluated request.

# $defs.preflightRecord.properties.actor.description
Identity-free actor context: declared actor type plus an optional caller label. MUST NOT contain wallet addresses, ENS names, emails, or biometric/identity data.