Some checks failed
Build pitch-deck / build-push-deploy (push) Failing after 1m4s
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 57s
CI / test-python-voice (push) Successful in 42s
CI / test-bqas (push) Successful in 42s
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>
43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import pool from '@/lib/db'
|
|
import { SHEET_LIST } from '@/lib/finanzplan/types'
|
|
|
|
export async function GET(request: NextRequest) {
|
|
// Only expose scenario list to admin callers (bearer token)
|
|
const secret = process.env.PITCH_ADMIN_SECRET
|
|
const auth = request.headers.get('authorization') ?? ''
|
|
const isAdmin = secret && auth === `Bearer ${secret}`
|
|
|
|
try {
|
|
// Investors see only the default scenario — no names of other scenarios leaked
|
|
const scenarios = isAdmin
|
|
? await pool.query('SELECT * FROM fp_scenarios ORDER BY is_default DESC, name')
|
|
: await pool.query('SELECT id FROM fp_scenarios WHERE is_default = true LIMIT 1')
|
|
|
|
// Get row counts per sheet
|
|
const sheets = await Promise.all(
|
|
SHEET_LIST.map(async (s) => {
|
|
const tableName = `fp_${s.name}`
|
|
try {
|
|
const { rows } = await pool.query(
|
|
`SELECT COUNT(*) as total, COUNT(*) FILTER (WHERE is_editable = true) as editable FROM ${tableName} WHERE scenario_id = (SELECT id FROM fp_scenarios WHERE is_default = true LIMIT 1)`
|
|
)
|
|
return { ...s, rows: parseInt(rows[0]?.total || '0'), editable_rows: parseInt(rows[0]?.editable || '0') }
|
|
} catch {
|
|
return s
|
|
}
|
|
})
|
|
)
|
|
|
|
return NextResponse.json({
|
|
sheets,
|
|
scenarios: scenarios.rows,
|
|
months: { start: '2026-01', end: '2030-12', count: 60, founding: '2026-08' },
|
|
}, {
|
|
headers: { 'Cache-Control': 'no-store' },
|
|
})
|
|
} catch (error) {
|
|
return NextResponse.json({ error: String(error) }, { status: 500 })
|
|
}
|
|
}
|