Skip to content

[schemas] CRM person tiers — relationship tier schema + dashboard page#219

Open
alanshurafa wants to merge 4 commits into
NateBJones-Projects:mainfrom
alanshurafa:contrib/alanshurafa/crm-person-tiers
Open

[schemas] CRM person tiers — relationship tier schema + dashboard page#219
alanshurafa wants to merge 4 commits into
NateBJones-Projects:mainfrom
alanshurafa:contrib/alanshurafa/crm-person-tiers

Conversation

@alanshurafa
Copy link
Copy Markdown
Collaborator

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 to connected automatically.

What's included

  • crm_persons — UUID PK, relationship_tier CHECK-constrained to the four tiers, unique lowercased canonical_name, and an updated_at touch trigger.
  • crm_person_mentions — join table linking a person to a thought. No FK to thoughts by 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).
  • Optional page.tsx dashboard snippet for drop-in viewing.

Design notes

  • Standalone by intent — not dependent on an entity graph (differs from upstream ExoCortex's entity-embedded approach), so it works on a fresh Open Brain install.
  • thought_id is typed UUID to match docs/01-getting-started.md. README calls out the BIGINT alternative for older installs.
  • Core thoughts table is not modified.

Security model

The RPC runs as SECURITY INVOKER, so the caller's RLS applies. EXECUTE is granted only to service_role — no anon exposure. 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_tier was 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

@github-actions github-actions Bot added schema Contribution: database extension recipe Contribution: step-by-step recipe labels Apr 21, 2026
@alanshurafa
Copy link
Copy Markdown
Collaborator Author

Refreshing upstream checks after fork-side readiness cleanup.

@alanshurafa alanshurafa reopened this Apr 22, 2026
@alanshurafa alanshurafa added area: schemas Review area: schemas/primitives/data model risk: schema Touches database schema, migration, or data model behavior review: needs-refresh Branch is stale, conflicted, or needs rebase before review alan-reviewed Reviewed by Alan Shurafa in Community Reviewer role labels May 20, 2026
@alanshurafa
Copy link
Copy Markdown
Collaborator Author

Conflicts with main. This is tied to the design discussion in #192; I'll rebase once there's a direction there.

…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.
@alanshurafa alanshurafa force-pushed the contrib/alanshurafa/crm-person-tiers branch from 6b15a76 to 1a2acf0 Compare May 20, 2026 17:13
@alanshurafa
Copy link
Copy Markdown
Collaborator Author

Rebased onto main — conflicts cleared. The only conflict was a stray repo-wide markdown-lint commit on this branch that collided with main's own lint cleanup; I dropped that commit. The branch's actual changes are untouched. Now mergeable.

@alanshurafa alanshurafa added review: ready-for-maintainer Community reviewer recommends maintainer review and removed review: needs-refresh Branch is stale, conflicted, or needs rebase before review labels May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

alan-reviewed Reviewed by Alan Shurafa in Community Reviewer role area: schemas Review area: schemas/primitives/data model recipe Contribution: step-by-step recipe review: ready-for-maintainer Community reviewer recommends maintainer review risk: schema Touches database schema, migration, or data model behavior schema Contribution: database extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant