<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: David Julian Rizo Lopez</title>
    <description>The latest articles on DEV Community by David Julian Rizo Lopez (@davidjulian_rl).</description>
    <link>https://dev.to/davidjulian_rl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4012817%2Fb55efb76-f077-4bef-8407-99d92a9c67ec.png</url>
      <title>DEV Community: David Julian Rizo Lopez</title>
      <link>https://dev.to/davidjulian_rl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidjulian_rl"/>
    <language>en</language>
    <item>
      <title>The gap EU AI Act Article 12 leaves open</title>
      <dc:creator>David Julian Rizo Lopez</dc:creator>
      <pubDate>Thu, 02 Jul 2026 22:13:30 +0000</pubDate>
      <link>https://dev.to/davidjulian_rl/the-gap-eu-ai-act-article-12-leaves-open-4k4f</link>
      <guid>https://dev.to/davidjulian_rl/the-gap-eu-ai-act-article-12-leaves-open-4k4f</guid>
      <description>&lt;p&gt;It's late 2026. An AI system at a European lender rejected a consumer's loan application back in April. The applicant has complained, and a supervisor is now asking a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Show me what the system decided, on what basis — and prove this record hasn't been altered since it was created.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You reach for your logs. And you find the uncomfortable truth: you have plenty of logs, and none of them answer the question.&lt;/p&gt;

&lt;h2&gt;
  
  
  The logs you have are the wrong logs
&lt;/h2&gt;

&lt;p&gt;Most AI deployments produce two kinds of logs. Application logs record API calls and latency. Inference logs record the model's input and output tokens. Both are useful for debugging. Neither captures the thing a regulator, an auditor, or a court actually asks about: &lt;strong&gt;the decision&lt;/strong&gt; — who decided, under what authority, on what basis, and what happened next.&lt;/p&gt;

&lt;p&gt;EU AI Act Article 12 requires high-risk AI systems to automatically record events over the system's lifetime. Credit scoring, hiring, insurance pricing, and benefits decisions fall under Annex III, and the high-risk obligations are landing across 2026 and 2027. Deployers must retain those logs for at least six months — longer in finance, where they fold into existing record-keeping law.&lt;/p&gt;

&lt;p&gt;Here is the gap. Article 12 is precise about the &lt;em&gt;objective&lt;/em&gt; and almost silent on the &lt;em&gt;mechanics&lt;/em&gt;. It does not specify a format. It does not say who is responsible for integrity. And it does not use the word &lt;strong&gt;tamper-evident&lt;/strong&gt;. But consider what a log is worth as evidence if it can be silently edited after the fact. If the same system that made the decision also writes — and can rewrite — the record of it, then the record is just a story the system tells about itself. Its evidentiary value is close to zero.&lt;/p&gt;

&lt;p&gt;A log says &lt;em&gt;"trust me, this is what happened."&lt;/em&gt; Evidence says &lt;em&gt;"you don't have to trust me — here's the proof."&lt;/em&gt; That difference is the whole problem, and it is under-served.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a decision record looks like when it's built to be proven
&lt;/h2&gt;

&lt;p&gt;There is a well-understood way to close this gap, borrowed from how the web secures itself (Certificate Transparency, RFC 6962) and how transparency logs prove integrity: keep the records append-only, hash each complete record into a Merkle tree — with the record's position in the log bound &lt;em&gt;inside&lt;/em&gt; the hashed leaf, so nothing can be reordered or rewritten silently — and let anyone verify any single record against a small published root, without trusting the party that produced it. Change one byte of one record and the math stops adding up. Tampering becomes visible, automatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb5g7m0mqf0g6cvcs2a9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb5g7m0mqf0g6cvcs2a9o.png" alt="Decision record flow: a decision and outcome are recorded in an append-only log, anchored in a Merkle checkpoint, and checked by an inclusion proof — an unchanged record verifies, an edited record fails" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Open Decision Standard (ODS)&lt;/strong&gt; applies exactly this to &lt;em&gt;decisions&lt;/em&gt;. Below is the real output of a ~250-line, dependency-free reference demo. It records a credit-scoring rejection, anchors it, proves it — and then tampers with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1] DECISION recorded
    record_id : loan-2026-04-19-0098
    authority : policy_hash 58f7a207e5617d78… (which rules governed)
    rationale : DTI 0.58 exceeds 0.45 ceiling; thin file; 2 recent delinquencies.
    action    : REJECT (score 0.31 &amp;lt; 0.5)
    seq #1  merkle_leaf 5932912a087cba70… (SHA-256 over the canonical stored record)

[2] OUTCOME recorded (linked to the decision, append-only)
    parent_id : loan-2026-04-19-0098
    seq #2  (append-only; its sequence_number fixes its position in the Merkle log)

[3] CHECKPOINT — Merkle root over all records (the anchor a regulator keeps)
    tree_size   : 2
    merkle_root : f930c641be518ffde1b3e56553ac2c05a76ec7a674f162044d2da21b7ed68aab

[4] INCLUSION PROOF for the decision record
    verifies against the checkpoint root: True  &amp;lt;- provable, not asserted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(The hash values differ on each run — records are timestamped — so what reproduces is the behaviour, not the exact digits: the proof verifies.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Notice what the decision record holds that an inference log never does: the &lt;strong&gt;authority&lt;/strong&gt; the decision ran under (a hash of the governing policy), the &lt;strong&gt;rationale&lt;/strong&gt;, the &lt;strong&gt;action&lt;/strong&gt;, and — appended right after it, linked by &lt;code&gt;parent_id&lt;/code&gt; — the &lt;strong&gt;outcome&lt;/strong&gt;. Each record's store-assigned sequence number lives inside the hashed leaf, so its position in the log is part of what gets proven. That is the accountability layer, captured as a record instead of reconstructed from fragments after the fact.&lt;/p&gt;

&lt;p&gt;Now the part that matters. Someone edits the stored decision — quietly flips the rejection to an approval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[5] Now someone quietly edits the stored decision: REJECT -&amp;gt; APPROVE
    leaf recomputed over the edited stored record
    integrity check       : FAIL — edit changed the leaf; proof no longer matches the root
    inclusion proof now   : FAILS against the regulator-held root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no separate integrity field to forge: the canonical stored record &lt;em&gt;is&lt;/em&gt; the leaf pre-image. The edit is mathematically visible. Anyone holding the checkpoint root — the regulator, the auditor, the applicant's lawyer — can detect it, without trusting the operator and without access to the rest of the records. The record became evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this sits
&lt;/h2&gt;

&lt;p&gt;The landscape is moving fast, and ODS is deliberately not trying to own all of it. The IETF and the Linux Foundation are building the agent-&lt;em&gt;identity&lt;/em&gt; and delegation-&lt;em&gt;provenance&lt;/em&gt; layers — which agent acted, under whose authorization. ODS is the layer above that: the verifiable record of &lt;em&gt;what was decided, on what basis, with what outcome.&lt;/em&gt; It is designed to interoperate with that emerging stack, not to replace it. Article 12 told everyone to keep records; it did not tell them how to make those records worth anything when someone finally asks. That is the gap ODS is built to fill.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run it, then tell me where it's wrong
&lt;/h2&gt;

&lt;p&gt;ODS is an open standard (Apache 2.0). The reference demo is intentionally tiny and has zero dependencies — Python 3.9+, stdlib only — so you can read every line and confirm there is no magic: just canonical records, domain-separated Merkle leaves (RFC 6962), and inclusion proofs applied to the events that carry accountability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/ODS-Foundation/ods-specification
cd ods-specification/examples/quickstart
python orpi_demo.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full schema, reference validator, and a conformance suite that certifies implementations against the standard — with honest, scope-qualified verdicts, so it never claims to prove more than it does — live in the same repository.&lt;/p&gt;

&lt;p&gt;If you work in AI governance, compliance, RegTech, or you build or buy high-risk AI in the EU: I would value your honest feedback. Run the demo and tell me where the model breaks, what prior art I'm missing, or where the threat model is wrong. That critique is more useful to the standard right now than agreement.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>mlops</category>
      <category>compliance</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
