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:
Moheeb Zara
2026-05-16 20:13:22 -07:00
parent f32743d8bd
commit a8892a2dc8
15 changed files with 672 additions and 5 deletions
+6
View File
@@ -95,12 +95,18 @@ export default async function MembersPage() {
sid: self.space_id,
perm: 'certifications.grant',
})
const { data: canManageCards } = await supabase.rpc('user_has_permission', {
uid: user.id,
sid: self.space_id,
perm: 'door.manage',
})
return (
<MembersClient
members={members ?? []}
currentRole={self.role}
canGrantCerts={!!canGrantCerts}
canManageCards={!!canManageCards}
areaLeadRoles={(areaLeadRoles ?? []) as Array<{ id: string; area_name: string; lead_id: string | null }>}
inviteSlot={
canInvite ? (