security: WS membership check, rate limiting, Zod WS validation, remove /repair

- WebSocket upgrade now verifies user is member of the household (prevents cross-household access)
- Rate limiting: invite/join 10/h, scanner 50/h, auth sign-in 10/min
- WebSocket commands validated via Zod discriminatedUnion (no unsafe cast)
- Removed /repair endpoint (dev artifact, bypassed tenant middleware)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
René Schober
2026-03-20 13:14:45 +01:00
parent f5c4b33f60
commit 51f0028883
8 changed files with 63 additions and 36 deletions

View File

@@ -31,9 +31,12 @@ export type ShoppingServerEvent =
| { type: "sync"; items: ShoppingItem[] };
// WebSocket command types sent from client → server
export type ShoppingClientCommand =
| { type: "item:add"; label: string; quantity?: string }
| { type: "item:check"; itemId: string }
| { type: "item:uncheck"; itemId: string }
| { type: "item:delete"; itemId: string }
| { type: "item:clear" };
export const shoppingClientCommandSchema = z.discriminatedUnion("type", [
z.object({ type: z.literal("item:add"), label: z.string().min(1), quantity: z.string().optional() }),
z.object({ type: z.literal("item:check"), itemId: z.string() }),
z.object({ type: z.literal("item:uncheck"), itemId: z.string() }),
z.object({ type: z.literal("item:delete"), itemId: z.string() }),
z.object({ type: z.literal("item:clear") }),
]);
export type ShoppingClientCommand = z.infer<typeof shoppingClientCommandSchema>;