Aller au contenu principal

Explorateur de reçus

Examinez l’enregistrement. Essayez de modifier une valeur.

Un exemple neutre sur des valeurs synthétiques. Votre navigateur recalcule trois empreintes à partir du fichier — l’empreinte d’entrée, l’empreinte de sortie et l’empreinte de l’événement de preuve précédent — sans clé. Modifiez une valeur et la ligne qui en dépend affiche une discordance. Le reçu reste dans votre navigateur.

Échantillon synthétique

Ce qui a été recalculé
Calcul en cours…
Empreinte d’entrée
—Calcul en cours…
Empreinte de sortie
—Calcul en cours…
Empreinte de preuve
—Calcul en cours…

Modifiez n’importe quelle valeur : les trois contrôles suivent pendant que vous tapez.

Exemple de reçu au format de production : valeurs synthétiques, aucune interaction réelle.

Ce qu’Audact a contrôlé

Tel qu’enregistré dans ce fichier d’exemple : lu, non recalculé.

Décision
—
Version de la politique
—
Version de la configuration
—
Entrée et sortie
Enregistrées sous forme d’empreintes, pas de mots

Ce que vous pouvez recalculer

Trois valeurs, sans clé, dans votre propre navigateur.

  • Empreinte d’entréeCalcul en cours…

    SHA-256 sur le texte UTF-8 brut de sample_texts.input.

    Recalculé ici
    —
    Dans le reçu
    —
  • Empreinte de sortieCalcul en cours…

    SHA-256 sur le texte UTF-8 brut de sample_texts.output. Règle de verdict (F21) : ALLOW : la sortie est égale à l’entrée ; MODIFY ou BLOCK : la sortie diffère.

    Recalculé ici
    —
    Dans le reçu
    —
  • Empreinte de preuveCalcul en cours…

    SHA-256 sur la préimage de preceding_event, délimitée par des barres verticales : event_id, call_id, sequence, event_type, timestamp, canonicalJSON(data), previous_hash.

    Recalculé ici
    —
    Dans le reçu
    —

Ce qui demande une autre preuve

Une empreinte qui concorde montre que le fichier est cohérent avec lui-même. Ces quatre questions demandent autre chose.

  • Qui l’a émisÉmetteur non établi

    Le code d’authentification (HMAC-SHA256) exige la clé symétrique détenue par Audact, et quiconque peut le contrôler peut aussi le produire.

  • Inclusion dans une racine de MerkleInclusion Merkle non contrôlée

    Ce fichier d’exemple ne porte aucune preuve d’inclusion. Pour un appel réel, la preuve figure dans son rapport de l’article 50 et se confronte à la racine publiée.

  • L’export dans son ensembleAbsent de ce reçu

    La signature ECDSA-P256 appartient à un conteneur d’export, avec sa clé publique à /v1/keys/{kid}. Un reçu isolé ne la porte pas.

  • Si le résultat métier a eu lieuRésultat métier non établi

    Un paiement, un remboursement ou une réservation est confirmé par le système qui l’exécute, pas par un reçu.

Ou modifiez vous-même une valeur : la ligne qui en dépend cesse de concorder.

Sans cette page

Les mêmes trois contrôles dans un terminal.

Les mêmes trois contrôles dans un terminal. Il affiche trois fois ok sur ce fichier.

La forme canonique est la partie que l’on oublie : deux textes JSON qui veulent dire la même chose peuvent être des octets différents, et alors les empreintes diffèrent alors que rien n’a changé. Clés triées, sans espaces — c’est l’ordre RFC 8785 pour les types de valeurs de ce fichier (chaînes de caractères et entiers). Il est détaillé à /sample-receipt-readme.txt, avec les trois recalculs et ce qui ne peut pas être contrôlé.

import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
const r = JSON.parse(readFileSync("sample-receipt.json", "utf8"));
const sha = (s) => createHash("sha256").update(s).digest("hex");
// Canonical form: RFC 8785 (JCS), prefixed `audact-receipt-version:<receipt_format_version>\n` for the authentication code.
const canon = (v) => {
  if (v === null || typeof v !== "object") return JSON.stringify(v) ?? "null";
  if (Array.isArray(v)) return "[" + v.map(canon).join(",") + "]";
  const keys = Object.keys(v).sort();
  return "{" + keys.map((k) => JSON.stringify(k) + ":" + canon(v[k])).join(",") + "}";
};
const e = r.preceding_event;
const evidenceHash = sha(
  [e.event_id, e.call_id, e.sequence, e.event_type, e.timestamp, canon(e.data), e.previous_hash].join("|")
);
const results = [
  ["input_hash",    sha(r.sample_texts.input),  r.receipt.input_hash],
  ["output_hash",   sha(r.sample_texts.output), r.receipt.output_hash],
  ["evidence_hash", evidenceHash,               r.receipt.evidence_hash],
].map(([name, got, want]) => { console.log(`${got === want ? "ok  " : "FAIL"} ${name}`); return [name, got === want]; });
process.exitCode = results.every(([, ok]) => ok) ? 0 : 1;

Où cela s’inscrit

Un reçu est ce qu’une interaction encadrée laisse derrière elle.

Pour les interactions encadrées, un reçu est visible dans le produit : une empreinte de ce qui est entré, une empreinte de ce qui a été libéré, le verdict, la version de la politique et l’empreinte de l’événement de preuve précédent. La chaîne est en ajout seul ; une modification ou un réordonnancement ultérieur apparaît quand la chaîne est recalculée par rapport à l’engagement stocké.

L’article 50 du règlement (UE) 2024/1689 sur l’intelligence artificielle (AI Act) s’applique depuis le 2 août 2026. C’est une obligation de transparence : les personnes sont informées qu’elles ont affaire à un système d’IA. La chaîne de preuves permet de montrer, après coup, le texte d’information approuvé et le moment où l’envoi de son audio s’est terminé, la version de la politique en vigueur et la décision — l’entrée et la sortie étant stockées sous forme d’empreintes plutôt que de mots.

Suite

Ce que montre chaque contrôle — et ce qu’il ne montre pas.

Sept contrôles côte à côte : les empreintes de l’exemple, le HMAC du reçu, les racines de Merkle, l’horodatage RFC 3161, C2PA, le résultat externe et l’export signé.