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:
@@ -0,0 +1,14 @@
|
||||
// Pure, dependency-free logic for the Door epic. No Supabase/React/Next.
|
||||
// Unit-tested directly. The card UID is a credential, so the canonical
|
||||
// masking lives here and is reused everywhere a non-manager could see it.
|
||||
|
||||
export function last4(uid: string): string {
|
||||
return uid.length <= 4 ? uid : uid.slice(-4)
|
||||
}
|
||||
|
||||
// "••••AB12" — never reveals more than the last 4 characters. For a UID of 4
|
||||
// or fewer characters nothing is revealed.
|
||||
export function maskCardUid(uid: string): string {
|
||||
if (uid.length <= 4) return '•'.repeat(uid.length || 4)
|
||||
return '•'.repeat(uid.length - 4) + uid.slice(-4)
|
||||
}
|
||||
Reference in New Issue
Block a user