feat(marketing): savings-scan form -> compliance backend (real submit + polling)
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 39s
CI / test-python-voice (push) Successful in 31s
CI / test-bqas (push) Successful in 32s

- POST /api/scan/start: server-proxy zu api-dev.breakpilot.ai/saving-scan/start
  (kein CORS-Bypass, env-konfigurierbar via COMPLIANCE_BACKEND_URL)
- GET /api/scan/status/<checkId>: server-proxy fuer Status-Polling
- savings-scan/page.tsx: echte Submission + 5s-Polling + Progress-Bar + Consent-
  Checkbox + Error-Branch (skipped_tdm, failed)
- Datenschutzhinweis im Disclaimer ergaenzt (§ 44b UrhG TDM-Respekt)

Backend-Endpoint in breakpilot-compliance@6c223c7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-18 23:52:07 +02:00
parent 911697bab4
commit 9a1ad87acd
3 changed files with 170 additions and 18 deletions
@@ -0,0 +1,43 @@
/**
* POST /api/scan/start
* Proxy to compliance backend /api/compliance/agent/saving-scan/start.
*
* Body: { url: string; email: string; consent?: boolean }
*
* Server-side proxy avoids cross-origin POST from breakpilot.ai to
* api-dev.breakpilot.ai — same-origin from the browser, secure egress
* from the Next.js server. Backend handles rate-limit + TDM + lead-DB.
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL =
process.env.COMPLIANCE_BACKEND_URL || 'https://api-dev.breakpilot.ai'
export async function POST(request: NextRequest) {
let body: unknown
try {
body = await request.json()
} catch {
return NextResponse.json(
{ error: 'Body muss JSON sein' }, { status: 400 },
)
}
try {
const res = await fetch(
`${BACKEND_URL}/api/compliance/agent/saving-scan/start`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
signal: AbortSignal.timeout(20000),
},
)
const data = await res.json().catch(() => ({}))
return NextResponse.json(data, { status: res.status })
} catch {
return NextResponse.json(
{ error: 'Backend nicht erreichbar' }, { status: 503 },
)
}
}
@@ -0,0 +1,29 @@
/**
* GET /api/scan/status/<checkId>
* Proxy to compliance backend /api/compliance/agent/compliance-check/<id>.
*
* Polled every ~5s by the savings-scan page until status==completed/failed.
*/
import { NextRequest, NextResponse } from 'next/server'
const BACKEND_URL =
process.env.COMPLIANCE_BACKEND_URL || 'https://api-dev.breakpilot.ai'
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ checkId: string }> },
) {
const { checkId } = await params
try {
const res = await fetch(
`${BACKEND_URL}/api/compliance/agent/compliance-check/${checkId}`,
{ signal: AbortSignal.timeout(15000) },
)
const data = await res.json().catch(() => ({}))
return NextResponse.json(data, { status: res.status })
} catch {
return NextResponse.json(
{ error: 'Backend nicht erreichbar' }, { status: 503 },
)
}
}