feat(classes): schema + RLS + permissions (data layer)

Migration 032 adds classes (offering; optional payment_link and
grants_certification_id, is_active archive), class_sessions (scheduled
occurrence; denormalized space_id) and class_signups (member signup;
partial unique = one non-cancelled signup per member+session). RLS is
additive and default-deny: classes readable by managers (all) or members
(active only), class_sessions by any space member, class_signups by
managers/instructors (all) or the member (own) with instructor-only
UPDATE and no INSERT/DELETE policy so signup/cancel funnels through a
validated service-client action (capacity/waitlist/dedupe). New
classes.manage + classes.instruct permissions (group Classes) seeded to
board and backfilled. Mirrored idempotently in schema.sql; types and
schema docs updated.
This commit is contained in:
Moheeb Zara
2026-05-16 19:27:32 -07:00
parent f783541a87
commit 0c028f52cc
6 changed files with 360 additions and 2 deletions
+18
View File
@@ -118,6 +118,24 @@ export type Database = {
Update: { id?: string; space_id?: string; member_id?: string; certification_id?: string; granted_by?: string | null; granted_at?: string; expires_at?: string | null; revoked_at?: string | null; revoked_by?: string | null; revoked_reason?: string | null; note?: string | null; created_at?: string }
Relationships: []
}
classes: {
Row: { id: string; space_id: string; title: string; description: string | null; payment_link: string | null; capacity: number | null; is_active: boolean; grants_certification_id: string | null; created_by: string | null; created_at: string; updated_at: string }
Insert: { id?: string; space_id: string; title: string; description?: string | null; payment_link?: string | null; capacity?: number | null; is_active?: boolean; grants_certification_id?: string | null; created_by?: string | null; created_at?: string; updated_at?: string }
Update: { id?: string; space_id?: string; title?: string; description?: string | null; payment_link?: string | null; capacity?: number | null; is_active?: boolean; grants_certification_id?: string | null; created_by?: string | null; created_at?: string; updated_at?: string }
Relationships: []
}
class_sessions: {
Row: { id: string; class_id: string; space_id: string; starts_at: string; ends_at: string | null; location: string | null; capacity: number | null; status: string; notes: string | null; created_at: string; updated_at: string }
Insert: { id?: string; class_id: string; space_id: string; starts_at: string; ends_at?: string | null; location?: string | null; capacity?: number | null; status?: string; notes?: string | null; created_at?: string; updated_at?: string }
Update: { id?: string; class_id?: string; space_id?: string; starts_at?: string; ends_at?: string | null; location?: string | null; capacity?: number | null; status?: string; notes?: string | null; created_at?: string; updated_at?: string }
Relationships: []
}
class_signups: {
Row: { id: string; session_id: string; space_id: string; member_id: string; status: string; attended: boolean; signed_up_at: string; created_at: string }
Insert: { id?: string; session_id: string; space_id: string; member_id: string; status?: string; attended?: boolean; signed_up_at?: string; created_at?: string }
Update: { id?: string; session_id?: string; space_id?: string; member_id?: string; status?: string; attended?: boolean; signed_up_at?: string; created_at?: string }
Relationships: []
}
activity_log: {
Row: {
action: string