shieldx/ai-act-kompass/src/engine/classify.test.ts
Claude fb2da0db00
feat: add AI-Act-Kompass — standalone EU AI Act compliance toolkit for SMEs
Local-first React/Vite app (no cloud, no telemetry, localStorage only):
- Assessment wizard classifying AI systems per AI Act systematics
  (Art. 3 definition, Art. 5 prohibitions, Art. 6/Annex I+III high-risk
  incl. Art. 6(3) exception and profiling bar, Art. 50 transparency, GPAI)
- Role-specific obligation checklists (provider/deployer/importer/distributor)
  with legal basis, deadlines and implementation status
- Document generator: risk report, action plan, Annex IV skeleton (Markdown)
- AI inventory with export, deadline overview incl. Digital Omnibus shift
- Versioned regulatory content pack modeled as data for future update feed
- Engine fully unit-tested (24 tests), TS strict, static build

Claude-Session: https://claude.ai/code/session_017YjohVNx1ZGNM4MX7tHpfv
2026-07-04 08:03:16 +00:00

112 lines
3.6 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { CONTENT_PACK } from '../content/pack';
import { classify } from './classify';
import type { AssessmentAnswers } from './types';
const base: AssessmentAnswers = {
isAISystem: true,
role: 'deployer',
isGPAIModel: false,
prohibitedPractices: [],
annexIIICategories: [],
art63Exception: false,
involvesProfiling: false,
isAnnexISafetyComponent: false,
transparencyTriggers: [],
};
describe('classify', () => {
it('stuft Nicht-KI-Systeme als out-of-scope ein', () => {
const result = classify({ ...base, isAISystem: false }, CONTENT_PACK);
expect(result.riskClass).toBe('out-of-scope');
expect(result.transparencyDuties).toBe(false);
});
it('stuft verbotene Praktiken als prohibited ein — vor allen anderen Prüfungen', () => {
const result = classify(
{
...base,
prohibitedPractices: ['proh-social-scoring'],
annexIIICategories: ['a3-employment'],
transparencyTriggers: ['tr-chatbot'],
},
CONTENT_PACK,
);
expect(result.riskClass).toBe('prohibited');
expect(result.reasons[0]).toContain('Art. 5');
});
it('stuft Annex-I-Sicherheitsbauteile als high ein', () => {
const result = classify({ ...base, isAnnexISafetyComponent: true }, CONTENT_PACK);
expect(result.riskClass).toBe('high');
});
it('stuft Annex-III-Bereiche als high ein', () => {
const result = classify({ ...base, annexIIICategories: ['a3-employment'] }, CONTENT_PACK);
expect(result.riskClass).toBe('high');
expect(result.reasons.some((r) => r.includes('Annex III'))).toBe(true);
});
it('lässt die Art.-6(3)-Ausnahme greifen, wenn kein Profiling vorliegt', () => {
const result = classify(
{ ...base, annexIIICategories: ['a3-employment'], art63Exception: true },
CONTENT_PACK,
);
expect(result.riskClass).toBe('minimal');
expect(result.art64DocumentationDuty).toBe(true);
});
it('schließt die Art.-6(3)-Ausnahme bei Profiling aus', () => {
const result = classify(
{
...base,
annexIIICategories: ['a3-employment'],
art63Exception: true,
involvesProfiling: true,
},
CONTENT_PACK,
);
expect(result.riskClass).toBe('high');
});
it('kombiniert Art.-6(3)-Ausnahme mit Transparenzpflichten zu limited', () => {
const result = classify(
{
...base,
annexIIICategories: ['a3-employment'],
art63Exception: true,
transparencyTriggers: ['tr-chatbot'],
},
CONTENT_PACK,
);
expect(result.riskClass).toBe('limited');
expect(result.transparencyDuties).toBe(true);
expect(result.art64DocumentationDuty).toBe(true);
});
it('stuft reine Transparenz-Auslöser als limited ein (Chatbot-Fall)', () => {
const result = classify({ ...base, transparencyTriggers: ['tr-chatbot'] }, CONTENT_PACK);
expect(result.riskClass).toBe('limited');
});
it('behält Transparenzpflichten bei Hochrisiko-Systemen bei', () => {
const result = classify(
{ ...base, annexIIICategories: ['a3-employment'], transparencyTriggers: ['tr-chatbot'] },
CONTENT_PACK,
);
expect(result.riskClass).toBe('high');
expect(result.transparencyDuties).toBe(true);
});
it('stuft Systeme ohne Auffälligkeiten als minimal ein', () => {
const result = classify(base, CONTENT_PACK);
expect(result.riskClass).toBe('minimal');
});
it('setzt das GPAI-Flag unabhängig von der Risikoklasse', () => {
const result = classify({ ...base, isGPAIModel: true }, CONTENT_PACK);
expect(result.riskClass).toBe('minimal');
expect(result.gpaiObligations).toBe(true);
});
});