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
companySignature: la signature Ed25519 de l'entreprise sur l'offre.citizenAssertion: l'assertion WebAuthn de la clé d'accès du citoyen.disclosureCopy: recoupement facultatif qui récupère la copie de divulgation sur IPFS et la compare audisclosureHashdu reçu. Activé par--ipfsà la CLI (ou l'optionverifyDisclosure); autrementskipped.documentAnchor: recoupement facultatif sur la chaîne qui confirme que le document a été ancré. Activé par--onchain, qui exige une URL RPC (--rpc-urlouAGREELY_RPC_URL); autrementskipped.
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) :
- sample-receipt.json : le reçu attesté par l'entreprise
- sample-did.json : le document DID de l'émetteur
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
- Vérifier un ConsentReceipt : la matrice complète « ce qui est prouvé contre ce qui est présumé » et toutes les options.
- La recette de vérification au niveau des champs, pour reconstruire le contrôle à quatre étapes sans le SDK.