security headers, notifications, GDPR consent, masked fields

This commit is contained in:
2026-08-21 19:03:14 +02:00
parent 81fa409513
commit 05b3dc8cb1
37 changed files with 569 additions and 14 deletions
+9 -2
View File
@@ -14,7 +14,7 @@ import { validateSubmission } from './validateSubmission.js';
* which goes out over panelSmtpAdapter. Storing the submission is enough.
*
* server-only: touches the Turnstile secret.
*/ export async function submitForm({ data, formId, ip, maxPerMinute = 5, payload, turnstileToken }) {
*/ export async function submitForm({ consentFieldName, data, formId, ip, maxPerMinute = 5, payload, turnstileToken }) {
// 1. Rate limit — cheapest gate, drops a flood before any real work.
if (maxPerMinute > 0 && ip) {
if (!checkRateLimit({
@@ -43,7 +43,7 @@ import { validateSubmission } from './validateSubmission.js';
}
// 3. Validate against the form's schema. A public endpoint can't trust the
// shape of `data` — drop unknown keys, enforce required, cap length.
const validation = await validateSubmission(payload, formId, data);
const validation = await validateSubmission(payload, formId, data, consentFieldName);
if (!validation.ok) {
if (validation.reason === 'not_found') {
return {
@@ -51,6 +51,13 @@ import { validateSubmission } from './validateSubmission.js';
success: false
};
}
if (validation.reason === 'consent') {
return {
field: validation.field,
reason: 'consent',
success: false
};
}
return {
reason: 'validation',
success: false,