D1: Remove /api/admin/fp-patch from PUBLIC_PATHS — it was returning live financial
data (fp_liquiditaet rows) to any unauthenticated caller; middleware admin gate now
applies as it does for all /api/admin/* paths.
D2: Add PITCH_ADMIN_SECRET bearer guard to POST /api/financial-model (create scenario)
and PUT /api/financial-model/assumptions (update assumptions) — any authenticated
investor could previously create/modify global financial model data.
D3: Add PITCH_ADMIN_SECRET bearer guard to POST /api/finanzplan/compute — any
investor could trigger a full DB recomputation across all fp_* tables. Also replace
String(error) in error response with a static message.
D4: GET /api/finanzplan/[sheetName] now ignores ?scenarioId= for non-admin callers;
investors always receive the default scenario only. Previously any investor could
enumerate UUIDs and read any scenario's financials including other investors' plans.
D9: Remove `name` from the non-admin /api/finanzplan response — scenario names like
"Wandeldarlehen v2" reveal internal versioning to investors.
D10: Remove hardcoded postgres://breakpilot:breakpilot123@localhost fallback from
lib/db.ts — missing DATABASE_URL now fails loudly instead of silently using stale
credentials that are committed to the repository.
D6: Fix all 4 TypeScript errors that were masked by ignoreBuildErrors:true; bump
tsconfig target to ES2018 (regex s flag in ChatFAB), type lang as 'de'|'en' in
chat route, add 'as string' assertion in adapter.ts. Remove ignoreBuildErrors:true
from next.config.js so future type errors fail the build rather than being silently
shipped.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
C3: Split SYSTEM_PROMPT into PART1/PART2/PART3 constants; Kernbotschaft #9 and
VERSIONS-ISOLATION now concatenated directly at runtime instead of .replace() — a
whitespace mismatch can no longer cause placeholder text to leak verbatim to the LLM.
I2: Add second liquidity-chain pass (sumAus→ÜBERSCHUSS→rolling balance) after tax rows
(Gewerbesteuer/Körperschaftsteuer) are written to fp_liquiditaet, so first-run LIQUIDITÄT
figures include tax outflows without requiring a second engine invocation.
I6: Warn when loadFpLiquiditaetSummary finds no fp_liquiditaet rows for a named scenario,
surfacing scenario-name mismatches that would otherwise silently return empty context.
I8: Sanitize console.error calls in chat/route.ts (3 sites) and data/route.ts; cap
LiteLLM error body to 200 chars, use (error as Error).message for stream/handler errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Using terms like 'Version X' or 'Szenario Y' in the VERSIONS-ISOLATION
instruction implies other versions exist. Rewritten to never reference
version/scenario names — just 'this pitch deck, created for you, the only one'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes all hardcoded version-specific numbers from SYSTEM_PROMPT (200k,
40k/160k L-Bank split, 195 Kunden, 3.3 Mio, 9 MA). These are now generated
at runtime from the investor's assigned pitch_version_data: funding amount,
instrument, fm_scenarios name, and 2030 financials (customers, revenue,
employees).
loadPitchContext() now returns { contextString, meta } so the POST handler
can build correct isolation and Kernbotschaft strings for any version —
Wandeldarlehen 200k, 1 Mio, or any future scenario.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FAQ entries contain hardcoded financial numbers written for specific scenarios
(e.g. 470k Liquidität 2027, 200k/40k WD amounts). When an investor is on a
different version, those FAQ numbers would override the correct version-specific
context already injected from pitch_version_data.
Added an explicit priority instruction: version-specific Unternehmensdaten
always override FAQ content for any conflicting numbers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
loadPitchContext() now accepts a versionId and loads data from
pitch_version_data instead of hardcoded base table queries, matching
the pattern used by /api/data and /api/financial-model.
Also pulls fp_liquiditaet yearly summaries (LIQUIDITÄT, Summe ERTRÄGE,
etc.) for the matching fp_scenario so the agent quotes the correct
finanzplan numbers. Falls back to base tables when no version is assigned.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Engine now uses dynamic row_type-based summation instead of hardcoded label
strings that differed between scenarios (e.g. 'Summe ERTRÄGE' vs
'Summe EINZAHLUNGEN'), fixing stale 9.2M value in Wandeldarlehen scenarios.
Rolling balance now includes all financing cash flows via ÜBERSCHUSS chain.
MilestonesSlide: widen Theme type to union so t.key comparisons compile.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds confidence scoring, escalation detection, and reasoning to the
deterministic filter. All assessment is deterministic (no LLM).
Confidence scoring (0.0-1.0):
- +0.25 industry specified
- +0.15 company size specified
- +0.20-0.30 scope signals provided
- +0.15 controls found
- +0.15 no contradictions
- Capped at 0.75 for escalation cases
Escalation triggers:
- Contradictory signals (holds_client_funds without operates_payment_service)
- Ambiguous signals (provides_embedded_connectivity)
- Financial signals without explicit payment service declaration
- Incomplete profile (no industry, size, or signals)
Reasoning: template-based, includes active signals, control count,
scope-condition descriptions, and warnings.
Response now includes "assessment" field with confidence, escalation_flag,
escalation_reason, inferred_signals, reasoning, and warnings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deleted 3 packages that were copied without validation:
- applicability_demo/ (fictional control IDs, wrong API schema)
- applicability_demo_sdk/ (wrong endpoint URL, fictional request format)
- applicability_demo_ci/ (GitHub Actions instead of Gitea, duplicated code)
Replaced with real integration in test_applicability_use_cases.py:
- TestApplicabilityIntegration calls real get_applicable_controls()
- Checks source_citation->source and control_id domain prefixes
- Runs against actual DB when DATABASE_URL is set
- 128 structure/acceptance tests pass, 24 integration tests skip without DB
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Makefile + pytest + GitHub Actions workflow for automated regression:
- make install / make eval / make test
- pytest integration with demo_cases.yaml
- Golden outputs for 6 priority cases
- Report generation (JSON + Markdown)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Request payloads + response contract + api_runner.py for 6 priority cases.
Can be run directly against /v1/applicability/evaluate endpoint.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Stage 4 (Harmonization) now uses two-tier approach:
- Score >= 0.92: auto-duplicate (embedding only, fast)
- Score 0.85-0.92: LLM verification via local qwen3.5 (think=false, ~3s)
- Score < 0.85: not a duplicate
This eliminates ~44% false positives from pure embedding similarity.
LLM_DEDUP_ENABLED env var controls the feature (default: true).
Also adds 10 applicability use case tests (bank+TAN, webshop+Stripe,
SaaS startup, energy provider, health app, automotive, law firm, etc.)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
POST /v1/canonical/generate/backfill-applicability enriches controls
with applicable_industries, applicable_company_size, scope_conditions
via Anthropic API. Targets ~26k controls from pipeline version < 3.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Frontend was recalculating Summe EINZAHLUNGEN including funding (1M),
which made liquidity appear as ~1M throughout. Now all Liquidität
sum/balance rows (Summe, ÜBERSCHUSS, Kontostand, LIQUIDITÄT) come
directly from the engine-computed DB values.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>