Independent verification

Re-verify a device-signed payment yourself. No account required.

Yebo's core claim is that approval evidence outlives the vendor, including us. Below is a payment approval signed by the approver's own passkey, Yebo's gateway key, the approver's public key, an evidence bundle, and the verifier. Prove the claim without trusting us.

Sample: a test approval made by a software passkey in a local Yebo gateway, with a test identity and a test gateway key. Production artifacts have the same format; verify them with the gateway's published key. The payment is 150 USD to sample-vendor and ran as a dry run: no money moved. Per-payment device signing is live and has been exercised in production with a real device; these files are a test so that no real person's identifiers are published. Everything on this page works offline. The verifier makes no network calls, needs no API key, and never contacts Yebo. If Yebo disappeared tomorrow, this procedure would still work.

Step by step

Verify a device-signed payment approval

Three steps, one command. You need Node.js 18 or newer, nothing else: the commands run the open-source npm package yebo-verify, pinned to 0.2.0 as shown. Versions before 0.2.0 cannot read device-signed artifacts, so the commands pin 0.2.0.

  1. 1

    Download the artifact and the two public keys

    sample-mandate.json: the mandate artifact for a 150 USD payment to sample-vendor, approved by the test identity user:sample-approver with its passkey. sample-gateway-key.pem: the public key of the (test) Yebo gateway that countersigned the record. sample-approver-key.jwk: the approver's registered passkey public key (P-256 JWK).
  2. 2

    Run the verifier

    In a terminal, in the folder where you downloaded the three files:
    npx yebo-verify@0.2.0 sample-mandate.json --gateway-key sample-gateway-key.pem --require-hardware --approver-key sample-approver-key.jwk
    --require-hardware fails the check unless the approver's own device signed the payment. --approver-key pins the key that must have made that signature. Add --explain for a plain-language explanation of every field.
  3. 3

    Read the output

    This is the verifier's actual output on the sample files:
expected: PASS
YEBO MANDATE VERIFICATION

  artifact  sample-mandate.json
  key       sample-gateway-key.pem (Yebo gateway key)
  approver  sample-approver-key.jwk (pinned approver key)

  RESULT: PASS - the approver's own device signed exactly this payment, and Yebo's gateway countersigned the record.

  Field breakdown
  action          payment
  amount          150 USD
  payee           sample-vendor
  requested by    user:sample-approver
  approver        passkey:user:sample-approver
  approval type   human_device
  policy version  sha256:d01a6c9d2614f735dc65…
  approved at     2026-10-09T03:18:10.059Z
  valid window    2026-10-09T03:18:10.050Z → 2026-10-09T03:33:10.050Z
  mandate id      1e999a0f-2bd8-42f8-8aa8-fe16e803017c
  approver device SIGNED (WebAuthn assertion over this payment)
  Yebo gateway sigVALID (ECDSA P-256 / SHA-256)

  Checks
  [PASS] Artifact structure
         All required mandate and approval fields are present.
  [PASS] Public key
         Key fingerprint c0fab81305d6e928… accepted for verification.
  [PASS] Mandate integrity
         Recomputed mandate hash 3456d13ddf4e0339… matches the hash signed at approval.
  [PASS] Policy binding
         The policy hash in the mandate matches the policy hash the approver signed.
  [PASS] Signed approval fields
         artifact_version 2.0: the approver signature covers approved_by, mandate_hash, policy_hash, timestamp, algorithm, key_fingerprint. Editing the approver name or any of these fields fails the signature check.
  [PASS] Yebo gateway signature
         Yebo's gateway signed the approval record (approver, approval type, mandate hash, policy hash, timestamp, algorithm, key fingerprint, device key fingerprint) with its published key. This is Yebo's counter-signature, not the approver's.
  [PASS] Approver device signature (WebAuthn)
         The approver's own device (passkey:user:sample-approver) signed SHA-256 of exactly this payment and approver (WebAuthn, user verified) under the credential key 3ed058baf3db478b….
  [PASS] Pinned approver key
         The device signature was made with the pinned approver key (fingerprint 3ed058baf3db478b…).
  [PASS] Approval inside validity window
         Approved at 2026-10-09T03:18:10.059Z, inside the mandate's validity window (2026-10-09T03:18:10.050Z to 2026-10-09T03:33:10.050Z).

In plain words

What each check proves

Each line of the output answers one question an auditor would ask about this payment.

Approver device signature (WebAuthn)The approver's device signed exactly this payment

The approver's own passkey signed a hash of this exact payment (amount, payee, requesting agent, validity window) and of the approver's identity, with user verification. Change one cent, the payee or the approver and this check fails.

Yebo gateway signatureYebo countersigned the record

Yebo's gateway signed the approval record with its published key. This is Yebo's counter-signature, never the approver's: it shows the record is the one the gateway issued, unaltered.

Pinned approver keyIt was the approver's registered key

The device signature was made with the key you supplied, not just any key carried inside the artifact. For a real payment, take the approver's registered passkey public key from your organisation's own records, not from the artifact.

Approval inside validity windowApproved while the payment was valid

The approval was recorded between the mandate's issued_at and expires_at. An approval outside the window fails.

Mandate integrity and policy bindingNothing changed after approval

The verifier recomputes the mandate's content hash and checks it against the hash that was signed, and checks the policy hash in force at approval. The tampered sample below fails here.

Contained execution receipts (bundle)The receipt is chained to the approval

In the evidence bundle, the gateway-signed execution receipt carries the mandate hash and a reference to this approval's signature, so it points back to exactly this device-signed approval. The bundle's signed manifest covers every file in it.

The part that matters

Now try to break it

Verification you cannot break is verification you cannot trust. This artifact is the same mandate, with the amount changed from 150 to 1500 after approval. Run the same command and watch it fail.

sample-mandate-tampered.json: download it into the same folder and run:

npx yebo-verify@0.2.0 sample-mandate-tampered.json --gateway-key sample-gateway-key.pem --require-hardware --approver-key sample-approver-key.jwk
expected: FAIL
YEBO MANDATE VERIFICATION

  artifact  sample-mandate-tampered.json
  key       sample-gateway-key.pem (Yebo gateway key)
  approver  sample-approver-key.jwk (pinned approver key)

  RESULT: FAIL - this artifact does not verify.

  Field breakdown
  action          payment
  amount          1500 USD
  payee           sample-vendor
  requested by    user:sample-approver
  approver        passkey:user:sample-approver
  approval type   human_device
  policy version  sha256:d01a6c9d2614f735dc65…
  approved at     2026-10-09T03:18:10.059Z
  valid window    2026-10-09T03:18:10.050Z → 2026-10-09T03:33:10.050Z
  mandate id      1e999a0f-2bd8-42f8-8aa8-fe16e803017c
  approver device INVALID
  Yebo gateway sigVALID (ECDSA P-256 / SHA-256)

  Checks
  [PASS] Artifact structure
         All required mandate and approval fields are present.
  [PASS] Public key
         Key fingerprint c0fab81305d6e928… accepted for verification.
  [FAIL] Mandate integrity
         The mandate contents do NOT match what was approved. Recomputed hash 2d0a8546c2aed61f… differs from the signed hash 3456d13ddf4e0339…. One or more of these fields has been altered since approval: mandate_id, subject_identity, counterparty_identity, capability, policy_hash, nonce, issued_at, expires_at, amount, currency.
  [PASS] Policy binding
         The policy hash in the mandate matches the policy hash the approver signed.
  [PASS] Signed approval fields
         artifact_version 2.0: the approver signature covers approved_by, mandate_hash, policy_hash, timestamp, algorithm, key_fingerprint. Editing the approver name or any of these fields fails the signature check.
  [PASS] Yebo gateway signature
         Yebo's gateway signed the approval record (approver, approval type, mandate hash, policy hash, timestamp, algorithm, key fingerprint, device key fingerprint) with its published key. This is Yebo's counter-signature, not the approver's.
  [FAIL] Approver device signature (WebAuthn)
         WebAuthn assertion does NOT verify for this mandate and approver: the authenticator signed a different challenge: clientDataJSON.challenge does not equal SHA-256 of what this evidence says was approved.
  [PASS] Pinned approver key
         The device signature was made with the pinned approver key (fingerprint 3ed058baf3db478b…).
  [PASS] Approval inside validity window
         Approved at 2026-10-09T03:18:10.059Z, inside the mandate's validity window (2026-10-09T03:18:10.050Z to 2026-10-09T03:33:10.050Z).

  What did not verify:
   - tampered mandate - the contents differ from what the approver signed
   - bad hardware approval - the WebAuthn assertion does not verify over what this evidence says was approved

Both signatures on the record are still authentic, but the mandate no longer matches what was signed: the content hash differs, and the approver's device signature no longer covers this payment. Verification fails and says exactly why. Try it yourself: change the payee, the approver, or one cent of the amount and re-run. Every edit fails.

Also try a different approver key: generate any other P-256 key and pass it as --approver-key. The verifier fails with an approver key mismatch.

Evidence bundle

Verify the whole record: approval, receipt and audit trail

The evidence bundle is what the gateway exports for a payment: the execution receipt (a dry run, so no money moved), the mandate record, the device-signed mandate artifact and the audit events, sealed by one gateway-signed manifest.

  1. 1

    Download the bundle

    sample-evidence-bundle.json, into the same folder as the two keys.
  2. 2

    Run the verifier in bundle mode

    npx yebo-verify@0.2.0 bundle sample-evidence-bundle.json --gateway-key sample-gateway-key.pem --require-hardware --approver-key sample-approver-key.jwk
expected: PASS
YEBO EVIDENCE BUNDLE VERIFICATION

  bundle        sample-evidence-bundle.json
  gateway key   sample-gateway-key.pem
  approver key  sample-approver-key.jwk

  RESULT: PASS - every check verified.

  Checks
  [PASS] Bundle structure
         Bundle contains 4 artifact(s) and a signed manifest.
  [PASS] Gateway public key
         Gateway key fingerprint c0fab81305d6e928… accepted for verification.
  [PASS] Per-artifact digests
         All 4 artifact content digest(s) recompute to their manifest values.
  [PASS] Manifest root hash
         Root hash cda6e4329747e18d… recomputes from the per-artifact digests.
  [PASS] Manifest signature
         ECDSA P-256 signature over the root hash is valid under the supplied gateway key.
  [PASS] Contained execution receipts
         All 1 execution receipt(s) verify under the gateway key; 1 of them chain-verified against mandate artifacts in this bundle.
  [PASS] Artifact structure (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         All required mandate and approval fields are present.
  [PASS] Public key (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         Key fingerprint c0fab81305d6e928… accepted for verification.
  [PASS] Mandate integrity (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         Recomputed mandate hash 3456d13ddf4e0339… matches the hash signed at approval.
  [PASS] Policy binding (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         The policy hash in the mandate matches the policy hash the approver signed.
  [PASS] Signed approval fields (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         artifact_version 2.0: the approver signature covers approved_by, mandate_hash, policy_hash, timestamp, algorithm, key_fingerprint. Editing the approver name or any of these fields fails the signature check.
  [PASS] Yebo gateway signature (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         Yebo's gateway signed the approval record (approver, approval type, mandate hash, policy hash, timestamp, algorithm, key fingerprint, device key fingerprint) with its published key. This is Yebo's counter-signature, not the approver's.
  [PASS] Approver device signature (WebAuthn) (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         The approver's own device (passkey:user:sample-approver) signed SHA-256 of exactly this payment and approver (WebAuthn, user verified) under the credential key 3ed058baf3db478b….
  [PASS] Pinned approver key (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         The device signature was made with the pinned approver key (fingerprint 3ed058baf3db478b…).
  [PASS] Approval inside validity window (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         Approved at 2026-10-09T03:18:10.059Z, inside the mandate's validity window (2026-10-09T03:18:10.050Z to 2026-10-09T03:33:10.050Z).

sample-evidence-bundle-tampered.json: the same bundle with the execution receipt's amount changed from 150 to 1500.

npx yebo-verify@0.2.0 bundle sample-evidence-bundle-tampered.json --gateway-key sample-gateway-key.pem --require-hardware --approver-key sample-approver-key.jwk
expected: FAIL
YEBO EVIDENCE BUNDLE VERIFICATION

  bundle        sample-evidence-bundle-tampered.json
  gateway key   sample-gateway-key.pem
  approver key  sample-approver-key.jwk

  RESULT: FAIL - this does not verify.

  Checks
  [PASS] Bundle structure
         Bundle contains 4 artifact(s) and a signed manifest.
  [PASS] Gateway public key
         Gateway key fingerprint c0fab81305d6e928… accepted for verification.
  [FAIL] Per-artifact digests
         Artifact content does NOT match its manifest digest - the content was altered after the bundle was sealed: execution-receipt-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json (manifest b9fc969dc3e9816f…, recomputed 290c067d23144988…).
  [PASS] Manifest root hash
         Root hash cda6e4329747e18d… recomputes from the per-artifact digests.
  [PASS] Manifest signature
         ECDSA P-256 signature over the root hash is valid under the supplied gateway key.
  [PASS] Contained execution receipts
         All 1 execution receipt(s) verify under the gateway key; 1 of them chain-verified against mandate artifacts in this bundle.
  [PASS] Artifact structure (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         All required mandate and approval fields are present.
  [PASS] Public key (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         Key fingerprint c0fab81305d6e928… accepted for verification.
  [PASS] Mandate integrity (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         Recomputed mandate hash 3456d13ddf4e0339… matches the hash signed at approval.
  [PASS] Policy binding (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         The policy hash in the mandate matches the policy hash the approver signed.
  [PASS] Signed approval fields (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         artifact_version 2.0: the approver signature covers approved_by, mandate_hash, policy_hash, timestamp, algorithm, key_fingerprint. Editing the approver name or any of these fields fails the signature check.
  [PASS] Yebo gateway signature (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         Yebo's gateway signed the approval record (approver, approval type, mandate hash, policy hash, timestamp, algorithm, key fingerprint, device key fingerprint) with its published key. This is Yebo's counter-signature, not the approver's.
  [PASS] Approver device signature (WebAuthn) (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         The approver's own device (passkey:user:sample-approver) signed SHA-256 of exactly this payment and approver (WebAuthn, user verified) under the credential key 3ed058baf3db478b….
  [PASS] Pinned approver key (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         The device signature was made with the pinned approver key (fingerprint 3ed058baf3db478b…).
  [PASS] Approval inside validity window (mandate-artifact-1e999a0f-2bd8-42f8-8aa8-fe16e803017c.json)
         Approved at 2026-10-09T03:18:10.059Z, inside the mandate's validity window (2026-10-09T03:18:10.050Z to 2026-10-09T03:33:10.050Z).

  What did not verify:
   - tampered bundle - artifact content does not match its manifest digest

The receipt's amount is not one of the receipt's own signed fields; the receipt is bound to the amount through its mandate hash, which points to the device-signed mandate. Inside a bundle, the edit is caught by the signed manifest, which no longer matches the altered file.

Field reference

What each field is, and why an auditor cares

The artifact (version 2.0) has three parts: the mandate (what was asked), the approval (who approved it, signed by their device and countersigned by Yebo), and the gateway key reference. In this sample the identity is a test identity.

capabilityAction

The action that was authorized, here payment. An approval for one action cannot be reused for another.

amount / currencyAmount

The exact amount approved. Covered by the mandate hash that the approver's device signed: altering it after approval fails verification. This is the field the tampered sample changes.

counterparty_identityPayee

Who the payment is to. Also covered by the signed hash: the payee cannot be swapped after approval.

subject_identityRequested by

The identity the payment was requested under. The approval below records who authorized it.

approval.approved_byApprover

The approver's identity. In artifact version 2.0 it is signed, by Yebo's gateway and inside the approver's own device signature, so an edited approver fails. Match it to your delegation of authority.

approval.webauthnDevice signature

The WebAuthn assertion from the approver's passkey over SHA-256 of { payload, mandate_hash, approver }, with the credential's public key. This is the approver's own signature.

approval.signatureYebo counter-signature

ECDSA P-256 signature by Yebo's gateway over the approval record. Checked with the gateway key named in gateway_key.key_id, which the gateway publishes.

policy_hashPolicy version

A digest of the exact policy configuration in force at approval time. Lets you confirm which control governed the item.

nonceSingle-use value

A random value consumed at execution. Prevents the same approval from being replayed for a second payment.

issued_at / expires_atValidity window

Mandates are short-lived: a per-payment approval is bound to one request and must happen inside this window.

Testing procedure

How to test this as an approval control

The same four steps you would apply to any approval control, except that step 3 requires no vendor cooperation.

  1. 1

    Sample

    Select a sample of disbursements over threshold from the payment population, exactly as with any approval control.
  2. 2

    Obtain

    For each sampled item, obtain its mandate artifact (the gateway serves it at /mandate-artifact/<mandate id>) and its evidence bundle (/evidence/export). Execution runs in dry-run mode today, so these are dry-run receipts and no money moves.
  3. 3

    Re-verify

    Run npx yebo-verify@0.2.0 against each artifact or bundle with the gateway's published key (listed at the gateway's /authorization-receipt/keys endpoint) and, with --approver-key, the approver's registered passkey public key from your organisation's own records. No access to the AP platform, the payment rail, or Yebo is required. The exit code is machine-readable (0 = pass), so a full sample can be verified in one scripted pass.
  4. 4

    Match authority

    Match approval.approved_by against the delegation of authority in effect at the payment date, and match mandate_id against the system of record for the item.

The verifier is the open-source npm package yebo-verify (MIT license): view the package on npm. It uses only Node's built-in crypto, and every check can be re-implemented in any language, so you do not have to trust our binary either.

Practitioner validation

Did this hold up?

If you test approval controls for a living, your answer to these two questions is the test we care about.

Could you complete this verification in under 15 minutes?
Would this satisfy your testing of an approval control?

No login required. Responses are tagged practitioner-validation and used to test whether this verification procedure holds up with the people who would actually run it.