YONA Conformance Test Suite
Companion to: yona:ruleset:v1.0
Scope of this document: normative conformance-verification material for implementations claiming YONA conformance to yona:ruleset:v1.0
Conformance status: Requirements in this document are normative only when stated using capitalized keywords (MUST, MUST NOT, REQUIRED, SHOULD, MAY) as defined by BCP 14 (RFC 2119 / RFC 8174). All other text is non-normative.
License
Copyright © 2026 YONA LLC.
Text and explanatory content in this document are licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).
Machine-readable artifacts published with this document, including JSON, .jws samples, test vectors, fixtures, and expected.json assertions, are licensed under the Apache License 2.0 (Apache-2.0), unless a specific bundle states otherwise.
Names and marks: CC BY 4.0 and Apache-2.0 do not grant trademark rights. Nothing in this document grants rights to use any names, logos, or other marks beyond what is permitted under applicable law.
Disclaimer: This document and all included artifacts are provided “AS IS”, without warranties or conditions of any kind, and without liability for damages arising from their use.
Patent policy: See Patent Policy published on YONA's website for its royalty-free implementation commitment for any Essential Claims it owns or controls.
License texts: CC BY 4.0 & Apache-2.0
1. Scope and Interpretation
1.1 Purpose
This document defines the YONA Conformance Test Suite for implementations claiming YONA conformance under yona:ruleset:v1.0.
This document provides:
- a normative conformance matrix
- parameterized invalid-case families
- byte-exact hashing fixtures for
request_jws_sha256 - deterministic
REJECTversusNO_RESPONSEdecision tables - transport, discovery, parsing, signature, replay, and binding test requirements
This document adds no new protocol requirements beyond the ruleset and the companion BIP. It exists only to verify conformance to those documents.
1.2 Relationship to companion documents
| Document | Purpose |
|---|---|
| YONA Ruleset 1.0 | Defines authoritative YONA message semantics, message validity, terminal authorization outcomes, timeout and NO_RESPONSE handling, request/response binding, replay and repeated-request behavior, and out-of-scope boundaries. |
| Base Interoperability Profile (BIP) | Defines the interoperable discovery, transport, and endpoint behavior baseline required for YONA conformance under yona:ruleset:v1.0. |
| YONA Conformance Test Suite | Defines the normative test cases used to verify conformance to YONA Ruleset 1.0 and the BIP. It adds no new protocol requirements beyond those documents. |
| Reference Messages and DID Examples | Provides illustrative, non-normative examples of YONA-conformant messages, DID service entries, capability documents, and related structures. |
| YONA Conformance Report Template | Optional, non-normative report template for the YONA Conformance Test Suite. |
If this test suite appears to conflict with the ruleset or the companion BIP, the ruleset controls first, then the companion BIP, and this test suite MUST be interpreted accordingly.
1.3 What this suite verifies
This suite verifies the technical conditions needed for YONA conformance under yona:ruleset:v1.0, including:
did:webresolution for VASP DID documents- required DID service discovery
- advertised optional
YonaTravelRuleServiceentries and any BIP-required capability document they point to - advertised optional
YonaAssuranceServiceentries and any BIP-defined requirements tied to them - HTTPS
POST Content-Type: application/joseandAccept: application/jose- JWS Compact request and response bodies
- deterministic validation-gating behavior
- byte-exact request/response binding via
request_jws_sha256 - endpoint-specific success, failure, and no-response handling
1.4 Using this suite after pilot completion
The standalone YONA Pilot duplicates the push-payment authorization subset of this suite so that pilot participants can implement, test, and report that lower-lift path from one document.
An implementation that has already completed the standalone YONA Pilot for the same implementation version and material configuration SHOULD skip the duplicated push-payment authorization material in this suite and continue with the retrieval, pull-payment, and other newly applicable full-BIP cases.
Passing the standalone YONA Pilot does not establish full YONA conformance.
2. Conformance Claim Semantics
2.1 What a YONA conformance claim requires
A YONA conformance claim for yona:ruleset:v1.0 MUST NOT be made unless the implementation:
- satisfies all applicable normative requirements in YONA Ruleset 1.0;
- satisfies all applicable normative requirements in the companion Base Interoperability Profile (BIP); and
- passes all applicable normative test cases in this YONA Conformance Test Suite.
If the implementation advertises an optional BIP-defined DID service entry, any normative test cases in this YONA Conformance Test Suite that correspond to that service entry are applicable and MUST be passed for a YONA conformance claim.
If the BIP requires that advertised service entry to point to a capability document or other required document, the corresponding normative test cases for that document are also applicable and MUST be passed.
A conformant implementation MUST produce deterministic outcomes for repeated executions of the same test vectors under the same configuration.
If a conformance report is produced, it SHOULD state:
- the tested
ruleset_id; - any optional BIP-defined DID service entries advertised during testing; and
- any configuration inputs that materially affect validation, timeout handling, replay handling, caching, or repeated-request behavior.
2.2 Issuance and publication of conformance claims
This test suite defines only the technical conditions for making a YONA conformance claim under yona:ruleset:v1.0.
This suite does not define or require:
- a specific issuer;
- a publication venue;
- a display method;
- a registry;
- a trust framework; or
- a credential format.
Passing this suite does not require review, approval, issuance, publication, registration, contract, or purchase of services from YONA LLC, from any future YONA successor body, or from any other specific party.
A self-asserted statement or third-party attestation MAY be accompanied by or expressed through a report, certificate, registry entry, or verifiable credential, but those mechanisms are outside the scope of this test suite.
The presence, absence, or format of a conformance claim, attestation, report, certificate, registry entry, or credential does not alter the underlying technical pass/fail result for the implementation under test.
3. Test Harness Conventions
3.1 Roles under test
| Role under test | Covered behavior |
|---|---|
| Beneficiary VASP server | YonaPaymentIntentService; YonaAuthorizationService |
| Originator VASP client | retrieval client behavior (yona.retrieve_intent / yona.payment_intent); authorization client behavior (yona.authorization_request / yona.authorization_response) |
For a YONA conformance claim under yona:ruleset:v1.0, the test harness MUST cover both roles listed in this subsection.
3.2 Clock control and timeout testing
The harness MUST be able to control or simulate time sufficiently to test:
Time-dependent behavior
- valid
exp - expired
exp - the 60-second authorization no-response cutoff
- late terminal authorization response handling
The test harness MUST simulate the case where the client sends an authorization request and gets no usable response at all until the timeout is reached.
3.3 Replay and repeated-request window
Because replay-protection windows and repeated-request retention periods are implementation-defined, this suite verifies the following within the active test session:
- immediate signed-message replay handling
- repeated-request handling for
yona.authorization_requestwithin the same (iss,intent_id) scope
This suite does not assert behavior after the implementation's retention window expires.
3.4 Fixture bytes are authoritative
For tests involving request_jws_sha256, the fixture's exact JWS Compact Serialization is authoritative.
The following are not equivalent for hashing or comparison:
- reconstructed JSON
- reserialized JSON
- trimmed strings
- normalized strings
- re-encoded JOSE parts
3.5 Endpoint-specific interpretation
The harness MUST preserve the distinction between:
| Endpoint category | Interpretation |
|---|---|
YonaPaymentIntentService | retrieval failure |
YonaAuthorizationService | authorization outcomes and no-response behavior |
A retrieval failure MUST NOT be treated as ACCEPT, REJECT, or authorization NO_RESPONSE.
4. BIP Transport and Message-Handling Requirements Under Test
4.1 HTTP request requirements (client-side)
For BIP requests, the originator client MUST:
Client requirement
- send HTTPS
POSTto theserviceEndpointresolved viadid:web - send a signed YONA request message in JWS Compact Serialization form
- send
Content-Type: application/jose - send
Accept: application/jose
For request bodies:
Request body requirement
- the HTTP request body MUST consist solely of the JWS Compact Serialization of the YONA request
- the decoded JWS payload MUST contain all required members for the declared
message_typeandruleset_id - any required objects or fields, such as
intent_locator,payment_terms, orintended_asset_type, MUST be carried inside the JWS payload JSON and MUST NOT be sent as standalone HTTP bodies
4.2 HTTP response requirements (server-side, authorization endpoint)
When a bound terminal authorization response can be formed, the beneficiary server MUST return:
Server-side authorization response requirement
HTTP 200Content-Type: application/jose- an HTTP response body that is the byte-exact JWS Compact Serialization of a
yona.authorization_response
If a bound terminal response cannot be formed, the server MUST NOT return a YONA response message.
Examples of outcomes that are not YONA response messages include:
Not a YONA response message
- non-200 status
- non-JOSE body
- malformed JOSE body
- connection close
- timeout
- no response
4.3 Authorization no-response mapping (client-side)
For authorization requests:
| Condition | Required client interpretation |
|---|---|
absence of a valid, verified terminal yona.authorization_response by the cutoff | NO_RESPONSE |
NO_RESPONSE | MUST be treated as REJECT |
terminal response received after the client has concluded NO_RESPONSE | MUST be ignored for outcome purposes |
In all cases, the implementation MUST NOT proceed to post-ACCEPT steps without a valid, verified terminal ACCEPT.
4.4 Retrieval failure behavior (client-side)
For payment-intent retrieval:
| Condition | Required client behavior |
|---|---|
no valid, verified yona.payment_intent obtained | MUST NOT proceed to authorization using locator-only data |
| retrieval transport errors or malformed responses | do not carry YONA authorization semantics |
5. YONA Conformance Test Matrix
5.1 Matrix structure
Each applicable test case in this matrix MUST be executed for a YONA conformance claim unless this suite expressly marks the case not applicable to the implementation, endpoint, role, interaction scope, or advertised optional DID service entry under test.
For optional BIP-defined DID service entries, corresponding test cases in this suite are applicable only when the implementation advertises that service entry.
The matrix contains:
- explicit named test cases
- parameterized case families that MUST be instantiated for each required field, binding rule, parsing rule, or protected-header rule
Each test case defines input, expected result, and pass/fail criteria. For each applicable case, the implementation under test MUST produce the expected result shown.
5.2 Core valid-path cases
Implementations that have already completed the standalone YONA Pilot for the same implementation version and material configuration SHOULD skip BIP-VAL-004 through BIP-VAL-007 and continue with the retrieval and pull-payment valid-path cases in this section.
| ID | Test Role | Endpoint / Flow | Case | Expected Result |
|---|---|---|---|---|
| BIP-VAL-001 | Beneficiary server | YonaPaymentIntentService | Valid yona.retrieve_intent (pull-payment) | Returns valid signed yona.payment_intent (HTTP 200 + application/jose) |
| BIP-VAL-002 | Originator client | Pull retrieval | Valid yona.payment_intent response | Verifies and treats it as the authoritative payment intent |
| BIP-VAL-003 | Beneficiary server | YonaAuthorizationService (pull) | Valid pull-payment yona.authorization_request | Returns signed terminal yona.authorization_response (ACCEPT or REJECT) |
| BIP-VAL-004 | Beneficiary server | YonaAuthorizationService (push) | Valid push-payment yona.authorization_request | Returns signed terminal yona.authorization_response (ACCEPT or REJECT) |
| BIP-VAL-005 | Originator client | Authorization response | Valid yona.authorization_response with correct request_jws_sha256 | Accepts the response and applies terminal semantics |
| BIP-VAL-006 | Beneficiary server | YonaAuthorizationService repeated-request handling | Repeat same (iss, intent_id) with materially equivalent inputs; the harness MUST vary only non-material fields such as jti, iat, exp, kid, or signature bytes | Returns the same terminal decision and re-binds to the repeated request bytes |
| BIP-VAL-007 | Beneficiary server | YonaAuthorizationService repeated-request handling | Repeat same (iss, intent_id) with one or more material authorization inputs changed | Deterministically returns terminal REJECT if bindable; otherwise MUST NOT return a YONA response message |
6. Parameterized Required-Field Invalid-Case Families
6.1 Family rule
For each required defined field listed in the message-specific subsections below, the harness MUST instantiate the following cases unless marked not applicable:
| Invalid-case family | Meaning |
|---|---|
MISSING | field omitted |
WRONG_TYPE | JSON type differs from the required type |
BAD_VALUE | field present with an invalid semantic value |
Expected result:
| Endpoint type | Expected result |
|---|---|
| any receiver | MUST fail validation gating and MUST NOT proceed to authorization evaluation |
| authorization endpoint | server MUST return a bound terminal REJECT if bindable; otherwise it MUST NOT return a YONA response message |
| retrieval endpoint | request MUST fail, meaning no successful yona.payment_intent is returned; this suite does not require a retrieval-REJECT message |
This family rule applies only to defined required fields.
A non-duplicate unknown additional field is not invalid by itself and MUST NOT change validation, binding, timeouts, or outcomes. The harness SHOULD include at least one non-failing tolerance case for this rule in request and response directions relevant to the tested role.
6.2 yona.retrieve_intent request (beneficiary server receives)
| Category | Fields |
|---|---|
| Common claims | iss, aud, iat, exp, jti, message_type, ruleset_id |
| Message-specific fields | intent_locator, intent_locator.type, intent_locator.beneficiary_vasp_did, intent_locator.beneficiary_intent_id |
Minimum BAD_VALUE examples (non-exhaustive) that MUST be covered:
message_type != yona.retrieve_intentruleset_id != yona:ruleset:v1.0aud != intent_locator.beneficiary_vasp_didintent_locator.typeinvalidintent_locator.beneficiary_intent_idviolates ASCII-restricted identifier rules- non-integer
iatorexp - expired
exp - replayed
jti
6.3 yona.payment_intent response (originator client receives)
| Category | Fields |
|---|---|
| Common claims | iss, aud, iat, exp, jti, message_type, ruleset_id |
| Message-specific fields | intent_locator, intent_locator.type, intent_locator.beneficiary_vasp_did, intent_locator.beneficiary_intent_id, payment_terms, payment_terms.amount, payment_terms.amount_units, payment_terms.currency, acceptable_asset_types |
Minimum BAD_VALUE examples (non-exhaustive) that MUST be covered:
message_type != yona.payment_intentruleset_id != yona:ruleset:v1.0iss != retrieve_intent.audaud != retrieve_intent.iss- returned
intent_locatordoes not match the requested locator payment_terms.amountnon-canonicalpayment_terms.amount_units != minorpayment_terms.currencynon-canonicalacceptable_asset_typesempty where the ruleset requires at least one acceptable asset typeacceptable_asset_types[*]invalid under CAIP-19- expired
exp - replayed
jti
6.4 yona.authorization_request (beneficiary server receives)
6.4.1 Common fields for both request forms
| Category | Fields |
|---|---|
| Common claims | iss, aud, iat, exp, jti, message_type, ruleset_id |
| Message-specific common field | intent_id |
Minimum BAD_VALUE examples (non-exhaustive) that MUST be covered:
message_type != yona.authorization_requestruleset_id != yona:ruleset:v1.0intent_idviolates ASCII-restricted identifier rules- non-integer
iatorexp - expired
exp
6.4.2 Pull-payment form
| Category | Fields |
|---|---|
| Pull-payment form | embedded_payment_intent |
Minimum BAD_VALUE examples (non-exhaustive) that MUST be covered:
embedded_payment_intentis not a JWS Compact Serialization stringembedded_payment_intentsignature invalidembedded_payment_intentexpexpiredembedded_payment_intentjtireplayed under receiver policyembedded_payment_intentdoes not match a previously returnedyona.payment_intentJWS Compact Serializationauthorization_request.iss != decoded_payment_intent.audauthorization_request.aud != decoded_payment_intent.iss
6.4.3 Push-payment form
| Category | Fields |
|---|---|
| Push-payment form | beneficiary_handle, payment_terms, payment_terms.amount, payment_terms.amount_units, payment_terms.currency, intended_asset_type |
Minimum BAD_VALUE examples (non-exhaustive) that MUST be covered:
beneficiary_handleviolates required form or constraintsaud !=DID encoded inbeneficiary_handlepayment_terms.amountnon-canonicalpayment_terms.amount_units != minorpayment_terms.currencynon-canonicalintended_asset_typeinvalid under CAIP-19
6.4.4 Request-form classification and mixed-field cases
The harness MUST instantiate cases showing that the receiver deterministically rejects:
Mixed-field / classification case
- a request with
embedded_payment_intentpresent and any ofbeneficiary_handle,payment_terms, orintended_asset_typealso present - a request with
beneficiary_handle,payment_terms, andintended_asset_typepresent butembedded_payment_intentalso present - a request with neither valid pull form nor valid push form
- a push-form request missing required
intended_asset_type - a push-form request that includes
embedded_payment_intent - a pull-form request that includes any disallowed push-form fields
6.5 yona.authorization_response (originator client receives)
| Category | Fields |
|---|---|
| Common claims | iss, aud, iat, exp, jti, message_type, ruleset_id |
| Message-specific fields | intent_id, decision, request_jws_sha256 |
Minimum BAD_VALUE examples (non-exhaustive) that MUST be covered:
message_type != yona.authorization_responseruleset_id != yona:ruleset:v1.0decisionnot equal toACCEPTorREJECTiss != authorization_request.audaud != authorization_request.issintent_id != authorization_request.intent_idrequest_jws_sha256mismatch- expired
exp - replayed
jti
7. Duplicate JSON Member Tests
A separate duplicate-member case MUST be instantiated for each message type:
| ID | Case |
|---|---|
| BIP-DUP-001 | duplicate JSON member in yona.retrieve_intent |
| BIP-DUP-002 | duplicate JSON member in yona.payment_intent |
| BIP-DUP-003 | duplicate JSON member in yona.authorization_request |
| BIP-DUP-004 | duplicate JSON member in yona.authorization_response |
Expected result:
- message is invalid
- receiver MUST reject
- for authorization, the receiver MUST return terminal
REJECTif bindable; otherwise it MUST NOT return a YONA response message - for retrieval, the endpoint MUST NOT produce a successful
yona.payment_intent
8. DID / JOSE / Signature Profile Matrix
The harness MUST verify the following DID resolution, JOSE, signature, and service-discovery cases.
8.1 Required DID discovery and signature-profile cases
| ID | Case | Expected Receiver Behavior |
|---|---|---|
| BIP-SIG-001 | JWS missing signature segment or malformed compact form | Reject |
| BIP-SIG-002 | Protected header alg missing or not EdDSA | Reject |
| BIP-SIG-003 | Protected header typ missing or not JWT | Reject |
| BIP-SIG-004 | kid missing from protected header | Reject |
| BIP-SIG-005 | kid present but not a DID URL | Reject |
| BIP-SIG-006 | Sender DID (iss) cannot be resolved via did:web | Reject |
| BIP-SIG-007 | kid does not resolve in the sender DID document | Reject |
| BIP-SIG-008 | kid resolves but key is not authorized or usable for verification | Reject |
| BIP-SIG-009 | Signature verification fails with the resolved key | Reject |
| BIP-SIG-010 | kid points to a key under a DID different from iss | Reject |
| BIP-SIG-011 | DID resolves but required service entry is missing | Client MUST NOT send the request and MUST NOT proceed as if ACCEPT occurred |
| BIP-SIG-012 | DID resolves but serviceEndpoint is unusable or an invalid URL | Client MUST NOT send the request and MUST NOT proceed as if ACCEPT occurred |
8.2 Optional advertised DID service entries and referenced outputs
If the implementation advertises an optional BIP-defined DID service entry, the corresponding cases in this subsection are applicable and MUST be passed for a YONA conformance claim.
If the implementation does not advertise that optional service entry, those cases are not applicable.
Illustrative examples of optional DID service entries and related capability documents appear in Reference Messages and DID Examples. Those examples are non-normative and do not alter the requirements under test in this suite.
8.2.1 YonaTravelRuleService
Applicability: only if YonaTravelRuleService is advertised in the relevant DID document.
| ID | Case | Expected Result |
|---|---|---|
| BIP-SVC-001 | Advertised YonaTravelRuleService entry is structurally valid and its referenced capability document contains all BIP-required minimum fields | Pass |
| BIP-SVC-002 | Advertised YonaTravelRuleService entry is missing one or more DID-service members required by the BIP, or a required member is malformed | Fail conformance |
| BIP-SVC-003 | Advertised YonaTravelRuleService serviceEndpoint is unusable or an invalid URL | Fail conformance |
| BIP-SVC-004 | The referenced capability document cannot be obtained from the advertised serviceEndpoint as required by the BIP | Fail conformance |
| BIP-SVC-005 | The referenced capability document is missing one or more BIP-required minimum fields | Fail conformance |
| BIP-SVC-006 | The referenced capability document contains a BIP-required field with the wrong JSON type or an invalid semantic value | Fail conformance |
8.2.2 YonaAssuranceService
Applicability: only if YonaAssuranceService is advertised in the relevant DID document.
If the companion BIP defines only DID-service-entry requirements for YonaAssuranceService, the harness MUST cover:
| ID | Case | Expected Result |
|---|---|---|
| BIP-SVC-007 | Advertised YonaAssuranceService entry is structurally valid | Pass |
| BIP-SVC-008 | Advertised YonaAssuranceService entry is missing one or more DID-service members required by the BIP, or a required member is malformed | Fail conformance |
| BIP-SVC-009 | Advertised YonaAssuranceService serviceEndpoint is unusable or an invalid URL | Fail conformance |
If the companion BIP defines required referenced outputs for YonaAssuranceService, the harness MUST also instantiate valid-path and invalid-path cases analogous to BIP-SVC-001 through BIP-SVC-006 for those required outputs.
9. request_jws_sha256 Tests
| ID | Role Under Test | Case | Expected Result |
|---|---|---|---|
| BIP-HASH-001 | Originator client | Correct request_jws_sha256 for exact request bytes | Accept response, subject to other checks |
| BIP-HASH-002 | Originator client | Hash computed over semantically equivalent but differently serialized request bytes | Reject response |
| BIP-HASH-003 | Originator client | request_jws_sha256 character value mutated by one character | Reject response |
| BIP-HASH-004 | Beneficiary server | Response generated with hash over exact received bytes | Pass |
| BIP-HASH-005 | Beneficiary server | Response generated over reconstructed, normalized, trimmed, or reserialized bytes | Fail conformance |
10. Malformed JOSE Body Tests
| ID | Direction | Case | Expected Behavior |
|---|---|---|---|
| BIP-JOSE-001 | Request to server | Body contains bytes outside US-ASCII | Not valid JWS Compact Serialization; server MUST NOT return a YONA response message |
| BIP-JOSE-002 | Request to server | Not JWS Compact Serialization (. count != 2) | Unbindable; server MUST NOT return a YONA response message |
| BIP-JOSE-003 | Request to server | Invalid base64url segment | Unbindable; server MUST NOT return a YONA response message |
| BIP-JOSE-004 | Request to server | Payload bytes are not valid UTF-8 JSON text | Unbindable; server MUST NOT return a YONA response message |
| BIP-JOSE-005 | Request to server | Payload decodes to non-JSON | Unbindable; server MUST NOT return a YONA response message |
| BIP-JOSE-006 | Response to client (authorization) | Non-200 status | No valid terminal response obtained; treat as NO_RESPONSE (MUST be treated as REJECT) |
| BIP-JOSE-007 | Response to client (authorization) | HTTP 200 but non-application/jose body | No valid terminal response obtained; treat as NO_RESPONSE (MUST be treated as REJECT) |
| BIP-JOSE-008 | Response to client (authorization) | HTTP 200 with application/jose but malformed JWS | No valid terminal response obtained; treat as NO_RESPONSE (MUST be treated as REJECT) |
| BIP-JOSE-009 | Response to client (authorization) | Terminal response arrives after client has concluded NO_RESPONSE | Ignore for outcome purposes |
| BIP-JOSE-010 | Response to client (retrieval) | Retrieval response malformed, non-200, or timed out | No verified yona.payment_intent; client MUST NOT proceed to authorization using locator-only data |
11. Wrong-Binding Cases
| ID | Message | Wrong Binding | Expected Result |
|---|---|---|---|
| BIP-BIND-001 | yona.retrieve_intent | aud != intent_locator.beneficiary_vasp_did | Beneficiary rejects request; no successful retrieval |
| BIP-BIND-002 | yona.payment_intent | iss != retrieve_intent.aud | Originator rejects |
| BIP-BIND-003 | yona.payment_intent | aud != retrieve_intent.iss | Originator rejects |
| BIP-BIND-004 | yona.payment_intent | returned intent_locator does not equal the requested locator | Originator rejects |
| BIP-BIND-005 | Pull yona.authorization_request | outer iss != embedded_payment_intent.aud | Beneficiary rejects |
| BIP-BIND-006 | Pull yona.authorization_request | outer aud != embedded_payment_intent.iss | Beneficiary rejects |
| BIP-BIND-007 | Pull yona.authorization_request | embedded_payment_intent does not match a previously returned yona.payment_intent JWS Compact Serialization | Beneficiary rejects |
| BIP-BIND-008 | Push yona.authorization_request | aud != DID encoded in beneficiary_handle | Beneficiary rejects |
| BIP-BIND-009 | yona.authorization_response | iss != authorization_request.aud | Originator rejects |
| BIP-BIND-010 | yona.authorization_response | aud != authorization_request.iss | Originator rejects |
| BIP-BIND-011 | yona.authorization_response | intent_id != authorization_request.intent_id | Originator rejects |
| BIP-BIND-012 | yona.authorization_response | request_jws_sha256 mismatch | Originator rejects |
12. Replay and Freshness Tests
12.1 Signed-message replay tests
For each message type other than yona.authorization_request, the harness MUST replay the exact same valid JWS within the active test session.
Replay rule:
- the implementation under test MUST apply its local replay policy to (
iss,jti) - a replayed message MUST NOT be treated as a new valid message
Repeated yona.authorization_request messages are tested under Section 12.2, not here.
12.2 Repeated yona.authorization_request tests
For yona.authorization_request, the harness MUST test repeated requests within the same (iss, intent_id) scope.
The harness MUST cover:
- a materially equivalent repeat whose non-material differences include one or more of:
jti,iat,exp,kid, or signature bytes - a materially changed repeat with one or more material authorization inputs changed
- a repeated request that receives a newly generated response bound to the repeated request bytes
Expected behavior:
- a materially equivalent repeat MUST NOT be treated as a replay solely because it is a new signed message with a different
jti - a materially equivalent repeat MUST receive the same terminal decision, newly bound to the repeated request bytes
- a materially changed repeat MUSTbe handled according to the ruleset's repeated-request outcome rules
12.3 Freshness tests
For each message type, the harness MUST instantiate:
- valid
exp - expired
exp - boundary case where
expequals the current test time according to receiver policy
The expected boundary-case outcome MUST be documented by the implementation and MUST be consistent across runs.
13. Prohibited Content Tests
Where the ruleset requires rejection if prohibited PII, Travel Rule payload data, destination addresses, settlement instructions, or other prohibited content appears in defined YONA semantic fields, the suite MUST include explicit tests placing clearly prohibited content into:
- defined fields of push-form
yona.authorization_request - defined fields of pull-form
yona.authorization_request, includingembedded_payment_intent - defined fields of
yona.authorization_response
These tests MUST NOT assume any global PII detector for unknown fields.
If the suite includes unknown-field cases, it MUST enumerate those unknown field names explicitly as suite fixtures and treat them as suite-specific checks rather than protocol semantics.
14. Byte-Exact Hashing Fixtures for request_jws_sha256
This section provides exact-byte fixtures for validating request_jws_sha256 handling under yona:ruleset:v1.0.
The canonical fixture bytes for this section are the raw downloadable .jws artifacts published with this suite release. The exact JWS Compact Serialization shown below are derived from those raw artifacts and are included for inspection and cross-checking.
For hashing and comparison, implementations MUST use the exact JWS Compact Serialization of the published raw artifact. Reserialized JSON, reconstructed JOSE objects, normalized strings, trimmed strings, or reformatted document renderings are not equivalent.
14.1 Fixture publication rule
For this release, the following raw artifacts are published as companion fixtures:
fixture-a-push-authorization-request.jwsfixture-b-pull-authorization-request.jwsfixture-c-authorization-response.jwsexpected.json
expected.json records the expected SHA-256 digests (hex and base64url) and request-binding values for these fixtures, plus fixture metadata. If a rendered HTML or PDF representation wraps lines or otherwise alters presentation, the raw artifact bytes remain authoritative.
14.2 Fixture A — Push-payment authorization request
Raw artifact: fixture-a-push-authorization-request.jws
Exact JWS Compact Serialization:
eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6ImRpZDp3ZWI6b3JpZ2luYXRvci5leGFtcGxlI2sxIn0.eyJpc3MiOiJkaWQ6d2ViOm9yaWdpbmF0b3IuZXhhbXBsZSIsImF1ZCI6ImRpZDp3ZWI6YmVuZWZpY2lhcnkuZXhhbXBsZSIsImlhdCI6MTc2MDAwMjAwMCwiZXhwIjoxNzYwMDAyMDYwLCJqdGkiOiJqdGlfcHVzaF9hdXRob3JpemF0aW9uX3JlcXVlc3RfMDAwMSIsIm1lc3NhZ2VfdHlwZSI6InlvbmEuYXV0aG9yaXphdGlvbl9yZXF1ZXN0IiwicnVsZXNldF9pZCI6InlvbmE6cnVsZXNldDp2MS4wIiwiaW50ZW50X2lkIjoib3JpZ2luYXRvcl9wdXNoX2ludGVudF8wMDAxIiwiYmVuZWZpY2lhcnlfaGFuZGxlIjoiZGlkPWRpZDp3ZWI6YmVuZWZpY2lhcnkuZXhhbXBsZTthbGlhcz1hbGlhc18wMDAxIiwicGF5bWVudF90ZXJtcyI6eyJhbW91bnQiOiIxMjUwIiwiYW1vdW50X3VuaXRzIjoibWlub3IiLCJjdXJyZW5jeSI6IlVTRCJ9LCJpbnRlbmRlZF9hc3NldF90eXBlIjoiZWlwMTU1OjEvZXJjMjA6MHhBMGI4Njk5MWM2MjE4YjM2YzFkMTlENGEyZTlFYjBjRTM2MDZlQjQ4In0.AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-PwDecoded header (non-normative, reference only):
{
"alg": "EdDSA",
"typ": "JWT",
"kid": "did:web:originator.example#k1"
}Decoded payload (non-normative, reference only):
{
"iss": "did:web:originator.example",
"aud": "did:web:beneficiary.example",
"iat": 1760002000,
"exp": 1760002060,
"jti": "jti_push_authorization_request_0001",
"message_type": "yona.authorization_request",
"ruleset_id": "yona:ruleset:v1.0",
"intent_id": "originator_push_intent_0001",
"beneficiary_handle": "did=did:web:beneficiary.example;alias=alias_0001",
"payment_terms": {
"amount": "1250",
"amount_units": "minor",
"currency": "USD"
},
"intended_asset_type": "eip155:1/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
}Expected output
| Value | Expected value |
|---|---|
| SHA-256 digest (hex) | 38f1a94f0cf983212b1738aca2e50eab9e1b3b207a9f3dc2a21897986f8fb00e |
SHA-256 digest (base64url) / expected request_jws_sha256 | OPGpTwz5gyErFzisouUOq54bOyB6nz3CohiXmG-PsA4 |
14.3 Fixture B — Pull-payment authorization request
Raw artifact: fixture-b-pull-authorization-request.jws
Exact JWS Compact Serialization:
eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6ImRpZDp3ZWI6b3JpZ2luYXRvci5leGFtcGxlI2sxIn0.eyJpc3MiOiJkaWQ6d2ViOm9yaWdpbmF0b3IuZXhhbXBsZSIsImF1ZCI6ImRpZDp3ZWI6YmVuZWZpY2lhcnkuZXhhbXBsZSIsImlhdCI6MTc2MDAwMTAwMiwiZXhwIjoxNzYwMDAxMDYyLCJqdGkiOiJqdGlfcHVsbF9hdXRob3JpemF0aW9uX3JlcXVlc3RfMDAwMSIsIm1lc3NhZ2VfdHlwZSI6InlvbmEuYXV0aG9yaXphdGlvbl9yZXF1ZXN0IiwicnVsZXNldF9pZCI6InlvbmE6cnVsZXNldDp2MS4wIiwiaW50ZW50X2lkIjoib3JpZ2luYXRvcl9wdWxsX2ludGVudF8wMDAxIiwiZW1iZWRkZWRfcGF5bWVudF9pbnRlbnQiOiJleUpoYkdjaU9pSkZaRVJUUVNJc0luUjVjQ0k2SWtwWFZDSXNJbXRwWkNJNkltUnBaRHAzWldJNlltVnVaV1pwWTJsaGNua3VaWGhoYlhCc1pTTnJNU0o5LmV5SnBjM01pT2lKa2FXUTZkMlZpT21KbGJtVm1hV05wWVhKNUxtVjRZVzF3YkdVaUxDSmhkV1FpT2lKa2FXUTZkMlZpT205eWFXZHBibUYwYjNJdVpYaGhiWEJzWlNJc0ltbGhkQ0k2TVRjMk1EQXdNVEF3TVN3aVpYaHdJam94TnpZd01EQXhNRFl4TENKcWRHa2lPaUpxZEdsZmNIVnNiRjl3WVhsdFpXNTBYMmx1ZEdWdWRGOHdNREF4SWl3aWJXVnpjMkZuWlY5MGVYQmxJam9pZVc5dVlTNXdZWGx0Wlc1MFgybHVkR1Z1ZENJc0luSjFiR1Z6WlhSZmFXUWlPaUo1YjI1aE9uSjFiR1Z6WlhRNmRqRXVNQ0lzSW1sdWRHVnVkRjlzYjJOaGRHOXlJanA3SW5SNWNHVWlPaUo1YjI1aExtbHVkR1Z1ZEY5c2IyTmhkRzl5SWl3aVltVnVaV1pwWTJsaGNubGZkbUZ6Y0Y5a2FXUWlPaUprYVdRNmQyVmlPbUpsYm1WbWFXTnBZWEo1TG1WNFlXMXdiR1VpTENKaVpXNWxabWxqYVdGeWVWOXBiblJsYm5SZmFXUWlPaUppWlc1bFptbGphV0Z5ZVY5cGJuUmxiblJmTURBd01TSjlMQ0p3WVhsdFpXNTBYM1JsY20xeklqcDdJbUZ0YjNWdWRDSTZJakV5TlRBaUxDSmhiVzkxYm5SZmRXNXBkSE1pT2lKdGFXNXZjaUlzSW1OMWNuSmxibU41SWpvaVZWTkVJbjBzSW1GalkyVndkR0ZpYkdWZllYTnpaWFJmZEhsd1pYTWlPbHNpWldsd01UVTFPakV2WlhKak1qQTZNSGhCTUdJNE5qazVNV00yTWpFNFlqTTJZekZrTVRsRU5HRXlaVGxGWWpCalJUTTJNRFpsUWpRNElsMTkuUWtKQ1FrSkNRa0pDUWtKQ1FrSkNRa0pDUWtKQ1FrSkNRa0pDUWtKQ1FrSkNRa0pDUWtKQ1FrSkNRa0pDUWtKQ1FrSkNRa0pDUWtKQ1FrSkNRa0pDUWcifQ.__79_Pv6-fj39vX08_Lx8O_u7ezr6uno5-bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwADecoded outer header (non-normative, reference only):
{
"alg": "EdDSA",
"typ": "JWT",
"kid": "did:web:originator.example#k1"
}Decoded outer payload (non-normative, reference only):
embedded_payment_intent is the exact JWS Compact Serialization of a previously returned yona.payment_intent
{
"iss": "did:web:originator.example",
"aud": "did:web:beneficiary.example",
"iat": 1760001002,
"exp": 1760001062,
"jti": "jti_pull_authorization_request_0001",
"message_type": "yona.authorization_request",
"ruleset_id": "yona:ruleset:v1.0",
"intent_id": "originator_pull_intent_0001",
"embedded_payment_intent": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6ImRpZDp3ZWI6YmVuZWZpY2lhcnkuZXhhbXBsZSNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmJlbmVmaWNpYXJ5LmV4YW1wbGUiLCJhdWQiOiJkaWQ6d2ViOm9yaWdpbmF0b3IuZXhhbXBsZSIsImlhdCI6MTc2MDAwMTAwMSwiZXhwIjoxNzYwMDAxMDYxLCJqdGkiOiJqdGlfcHVsbF9wYXltZW50X2ludGVudF8wMDAxIiwibWVzc2FnZV90eXBlIjoieW9uYS5wYXltZW50X2ludGVudCIsInJ1bGVzZXRfaWQiOiJ5b25hOnJ1bGVzZXQ6djEuMCIsImludGVudF9sb2NhdG9yIjp7InR5cGUiOiJ5b25hLmludGVudF9sb2NhdG9yIiwiYmVuZWZpY2lhcnlfdmFzcF9kaWQiOiJkaWQ6d2ViOmJlbmVmaWNpYXJ5LmV4YW1wbGUiLCJiZW5lZmljaWFyeV9pbnRlbnRfaWQiOiJiZW5lZmljaWFyeV9pbnRlbnRfMDAwMSJ9LCJwYXltZW50X3Rlcm1zIjp7ImFtb3VudCI6IjEyNTAiLCJhbW91bnRfdW5pdHMiOiJtaW5vciIsImN1cnJlbmN5IjoiVVNEIn0sImFjY2VwdGFibGVfYXNzZXRfdHlwZXMiOlsiZWlwMTU1OjEvZXJjMjA6MHhBMGI4Njk5MWM2MjE4YjM2YzFkMTlENGEyZTlFYjBjRTM2MDZlQjQ4Il19.QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQg"
}Decoded inner yona.payment_intent header (non-normative, reference only):
{
"alg": "EdDSA",
"typ": "JWT",
"kid": "did:web:beneficiary.example#k1"
}Decoded inner yona.payment_intent payload (non-normative, reference only):
{
"iss": "did:web:beneficiary.example",
"aud": "did:web:originator.example",
"iat": 1760001001,
"exp": 1760001061,
"jti": "jti_pull_payment_intent_0001",
"message_type": "yona.payment_intent",
"ruleset_id": "yona:ruleset:v1.0",
"intent_locator": {
"type": "yona.intent_locator",
"beneficiary_vasp_did": "did:web:beneficiary.example",
"beneficiary_intent_id": "beneficiary_intent_0001"
},
"payment_terms": {
"amount": "1250",
"amount_units": "minor",
"currency": "USD"
},
"acceptable_asset_types": [
"eip155:1/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
]
}Expected output
| Value | Expected value |
|---|---|
| SHA-256 digest (hex) | 072c83eebcc68811299a78a4fb2ca116a3b8e0a52a323e96d7d67714856d8d77 |
SHA-256 digest (base64url) / expected request_jws_sha256 | ByyD7rzGiBEpmnik-yyhFqO44KUqMj6W19Z3FIVtjXc |
14.4 Fixture C — Authorization response referencing Fixture A
Fixture C is a terminal yona.authorization_response paired with Fixture A. The request_jws_sha256 claim in this response is the base64url(SHA-256(exact Fixture A compact JWS bytes)) (the same value as the “expected request_jws_sha256” row in Section 14.2).
Raw artifact: fixture-c-authorization-response.jws
Exact response JWS Compact Serialization
eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6ImRpZDp3ZWI6YmVuZWZpY2lhcnkuZXhhbXBsZSNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmJlbmVmaWNpYXJ5LmV4YW1wbGUiLCJhdWQiOiJkaWQ6d2ViOm9yaWdpbmF0b3IuZXhhbXBsZSIsImlhdCI6MTc2MDAwMjAwMSwiZXhwIjoxNzYwMDAyMDYxLCJqdGkiOiJqdGlfcHVzaF9hdXRob3JpemF0aW9uX3Jlc3BvbnNlXzAwMDEiLCJtZXNzYWdlX3R5cGUiOiJ5b25hLmF1dGhvcml6YXRpb25fcmVzcG9uc2UiLCJydWxlc2V0X2lkIjoieW9uYTpydWxlc2V0OnYxLjAiLCJpbnRlbnRfaWQiOiJvcmlnaW5hdG9yX3B1c2hfaW50ZW50XzAwMDEiLCJkZWNpc2lvbiI6IkFDQ0VQVCIsInJlcXVlc3RfandzX3NoYTI1NiI6Ik9QR3BUd3o1Z3lFckZ6aXNvdVVPcTU0Yk95QjZuejNDb2hpWG1HLVBzQTQifQ.CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQDecoded header (non-normative, reference only):
{
"alg": "EdDSA",
"typ": "JWT",
"kid": "did:web:beneficiary.example#k1"
}Decoded payload (non-normative, reference only):
{
"iss": "did:web:beneficiary.example",
"aud": "did:web:originator.example",
"iat": 1760002001,
"exp": 1760002061,
"jti": "jti_push_authorization_response_0001",
"message_type": "yona.authorization_response",
"ruleset_id": "yona:ruleset:v1.0",
"intent_id": "originator_push_intent_0001",
"decision": "ACCEPT",
"request_jws_sha256": "OPGpTwz5gyErFzisouUOq54bOyB6nz3CohiXmG-PsA4"
}15. Deterministic REJECT vs NO_RESPONSE Decision Tables
15.1 Authorization endpoint (YonaAuthorizationService)
A beneficiary server receiving yona.authorization_request MUST apply the following logic:
| Condition | Can server preserve exact request bytes? | Can server extract iss, aud, and intent_id as strings from payload bytes? | Can server sign response? | Expected Behavior |
|---|---|---|---|---|
| Valid request; policy decision reached | Yes | Yes | Yes | Return HTTP 200 with signed bound terminal yona.authorization_response (ACCEPT or REJECT) |
| Invalid request (bad signature, expired, replayed signed message, wrong binding, invalid form, and so on), but bindable | Yes | Yes | Yes | Return HTTP 200 with signed bound terminal REJECT |
| Malformed JOSE body (not compact, bad base64url, not ASCII compact form) | No, or not meaningfully as valid compact JWS | No | N/A | Server MUST NOT return a YONA response message |
| Payload invalid UTF-8, non-JSON, or duplicate members prevent claim extraction | Yes | No | N/A | Server MUST NOT return a YONA response message |
Missing or invalid iss, aud, or intent_id prevents a structurally valid response | Yes | No | N/A | Server MUST NOT return a YONA response message |
| Server signing key unavailable or internal signing failure | Yes | Yes | No | Server MUST NOT return a YONA response message |
| Transport failure before response sent | Unknown | Unknown | Unknown | Server MUST NOT return a YONA response message |
Client interpretation (authorization flow):
- if no valid, verified terminal response is obtained by the cutoff, the outcome is
NO_RESPONSE NO_RESPONSEMUST be treated asREJECT
15.2 Payment-intent retrieval endpoint (YonaPaymentIntentService)
Because yona:ruleset:v1.0 does not define a retrieval-REJECT message type, this suite does not require any signed retrieval-REJECT message.
For each applicable condition below, client and server behavior MUST match the expected outcomes shown.
| Condition | Expected Server/Test Outcome | Expected Client Outcome |
|---|---|---|
Valid yona.retrieve_intent | Return valid yona.payment_intent | Verify and use it as the authoritative payment intent |
| Invalid retrieval request | No successful yona.payment_intent | MUST NOT proceed to authorization using locator-only data |
| Non-200, malformed response, or timeout | Retrieval failure | MUST NOT proceed to authorization using locator-only data |