security: CAPA privilege escalation, CSV injection, AI rate-limit, prompt injection guard, open redirect, timing-safe cron secret, server-only admin client, notifications RLS

This commit is contained in:
2026-07-12 17:33:58 +08:00
parent c0ec6660ef
commit c80091c8d6
7 changed files with 49 additions and 6 deletions
+17 -1
View File
@@ -78,6 +78,20 @@ export async function POST() {
second_half: a.second_half,
}))
// Rate limit: 1 AI call per 60s per user (checked via audit_log)
const { data: lastCall } = await supabase
.from('audit_log')
.select('changed_at')
.eq('changed_by', user.id)
.eq('action', 'ai_risk_flags')
.order('changed_at', { ascending: false })
.limit(1)
.single()
if (lastCall && Date.now() - new Date(lastCall.changed_at).getTime() < 60_000) {
return NextResponse.json({ error: 'Rate limit: wait 60 seconds between AI requests' }, { status: 429 })
}
const anthropicKey = await getApiKey(supabase, 'ANTHROPIC_API_KEY')
const anthropic = createAnthropicClient(anthropicKey)
@@ -119,7 +133,9 @@ export async function POST() {
Flag zones with rising or elevated risk (at most 5 flags; do not flag healthy zones). Base every rationale strictly on the numbers given.
${JSON.stringify(aggregates, null, 2)}`,
<zone_data>
${JSON.stringify(aggregates, null, 2)}
</zone_data>`,
}],
})
} catch {