Files
breakpilot-compliance/admin-compliance/lib/sdk/drafting-engine/allowed-facts-v2.ts
Benjamin Boenisch 06711bad1c
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 44s
CI / test-python-backend-compliance (push) Successful in 37s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 20s
feat(sdk,iace): add Personalized Drafting Pipeline v2 and IACE engine
Drafting Engine: 7-module pipeline with narrative tags, allowed facts governance,
PII sanitizer, prose validator with repair loop, hash-based cache, and terminology
guide. v1 fallback via ?v=1 query param.

IACE: Initial AI-Act Conformity Engine with risk classifier, completeness checker,
hazard library, and PostgreSQL store for AI system assessments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:27:06 +01:00

86 lines
3.0 KiB
TypeScript

/**
* Allowed Facts v2 Adapter — Baut AllowedFacts aus DraftContext
*
* Die Haupt-AllowedFacts Datei (allowed-facts.ts) erwartet SDKState,
* aber in der Draft API Route haben wir nur DraftContext.
* Dieser Adapter ueberbrueckt die Luecke.
*
* Re-exportiert auch die Serialisierungs-/Validierungsfunktionen.
*/
import type { AllowedFacts, FactPolicy } from './allowed-facts'
import {
DEFAULT_FACT_POLICY,
allowedFactsToPromptString,
disallowedTopicsToPromptString,
checkForDisallowedContent,
} from './allowed-facts'
import type { NarrativeTags } from './narrative-tags'
import type { DraftContext } from './types'
// Re-exports
export { allowedFactsToPromptString, disallowedTopicsToPromptString, checkForDisallowedContent }
/**
* Baut AllowedFacts aus einem DraftContext (API Route Kontext).
* Der DraftContext hat bereits projizierte Firmendaten.
*/
export function buildAllowedFactsFromDraftContext(
context: DraftContext,
narrativeTags: NarrativeTags
): AllowedFacts {
const profile = context.companyProfile
return {
companyName: profile.name || 'Unbekannt',
legalForm: '', // Nicht im DraftContext enthalten
industry: profile.industry || '',
location: '', // Nicht im DraftContext enthalten
employeeCount: profile.employeeCount || 0,
teamStructure: deriveTeamStructure(profile.employeeCount),
itLandscape: deriveItLandscape(profile.businessModel, profile.isPublicSector),
specialFeatures: deriveSpecialFeatures(profile),
triggeredRegulations: deriveRegulations(context),
primaryUseCases: [], // Nicht im DraftContext enthalten
narrativeTags,
}
}
// ============================================================================
// Private Helpers
// ============================================================================
function deriveTeamStructure(employeeCount: number): string {
if (employeeCount > 500) return 'Konzernstruktur'
if (employeeCount > 50) return 'mittelstaendisch'
return 'Kleinunternehmen'
}
function deriveItLandscape(businessModel: string, isPublicSector: boolean): string {
if (businessModel?.includes('SaaS') || businessModel?.includes('Cloud')) return 'Cloud-First'
if (isPublicSector) return 'On-Premise'
return 'Hybrid'
}
function deriveSpecialFeatures(profile: DraftContext['companyProfile']): string[] {
const features: string[] = []
if (profile.isPublicSector) features.push('Oeffentlicher Sektor')
if (profile.employeeCount > 250) features.push('Grossunternehmen')
if (profile.dataProtectionOfficer) features.push('Interner DSB benannt')
return features
}
function deriveRegulations(context: DraftContext): string[] {
const regs = new Set<string>(['DSGVO'])
const triggers = context.decisions.hardTriggers || []
for (const t of triggers) {
if (t.id.includes('ai_act') || t.id.includes('ai-act')) regs.add('AI Act')
if (t.id.includes('nis2') || t.id.includes('NIS2')) regs.add('NIS2')
if (t.id.includes('ttdsg') || t.id.includes('TTDSG')) regs.add('TTDSG')
}
return Array.from(regs)
}