{"criteria_id":"failure-translation/v1","criteria_revision":"1.0.0","family":"payer-preflight/v1","family_note":"Family payer-preflight/v1 (FIX-CANDIDATES §C): this build opens the family; §C2 names its criteria failure-translation/v1 — the criteria id is pinned as named, and the family/criteria relationship is recorded as an interpretation in REGISTRY.md.","op":"translate","ops_not_offered":[],"corpus":{"id":"failure-translation-corpus/v1","sha256":"95d16014bc6cd234294e2ab2cc28ad5138c2e591c4c28646ee59c1ed4482d7cc"},"corpus_pin_definition":"The corpus pin is the SHA-256 of the corpus's canonical serialization (the corpus object excluding its sha256 field), computed and verifiable by the published harness (harness.mjs). Expected outputs inside corpus cases are derived from the criteria text by an independent implementation in gen-corpus.mjs (never the engine's code path), and each case labels its provenance (constructed from on-disk fleet records vs synthetic).","price":{"usdc_units_per_call":10000,"label":"$0.01","basis":"per outcome"},"free_tier":{"per_day":100,"min_interval_ms":5000,"on_exhaustion":"402"},"input_contract":{"body":"One JSON request body: { outcome, caller? (free pre-check only) }. outcome is the failed call's artefact set under the published artefact contract.","caps":{"body_bytes":262144},"over_cap":"A request body over 262,144 bytes is a free pre-gate refusal naming the cap.","validation":"The artefact set is validated FREE, before any payment: shape, per-field shape rules under the published malformed rule, and the no-artefacts refusal. A malformed submission fails free and never consumes a payment. The translation itself is computed only after payment verification (or a verified-marker resume)."},"artefact_contract":"Artefact contract: the request body is one JSON object { outcome, caller? (free pre-check only) }. outcome is one JSON object carrying any of: http_status (integer 100-599 — the status the failed call answered with); settle_attempted (boolean — whether a /settle attempt was made for the original payment); facilitator_error (an object or null — the facilitator's error body as returned: isValid, invalidReason / errorReason (the reason CODE), invalidMessage / errorMessage (the free-form message); its reason fields, when present, must be strings); reissued_402 (an object or null — the re-issued 402 challenge as returned: x402Version, accepts[] with scheme / network / amount or maxAmountRequired / payTo / asset / extra); original_payload (an object or null — the payment payload as sent: x402Version, scheme, network, accepted (with extra where the client carried it), payload.authorization { from, to, value, validAfter, validBefore, nonce }); headers (an object or null — the response headers as received, name/value strings). At least one artefact field must be present and non-null, or the submission refuses free (no_outcome_artefacts). A field of the wrong shape refuses free, naming the field. Only the published signals are read: the facilitator reason code/message, the two x402Version fields, the authorization value vs the challenge amount, the accepted-terms extra name/version, the HTTP status, and settle_attempted. The nonce is read only for presence — its value is never printed, stored, or returned anywhere.","malformed_rule":"Malformed artefact sets (named FREE refusals, before any payment): outcome missing or not an object (outcome_required); no artefact field present and non-null (no_outcome_artefacts); http_status present but not an integer 100-599 (http_status_malformed); settle_attempted present but not a boolean (settle_attempted_malformed); facilitator_error present but neither an object nor null, or a reason field present but not a string (facilitator_error_malformed); reissued_402 present but neither an object nor null, its x402Version present but not a number, or its accepts present but not an array (reissued_402_malformed); original_payload present but neither an object nor null (original_payload_malformed), its authorization present but not an object, its authorization value present but not a string (authorization_malformed), or its authorization nonce present but not a string (nonce_malformed); headers present but neither an object nor null (headers_malformed). A malformed submission fails free and never consumes a payment.","classification_rule":"Classification: the published mapping table (ENGINE_CONFIG.mapping_table) is evaluated in its published precedence order R1, R2, R3, R4, R5, R6, R7, R8a, R8b, R9a, R9b; the first matching row wins and names both the reason class and the verdict. HARD RULE: the authorization-already-used class (R1) carries RECONCILE-FIRST as its only verdict in the table — no input can make this engine recommend paying again for that class. The seller-5xx and opaque classes split on settle_attempted exactly as rows R8a/R8b and R9a/R9b publish. A signature-failure code WITHOUT domain evidence is not a domain mismatch: it falls to R7 and the raw reason is surfaced (the evidence-bound reading). settlement_pending (R2) is a facilitator rejection whose verdict is RECONCILE-FIRST because the state is non-terminal.","raw_reason_rule":"Raw-reason rule: where the facilitator returned a reason, the report's raw_reason field prints it verbatim — the returned message (invalidMessage / errorMessage) when one was returned, otherwise the returned reason code (invalidReason / errorReason). Where no reason was returned in the submitted artefacts, raw_reason is null, raw_reason_returned is false, and the report states plainly that no facilitator reason was returned and none exists in the report — a reason is never invented, paraphrased into existence, or inferred from the class.","no_reason_line":"No facilitator reason was returned in the submitted artefacts; none exists in this report — no reason has been invented.","mapping_table":[{"row":"R1","signal":"The facilitator reason code or message contains AuthorizationUsed (case-insensitive; also the authorization_used / 'authorization already used' spellings).","reason_class":"authorization-already-used","verdict":"RECONCILE-FIRST","provenance":"FRICTION-MAP friction 20 + lane-1 F-21 (issue record #452/#831 as held on disk): re-submitting the same authorization surfaces AuthorizationUsed, indistinguishable from genuine failure; FIX-CANDIDATES §C2 hard rule."},{"row":"R2","signal":"The facilitator reason code is settlement_pending.","reason_class":"facilitator-rejection-with-reason","verdict":"RECONCILE-FIRST","provenance":"lane-3 G-04: settlement_pending is non-terminal and MUST carry the broadcast transaction hash so the caller can reconcile on chain before deciding whether to retry; lane-2 records PayAI's own docs to the same effect."},{"row":"R3","signal":"The facilitator reason code names an authorization validity bound (contains valid_before or valid_after), or the returned reason text states the authorization expired.","reason_class":"authorization-expired","verdict":"RETRY","provenance":"lane-1 validity-window entry (error names …_authorization_valid_before / …_valid_after); lane-3 §9 core code list (the four invalid_exact_evm_payload_authorization_* codes)."},{"row":"R4","signal":"The facilitator reason code is invalid_x402_version, OR both x402Version fields are present (original payload and re-issued 402) and differ.","reason_class":"version-mismatch","verdict":"DO-NOT-RETRY","provenance":"lane-3 §9 core code invalid_x402_version; FRICTION-MAP friction 09 (v1↔v2 silent incompatibility — a wrong-version payment is never seen and returns a bare fresh 402)."},{"row":"R5","signal":"The facilitator reason code names a value mismatch (contains value_mismatch), OR both amounts are present (the original payload's authorization value and the re-issued 402's amount) and differ.","reason_class":"amount-mismatch","verdict":"DO-NOT-RETRY","provenance":"lane-3 G-09: invalid_exact_evm_payload_authorization_value_mismatch — under EVM exact the value must match exactly; FRICTION-MAP frictions 05/07."},{"row":"R6","signal":"The facilitator reason code names a payload signature failure (contains payload_signature) AND domain evidence is present: the returned reason text mentions the domain / EIP-712 / chain id / token name or version, OR the EIP-712 extra name/version in the payload's accepted terms differs from the re-issued 402's.","reason_class":"domain-mismatch","verdict":"DO-NOT-RETRY","provenance":"lane-1 F-11 (the EIP-712 domain trap: server omits extra.name/extra.version, JS and Python verifiers hash two different domains, signature always invalid); the Fizzl checklist table recorded in lane-1 (invalid_exact_evm_payload_signature = wrong token name/version in extra, or another chain id)."},{"row":"R7","signal":"A facilitator reason was returned (a reason code or message) and no row above matched.","reason_class":"facilitator-rejection-with-reason","verdict":"DO-NOT-RETRY","provenance":"FRICTION-MAP frictions 30/31: screening declines and other facilitator rejections arrive as generic verification rejections (CDP OFAC/KYT screening docs, via lane-1 F-25); the raw reason is surfaced verbatim where returned. Our own probe record adds local codes (e.g. PayAI's invalid_exact_svm_payload_transaction_instructions_compute_limit_instruction, lane-1, ~100 structural /verify probes 2026-10-12)."},{"row":"R8a","signal":"The HTTP status is 5xx, no facilitator reason was returned, and a settle attempt was made (settle_attempted true).","reason_class":"seller-5xx","verdict":"RECONCILE-FIRST","provenance":"FRICTION-MAP frictions 16/31: errors after payment are measured (our PayAI sweep 2026-10-12: 9 of 74 errored after the payment path engaged, 8 settle-confirmed) — a 5xx after a settle attempt does not prove nothing settled."},{"row":"R8b","signal":"The HTTP status is 5xx, no facilitator reason was returned, and no settle attempt was made.","reason_class":"seller-5xx","verdict":"RETRY","provenance":"FRICTION-MAP friction 31: seller 5xx with no payment consumed is a transient server failure; nothing was settled, so a retry risks no double-pay."},{"row":"R9a","signal":"No row above matched and a settle attempt was made (settle_attempted true).","reason_class":"opaque","verdict":"RECONCILE-FIRST","provenance":"FRICTION-MAP frictions 19/20: with a settle attempt behind it and no readable signal, the outcome is ambiguous — reconcile on-chain before any new payment."},{"row":"R9b","signal":"No row above matched and no settle attempt was made.","reason_class":"opaque","verdict":"DO-NOT-RETRY","provenance":"FRICTION-MAP friction 31 (failure signalling collapse: nearly all failures collapse to the same bare 402) + friction 20 (a blind fresh retry signs a fresh settleable authorization — the double-pay risk)."}],"reason_classes":["version-mismatch","domain-mismatch","amount-mismatch","authorization-already-used","authorization-expired","facilitator-rejection-with-reason","seller-5xx","opaque"],"retry_verdicts":["RETRY","DO-NOT-RETRY","RECONCILE-FIRST"],"verdict_guidance":{"RETRY":"Retry only with a fresh authorization and a fresh nonce; never re-submit a consumed authorization.","DO-NOT-RETRY":"Do not retry this payment as-is: retrying the same payload repeats the same failure, and paying again blindly risks a double-pay. Fix the named cause first.","RECONCILE-FIRST":"Reconcile first: check whether the original payment settled on-chain (fleet B1 Settlement Verification, /toll/settlement) before paying anything again. Never treat this outcome as 'failed, pay again'."},"verdict_grammar":{"line":"FAILURE TRANSLATION — class: <reason class> · verdict: <RETRY / DO-NOT-RETRY / RECONCILE-FIRST> — <check-end UTC>","vocabulary":"The line carries the reason class and the retry verdict. There is no composite score, grade, or band anywhere in this op."},"free_precheck":"The free pre-check (POST /precheck) validates the submitted artefact set under the published contract and returns assessability ONLY: the common signed fields, whether the set is assessable (or the free refusal naming the failure), and the artefact facts (which artefact fields are present, whether a facilitator reason was returned, whether a settle was attempted). It returns no reason class and no verdict. Free allowance: 100 per day per caller wallet, minimum interval 5,000 ms, 402 on exhaustion.","custody":{"construction":"In-memory processing within a single request lifetime; the submitted artefacts persist nowhere, on any path including errors. No hash of a submitted artefact appears anywhere.","ledger_closed_fields":["payer wallet","timestamp/day","price (USDC units) with the CAD fair-market-value block (rate, rate date, basis, cad_pending, refund)","payment tx id + Solana fee (lamports)","criteria version","verdict line","reason class","retry verdict","raw reason returned (boolean only — never the reason text)","house flag"],"ledger_note":"The ledger list above is closed: adding a field is a criteria/handling version change. The ledger NEVER carries any artefact, fragment, nonce value, payload value, header value, or facilitator reason text.","errors":"Error handling is closed-form: static strings plus numeric facts only (lengths against caps, rule ids). No error path interpolates any part of a submitted artefact set."},"forbidden":"Forbidden in every surface of this op (report, pre-check, errors, ledger, metrics): any composite score or grade; any submitted nonce, payload, or header value; any invented facilitator reason (where none was returned, the report states none exists); any RETRY or DO-NOT-RETRY verdict for the authorization-already-used class; any fetched or chain-read data (this op fetches nothing and reads no chain).","boundary_statement":"Boundary vs B1 Settlement Verification (/toll/settlement, settlement-evidence/v1, op verify): B1 reads the chain per payment — one signature, the fields as found. This op never reads the chain and never sees a payment: it classifies the submitted outcome artefacts of a failed call, and its RECONCILE-FIRST verdict is the instruction to run B1 before paying again — it is not itself a settlement check. Boundary vs C1 Payment Payload Pre-flight (same family, payer-preflight/v1): C1 lints a payload BEFORE signing; this op translates an outcome AFTER a failed call. Boundary vs A3 Rail-Coverage & Reject-Shape Probes (payability/v1): A3 grades how a live endpoint rejects garbage payloads; this op classifies one real failed call the caller already made, from its submitted artefacts, and probes nothing.","disclosure_sentence":"Submitting a failed call's outcome artefacts to any third party, this service included, discloses those artefacts to it; they are processed in memory only and never stored, but the translation does not undo the disclosure.","honesty_line":"The translation classifies the artefacts exactly as submitted, under the published mapping table; it reads no chain, fetches nothing, and knows nothing about the failed call beyond the submitted artefacts — an outcome whose artefacts carry no readable signal is classified opaque, never guessed into a specific cause.","retention":"Submitted artefacts are processed in memory only and are never stored — not in KV, not in logs, not in the payments ledger, not in metrics, and not in error records. No artefact, fragment, nonce value, payload value, header value, or hash of an artefact is recorded anywhere; the only artefact-derived values that persist are the ledger's closed fields (the reason class and the verdict). The paid report carries the class, the verdict, the factors, and the facilitator's raw reason where one was returned, because that report is the delivery the buyer paid for. The payments ledger records only the closed field list published in the criteria. Because nothing is kept, a paid retry re-submits the artefacts.","payment_includes":"$0.01 per failed-call outcome. The payment includes: one failure translation of the outcome artefacts you submit (the re-issued 402, the facilitator error body, the HTTP status/headers, the original payload's nonce) — a reason class from the published mapping table of failure-translation/v1 and a RETRY / DO-NOT-RETRY / RECONCILE-FIRST verdict — computed mechanically from the artefacts exactly as submitted, returned as one signed report with all factors printed. An authorization-already-used outcome always routes to RECONCILE-FIRST, never to 'pay again'. The facilitator's raw reason is printed verbatim where one was returned; where none was returned, the report says none exists. A free pre-check validates the artefact set's shape before any payment and returns no class and no verdict. The submitted artefacts are processed in memory only and are never stored; the payments ledger records only the payer, the time, the price, the reason class, the verdict, and the verdict line.","kill_line":"Kill line (M-26 / C2, under the operator's 2026-11-03 build-bank-hold doctrine): build, bank, and hold; judged at the fleet's periodic reviews. There is NO demand kill line for this item. Day-0 = first outside paid settle (accounting only; house proofs never count). Tripwires, all stop-and-review: (1) refunds >5% in any 30-day window; (2) free use >10x paid use; (3) a mistranslation — a wrong class or verdict from undisclosed stale or partial data (the error enters the corpus first as a regression case, corrected rules publish as a new criteria version, the corpus re-passes at 100% before serving resumes; issued reports are never amended); (4) custody: any surface emitting a submitted nonce, payload, or header value; (5) any verdict of RETRY or DO-NOT-RETRY ever issued for the authorization-already-used class.","never":"This op never fetches any URL; never reads the chain; never stores a submitted artefact; never computes a composite score; never invents a facilitator reason; never recommends paying again for an authorization-already-used outcome.","service":"failure-translator","version":"1.0.0","endpoints":{"criteria":"GET /criteria (free)","precheck":"POST /precheck (free, artefact validation + assessability only: no class, no verdict)","translate":"POST /translate (paid, $0.01 per outcome: signed failure translation + retry verdict)","metrics":"GET /metrics","not_offered":"Any other POST path answers NOT COVERED — this worker serves op translate only."}}