Centre de confiance
Une page pour un acheteur ou un auditeur pressé. Chaque affirmation ci-dessous est soit recalculable depuis un endpoint public, soit bornée par une constante de notre code. Ce que nous ne pouvons pas prouver, nous le disons aussi.
C'est la distinction la plus mal comprise du secteur, et celle qu'on nous demande le plus souvent de clarifier en audit. Une unité appartient à un lot dont la racine de Merkle est publiée sur Base. La feuille de Merkle de cette unité est composée de trois valeurs, et l'empreinte du passeport n'en fait pas partie.
La feuille de Merkle, telle que calculée par notre code et par le contrat
keccak256(abi.encode(tokenId, keccak256(uid), keccak256(metadata_uri)))Une unité dont le lot n'a jamais été ancré retombe sur sa propre transaction d'émission, qui prouve seulement que le jeton existe. Nos pages affichent alors « enregistrement on-chain », le mot « ancrage » restant réservé aux lots réellement ancrés : la portée de chaque référence est décidée côté serveur, pour qu'aucun client n'ait à la déduire du nom d'un champ, ce qui est la façon dont on finit par en sur-affirmer la portée.
Quatre maillons indépendants. Chacun est vérifiable séparément, et l'échec de l'un ne masque pas les autres.
Le contenu du passeport est sérialisé en JSON canonique (clés triées) puis haché en SHA-256. L'empreinte est stockée avec le passeport et republiée telle quelle : n'importe qui peut la recalculer depuis les données publiées et comparer.
À la publication, seule la projection publique du passeport est épinglée sur IPFS. Les données complètes n'y figurent jamais. Le lien IPFS n'est exposé publiquement qu'après avoir été récupéré et vérifié contre l'empreinte de cette projection. Tous les passeports ne sont pas épinglés : quand la copie manque, l'API l'omet au lieu de l'inventer.
Les unités sont regroupées en lots, la racine de Merkle du lot est publiée on-chain sur Base (chain id 8453) et le contrat conserve la racine, le nombre de feuilles et une empreinte d'identité du lot. La preuve d'inclusion de chaque unité est servie publiquement.
Le passeport est aussi émis comme attestation vérifiable SD-JWT-VC, signée en ES256 par une clé propre à la marque, générée dans AWS KMS et jamais exportée. La clé publique correspondante est publiée dans un document DID did:web : la signature se vérifie sans nous.
Ces endpoints sont publics et non authentifiés. Un auditeur, un client ou une place de marché peut les appeler directement.
| Endpoint | Ce qu'il renvoie |
|---|---|
| GET /passport/{id} | Le passeport numérique publié, filtré selon le niveau d'accès ESPR (public par défaut). |
| GET /passport/{id}/proof | Le bloc de preuves : empreinte SHA-256, copie IPFS si épinglée, référence on-chain avec sa portée, statut de l'attestation. |
| GET /passport/{id}/verify | Le contrôle d'intégrité : comparaison entre l'empreinte stockée, l'empreinte recalculée et la copie IPFS. |
| GET /passport/{id}/vc/verify | La vérification de la signature SD-JWT-VC contre la clé publiée de la marque. |
| GET /verify/merkle/{id} | La preuve d'inclusion de Merkle : feuille, index, nœuds frères, racine ancrée et lien BaseScan. |
| GET /certificate/{id} | Le certificat d'authenticité public, également disponible en PDF. |
| GET /resolve/{id} | La vue consolidée : produit, certificat, passeport, événements et ancrage. |
| GET /01/{gtin}/21/{serial} | Le résolveur GS1 Digital Link : d'un GTIN et d'un numéro de série vers le passeport. |
| GET /brand/{id}/did.json | Le document DID de la marque (did:web) : les clés publiques de signature au format JsonWebKey2020. |
Base publique de l'API : api.sealtrust.io. Les mêmes routes existent aussi sous le préfixe /v1.
Plutôt qu'un schéma, voici une unité réellement émise et réellement ancrée sur Base mainnet. Suivez chaque lien : rien ne vous oblige à nous croire sur parole.
À lire avant de conclure quoi que ce soit
Le jeton, le lot et la transaction d'ancrage sont réels. Le contenu du passeport, lui, est une démonstration : la marque est un atelier fictif et le site de production n'existe pas. Cette unité illustre la mécanique de preuve, ce n'est pas un produit commercialisé.
Chaîne
Base mainnet · 8453
Feuilles du lot
3
Racine de Merkle
0x64ee41e6800f397208e0f319af87bf1db25eae99a8be594b7886aa980f4374d0
Transaction d'ancrage
0x0e74e132bc7c281a196fe5f9c24dd6673ee00a1068a01e0dafea748978b7ab6b
Contrat
0x9d55ad8b11bc883c454bdf16e9fe39b79620ce62
Empreinte d'UID (= token id)
0x9b724603fac23a6990fc86edda52af205c2785e85a62235632cc7e218fcb0f36
Le contrôle que nous vous invitons à refaire
Appelez l'endpoint de preuve : il renvoie la feuille de cette unité, son index et deux nœuds frères. Hachez-les deux à deux en keccak-256, paires triées, à la manière d'OpenZeppelin. Vous devez retomber exactement sur la racine ci-dessus, celle que porte la transaction on-chain. Pour cette unité, le token id est par ailleurs identique à l'empreinte de l'UID de la puce.
Ces valeurs ne sont pas des intentions : ce sont les constantes que lisent nos tâches planifiées, qui tournent en continu dans l'application.
| Donnée | Délai | Traitement |
|---|---|---|
| Adresses IP des journaux de scan et d'audit | 30 jours | Anonymisées : le dernier octet IPv4 est mis à zéro, les 80 derniers bits en IPv6. La tâche repasse deux fois par jour. |
| User-agents des journaux | 30 jours | Effacés. |
| Coordonnées de géolocalisation des scans | 90 jours | Dégradées à une décimale, soit une maille d'environ 11 km : la ville reste, le point précis disparaît. |
| Journaux d'authentification NFC | 365 jours | Supprimés. |
| Données de scan non étiquetées (apprentissage) | 365 jours | Supprimées. Seules les lignes étiquetées sont conservées pour le modèle, et leur géolocalisation est dégradée. |
| Journaux d'usage des clés API partenaires | 365 jours | Supprimés. |
| Journaux d'audit administrateur | 730 jours | Supprimés au bout de 24 mois. |
L'export des données (article 15) et l'effacement (article 17) sont deux endpoints authentifiés. L'effacement s'exécute immédiatement, sans délai de grâce, et propage l'anonymisation à travers une douzaine de tables : compte, transferts, produits, portefeuille, journaux de scan, newsletter, retours, rachats, déclarations de vol. Les jetons de session en cours sont révoqués dans la foulée.
Les pièces comptables restent dix ans au titre de l'obligation légale prévue par l'article 17(3)(b). L'historique on-chain n'est pas effaçable par nature. La clé du portefeuille custodial est conservée pour ne pas orphelin les actifs détenus : seul le lien avec votre identité est rompu. Les événements de cycle de vie d'un produit restent attachés au produit, plus à vous.
Les points sur lesquels un audit nous interroge en premier, énoncés avec leurs paramètres réels.
Paramètres appliqués : coût temporel 3, 64 Mio de mémoire, parallélisme 4. Les anciens condensats bcrypt sont ré-hachés en Argon2id de façon transparente à la première connexion réussie. Une adresse inconnue déclenche une vérification factice pour que le temps de réponse ne la trahisse pas.
Chaque rafraîchissement émet un nouveau jeton et invalide celui qui vient d'être présenté. Si un jeton déjà consommé revient, c'est le signe d'un vol : la session n'est pas seulement refusée, tous les jetons du compte sont révoqués d'un coup. Jeton d'accès valable 60 minutes, jeton de rafraîchissement 7 jours.
La clé de signature blockchain de la plateforme et les clés d'attestation propres à chaque marque sont générées dans AWS KMS et n'en sortent jamais : la signature s'effectue côté KMS. En production, le code refuse de signer si l'identifiant de clé KMS est absent. Les clés maîtresses NFC, elles, sont conservées chiffrées par KMS, jamais en clair au repos.
Cinq tentatives par couple adresse/IP sur une fenêtre de 15 minutes, plus un plafond de 25 tentatives par adresse tous IP confondus pour couper les attaques distribuées. Le double facteur TOTP est disponible, avec codes de secours à usage unique.
HSTS d'un an avec includeSubDomains et preload, politique de sécurité de contenu dont les scripts sont restreints par nonce et sans 'unsafe-inline'. Les styles en ligne restent autorisés. Protection anti-framing, nosniff. La limitation de débit s'applique par adresse IP sur la connexion, la vérification et la réinitialisation de mot de passe. Les seuils ne sont pas publiés : les donner reviendrait à indiquer la cadence à tenir pour rester en dessous.
Chaque changement passe un balayage de secrets sur l'intégralité de l'historique git. L'analyse de vulnérabilités des images de conteneur s'exécute à chaque version publiée, et l'audit des dépendances Python et Node à chaque modification de manifeste ainsi que toutes les nuits. Les actions tierces sont épinglées à un commit précis.
Une affirmation de cette page vous paraît fragile, ou vous en attendiez une que nous n'avons pas faite ? C'est exactement la conversation qui nous intéresse.