ms-ai-architect/tests/kb-update/test-governance-refs-reg-lint.test.mjs
Kjell Tore Guttormsen 9e5e4a338a fix(ms-ai-architect): RX-REG² nudifiers/CSAM Art. 5-forbud — caveatet KB-tillegg (verifisert, avventer OJ) [skip-docs]
Digital Omnibus legger til nytt Art. 5-forbud mot AI som genererer/manipulerer
NCII eller CSAM (nudifier-apper), anvendelse 2026-12-02. Substans + dato verifisert
mot EU-rådet 2026-06-29 + Gibson Dunn/Freshfields-analyser. Eksakt underpunkt +
boetenivaa kan ikke pinnes foer OJ — caveatet «avventer OJ», ingen fabrikkert (i)/figur.

- classification-methodology: caveat-notis under Art. 5-forbudstabellen
- ai-act-assessor: «8 forbudte praksiser» → «8 i kraft + nudifiers/CSAM avventer OJ»
- reg-lint seksjon #11 (2 tester): preventiv mekanisme (gap-disiplin)
2026-07-15 10:14:17 +02:00

348 lines
21 KiB
JavaScript

// tests/kb-update/test-governance-refs-reg-lint.test.mjs
// TDD for RX-REG-KB (kryssmodell-review 2026-07-09, replan §RX-REG-KB): the
// governance reference corpus carried EU AI Act errors that ground-truth
// verification (EUR-Lex CELEX:32024R1689, AI Act Explorer, regjeringen.no)
// confirmed as factually wrong. This lint is the *preventive mechanism*
// (gap-disiplin): once the surgical fixes land, these literals must never
// re-enter the corpus.
//
// Ground truth locked this session:
// - Art. 5(1) letters: (c) social scoring is NOT public-authority-limited;
// (d) crime-risk prediction by profiling; (e) untargeted facial-image
// scraping; (h) real-time RBI for law enforcement. The old table
// scrambled (c)/(d)/(e)/(h) and omitted scraping. (EUR-Lex art. 5(1).)
// - Art. 6(2): Annex III = high-risk MAIN RULE; Art. 6(3): narrow 4-condition
// exception; profiling ⇒ ALWAYS high-risk. The old decision tree inverted
// this (profiling as the sole trigger). (EUR-Lex art. 6(2)-(3).)
// - Art. 99 fines: (3) €35M/7 %; (4) incl. Art. 50 transparency (4)(g) €15M/3 %;
// (5) incorrect info €7,5M/1 %; (6) SMEs = «whichever is LOWER», NO separate
// reduced amounts. The old table put transparency at 7,5M/1,5 %, false-info
// at 1,5 %, and fabricated an SMB column. (EUR-Lex art. 99(3)-(6).)
// - Art. 49 registration timing = before placing on market / putting into
// service — NOT a fixed «fra august 2026». High-risk applicability deferred
// to 2027-12-02 (Annex III) / 2028-08-02 (Annex I) via Digital Omnibus.
// - Bokføringsloven § 13: 5 år (not «7 år»).
// - Nkom is the DESIGNATED coordinating market-surveillance authority
// (regjeringen besluttet) — «under etablering» is stale.
// - Digital Omnibus dropped any acceleration trigger → «fremskynde» must go.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
const pluginRoot = new URL('../../', import.meta.url);
const REF = 'skills/ms-ai-governance/references/responsible-ai/';
const read = (rel) => readFileSync(new URL(REF + rel, pluginRoot), 'utf8');
// Files in scope for this session's RX-REG-KB fixes.
const GOVERNANCE_FILES = [
'ai-act-classification-methodology.md',
'ai-act-compliance-guide.md',
'ai-act-conformity-assessment.md',
'ai-act-provider-obligations.md',
'ai-act-fria-template.md',
'ai-act-deployer-obligations.md',
];
// --- 0. Cross-file guards (apply to every governance ref) ---
test('no refuted Omnibus-acceleration claim survives anywhere', () => {
for (const f of GOVERNANCE_FILES) {
assert.ok(!/fremskynde/i.test(read(f)),
`${f}: «fremskynde» — the final Omnibus dropped the acceleration trigger`);
}
});
test('no stale «under etablering» authority phrasing survives (Nkom is designated)', () => {
for (const f of GOVERNANCE_FILES) {
assert.ok(!/under etablering/i.test(read(f)),
`${f}: «under etablering» — Nkom is the designated coordinating authority`);
}
});
// --- 1. Art. 5(1) prohibited-practices table (classification-methodology) ---
test('classification-methodology: Art. 5(1) letters are correctly assigned', () => {
const md = read('ai-act-classification-methodology.md');
// Forbidden: the old scrambled letter↔content pairings.
assert.ok(!md.includes('Sosial scoring av enkeltpersoner av offentlige myndigheter'),
'(c) social scoring is not limited to public authorities');
assert.ok(!md.includes('Sanntids biometrisk fjernidentifikasjon i offentlig rom (Art. 5(1)(d))'),
'real-time RBI is (h), not (d)');
assert.ok(!md.includes('Retrospektiv biometrisk identifikasjon uten lovhjemmel'),
'(e) is untargeted facial-image scraping, not retrospective ID');
assert.ok(!/basert på profiling \(Art\. 5\(1\)\(h\)\)/.test(md),
'crime prediction by profiling is (d), not (h)');
// Required: the correct pairings + the missing scraping row.
assert.ok(/skraping av ansiktsbilder/i.test(md), '(e) scraping row must exist');
assert.ok(/profilering \(Art\. 5\(1\)\(d\)\)/.test(md), '(d) crime-risk prediction by profiling');
assert.ok(/rettshåndhevelse \(Art\. 5\(1\)\(h\)\)/.test(md), '(h) real-time RBI for law enforcement');
});
// --- 2. Art. 6(2)/(3) high-risk classification (compliance-guide decision tree) ---
test('compliance-guide: Annex III is high-risk by default (Art. 6(2)/(3))', () => {
const md = read('ai-act-compliance-guide.md');
assert.ok(md.includes('Art. 6(2)'), 'Annex III = high-risk main rule (Art. 6(2))');
assert.ok(md.includes('Art. 6(3)'), 'narrow exception cited (Art. 6(3))');
});
// --- 3. Art. 99 administrative fines (compliance-guide) ---
test('compliance-guide: Art. 99 fine figures are correct + SMB rule cited', () => {
const md = read('ai-act-compliance-guide.md');
// Forbidden: wrong transparency %, wrong false-info %, fabricated SMB column.
assert.ok(!/1,5\s?%/.test(md), 'no 1,5 % anywhere (transparency=3 %, false-info=1 %)');
assert.ok(!/0,6\s?%/.test(md), 'no fabricated SMB 0,6 %');
assert.ok(!/0,3\s?%/.test(md), 'no fabricated SMB 0,3 %');
// Required: Art. 99(6) SMB rule = «whichever is lower».
assert.ok(md.includes('Art. 99(6)'), 'SMB rule Art. 99(6) must be cited');
assert.ok(/laveste/i.test(md), 'SMB = «whichever thereof is lower»');
});
// --- 4. AI Act applicability dates (compliance-guide): no stale «august 2026» ---
test('compliance-guide: no stale «august 2026» high-risk applicability strings', () => {
const md = read('ai-act-compliance-guide.md');
assert.ok(!/2\.?\s*august 2026:\*\* Providers må registrere/.test(md),
'registration is Art. 49 timing, not a fixed aug-2026 date');
assert.ok(!/august 2027:\*\* Full compliance/.test(md), 'high-risk deferred to 2027-12-02');
assert.ok(!/fra aug\.? 2026/i.test(md), 'no «fra aug 2026» registration string');
assert.ok(!/\(påkrevd fra august 2026\)/.test(md), 'no «påkrevd fra august 2026»');
assert.ok(!/fra før august 2026/.test(md), 'transition cutoff = applicability date, not aug 2026');
assert.ok(!/Før august 2026: mindre press/.test(md), 'stale advisory date');
// Required: the corrected deferred date.
assert.ok(md.includes('2. desember 2027'), 'Annex III high-risk applies 2027-12-02');
});
// --- 5. Bokføringsloven retention (compliance-guide): 5 år, not 7 år ---
test('compliance-guide: log retention is 5 år (bokføringsloven § 13), not 7 år', () => {
const md = read('ai-act-compliance-guide.md');
assert.ok(!/7 år/.test(md), 'bokføringsloven § 13 = 5 år primær, not 7 år');
assert.ok(/5 år/.test(md), 'corrected retention present');
});
// --- 6. Nkom named in the three files that carried «under etablering» ---
for (const f of ['ai-act-provider-obligations.md', 'ai-act-fria-template.md', 'ai-act-deployer-obligations.md']) {
test(`${f}: names Nkom as designated authority`, () => {
assert.ok(read(f).includes('Nkom'), 'Nkom (koordinerende markedstilsynsmyndighet) must be named');
});
}
// --- 7. M13 article-number citations (EUR-Lex CELEX:32024R1689 / AI Act Explorer, verified 2026-07-15) ---
// Ground truth this session (RX-REG-KB Økt 2, cluster «artikkelnr.»):
// - Registration duty = Art. 49 ("Registration"). Art. 71 is the EU DATABASE entity
// ("EU Database for High-Risk AI Systems Listed in Annex III"). Lines describing the ACT
// of registering must cite Art. 49, not Art. 71.
// - Serious-incident reporting = Art. 73 ("Reporting of Serious Incidents"). Art. 72 is
// post-market monitoring — correct where it means monitoring, wrong for incidents.
// - Substantial modification: definition = Art. 3(23); new-conformity trigger = Art. 43(4).
// Art. 83 is "Formal non-compliance" — never a substantial-modification citation.
// - Annex III 5(c) = risk assessment & pricing in life and health insurance (5(d) = emergency dispatch).
// - Six-month log retention = Art. 19(1) ("Automatically generated logs"); Art. 12 is the
// record-keeping capability, not the retention duration.
test('conformity-assessment: registration act = Art. 49; substantial-mod def = Art. 3(23)', () => {
const md = read('ai-act-conformity-assessment.md');
assert.ok(!/\(Art\. 71\)/.test(md), 'registration act cites Art. 49, not the Art. 71 database entity');
assert.ok(!/substantial modification, Art\. 83\)/.test(md), 'substantial-mod definition = Art. 3(23), not Art. 83');
assert.ok(/\(Art\. 49\)/.test(md), 'Art. 49 registration citation present');
assert.ok(/Art\. 3\(23\)/.test(md), 'Art. 3(23) substantial-mod definition present');
});
test('microsoft-tools-mapping: serious incidents = Art. 73; registration = Art. 49', () => {
const md = read('ai-act-microsoft-tools-mapping.md');
assert.ok(!/\*\*Art\. 72\*\* Alvorlige hendelser/.test(md), 'serious incidents = Art. 73, not Art. 72');
assert.ok(!/alvorlig-hendelse-rapportering \(Art\. 72\)/.test(md), 'serious-incident reporting = Art. 73');
assert.ok(!/\(Art\. 71\)/.test(md), 'registration act = Art. 49, not Art. 71');
assert.ok(/Art\. 73/.test(md), 'Art. 73 serious-incident citation present');
});
test('transparency-notices: substantial-mod re-conformity = Art. 43(4)', () => {
const md = read('ai-act-transparency-notices.md');
assert.ok(!/"vesentlig" \(Art\. 83\)/.test(md), 're-conformity on substantial mod = Art. 43(4), not Art. 83');
assert.ok(/Art\. 43\(4\)/.test(md), 'Art. 43(4) present');
});
test('fria-template + deployer-obligations: insurance = Annex III 5(c), not 5(d)', () => {
for (const f of ['ai-act-fria-template.md', 'ai-act-deployer-obligations.md']) {
const md = read(f);
assert.ok(!/Annex III pkt\. 5\(d\)/.test(md), `${f}: life/health insurance = Annex III 5(c), not 5(d)`);
assert.ok(/Annex III pkt\. 5\(c\)/.test(md), `${f}: Annex III 5(c) present`);
}
});
test('provider-obligations: six-month log retention = Art. 19(1), not Art. 12', () => {
const md = read('ai-act-provider-obligations.md');
assert.ok(!/Art\. 12\(2\) krever minst 6 måneder/.test(md), 'retention duration = Art. 19(1), not Art. 12(2)');
assert.ok(!/6-måneder minimum \(Art\. 12\)/.test(md), '6-month minimum retention = Art. 19(1), not Art. 12');
assert.ok(/Art\. 19\(1\)/.test(md), 'Art. 19(1) retention citation present');
});
// --- 8. M13 applicability-date nuance (Digital Omnibus deferral, verified 2026-07-15) ---
// Ground truth (RX-REG-KB Økt 3, cluster «M13-frister»): the high-risk obligation
// package — conformity assessment (Art. 43), CE marking (Art. 48), EU-database
// registration (Art. 49) and record-keeping (Art. 12) — is deferred for stand-alone
// Annex III systems from 2026-08-02 to 2027-12-02 via the Digital Omnibus (adopted,
// pending OJ). Canonical: scripts/kb-update/data/ai-act-deadlines.json. Each file
// below already carries the corrected 2027-12-02 date elsewhere; the registration/
// CE/record-keeping lines must not contradict it with a hard «2. august 2026» deadline.
const readMon = (rel) =>
readFileSync(new URL('skills/ms-ai-governance/references/monitoring-observability/' + rel, pluginRoot), 'utf8');
test('conformity-assessment: Art. 49 registration is not a hard «2. august 2026» deadline', () => {
const md = read('ai-act-conformity-assessment.md');
assert.ok(!/obligatorisk fra 2\.?\s*august 2026/.test(md),
'registration = pre-market (Art. 49); high-risk applicability deferred to 2027-12-02');
assert.ok(/2\. desember 2027/.test(md), 'corrected deferred date present');
});
test('microsoft-tools-mapping: conformity/CE deadline is 2027-12-02, not «2. august 2026»', () => {
const md = read('ai-act-microsoft-tools-mapping.md');
assert.ok(!/\(FØR 2\.?\s*august 2026\)/.test(md), 'phase header must not present aug-2026 as the legal deadline');
assert.ok(!/fullført før 2\.?\s*august 2026/.test(md), 'CE/registration goal must not cite aug-2026 as deadline');
assert.ok(!/2\.?\s*august 2026 er den kritiske datoen/.test(md),
'critical date for conformity/CE = 2. desember 2027, not 2. august 2026');
assert.ok(/2\.?\s*des(?:ember)? 2027/.test(md), 'corrected deferred date present');
});
test('data-residency: Art. 12 record-keeping baseline reflects the deferred high-risk date', () => {
const md = readMon('data-residency-audit-monitoring.md');
assert.ok(!/enforcement starter 2026-08-02/.test(md),
'Art. 12 is a high-risk obligation deferred to 2027-12-02, not enforced from 2026-08-02');
assert.ok(/2027/.test(md), 'deferred date reference present');
});
// --- 9. M14 Norwegian ministry/agency names (verified 2026-07-15 against regjeringen.no) ---
// Ground truth (RX-REG-KB Økt 3 forts., cluster «M14 Nkom/dept/navn»):
// - National coordination of the AI Act (KI-forordningen) sits with
// Digitaliserings- og forvaltningsdepartementet (DFD) — the ministry that sent
// the KI-loven to public hearing — NOT Nærings- og fiskeridepartementet.
// (regjeringen.no: «Lov om kunstig intelligens ... sendes nå på høring».)
// - Nkom is the DESIGNATED coordinating national market-surveillance authority
// and contact point (regjeringen besluttet) — conformity's «Norge har ikke ...
// utpekt» + its Nkom-omitting authority list are stale.
// - Digdir's national arena is officially «KI Norge», not «AI Norge».
// (digdir.no/kunstig-intelligens/digdir-etablerer-ki-norge/7412.)
// - The 2020 AI strategy's launching ministry (Kommunal- og moderniseringsdep.)
// is today Digitaliserings- og forvaltningsdepartementet — no ministry was ever
// named just «Digitaliseringsdepartementet».
const readGov = (rel) =>
readFileSync(new URL('skills/ms-ai-governance/references/norwegian-public-sector-governance/' + rel, pluginRoot), 'utf8');
test('provider-obligations: AI Act national coordination = DFD, not Nærings- og fiskeridep.', () => {
const md = read('ai-act-provider-obligations.md');
assert.ok(!/Nærings- og fiskeridepartementet koordinerer/.test(md),
'coordination sits with Digitaliserings- og forvaltningsdepartementet (DFD)');
assert.ok(/Digitaliserings- og forvaltningsdepartementet/.test(md), 'DFD named as coordinating ministry');
});
test('conformity-assessment: Nkom named as designated coordinating authority (not «uavklart»)', () => {
const md = read('ai-act-conformity-assessment.md');
assert.ok(!/Norge har ikke per 2026-02 utpekt/.test(md),
'Nkom is the designated coordinating market-surveillance authority');
assert.ok(/\bNkom\b/.test(md), 'Nkom must be named in the Norwegian-context authority section');
});
test('no «AI Norge» misnomer survives — official Digdir name is «KI Norge»', () => {
for (const [reader, f] of [[readGov, 'norge-ai-strategy-government.md'], [read, 'ai-act-compliance-guide.md']]) {
assert.ok(!/AI Norge/.test(reader(f)), `${f}: official name is «KI Norge», not «AI Norge»`);
}
assert.ok(/KI Norge/.test(readGov('norge-ai-strategy-government.md')), 'KI Norge present');
});
test('norge-ai-strategy: 2020-strategy successor ministry = Digitaliserings- og forvaltningsdep.', () => {
const md = readGov('norge-ai-strategy-government.md');
assert.ok(!/nå Digitaliseringsdepartementet/.test(md),
'current successor is Digitaliserings- og forvaltningsdepartementet (DFD)');
assert.ok(/Digitaliserings- og forvaltningsdepartementet/.test(md), 'DFD full name present');
});
// --- 10. RX-REG-KB deferred Økt 1 (verified 2026-07-15 against EUR-Lex CELEX:32024R1689,
// regjeringen.no id3093081 26.03.2025, and Lovdata) ---
// Ground truth this session (deferred cluster from Økt 1, each claim independently sourced):
// - Art. 49(3): deployers that are PUBLIC AUTHORITIES (or Union institutions/bodies)
// shall register themselves, select the system and register its use in the EU
// database — the checklist «kun provider» omitted this. (EUR-Lex art. 49(1) provider
// / 49(3) public-authority deployer.)
// - Art. 48(2): high-risk AI provided DIGITALLY uses a digital CE marking; the CE-marking
// duty is triggered by high-risk classification, not by delivery model. «Gjelder ikke
// SaaS» is false, and CE marking (Art. 48) is distinct from EU-database registration
// (Art. 49). (EUR-Lex art. 48(1)-(2).)
// - Nkom is the DESIGNATED coordinating market-surveillance authority + national single
// point of contact (regjeringen besluttet, id3093081 26.03.2025) — «Nkom som kandidat»
// and «fremtidig Nasjonal AI-tilsynsmyndighet» are stale.
// - Public-sector log retention beyond 6 months follows norsk ARKIVLOVGIVNING (arkivlova
// LOV-2025-06-20-96, bevaringsforskrifta), NOT forvaltningsloven; the «3-10 år» figure
// is unsourced — retention is set per documentation type / by Nasjonalarkivet.
test('compliance-guide: EU-database registration covers Art. 49(3) public-authority deployers', () => {
const md = read('ai-act-compliance-guide.md');
assert.ok(!/\*\*EU database registration\*\* — kun provider/.test(md),
'Art. 49(3): public-authority deployers must also register — not «kun provider»');
assert.ok(/Art\. 49\(3\)/.test(md), 'Art. 49(3) public-authority deployer registration cited');
});
test('compliance-guide: CE marking (Art. 48) applies to digitally-provided high-risk AI', () => {
const md = read('ai-act-compliance-guide.md');
assert.ok(!/Gjelder ikke SaaS-tjenester fra Microsoft/.test(md),
'digital CE marking (Art. 48(2)) applies to high-risk AI provided digitally, incl. SaaS');
assert.ok(/Art\. 48\(2\)/.test(md), 'digital CE marking Art. 48(2) cited');
assert.ok(/digital CE-merking/i.test(md), 'digital CE-marking concept present');
});
test('classification-methodology: Nkom named as designated authority, not «kandidat»/«fremtidig»', () => {
const md = read('ai-act-classification-methodology.md');
assert.ok(!/Nkom som kandidat/.test(md), 'Nkom is designated, not «kandidat»');
assert.ok(!/fremtidig Nasjonal AI-tilsynsmyndighet/.test(md),
'Nkom is the designated coordinating authority, not «fremtidig»');
assert.ok(/\bNkom\b/.test(md), 'Nkom named');
});
test('provider-obligations: extended log retention cites arkivlovgivning, not «forvaltningsloven … 3-10 år»', () => {
const md = read('ai-act-provider-obligations.md');
assert.ok(!/3-10 år avhengig av sakstype/.test(md), '«3-10 år» is unsourced/misattributed');
assert.ok(!/forvaltningsloven for offentlig sektor i Norge/.test(md),
'retention follows arkivlovgivning (arkivlova/bevaringsforskrifta), not forvaltningsloven');
assert.ok(/arkivlova/i.test(md), 'arkivlova cited as the retention basis');
});
// --- 11. RX-REG² — new Art. 5 nudifiers/NCII/CSAM prohibition (Digital Omnibus,
// adopted, PENDING OJ; verified 2026-07-15 against the EU Council
// 2026-06-29 final-green-light press release + Gibson Dunn / Freshfields
// Omnibus analyses) ---
// Ground truth this session: the Digital Omnibus adds a new Art. 5 prohibited
// practice against AI that generates or manipulates non-consensual intimate
// imagery (NCII) or child sexual abuse material (CSAM) — "nudifier" apps. Both
// placing on market AND use are banned; for providers it extends to reasonably
// foreseeable, reproducible generation without significant technical modification
// where adequate safeguards are absent. Safe harbour for effective preventive
// safeguards, consent-based intimate content, lawful CSAM detection/moderation,
// and underlying-capability development. Application from 2026-12-02.
// The EXACT Art. 5 subparagraph AND the fine tier cannot be pinned pre-OJ — the
// KB must caveat them («avventer OJ»), never fabricate a letter or a figure.
// Canonical machine note: scripts/kb-update/data/ai-act-deadlines.json (pending_oj).
test('classification-methodology: carries the Omnibus nudifiers/NCII/CSAM Art. 5 prohibition, correctly caveated', () => {
const md = read('ai-act-classification-methodology.md');
assert.ok(/nudifier/i.test(md), 'nudifier apps named');
assert.ok(/NCII|ikke-samtykkebasert intimt innhold/i.test(md), 'NCII / non-consensual intimate content present');
assert.ok(/CSAM/.test(md), 'CSAM present');
assert.ok(/markedsplassering og bruk/.test(md), 'both placing-on-market and use are banned');
assert.ok(/2\. desember 2026/.test(md), 'application date 2026-12-02 present');
assert.ok(/avventer OJ|bekreftes mot OJ/i.test(md), 'exact subparagraph + fine tier caveated pending OJ');
// Pre-OJ we must NOT fabricate the final subparagraph letter or a fine figure.
assert.ok(!/Art\. 5\(1\)\(i\)/.test(md), 'exact Art. 5 subparagraph is pending OJ — do not assert (i)');
});
test('ai-act-assessor: Art. 5 check reflects the pending-OJ nudifiers prohibition, not a closed «8»', () => {
const md = readFileSync(new URL('agents/ai-act-assessor.md', pluginRoot), 'utf8');
assert.ok(!/de 8 forbudte praksisene/.test(md),
'Art. 5 list = 8 in-force + nudifiers/CSAM pending OJ — not a closed «8 forbudte praksiser»');
assert.ok(/nudifiers|CSAM/i.test(md), 'assessor names the pending-OJ prohibition');
assert.ok(/avventer OJ/i.test(md), 'assessor caveats it as pending OJ');
});