feat(security): Session-Cookies statt X-User-Id und API-Härtung

Ersetzt die spoofbare X-User-Id-Auth durch signierte HttpOnly-Sessions nach
WebAuthn, erzwingt WRITE-only Sync, speichert den Master-Key nur im RAM und
ergänzt CORS, Rate-Limits, Helmet sowie Passkey-Reauth für sensible Aktionen.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-30 13:47:24 +02:00
co-authored by Cursor
parent 4f3f530f1f
commit dea33e3f00
33 changed files with 657 additions and 397 deletions
+3 -11
View File
@@ -1,3 +1,5 @@
import { apiFetch } from './api.js'
export type FeedbackCategory = 'bug' | 'feature' | 'general'
export class FeedbackApiError extends Error {
@@ -19,15 +21,6 @@ export function isValidFeedbackEmail(email: string): boolean {
return EMAIL_PATTERN.test(email.trim())
}
function buildFeedbackHeaders(): Record<string, string> {
const headers: Record<string, string> = {
'Content-Type': 'application/json'
}
const userId = localStorage.getItem('active_userid')
if (userId) headers['X-User-Id'] = userId
return headers
}
export async function sendFeedback(payload: {
category: FeedbackCategory
message: string
@@ -40,9 +33,8 @@ export async function sendFeedback(payload: {
throw new FeedbackApiError('Invalid email address', 'INVALID_EMAIL')
}
const res = await fetch('/api/feedback', {
const res = await apiFetch('/api/feedback', {
method: 'POST',
headers: buildFeedbackHeaders(),
body: JSON.stringify({
category: payload.category,
message: payload.message,