shieldx/ai-act-kompass/src/engine/documents.test.ts
Claude cd31274738
feat(ai-act-kompass): i18n, national modules, task checklist, legal gate, new documents
- Full i18n (DE/EN): UI, rules engine, content pack and generated
  documents; language switcher, browser-language default, architecture
  extensible to further EU languages via localized source texts
- National country modules (opt-in per company profile): DE (KI-MIG/
  BNetzA supervision, works council co-determination Sec. 87 BetrVG,
  GDPR/BDSG), AT (RTR AI service desk), IT (Law 132/2025: employer info
  duty, deepfake criminal liability, sector decrees), ES (AESIA,
  sandbox RD 817/2023), FR (CNIL guidance), NL (algorithm register);
  merged into obligation derivation, checklists and documents
- New EU obligations: corrective actions (Art. 20/21), authorised
  representative (Art. 22), EU database registration for public-body
  deployers (Art. 49(3)), post-market monitoring (Art. 72), serious
  incident reporting (Art. 73), GDPR DPIA (Art. 35 GDPR / 26(9))
- New documents: AI procurement requirements specification (MUST/SHOULD
  matrix for vendors) and EU declaration of conformity draft (Annex V)
- Cross-system checkable task list (due now / upcoming / done) with
  progress bar, one-tap toggling, per-system links
- Legal safety: first-run acknowledgement gate (working aid, no legal
  services), legal notice panel in settings, result-screen disclaimer,
  disclaimers on every document
- Responsive layout for phone/tablet (top-bar nav, scrollable tables,
  larger tap targets)
- 12 new tests (44 total): EN pack parity, national merge, checklist
  grouping, new document generators

Claude-Session: https://claude.ai/code/session_017YjohVNx1ZGNM4MX7tHpfv
2026-07-04 09:18:07 +00:00

91 lines
3.2 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { CONTENT_PACK } from '../content/pack';
import { classify } from './classify';
import { actionPlan, annexIVSkeleton, inventoryReport, riskReport } from './documents';
import { deriveObligations } from './obligations';
import type { AISystem, AssessmentAnswers, CompanyProfile } from './types';
const answers: AssessmentAnswers = {
isAISystem: true,
role: 'provider',
isGPAIModel: false,
prohibitedPractices: [],
annexIIICategories: ['a3-employment'],
art63Exception: false,
involvesProfiling: true,
isAnnexISafetyComponent: false,
transparencyTriggers: ['tr-chatbot'],
};
const system: AISystem = {
id: 'sys-1',
name: 'HR-Screening',
purpose: 'Vorauswahl von Bewerbungen',
vendor: 'Beispiel GmbH',
owner: 'Jane Doe',
createdAt: '2026-07-01T00:00:00.000Z',
updatedAt: '2026-07-01T00:00:00.000Z',
answers,
classification: classify(answers, CONTENT_PACK),
obligationStatus: { 'ob-risk-mgmt': 'in-progress' },
};
const TODAY = '2026-07-04';
describe('documents', () => {
it('riskReport enthält Klassifizierung, Begründung und Disclaimer', () => {
const md = riskReport(system, CONTENT_PACK, TODAY);
expect(md).toContain('# Risikoklassifizierung');
expect(md).toContain('Hochrisiko');
expect(md).toContain('Annex III');
expect(md).toContain('keine Rechtsberatung');
expect(md).toContain(CONTENT_PACK.version);
});
it('actionPlan listet Pflichten mit Status und Frist', () => {
const obligations = deriveObligations(system.classification, answers, CONTENT_PACK);
const md = actionPlan(system, obligations, CONTENT_PACK, TODAY);
expect(md).toContain('Risikomanagementsystem');
expect(md).toContain('In Umsetzung');
expect(md).toContain('02.12.2027');
});
it('annexIVSkeleton befüllt bekannte Felder und markiert offene Punkte', () => {
const md = annexIVSkeleton(system, CONTENT_PACK, TODAY);
expect(md).toContain('Vorauswahl von Bewerbungen');
expect(md).toContain('_[AUSFÜLLEN]_');
expect(md).toContain('Annex IV');
});
it('inventoryReport listet alle Systeme tabellarisch', () => {
const md = inventoryReport([system], CONTENT_PACK, TODAY);
expect(md).toContain('HR-Screening');
expect(md).toContain('| System |');
expect(md).toContain('Registrierte KI-Systeme: **1**');
});
it('übernimmt das Firmenprofil in den Berichtskopf', () => {
const profile: CompanyProfile = {
name: 'Muster GmbH',
street: 'Musterstraße 1',
zipCity: '60311 Frankfurt',
contactPerson: 'Max Mustermann',
email: 'compliance@muster.de',
phone: '+49 69 000000',
website: 'www.muster.de',
logoDataUrl: '',
countries: [],
};
const md = riskReport(system, CONTENT_PACK, TODAY, profile);
expect(md).toContain('| **Unternehmen** | Muster GmbH |');
expect(md).toContain('compliance@muster.de');
expect(md).toContain('| **Ansprechpartner** | Max Mustermann |');
expect(inventoryReport([system], CONTENT_PACK, TODAY, profile)).toContain('Muster GmbH · Stand');
});
it('lässt den Berichtskopf ohne Profil unverändert', () => {
const md = riskReport(system, CONTENT_PACK, TODAY);
expect(md).not.toContain('**Unternehmen**');
});
});