Vérifier un reçu

La vérifiabilité indépendante ne compte que si vous pouvez réellement le faire. Le moyen le plus court est Agreely.verifyReceipt : une méthode statique, sans aucune clé d'API, qui résout toujours. Un reçu falsifié rend un verdict, jamais une exception. La CLI expose exactement les mêmes statuts par agreely verify.

Vérifier avec le SDK ou la CLI

Passez le reçu. Le contrôle d'ancrage sur la chaîne est facultatif et n'a lieu que si vous fournissez une URL RPC.

import { Agreely } from "@agreely/sdk";

const v = await Agreely.verifyReceipt(receipt, { rpcUrl: process.env.BASE_SEPOLIA_RPC, // optional: enables the on-chain anchor check });

v.receiptType; // "company_attested" | "citizen" if (v.overall === "failed") { // a decisive check ACTIVELY failed: treat as tamper/forgery, reject } else if (v.overall === "unavailable") { // a DID or RPC could not be reached: inconclusive, NOT a forgery, retry later } else { // "verified" (company_attested) or "partial" (citizen, offline) }

use Agreely\Sdk\Agreely;

$v = Agreely::verifyReceipt($receipt, ['rpcUrl' => getenv('BASE_SEPOLIA_RPC')]);

$v->receiptType; // "company_attested" | "citizen" $v->overall; // "verified" | "partial" | "failed" | "unavailable"

# zero-install (no global install needed):
npx @agreely/cli verify ./receipt.json

or, if the CLI is installed globally:

agreely verify ./receipt.json --json

human mode prints a five-row honesty matrix + an overall verdict + notes

exit 0 = verified/partial, 4 = unavailable, 6 = failed (tamper)

air-gapped: supply the issuer DID document locally, no network at all:

agreely verify ./receipt.json --did-doc ./issuer-did.json

opt-in cross-checks:

agreely verify ./receipt.json --ipfs --onchain --rpc-url $AGREELY_RPC_URL

Le résultat est un ReceiptVerification : un receiptType, cinq statuts par contrôle (companySignature, citizenAssertion, disclosureCopy, documentAnchor, cellLabelBinding), un overall, et des notes en langage clair.

Les quatre contrôles

  1. companySignature : la signature Ed25519 de l'entreprise sur l'offre.
  2. citizenAssertion : l'assertion WebAuthn de la clé d'accès du citoyen.
  3. disclosureCopy : recoupement facultatif qui récupère la copie de divulgation sur IPFS et la compare au disclosureHash du reçu. Activé par --ipfs à la CLI (ou l'option verifyDisclosure); autrement skipped.
  4. documentAnchor : recoupement facultatif sur la chaîne qui confirme que le document a été ancré. Activé par --onchain, qui exige une URL RPC (--rpc-url ou AGREELY_RPC_URL); autrement skipped.

La matrice affiche aussi une cinquième ligne, cellLabelBinding : un résumé dérivé indiquant si les étiquettes lisibles (catégorie / finalité) sont liées cryptographiquement dans ce contrôle hors ligne. C'est le champ à lire avant de faire confiance à une étiquette affichée. Sur un reçu attesté par l'entreprise, elle suit companySignature (les étiquettes sont dans le corps signé, donc les modifier casse la vérification); sur un reçu citoyen, elle est unsupported hors ligne.

Essayez-le

Un régulateur à qui l'on dit « c'est vérifiable de façon indépendante » a besoin de quelque chose à essayer. Téléchargez un vrai reçu attesté par l'entreprise et le document DID de son émetteur, tirés des vecteurs de référence du SDK, puis vérifiez le reçu hors ligne (aucun réseau, aucune clé d'API) :

agreely verify sample-receipt.json --did-doc sample-did.json
✓ VERIFIED  (company_attested)
  companySignature  pass
  citizenAssertion  unsupported
  disclosureCopy    skipped
  documentAnchor    skipped
  cellLabelBinding  pass

  · Company signature verified against issuer DID did:web:api.agreely.ca:c:acme (key did:web:api.agreely.ca:c:acme#kms-1).
  · This proves the company ATTESTED to a hand-signed PDF (hash 0xabababababababababababababababababababababababababababababababab); it does NOT prove a human signed.
  · A company-attested receipt carries no citizen passkey assertion, so citizenAssertion is not applicable.
  · Cell labels bound: the category/purpose labels sit inside the company-signed body, so the verified signature covers them. Mutating any item label breaks it.
  · disclosureCopy skipped: the receipt carries no document.ipfsCid + disclosureHash pair to fetch and compare.
  · documentAnchor skipped: pass an rpcUrl to check the on-chain document anchor.

La sortie se termine par VERIFIED avec un code de sortie 0. C'est un reçu attesté par l'entreprise, donc la vérification est propre et non partial.

La matrice d'honnêteté

Le meilleur verdict possible dépend du type de reçu, et c'est le point d'honnêteté porteur de cette page.

Type de reçu Meilleur verdict Pourquoi
company_attested verified la signature de l'entreprise se vérifie entièrement hors ligne
citizen partial companySignature est unsupported hors ligne (voir plus bas)

Un reçu attesté par l'entreprise (typiquement un PDF signé à la main) atteint verified sans aucun réseau : sa signature d'entreprise se vérifie hors ligne. Un reçu citoyen plafonne honnêtement à partial : l'assertion par clé d'accès du citoyen se vérifie bel et bien hors ligne, mais la moitié « signature d'entreprise » ne le peut pas.

Pourquoi un reçu citoyen plafonne à partial hors ligne

Sur un reçu citoyen, l'entreprise a signé l'offre d'origine, qui inclut la référence du sujet et la divulgation complète; le reçu omet ces champs pour préserver la non-liaison. Un contrôle sain de la signature d'entreprise exige donc un point de terminaison serveur receipts/verify, qui n'existe pas encore (voir la feuille de route). C'est pourquoi companySignature est unsupported hors ligne sur un reçu citoyen, et partial est le verdict honnête, pas un échec.

Échec contre indisponible

verifyReceipt sépare une vérification qui a échoué (failed : la cryptographie a activement infirmé le reçu, une falsification) d'une vérification qui n'a pas pu aboutir (unavailable : le DID de l'émetteur ou du citoyen n'a pas pu être résolu, ou une passerelle était injoignable). Un fail actif l'emporte toujours sur un unavailable : un vrai négatif n'est jamais masqué par une indisponibilité, et un reçu valide durant une panne de résolution DID ne ressemble jamais à une contrefaçon. À la CLI, c'est sortie 6 (échec) contre sortie 4 (indisponible).

Ensuite