feat: Whistleblower backend + Scanner banner-check (last 2 gaps)
Whistleblower (HinSchG): - Migration 118: 3 tables (reports, messages, measures) with HinSchG deadlines (7d acknowledgment, 3mo feedback) - whistleblower_routes.py: 14 endpoints (CRUD, acknowledge, close, messages, measures, public submit, anonymous status check) - Frontend api-operations.ts rewired from Go SDK to compliance proxy - Access key format XXXX-XXXX-XXXX for anonymous reporters Scanner banner-check (TTDSG § 25): - CMP Dashboard: green "Kein Cookie-Banner erforderlich" when no trackers detected + no banner configured - Red warning "Cookie-Banner fehlt!" when trackers found but no banner - Mandatory note: Impressum (DDG § 5) + DSE (DSGVO Art. 13) still required [migration-approved] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,8 @@ import {
|
||||
// CONFIGURATION
|
||||
// =============================================================================
|
||||
|
||||
const WB_API_BASE = process.env.NEXT_PUBLIC_SDK_API_URL || 'http://localhost:8093'
|
||||
// Use compliance backend proxy (Python) instead of Go SDK
|
||||
const WB_API_BASE = '/api/sdk/v1/compliance'
|
||||
const API_TIMEOUT = 30000
|
||||
|
||||
// =============================================================================
|
||||
@@ -121,27 +122,27 @@ export async function fetchReports(filters?: ReportFilters): Promise<ReportListR
|
||||
}
|
||||
|
||||
const queryString = params.toString()
|
||||
const url = `${WB_API_BASE}/api/v1/admin/whistleblower/reports${queryString ? `?${queryString}` : ''}`
|
||||
const url = `${WB_API_BASE}/whistleblower/reports${queryString ? `?${queryString}` : ''}`
|
||||
|
||||
return fetchWithTimeout<ReportListResponse>(url)
|
||||
}
|
||||
|
||||
export async function fetchReport(id: string): Promise<WhistleblowerReport> {
|
||||
return fetchWithTimeout<WhistleblowerReport>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${id}`
|
||||
`${WB_API_BASE}/whistleblower/reports/${id}`
|
||||
)
|
||||
}
|
||||
|
||||
export async function updateReport(id: string, update: ReportUpdateRequest): Promise<WhistleblowerReport> {
|
||||
return fetchWithTimeout<WhistleblowerReport>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${id}`,
|
||||
`${WB_API_BASE}/whistleblower/reports/${id}`,
|
||||
{ method: 'PUT', body: JSON.stringify(update) }
|
||||
)
|
||||
}
|
||||
|
||||
export async function deleteReport(id: string): Promise<void> {
|
||||
await fetchWithTimeout<void>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${id}`,
|
||||
`${WB_API_BASE}/whistleblower/reports/${id}`,
|
||||
{ method: 'DELETE' }
|
||||
)
|
||||
}
|
||||
@@ -154,7 +155,7 @@ export async function submitPublicReport(
|
||||
data: PublicReportSubmission
|
||||
): Promise<{ report: WhistleblowerReport; accessKey: string }> {
|
||||
const response = await fetch(
|
||||
`${WB_API_BASE}/api/v1/public/whistleblower/submit`,
|
||||
`${WB_API_BASE}/whistleblower/submit`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@@ -173,7 +174,7 @@ export async function fetchReportByAccessKey(
|
||||
accessKey: string
|
||||
): Promise<WhistleblowerReport> {
|
||||
const response = await fetch(
|
||||
`${WB_API_BASE}/api/v1/public/whistleblower/report/${accessKey}`,
|
||||
`${WB_API_BASE}/whistleblower/check/${accessKey}`,
|
||||
{ method: 'GET', headers: { 'Content-Type': 'application/json' } }
|
||||
)
|
||||
|
||||
@@ -190,14 +191,14 @@ export async function fetchReportByAccessKey(
|
||||
|
||||
export async function acknowledgeReport(id: string): Promise<WhistleblowerReport> {
|
||||
return fetchWithTimeout<WhistleblowerReport>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${id}/acknowledge`,
|
||||
`${WB_API_BASE}/whistleblower/reports/${id}/acknowledge`,
|
||||
{ method: 'POST' }
|
||||
)
|
||||
}
|
||||
|
||||
export async function startInvestigation(id: string): Promise<WhistleblowerReport> {
|
||||
return fetchWithTimeout<WhistleblowerReport>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${id}/investigate`,
|
||||
`${WB_API_BASE}/whistleblower/reports/${id}/investigate`,
|
||||
{ method: 'POST' }
|
||||
)
|
||||
}
|
||||
@@ -207,7 +208,7 @@ export async function addMeasure(
|
||||
measure: Omit<WhistleblowerMeasure, 'id' | 'reportId' | 'completedAt'>
|
||||
): Promise<WhistleblowerMeasure> {
|
||||
return fetchWithTimeout<WhistleblowerMeasure>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${id}/measures`,
|
||||
`${WB_API_BASE}/whistleblower/reports/${id}/measures`,
|
||||
{ method: 'POST', body: JSON.stringify(measure) }
|
||||
)
|
||||
}
|
||||
@@ -217,7 +218,7 @@ export async function closeReport(
|
||||
resolution: { reason: string; notes: string }
|
||||
): Promise<WhistleblowerReport> {
|
||||
return fetchWithTimeout<WhistleblowerReport>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${id}/close`,
|
||||
`${WB_API_BASE}/whistleblower/reports/${id}/close`,
|
||||
{ method: 'POST', body: JSON.stringify(resolution) }
|
||||
)
|
||||
}
|
||||
@@ -232,14 +233,14 @@ export async function sendMessage(
|
||||
role: 'reporter' | 'ombudsperson'
|
||||
): Promise<AnonymousMessage> {
|
||||
return fetchWithTimeout<AnonymousMessage>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${reportId}/messages`,
|
||||
`${WB_API_BASE}/whistleblower/reports/${reportId}/messages`,
|
||||
{ method: 'POST', body: JSON.stringify({ senderRole: role, message }) }
|
||||
)
|
||||
}
|
||||
|
||||
export async function fetchMessages(reportId: string): Promise<AnonymousMessage[]> {
|
||||
return fetchWithTimeout<AnonymousMessage[]>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${reportId}/messages`
|
||||
`${WB_API_BASE}/whistleblower/reports/${reportId}/messages`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -269,7 +270,7 @@ export async function uploadAttachment(
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/reports/${reportId}/attachments`,
|
||||
`${WB_API_BASE}/whistleblower/reports/${reportId}/attachments`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers,
|
||||
@@ -290,7 +291,7 @@ export async function uploadAttachment(
|
||||
|
||||
export async function deleteAttachment(id: string): Promise<void> {
|
||||
await fetchWithTimeout<void>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/attachments/${id}`,
|
||||
`${WB_API_BASE}/whistleblower/attachments/${id}`,
|
||||
{ method: 'DELETE' }
|
||||
)
|
||||
}
|
||||
@@ -301,6 +302,6 @@ export async function deleteAttachment(id: string): Promise<void> {
|
||||
|
||||
export async function fetchWhistleblowerStatistics(): Promise<WhistleblowerStatistics> {
|
||||
return fetchWithTimeout<WhistleblowerStatistics>(
|
||||
`${WB_API_BASE}/api/v1/admin/whistleblower/statistics`
|
||||
`${WB_API_BASE}/whistleblower/reports/stats`
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user