fix(admin): resolve all 266 TypeScript errors, enable strict build
Eliminate the pre-existing TS errors that were masked by next.config.js `typescript.ignoreBuildErrors: true`, then turn the flag OFF so the compiler is a real safety net for future changes. `next build` and `tsc --noEmit` now pass with 0 errors. The errors were not cosmetic — several exposed real latent bugs hidden by the flag, e.g. the drafting-engine ConstraintEnforcer read non-existent fields (`t.rule.dsfaRequired`, `d.required`, `r.title`), so its DSFA hard gate and risk-flag checks were silently no-ops; scopeDefaults read snake_case CompanyProfile fields that never matched the camelCase type (generator defaults never populated). Both fixed by aligning code to the current types. Highlights: - Vitest globals: add vitest-globals.d.ts (config already had globals:true) so the test files type-check; exclude Playwright specs from vitest. - Add a minimal ambient `pg` module declaration (no @types/pg installed). - Fix Next 15 route handlers to await Promise params. - Reconcile drifted types across loeschfristen, compliance-scope, document- generator, drafting-engine, vendor-compliance, agent and more. Pre-existing (NOT caused here, proven by stashing the diff): 3 vitest logic tests still fail — getNextStep (2) and buildDocumentScope priority (1). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -152,7 +152,7 @@ const createMockState = (overrides: Partial<SDKState> = {}): SDKState => ({
|
||||
allowParallelWork: true,
|
||||
},
|
||||
...overrides,
|
||||
})
|
||||
} as unknown as SDKState)
|
||||
|
||||
describe('exportToPDF', () => {
|
||||
it('should return a Blob', async () => {
|
||||
|
||||
@@ -76,9 +76,9 @@ describe('parseRevenueRange', () => {
|
||||
// =============================================================================
|
||||
|
||||
describe('buildAssessmentPayload', () => {
|
||||
const baseProfile: CompanyProfile = {
|
||||
const baseProfile = {
|
||||
companyName: 'Test GmbH',
|
||||
legalForm: 'GmbH',
|
||||
legalForm: 'gmbh',
|
||||
industry: ['IT', 'Software'],
|
||||
employeeCount: '50-249',
|
||||
annualRevenue: '10-50 Mio',
|
||||
@@ -87,7 +87,7 @@ describe('buildAssessmentPayload', () => {
|
||||
isDataController: true,
|
||||
isDataProcessor: false,
|
||||
offerings: ['software_saas'],
|
||||
}
|
||||
} as unknown as CompanyProfile
|
||||
|
||||
const baseAnswers: ScopeProfilingAnswer[] = [
|
||||
{ questionId: 'data_art9', value: false, blockId: 'data' },
|
||||
@@ -115,7 +115,7 @@ describe('buildAssessmentPayload', () => {
|
||||
expect(payload.annual_revenue).toBe(30000000)
|
||||
expect(payload.country).toBe('DE')
|
||||
expect(payload.industry).toBe('IT, Software')
|
||||
expect(payload.legal_form).toBe('GmbH')
|
||||
expect(payload.legal_form).toBe('gmbh')
|
||||
expect(payload.is_controller).toBe(true)
|
||||
expect(payload.is_processor).toBe(false)
|
||||
expect(payload.cross_border_transfer).toBe(true)
|
||||
@@ -128,9 +128,9 @@ describe('buildAssessmentPayload', () => {
|
||||
})
|
||||
|
||||
it('uses defaults for null/undefined profile fields', () => {
|
||||
const emptyProfile: CompanyProfile = {
|
||||
const emptyProfile = {
|
||||
companyName: 'Minimal',
|
||||
}
|
||||
} as unknown as CompanyProfile
|
||||
const payload = buildAssessmentPayload(emptyProfile, [], null)
|
||||
|
||||
expect(payload.employee_count).toBe(10) // parseEmployeeRange(undefined)
|
||||
@@ -178,7 +178,7 @@ describe('buildAssessmentPayload', () => {
|
||||
const decision: ScopeDecision = {
|
||||
determinedLevel: 'L3',
|
||||
triggeredHardTriggers: [
|
||||
{ rule: { id: 'rule-1', name: 'Test Rule', description: '', targetLevel: 'L3', trigger: { field: '', op: 'eq', value: true } }, factValue: true },
|
||||
{ ruleId: 'rule-1', rule: { id: 'rule-1', name: 'Test Rule', description: '', targetLevel: 'L3', trigger: { field: '', op: 'eq', value: true } }, factValue: true },
|
||||
],
|
||||
requiredDocuments: [
|
||||
{ documentType: 'dsfa', reason: 'test', regulation: 'dsgvo' },
|
||||
|
||||
@@ -208,7 +208,7 @@ export class ComplianceScopeEngine {
|
||||
* Liest einen Wert aus dem MachineBuilderProfile anhand eines Feldnamens
|
||||
*/
|
||||
private getMachineBuilderValue(mb: MachineBuilderProfile, field: string): unknown {
|
||||
return (mb as Record<string, unknown>)[field]
|
||||
return (mb as unknown as Record<string, unknown>)[field]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,9 +269,9 @@ export class ComplianceScopeEngine {
|
||||
break
|
||||
case 'CONTAINS':
|
||||
if (Array.isArray(value)) {
|
||||
baseCondition = value.includes(rule.conditionValue)
|
||||
baseCondition = value.includes(rule.conditionValue as string)
|
||||
} else if (typeof value === 'string') {
|
||||
baseCondition = value.includes(rule.conditionValue)
|
||||
baseCondition = value.includes(rule.conditionValue as string)
|
||||
}
|
||||
break
|
||||
case 'IN':
|
||||
|
||||
@@ -163,7 +163,7 @@ export function prefillFromVVTAnswers(
|
||||
for (const [vvtQuestionId, vvtValue] of Object.entries(vvtAnswers)) {
|
||||
const scopeQuestionId = reverseMap[vvtQuestionId]
|
||||
if (scopeQuestionId) {
|
||||
answers.push({ questionId: scopeQuestionId, value: vvtValue })
|
||||
answers.push({ questionId: scopeQuestionId, value: vvtValue as string | number | boolean | string[] })
|
||||
}
|
||||
}
|
||||
return answers
|
||||
@@ -187,7 +187,7 @@ export function prefillFromLoeschfristenAnswers(
|
||||
for (const lfAnswer of lfAnswers) {
|
||||
const scopeQuestionId = reverseMap[lfAnswer.questionId]
|
||||
if (scopeQuestionId) {
|
||||
answers.push({ questionId: scopeQuestionId, value: lfAnswer.value })
|
||||
answers.push({ questionId: scopeQuestionId, value: lfAnswer.value as string | number | boolean | string[] })
|
||||
}
|
||||
}
|
||||
return answers
|
||||
|
||||
@@ -34,6 +34,8 @@ export interface ScopeDecision {
|
||||
createdAt: string;
|
||||
/** Zeitstempel letzte Änderung */
|
||||
updatedAt: string;
|
||||
/** Zeitstempel der Auswertung */
|
||||
evaluatedAt?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,6 +58,8 @@ export interface ScopeProfilingAnswer {
|
||||
questionId: string;
|
||||
/** Antwortwert (Typ abhängig von Fragentyp) */
|
||||
value: string | string[] | boolean | number;
|
||||
/** Optionaler Block-Kontext der Antwort */
|
||||
blockId?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import type { ScopeProfilingAnswer } from './questions'
|
||||
export type { ScopeProfilingAnswer } from './questions';
|
||||
import type { ScopeDecision } from './decisions'
|
||||
|
||||
/**
|
||||
@@ -15,6 +16,8 @@ export interface ComplianceScopeState {
|
||||
answers: ScopeProfilingAnswer[];
|
||||
/** Aktuelle Entscheidung (null wenn noch nicht berechnet) */
|
||||
decision: ScopeDecision | null;
|
||||
/** Zeitstempel letzte Aenderung */
|
||||
lastModified?: string;
|
||||
/** Zeitpunkt der letzten Evaluierung */
|
||||
lastEvaluatedAt: string | null;
|
||||
/** Sind alle Pflichtfragen beantwortet? */
|
||||
|
||||
@@ -48,6 +48,11 @@ export function generateDemoState(tenantId: string, userId: string): Partial<SDK
|
||||
annualRevenue: '2-10 Mio',
|
||||
headquartersCountry: 'DE',
|
||||
headquartersCity: 'Berlin',
|
||||
headquartersCountryOther: '',
|
||||
headquartersStreet: 'Beispielstrasse 1',
|
||||
headquartersZip: '10115',
|
||||
headquartersState: 'Berlin',
|
||||
offeringUrls: {},
|
||||
hasInternationalLocations: false,
|
||||
internationalCountries: [],
|
||||
targetMarkets: ['germany_only', 'dach'],
|
||||
|
||||
@@ -12,9 +12,9 @@ describe('ConstraintEnforcer', () => {
|
||||
scores: { risk_score: 50, complexity_score: 50, assurance_need: 50, composite_score: 50 },
|
||||
triggeredHardTriggers: [],
|
||||
requiredDocuments: [
|
||||
{ documentType: 'vvt', label: 'VVT', required: true, depth: 'Standard', detailItems: [], estimatedEffort: '2h', triggeredBy: [] },
|
||||
{ documentType: 'tom', label: 'TOM', required: true, depth: 'Standard', detailItems: [], estimatedEffort: '3h', triggeredBy: [] },
|
||||
{ documentType: 'lf', label: 'LF', required: true, depth: 'Basis', detailItems: [], estimatedEffort: '1h', triggeredBy: [] },
|
||||
{ documentType: 'vvt', label: 'VVT', requirement: 'mandatory' as const, priority: 'medium' as const, estimatedEffort: 2, triggeredBy: [] },
|
||||
{ documentType: 'tom', label: 'TOM', requirement: 'mandatory' as const, priority: 'medium' as const, estimatedEffort: 3, triggeredBy: [] },
|
||||
{ documentType: 'lf', label: 'LF', requirement: 'mandatory' as const, priority: 'medium' as const, estimatedEffort: 1, triggeredBy: [] },
|
||||
],
|
||||
riskFlags: [],
|
||||
gaps: [],
|
||||
@@ -66,7 +66,7 @@ describe('ConstraintEnforcer', () => {
|
||||
it('should warn but allow optional documents', () => {
|
||||
const decision = makeDecision({
|
||||
requiredDocuments: [
|
||||
{ documentType: 'vvt', label: 'VVT', required: true, depth: 'Standard', detailItems: [], estimatedEffort: '2h', triggeredBy: [] },
|
||||
{ documentType: 'vvt', label: 'VVT', requirement: 'mandatory' as const, priority: 'medium' as const, estimatedEffort: 2, triggeredBy: [] },
|
||||
],
|
||||
})
|
||||
const result = enforcer.check('dsfa', decision)
|
||||
@@ -115,18 +115,13 @@ describe('ConstraintEnforcer', () => {
|
||||
const decision = makeDecision({
|
||||
determinedLevel: 'L3',
|
||||
triggeredHardTriggers: [{
|
||||
rule: {
|
||||
id: 'HT-ART9',
|
||||
label: 'Art. 9 Daten',
|
||||
description: '',
|
||||
conditionField: '',
|
||||
conditionOperator: 'EQUALS' as const,
|
||||
conditionValue: null,
|
||||
minimumLevel: 'L3',
|
||||
mandatoryDocuments: ['dsfa'],
|
||||
dsfaRequired: true,
|
||||
legalReference: 'Art. 35 DSGVO',
|
||||
},
|
||||
ruleId: 'HT-ART9',
|
||||
category: '',
|
||||
description: 'Art. 9 Daten',
|
||||
minimumLevel: 'L3',
|
||||
requiresDSFA: true,
|
||||
mandatoryDocuments: ['dsfa'],
|
||||
legalReference: 'Art. 35 DSGVO',
|
||||
matchedValue: null,
|
||||
explanation: 'Art. 9 Daten verarbeitet',
|
||||
}],
|
||||
@@ -139,24 +134,19 @@ describe('ConstraintEnforcer', () => {
|
||||
const decision = makeDecision({
|
||||
determinedLevel: 'L3',
|
||||
triggeredHardTriggers: [{
|
||||
rule: {
|
||||
id: 'HT-ART9',
|
||||
label: 'Art. 9 Daten',
|
||||
description: '',
|
||||
conditionField: '',
|
||||
conditionOperator: 'EQUALS' as const,
|
||||
conditionValue: null,
|
||||
minimumLevel: 'L3',
|
||||
mandatoryDocuments: ['dsfa'],
|
||||
dsfaRequired: true,
|
||||
legalReference: 'Art. 35 DSGVO',
|
||||
},
|
||||
ruleId: 'HT-ART9',
|
||||
category: '',
|
||||
description: 'Art. 9 Daten',
|
||||
minimumLevel: 'L3',
|
||||
requiresDSFA: true,
|
||||
mandatoryDocuments: ['dsfa'],
|
||||
legalReference: 'Art. 35 DSGVO',
|
||||
matchedValue: null,
|
||||
explanation: '',
|
||||
}],
|
||||
requiredDocuments: [
|
||||
{ documentType: 'dsfa', label: 'DSFA', required: true, depth: 'Vollstaendig', detailItems: [], estimatedEffort: '8h', triggeredBy: [] },
|
||||
{ documentType: 'vvt', label: 'VVT', required: true, depth: 'Standard', detailItems: [], estimatedEffort: '2h', triggeredBy: [] },
|
||||
{ documentType: 'dsfa', label: 'DSFA', requirement: 'mandatory' as const, priority: 'medium' as const, estimatedEffort: 8, triggeredBy: [] },
|
||||
{ documentType: 'vvt', label: 'VVT', requirement: 'mandatory' as const, priority: 'medium' as const, estimatedEffort: 2, triggeredBy: [] },
|
||||
],
|
||||
})
|
||||
const result = enforcer.check('vvt', decision)
|
||||
@@ -169,9 +159,9 @@ describe('ConstraintEnforcer', () => {
|
||||
it('should note critical risk flags', () => {
|
||||
const decision = makeDecision({
|
||||
riskFlags: [
|
||||
{ id: 'rf-1', severity: 'CRITICAL', title: 'Offene Art. 9 Verarbeitung', description: '', recommendation: 'DSFA durchfuehren' },
|
||||
{ id: 'rf-2', severity: 'HIGH', title: 'Fehlende Verschluesselung', description: '', recommendation: 'TOM erstellen' },
|
||||
{ id: 'rf-3', severity: 'LOW', title: 'Dokumentation unvollstaendig', description: '', recommendation: '' },
|
||||
{ severity: 'CRITICAL', category: '', message: 'Offene Art. 9 Verarbeitung', recommendation: 'DSFA durchfuehren' },
|
||||
{ severity: 'HIGH', category: '', message: 'Fehlende Verschluesselung', recommendation: 'TOM erstellen' },
|
||||
{ severity: 'LOW', category: '', message: 'Dokumentation unvollstaendig', recommendation: '' },
|
||||
],
|
||||
})
|
||||
const result = enforcer.check('vvt', decision)
|
||||
|
||||
@@ -266,9 +266,9 @@ function deriveTriggeredRegulations(
|
||||
const regs = new Set<string>(['DSGVO'])
|
||||
const triggers = scope.decision.triggeredHardTriggers || []
|
||||
for (const t of triggers) {
|
||||
if (t.rule.id.includes('ai_act') || t.rule.id.includes('ai-act')) regs.add('AI Act')
|
||||
if (t.rule.id.includes('nis2') || t.rule.id.includes('NIS2')) regs.add('NIS2')
|
||||
if (t.rule.id.includes('ttdsg') || t.rule.id.includes('TTDSG')) regs.add('TTDSG')
|
||||
if (t.ruleId.includes('ai_act') || t.ruleId.includes('ai-act')) regs.add('AI Act')
|
||||
if (t.ruleId.includes('nis2') || t.ruleId.includes('NIS2')) regs.add('NIS2')
|
||||
if (t.ruleId.includes('ttdsg') || t.ruleId.includes('TTDSG')) regs.add('TTDSG')
|
||||
}
|
||||
return Array.from(regs)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
import type { ScopeDecision, ScopeDocumentType, ComplianceDepthLevel } from '../compliance-scope-types'
|
||||
import { DOCUMENT_SCOPE_MATRIX, getDepthLevelNumeric } from '../compliance-scope-types'
|
||||
import { DOCUMENT_SCOPE_MATRIX_CORE, getDepthLevelNumeric } from '../compliance-scope-types'
|
||||
import type { ConstraintCheckResult, DraftContext } from './types'
|
||||
|
||||
export class ConstraintEnforcer {
|
||||
@@ -57,9 +57,9 @@ export class ConstraintEnforcer {
|
||||
// -----------------------------------------------------------------------
|
||||
checkedRules.push('RULE-DOC-REQUIRED')
|
||||
const isRequired = decision.requiredDocuments.some(
|
||||
d => d.documentType === documentType && d.required
|
||||
d => d.documentType === documentType && d.requirement === 'mandatory'
|
||||
)
|
||||
const scopeReq = DOCUMENT_SCOPE_MATRIX[documentType]?.[level]
|
||||
const scopeReq = DOCUMENT_SCOPE_MATRIX_CORE[documentType]?.[level]
|
||||
|
||||
if (!isRequired && scopeReq && !scopeReq.required) {
|
||||
// Nicht blockieren, aber warnen
|
||||
@@ -96,7 +96,7 @@ export class ConstraintEnforcer {
|
||||
checkedRules.push('RULE-DSFA-ENFORCEMENT')
|
||||
if (documentType === 'dsfa') {
|
||||
const dsfaRequired = decision.triggeredHardTriggers.some(
|
||||
t => t.rule.dsfaRequired
|
||||
t => t.requiresDSFA
|
||||
)
|
||||
|
||||
if (!dsfaRequired && level !== 'L4') {
|
||||
@@ -110,10 +110,10 @@ export class ConstraintEnforcer {
|
||||
// Umgekehrt: Wenn DSFA verpflichtend und Typ != dsfa, ggf. hinweisen
|
||||
if (documentType !== 'dsfa') {
|
||||
const dsfaRequired = decision.triggeredHardTriggers.some(
|
||||
t => t.rule.dsfaRequired
|
||||
t => t.requiresDSFA
|
||||
)
|
||||
const dsfaInRequired = decision.requiredDocuments.some(
|
||||
d => d.documentType === 'dsfa' && d.required
|
||||
d => d.documentType === 'dsfa' && d.requirement === 'mandatory'
|
||||
)
|
||||
|
||||
if (dsfaRequired && dsfaInRequired) {
|
||||
@@ -136,7 +136,7 @@ export class ConstraintEnforcer {
|
||||
if (criticalRisks.length > 0) {
|
||||
adjustments.push(
|
||||
`${criticalRisks.length} kritische/hohe Risiko-Flags erkannt. ` +
|
||||
`Draft muss diese adressieren: ${criticalRisks.map(r => r.title).join(', ')}`
|
||||
`Draft muss diese adressieren: ${criticalRisks.map(r => r.message).join(', ')}`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ export class ConstraintEnforcer {
|
||||
// -----------------------------------------------------------------------
|
||||
checkedRules.push('RULE-HARD-TRIGGER-CONSISTENCY')
|
||||
for (const trigger of decision.triggeredHardTriggers) {
|
||||
const mandatoryDocs = trigger.rule.mandatoryDocuments
|
||||
const mandatoryDocs = trigger.mandatoryDocuments
|
||||
if (mandatoryDocs.includes(documentType)) {
|
||||
// Gut - wir erstellen ein mandatory document
|
||||
} else {
|
||||
@@ -175,35 +175,28 @@ export class ConstraintEnforcer {
|
||||
determinedLevel: context.decisions.level,
|
||||
scores: context.decisions.scores,
|
||||
triggeredHardTriggers: context.decisions.hardTriggers.map(t => ({
|
||||
rule: {
|
||||
id: t.id,
|
||||
label: t.label,
|
||||
description: '',
|
||||
conditionField: '',
|
||||
conditionOperator: 'EQUALS' as const,
|
||||
conditionValue: null,
|
||||
minimumLevel: context.decisions.level,
|
||||
mandatoryDocuments: [],
|
||||
dsfaRequired: false,
|
||||
legalReference: t.legalReference,
|
||||
},
|
||||
ruleId: t.id,
|
||||
category: '',
|
||||
description: t.label,
|
||||
legalReference: t.legalReference,
|
||||
minimumLevel: context.decisions.level,
|
||||
requiresDSFA: false,
|
||||
mandatoryDocuments: [],
|
||||
matchedValue: null,
|
||||
explanation: '',
|
||||
})),
|
||||
requiredDocuments: context.decisions.requiredDocuments.map(d => ({
|
||||
documentType: d.documentType,
|
||||
label: d.documentType,
|
||||
required: true,
|
||||
depth: d.depth,
|
||||
detailItems: d.detailItems,
|
||||
estimatedEffort: '',
|
||||
requirement: 'mandatory' as const,
|
||||
priority: 'medium' as const,
|
||||
estimatedEffort: 0,
|
||||
triggeredBy: [],
|
||||
})),
|
||||
riskFlags: context.constraints.riskFlags.map(f => ({
|
||||
id: `rf-${f.title}`,
|
||||
severity: f.severity as 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL',
|
||||
title: f.title,
|
||||
description: '',
|
||||
severity: f.severity,
|
||||
category: '',
|
||||
message: f.title,
|
||||
recommendation: f.recommendation,
|
||||
})),
|
||||
gaps: [],
|
||||
|
||||
@@ -14,7 +14,7 @@ export interface DocumentRAGConfig {
|
||||
query: string
|
||||
}
|
||||
|
||||
export const DOCUMENT_RAG_CONFIG: Record<ScopeDocumentType, DocumentRAGConfig> = {
|
||||
export const DOCUMENT_RAG_CONFIG: Partial<Record<ScopeDocumentType, DocumentRAGConfig>> = {
|
||||
dsfa: {
|
||||
collection: 'bp_dsfa_corpus',
|
||||
query: 'Art. 35 DSGVO Datenschutz-Folgenabschaetzung DSFA Risikobewertung WP248 EDPB',
|
||||
|
||||
@@ -221,6 +221,7 @@ describe('DSFA type', () => {
|
||||
it('should accept a complete DSFA object', () => {
|
||||
const dsfa: DSFA = {
|
||||
id: 'dsfa-001',
|
||||
version: 1,
|
||||
tenant_id: 'tenant-001',
|
||||
name: 'AI Chatbot DSFA',
|
||||
description: 'Data Protection Impact Assessment for AI Chatbot',
|
||||
|
||||
@@ -70,6 +70,7 @@ export interface CookieBannerEmbedCode {
|
||||
* Vollstaendige Cookie Banner Konfiguration
|
||||
*/
|
||||
export interface CookieBannerConfig {
|
||||
impressumUrl?: string
|
||||
id: string
|
||||
tenantId: string
|
||||
categories: CookieBannerCategory[]
|
||||
|
||||
@@ -18,13 +18,15 @@ export interface ProfilingQuestion {
|
||||
question: string // German
|
||||
helpText?: string
|
||||
type: 'single' | 'multi' | 'boolean' | 'number'
|
||||
options?: { value: string; label: string }[]
|
||||
options?: { value: string; label: string; description?: string }[]
|
||||
required: boolean
|
||||
}
|
||||
|
||||
export interface ProfilingAnswer {
|
||||
questionId: string
|
||||
value: string | string[] | boolean | number
|
||||
/** Index des Profiling-Schritts, zu dem die Antwort gehört */
|
||||
stepIndex?: number
|
||||
}
|
||||
|
||||
export interface ProfilingStep {
|
||||
|
||||
@@ -45,6 +45,8 @@ export type LegalHoldStatus = 'ACTIVE' | 'RELEASED' | 'EXPIRED'
|
||||
|
||||
export interface LegalHold {
|
||||
id: string
|
||||
name?: string
|
||||
createdAt?: string
|
||||
reason: string
|
||||
legalBasis: string
|
||||
responsiblePerson: string
|
||||
|
||||
@@ -109,7 +109,7 @@ export function buildAssessmentPayload(
|
||||
is_kritis: false, // Kann spaeter aus Branche abgeleitet werden
|
||||
is_financial_institution: isFinancial,
|
||||
determined_level: decision?.determinedLevel || 'L2',
|
||||
triggered_rules: decision?.triggeredHardTriggers?.map(t => t.rule.id) || [],
|
||||
triggered_rules: decision?.triggeredHardTriggers?.map(t => t.ruleId) || [],
|
||||
required_documents: decision?.requiredDocuments?.map(d => d.documentType) || [],
|
||||
cert_target: getAnswerString(scopeAnswers, 'org_cert_target'),
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ export interface ExportRecord {
|
||||
// =============================================================================
|
||||
|
||||
export interface TOMGeneratorState {
|
||||
metadata?: Record<string, unknown>
|
||||
id: string
|
||||
tenantId: string
|
||||
companyProfile: CompanyProfile | null
|
||||
|
||||
@@ -280,6 +280,7 @@ export interface CookieBannerGeneratedCode {
|
||||
}
|
||||
|
||||
export interface CookieBannerConfig {
|
||||
impressumUrl?: string
|
||||
id: string
|
||||
style: CookieBannerStyle
|
||||
position: CookieBannerPosition
|
||||
|
||||
@@ -91,6 +91,7 @@ export type TemplateType =
|
||||
export type Jurisdiction = 'DE' | 'AT' | 'CH' | 'EU' | 'US' | 'INTL'
|
||||
|
||||
export interface LegalTemplateResult {
|
||||
source?: string
|
||||
id: string
|
||||
score: number
|
||||
text: string
|
||||
@@ -257,6 +258,7 @@ export const DEFAULT_PLACEHOLDERS: Record<string, string> = {
|
||||
|
||||
export const TEMPLATE_TYPE_LABELS: Record<TemplateType, string> = {
|
||||
// Legal / Vertragsvorlagen
|
||||
standard_operating_procedure: 'Standard Operating Procedure (SOP)',
|
||||
privacy_policy: 'Datenschutzerkl\u00e4rung',
|
||||
terms_of_service: 'Nutzungsbedingungen',
|
||||
agb: 'Allgemeine Gesch\u00e4ftsbedingungen',
|
||||
|
||||
@@ -245,7 +245,7 @@ export function VendorComplianceProvider({
|
||||
startContractReview,
|
||||
loadData,
|
||||
refresh,
|
||||
}),
|
||||
} as VendorComplianceContextValue),
|
||||
[
|
||||
state,
|
||||
vendorStats,
|
||||
|
||||
@@ -190,6 +190,7 @@ export interface AuditEntry {
|
||||
}
|
||||
|
||||
export interface AnonymousMessage {
|
||||
sentAt?: string
|
||||
id: string
|
||||
reportId: string
|
||||
senderRole: 'reporter' | 'ombudsperson'
|
||||
|
||||
Reference in New Issue
Block a user