docs: fix doc drift from D/F/G work — migration 046, harness, subsystem-level facts

DATABASE_SCHEMA + DB_SCHEMA_MAP: 046 migration row (was missing — added
last turn but not table-rowed; CLAUDE.md doc-with-change rule).
README Features: Stripe recurring dues, transactional notifications,
member self-serve portal (Phase 1/2/3 — months of shipped product
spine were absent from the first thing a reader sees).
ARCHITECTURE: Known Limitations #1 now describes the DB-backed
integration harness (the previous 'no harness' claim was misleading);
Classes section notes the advisory-lock RPCs (045); Equipment notes
the GiST exclusion constraint + btree_gist (042); Door notes the
DNS-rebind defense (resolve-once, pin validated IP) + no-raw-reason
client policy + auth-param-aware redaction; Stripe webhook notes the
out-of-order monotonic period guard (D5), zero-decimal currency
handling (D7), and generic error responses (E3); Notifications notes
the per-space fair drain + per-attempt Idempotency-Key + .eq('status',
'pending') re-entrancy guard; Authorization adds the RLS-layer
privilege-eligible status gate (046).
This commit is contained in:
Moheeb Zara
2026-05-19 14:19:44 -07:00
parent 3703c2a76c
commit 19dc6321be
4 changed files with 60 additions and 8 deletions
+1
View File
@@ -411,6 +411,7 @@ Default channels created by trigger on space INSERT: `general`, `announcements`,
| 043 | `members_update` RLS gains a WITH CHECK mirroring its USING (defense-in-depth: a privileged caller can't mutate a member row into a space they don't administer). No new table/column |
| 044 | `prevent_member_self_role_change` also blocks self-change of payment_status, payment_note, dues_paid_until, last_paid_at, last_payment_at, stripe_customer_id, joined_at (member could otherwise forge a dues-good signal via PostgREST). Service-client/privileged writes still bypass. No new table/column |
| 045 | `class_signup_tx` / `class_cancel_tx` SECURITY DEFINER functions: capacity-decision+insert and cancel+waitlist-promote run under a per-session `pg_advisory_xact_lock` (concurrent signups can't over-enroll; concurrent cancels can't double-promote). Mirrors the pure computeSignupStatus/pickPromotion rule; RPC is runtime authority. No new table/column |
| 046 | `user_has_role_in_space` + `user_has_permission` gated on `status IN ('current','late')` (RLS-layer defense-in-depth for D2): unverified/inactive can no longer exercise a role/permission via direct PostgREST. `get_user_space_ids` + `user_effective_roles` intentionally NOT gated (would break unverified self-reads / onboarding). No new table/column |
---