feat(door): P1 member access cards + door permissions
Migration 034 adds member_cards (RFID/NFC UID -> member). The card UID is treated as a credential: door.manage-only RLS with no member SELECT policy; the member's own "My access cards" view goes through a service -client action that returns only count + last4 (never the raw UID). New door.manage / door.operate permissions (group Access), seeded to board and backfilled, introduced now for the whole Door epic. Pure door-logic masking is unit-tested. A per-member "Cards" panel on /members is gated to door.manage (independent of admin). No controller calls and no anonymous path in this phase. Mirrored in schema.sql; types and schema docs updated.
This commit is contained in:
@@ -874,6 +874,35 @@ export const listEquipmentReservationsSchema = z.object({
|
||||
equipmentId: z.string().uuid('Invalid equipment ID'),
|
||||
})
|
||||
|
||||
// ─── Member access cards (Door epic) ─────────────────────────────────────────
|
||||
|
||||
const cardUid = z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, 'Card UID is required')
|
||||
.max(200, 'Card UID is too long')
|
||||
|
||||
export const addMemberCardSchema = z.object({
|
||||
memberId: z.string().uuid('Invalid member ID'),
|
||||
card_uid: cardUid,
|
||||
card_type: z.enum(['rfid', 'nfc']).optional().default('rfid'),
|
||||
label: z.string().max(120).optional().nullable(),
|
||||
})
|
||||
|
||||
export const updateMemberCardSchema = z.object({
|
||||
cardId: z.string().uuid('Invalid card ID'),
|
||||
label: z.string().max(120).optional().nullable(),
|
||||
is_active: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export const cardIdSchema = z.object({
|
||||
cardId: z.string().uuid('Invalid card ID'),
|
||||
})
|
||||
|
||||
export const listMemberCardsSchema = z.object({
|
||||
memberId: z.string().uuid('Invalid member ID'),
|
||||
})
|
||||
|
||||
// ─── Generic ID schemas ──────────────────────────────────────────────────────
|
||||
|
||||
export const uuidSchema = z.string().uuid('Invalid ID format')
|
||||
|
||||
Reference in New Issue
Block a user