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
112 lines
3.6 KiB
TypeScript
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);
|
|
});
|
|
});
|