{
  "id": "2026-05-06-b2bea-org-data-model-spec-cdc61ccc56",
  "scope": "redkey",
  "source_of_truth": "repo",
  "source_path": "docs/specs/2026-05-06-b2bea-org-data-model-spec.md",
  "source_kind": "markdown",
  "visibility": "internal",
  "renderer_id": "design_doc.dreamborn-forge.generated.v1",
  "design_system": "dreamborn-design-system:forge",
  "generated_at": "2026-05-09T13:00:55.708Z",
  "artifact_type": "design_doc",
  "schema_version": "design_doc.generated.v1",
  "title": "B2BEA.org V1 Data Model Spec",
  "summary": "B2BEA.org V1 Data Model Spec Source of record: RedKey Supabase Studio artifact. Project: B2BEA.org Rebuild Project ID: a820dd0c 6cef 4133 bfbd d802fd806e44 Artifact: data model spec Artifact ID: 2f473004 9063 4fe9 8290 5cbd1b19dfb4 Version: 1 Status: draft Updated: 2026 05 06T20:34:52.749368+00:00 Live Supabase Check Checked against the active B2BEA Supabase...",
  "format_source": "markdown",
  "sections": [
    {
      "title": "B2BEA.org V1 Data Model Spec",
      "level": 1,
      "body": "Source of record: RedKey Supabase Studio artifact.\n\n- Project: `B2BEA.org Rebuild`\n- Project ID: `a820dd0c-6cef-4133-bfbd-d802fd806e44`\n- Artifact: `data-model-spec`\n- Artifact ID: `2f473004-9063-4fe9-8290-5cbd1b19dfb4`\n- Version: `1`\n- Status: `draft`\n- Updated: `2026-05-06T20:34:52.749368+00:00`"
    },
    {
      "title": "Live Supabase Check",
      "level": 2,
      "body": "Checked against the active B2BEA Supabase project through the live PostgREST OpenAPI schema.\n\n- Supabase host: `czqxkykbhoyyjccckpqq.supabase.co`\n- Public tables observed: `60`\n- RPC functions observed: `is_platform_admin`, `search_content`\n- Storage buckets observed through the current key: none returned\n- Migration files observed in repo: `supabase/migrations/00001_initial_schema.sql` through `00044_featured_cards.sql`, plus `20260412140000_b2bew_events.sql`\n\nThe live schema is real and populated. The largest observed tables are:\n\n| Table | Rows |\n|---|---:|\n| `people` | 6,733 |\n| `content_embeddings` | 441 |\n| `vendors` | 187 |\n| `vendor_category_assignments` | 142 |\n| `scrape_runs` | 124 |\n| `scrape_sources` | 123 |\n| `organizations` | 60 |\n| `subcategories` | 54 |\n| `events` | 46 |\n| `lessons` | 40 |\n| `b2bew_sponsors` | 39 |\n| `search_logs` | 36 |\n| `scraped_jobs` | 35 |\n| `jobs` | 30 |\n| `assessment_sessions` | 19 |"
    },
    {
      "title": "Decisions",
      "level": 2,
      "body": "| ID | Topic | Decision |\n|---|---|---|\n| `DM-DEC-001` | Profiles and operational data | B2BEA Supabase owns people, organizations, vendors, memberships, seats, academy, surveys/forms, jobs/events operations, analytics, notifications, and operational records. |\n| `DM-DEC-002` | Editorial content | Sanity owns standard public/editorial page content and SEO/GEO/social editorial fields. |\n| `DM-DEC-003` | CRM | HubSpot is primary CRM for leads, pipeline, sales activity, and renewals. B2BEA Supabase may store intake/submission references and profile relationships. |\n| `DM-DEC-004` | Public company profiles | Vendor public profiles remain V1. Practitioner company public profiles are excluded from V1; company workspace is private only. |\n| `DM-DEC-005` | Legacy `persons` table | The target model uses `people`. Any remaining `persons` references must be migrated or shimmed before production rebuild launch. |"
    },
    {
      "title": "Core Identity And Organizations",
      "level": 3,
      "body": "| Table | Rows | Notes |\n|---|---:|---|\n| `people` | 6,733 | Primary person/profile table. Includes auth, profile, careers, leadership, pro/member, and vendor-featured fields. |\n| `organizations` | 60 | Company/vendor/practitioner organization base. Also carries careers profile fields. |\n| `organization_members` | 0 | Intended organization-person membership table; currently unused. |\n| `person_roles` | 8 | Role grants such as vendor/admin/member/author-style access. |\n| `platform_admins` | 2 | Current light internal admin table. |"
    },
    {
      "title": "Vendors And Vendor Portal",
      "level": 3,
      "body": "| Table | Rows | Notes |\n|---|---:|---|\n| `vendors` | 187 | Public vendor profile source of truth. |\n| `vendor_category_assignments` | 142 | Vendor-to-subcategory mapping. |\n| `subcategories` | 54 | Current taxonomy table; `vendor_categories` was renamed. |\n| `vendor_updates` | 0 | Profile edits/claim updates for admin review. |\n| `vendor_content_submissions` | 0 | Vendor case-study/blog/content submissions. |\n| `vendor_memberships` | 0 | Vendor membership status/billing fields exist but are unused. |\n| `vendor_features` | 0 | Vendor feature bullets. |\n| `vendor_media` | 0 | Vendor screenshots/media. |\n| `vendor_partnerships` | 0 | Vendor partner relationships. |\n| `vendor_event_participation` | 0 | Vendor-to-event relation. |\n| `vendor_academy_items` | 0 | Vendor-linked academy content. |"
    },
    {
      "title": "Membership And Entitlements",
      "level": 3,
      "body": "| Table | Rows | Notes |\n|---|---:|---|\n| `membership_tiers` | 3 | Pro, Vendor, Registered seed model. |\n| `memberships` | 1 | Person/org-held memberships. |\n| `membership_seats` | 0 | Seat assignment base exists but is unused. |\n| `processed_webhook_events` | 0 | Stripe/webhook idempotency table. |"
    },
    {
      "title": "Academy And Learning",
      "level": 3,
      "body": "| Table | Rows | Notes |\n|---|---:|---|\n| `courses` | 9 | Course catalog and pricing/access fields. |\n| `modules` | 10 | Course modules. |\n| `lessons` | 40 | Lesson content. |\n| `course_enrollments` | 4 | Learner-course enrollment. |\n| `lesson_progress` | 7 | Lesson completion/progress. |\n| `module_progress` | 1 | Challenge/test/module progress state. |\n| `module_test_attempts` | 1 | AI/module test attempts. |\n| `knowledge_profile_topics` | 0 | Learner confidence/topic model. |"
    },
    {
      "title": "Careers And Scraping",
      "level": 3,
      "body": "| Table | Rows | Notes |\n|---|---:|---|\n| `jobs` | 30 | Published/manual career jobs. |\n| `scrape_sources` | 123 | Company career-page scrape sources. |\n| `scrape_runs` | 124 | Scrape run history. |\n| `scraped_jobs` | 35 | Scraped-job review queue/source data. |\n| `job_source_snapshots` | 0 | Raw scrape snapshot table. |\n| `company_mappings` | 0 | Scrape source to organization mapping. |"
    },
    {
      "title": "Events",
      "level": 3,
      "body": "There are two event models:\n\n| Table | Rows | Notes |\n|---|---:|---|\n| `events` | 46 | General public event table. |\n| `b2bew_events` | 3 | B2B eCommerce World operational event table. |\n| `b2bew_speakers` | 31 | Event speakers. |\n| `b2bew_sponsors` | 39 | Event sponsors. |\n| `b2bew_ticket_types` | 0 | Ticket types. |\n| `b2bew_registrations` | 0 | Registrations. |\n| `b2bew_purchases` | 0 | Purchases. |\n| `b2bew_sponsor_packages` | 0 | Sponsor packages. |\n| `b2bew_attendee_logos` | 0 | Attendee logos. |\n| `b2bew_applications` | 0 | Event applications. |\n\nV1 needs a boundary decision: keep `events` for marketing/public listings and `b2bew_*` for event operations, or consolidate."
    },
    {
      "title": "Search, Analytics, And Content Support",
      "level": 3,
      "body": "| Table | Rows | Notes |\n|---|---:|---|\n| `featured_cards` | 1 | Search/featured card configuration. |\n| `content_embeddings` | 441 | Search/semantic content index. |\n| `sponsored_slots` | 1 | Sponsored search slots. |\n| `search_suggestions` | 21 | Search suggestions. |\n| `search_logs` | 36 | Search analytics. |\n| `page_views` | 6 | Vendor/content analytics. |\n| `resource_downloads` | 0 | Gated/free resource download tracking. |\n| `podcast_episodes` | 0 | Podcast episode metadata. |\n| `episode_guests` | 0 | Podcast guest mapping. |"
    },
    {
      "title": "Assessments And Plan Builder",
      "level": 3,
      "body": "| Table | Rows | Notes |\n|---|---:|---|\n| `assessment_sessions` | 19 | Current maturity assessment sessions and results. |\n| `plan_builder_responses` | 0 | Plan-builder response model. |\n| `recommended_plans` | 0 | Recommended event/sponsorship plan model. |"
    },
    {
      "title": "Profile Extensions And Taxonomy Support",
      "level": 3,
      "body": "| Table | Rows | Notes |\n|---|---:|---|\n| `person_experiences` | 0 | Public/profile experience history. |\n| `person_goals` | 0 | Public/profile goals. |\n| `category_experts` | 2 | Expert-person links for taxonomy hubs. |\n| `category_faqs` | 7 | Taxonomy FAQ content. |"
    },
    {
      "title": "Target Entity Model",
      "level": 2,
      "body": "| Entity | Source Of Truth | Status | Notes |\n|---|---|---|---|\n| Person/profile | B2BEA Supabase: `people` | Current | Large live table; target replaces old `persons` usage. |\n| Organization/company | B2BEA Supabase: `organizations`, `organization_members` | Current, needs V1 extension | Private company workspace can build here, but seat/role/entitlement lifecycle needs hardening. |\n| Vendor | B2BEA Supabase: `vendors` and `vendor_*` | Current | Vendor profiles are public; self-service tables exist but are mostly empty. |\n| Membership/entitlement | B2BEA Supabase: `membership_tiers`, `memberships`, `membership_seats`, `vendor_memberships` | Partial | Needs unified access rules for pro, vendor, company seats, academy, careers, resources, and events. |\n| Course/learning | B2BEA Supabase: `courses`, `modules`, `lessons`, progress tables | Current, partial | Needs certification, learning paths, company assignment, and stronger entitlement links. |\n| Survey/assessment | B2BEA Supabase target | Partial | `assessment_sessions` exists; generalized survey/question/response/reporting tables do not. |\n| Forms/intake | B2BEA Supabase target | Missing | No generalized forms/submissions model in live public schema. |\n| Jobs/careers | B2BEA Supabase: `jobs`, `scrape_*` | Current, partial | Company-created job posting lifecycle needs explicit ownership/review fields. |\n| Events/sponsorship | B2BEA Supabase: `events`, `b2bew_*` | Current, split | Needs boundary or consolidation. |\n| Editorial/public pages | Sanity | External | Supabase supports operational references, analytics, downloads, and search embeddings. |\n| CRM lead/opportunity | HubSpot primary | External | B2BEA.org captures/routes lead intake; HubSpot owns pipeline and renewals. |\n| Notification | B2BEA Supabase target plus email provider logs | Missing | No notification event/preferences/delivery schema observed. |\n| Analytics | B2BEA Supabase: `page_views`, `resource_downloads`, `search_logs` | Current, partial | Needs event taxonomy and bounded export rules. |"
    },
    {
      "title": "V1 Schema Gaps",
      "level": 2,
      "body": "| ID | Severity | Area | Current | Required |\n|---|---:|---|---|---|\n| `DM-GAP-001` | P0 | Legacy `people`/`persons` split | Live schema has `people`; current code still references `persons` in `authbridge.js` and older docs/plans. | All production code uses `people`, or a compatibility view/shim is intentionally created and tested. |\n| `DM-GAP-002` | P0 | Generalized surveys | `assessment_sessions` exists; no live `surveys`, `survey_questions`, or `survey_responses` schema. | Create survey definitions, questions, assignments/audiences, responses, reporting/export tables. |\n| `DM-GAP-003` | P1 | Reusable forms/intake | No live `forms` or `form_submissions` schema. | Create form definitions, submissions, status/assignment, spam/rate metadata, export support. |\n| `DM-GAP-004` | P0 | Private company workspace | `organizations` and `organization_members` exist; company workspace seats/academy/careers entitlements are not first-class. | Define company account, employee roles, seat lifecycle, benefit grants, team reporting, and assignment tables or extend existing `membership_seats`/`organization_members`. |\n| `DM-GAP-005` | P0 | Entitlement model | Membership tiers, memberships, seats, course access fields, and vendor memberships exist separately. | Unify access decisions for resources, courses, events, company seats, vendor portal, and pro membership. |\n| `DM-GAP-006` | P1 | Events model split | Generic `events` and `b2bew_*` operational event tables coexist. | Define boundary or consolidate: marketing event pages vs event operations/registration/sponsorship. |\n| `DM-GAP-007` | P0 | Notifications | No notification event/preferences/delivery schema observed. | Email-first notification event log, template key, recipient, delivery status, provider IDs, retry/suppression. |\n| `DM-GAP-008` | P1 | Certification and learning paths | Courses/progress exist; no certificates/certifications/learning paths observed. | Certification requirements, issued certificates, learning paths, company assignments. |\n| `DM-GAP-009` | P1 | Media/storage | Code references `headshots` storage and `graphic_assets`; live storage bucket list returned empty and `graphic_assets` is not in public OpenAPI schema. | Verify storage buckets/RLS and define media asset source of truth for headshots, graphics, page/social images. |\n| `DM-GAP-010` | P1 | HubSpot handoff | HubSpot is decisioned as CRM primary; live Supabase has profile-level HubSpot contact linkage but no native pipeline tables. | Define lead capture/submission handoff, HubSpot IDs, sync status, failure handling, and audit fields. |"
    },
    {
      "title": "Implementation Rules",
      "level": 2,
      "body": "- Use B2BEA Supabase for operational product data and live user/workspace state.\n- Use Sanity for standard editorial/public content and page metadata authoring.\n- Use HubSpot for CRM pipeline, sales activity, renewals, and opportunity lifecycle.\n- Do not create public practitioner company profile routes or tables for V1.\n- Do not add new feature-specific one-off intake tables when a reusable forms model should cover the workflow.\n- Any member/vendor/company mutation requires ownership columns and a server-side validation path.\n- Every public projection needs lifecycle/status fields and archive behavior.\n- Analytics exports must be bounded to own-account data by vendor/company role."
    },
    {
      "title": "Next Specs",
      "level": 2,
      "body": "- `survey-system-spec`\n- `company-workspace-data-spec`\n- `entitlement-model-spec`\n- `notification-spec`\n- `sanity-schema-spec`\n- `media-asset-model-spec`"
    }
  ],
  "html_path": "artifacts/2026-05-06-b2bea-org-data-model-spec-cdc61ccc56.html",
  "json_path": "artifacts/2026-05-06-b2bea-org-data-model-spec-cdc61ccc56.json"
}