[schemas] CRM person tiers — relationship tier schema + dashboard page#219
Open
alanshurafa wants to merge 5 commits intoNateBJones-Projects:mainfrom
Open
[schemas] CRM person tiers — relationship tier schema + dashboard page#219alanshurafa wants to merge 5 commits intoNateBJones-Projects:mainfrom
alanshurafa wants to merge 5 commits intoNateBJones-Projects:mainfrom
Conversation
…VOKER The public crm_person_tiers RPC was declared SECURITY DEFINER with EXECUTE granted to anon. An exposed Supabase anon key would let any caller dump every person's canonical_name, aliases, and metadata from crm_persons -- no RLS is enabled and SECURITY DEFINER bypasses table grants. Least-privilege fix: function is now SECURITY INVOKER and execute is granted to authenticated + service_role only. Added README "Security" section documenting the intended install path (server-side service_role or authenticated-with-RLS) and how to opt into anon access on purpose. Flagged by Claude gsd-code-reviewer + Codex review.
The crm_person_tiers RPC applied LIMIT/OFFSET inside person_page CTE before mention_count and effective_tier were computed. The final ORDER BY effective_tier priority then only re-sorted the preselected page -- for datasets above p_limit, page 1 could miss high-mention "connected" people that sort later by last_seen, contradicting the documented ordering contract (tier priority first). Restructured the CTE chain to: filter -> aggregate mention_counts -> compute effective_tier -> global ORDER BY -> LIMIT/OFFSET. Added an inline comment explaining why ordering must precede pagination. Flagged by Claude gsd-code-reviewer + Codex review.
Two dashboard snippet fixes: P2 - per-tier summary strip derived counts from the first 400 loaded rows while the adjacent caption showed total persons, making the strip look like a global breakdown. Caption now reads "N loaded (of M total -- per-tier counts above reflect loaded rows only, capped at 400)" when total > loaded. No aggregate RPC required. P3 - server component threw on RPC failure, triggering Next.js's default error surface for drop-in consumers that lack a route-level error boundary. fetchPersonTiers now returns a typed discriminated union; CrmPage renders an in-page rose error panel with a troubleshoot hint (run NOTIFY pgrst, 'reload schema') and logs detail server-side. Flagged by Claude gsd-code-reviewer + Codex review.
Contributor
Author
|
Refreshing upstream checks after fork-side readiness cleanup. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
schemas/crm-person-tiers/— a standalone relationship-tier schema for Open Brain's person/contact data. Classifies people referenced in thoughts into four tiers (connected,contact,known,unknown) with a configurable mention-frequency boost that promotes high-touch contacts toconnectedautomatically.What's included
crm_persons— UUID PK,relationship_tierCHECK-constrained to the four tiers, unique lowercasedcanonical_name, and anupdated_attouch trigger.crm_person_mentions— join table linking a person to a thought. No FK tothoughtsby design — the contribution does not modify core tables (per repo guard rails).crm_person_tiers(p_limit, p_offset, p_search, p_promote_min_mentions, p_promote_within)RPC — paginated listing with a configurable "connected" boost (defaults: 20 mentions within 7 days).page.tsxdashboard snippet for drop-in viewing.Design notes
thought_idis typedUUIDto matchdocs/01-getting-started.md. README calls out theBIGINTalternative for older installs.thoughtstable is not modified.Security model
The RPC runs as
SECURITY INVOKER, so the caller's RLS applies.EXECUTEis granted only toservice_role— noanonexposure. README includes a dedicated "Security Model" section.Review status
Pre-review on the fork caught 2 P1s (SECURITY DEFINER + anon grant, and a pagination-before-ordering bug where LIMIT/OFFSET ran before
effective_tierwas globally ordered), 1 P2 (dashboard count label clarity), and 1 P3 (discriminated-union error panel). All addressed across 3 fix commits.Fork pre-review PR: alanshurafa#18