{
  "id": "2026-05-06-b2bea-org-permission-lifecycle-matrix-67d0d78e54",
  "scope": "redkey",
  "source_of_truth": "repo",
  "source_path": "docs/specs/2026-05-06-b2bea-org-permission-lifecycle-matrix.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.713Z",
  "artifact_type": "design_doc",
  "schema_version": "design_doc.generated.v1",
  "title": "B2BEA.org V1 Permission + Lifecycle Matrix",
  "summary": "B2BEA.org V1 Permission + Lifecycle Matrix Source of record: RedKey Supabase Studio artifact. Project: B2BEA.org Rebuild Project ID: a820dd0c 6cef 4133 bfbd d802fd806e44 Artifact: permission lifecycle matrix Artifact ID: dcfc8620 9f28 4019 aeeb de3e279fd7a7 Version: 3 Status: draft Updated: 2026 05 06T20:00:08.982+00:00 Principle Keep internal B2BEA administ...",
  "format_source": "markdown",
  "sections": [
    {
      "title": "B2BEA.org V1 Permission + Lifecycle Matrix",
      "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: `permission-lifecycle-matrix`\n- Artifact ID: `dcfc8620-9f28-4019-aeeb-de3e279fd7a7`\n- Version: `3`\n- Status: `draft`\n- Updated: `2026-05-06T20:00:08.982+00:00`"
    },
    {
      "title": "Principle",
      "level": 2,
      "body": "Keep internal B2BEA administration simple; enforce external self-service, entitlements, ownership, lifecycle, and public visibility rules rigorously."
    },
    {
      "title": "Internal Admin Model",
      "level": 2,
      "body": "Core admins: Brett, Sarah, and Justin.\n\nV1 rule: all three can make core site/admin changes. Avoid complex internal admin tiers for V1.\n\nRequired controls:\n\n- Preview.\n- Status.\n- Publish/archive.\n- Rollback where feasible.\n- Audit events for public/material changes.\n- Required fields and validation.\n\nNot V1:\n\n- Granular internal admin privilege tiers.\n- Multi-step internal approval chains for the core team."
    },
    {
      "title": "Decisions",
      "level": 2,
      "body": "| ID | Topic | Decision | Rationale |\n|---|---|---|---|\n| `DEC-001` | Public practitioner company profiles | Exclude from V1. Vendor public profiles are V1; practitioner company accounts are private workspace only. | Practitioner company value in V1 is operational access for seats, academy, careers, entitlements, and team reporting. Public company pages would add a new public directory/moderation surface without being required for V1. |\n| `DEC-002` | Company-created jobs | Require B2BEA admin review before public publishing in V1. | Jobs are public-facing and need quality, trust, and spam controls. |\n| `DEC-003` | Sanity versus Supabase source of truth | Sanity owns editorial/public content. B2BEA Supabase owns application and operational data, including people, company, vendor, membership, course, survey, job, event, analytics, and notification records. | Keep content editing in the CMS and product/workflow state in the application database. |\n| `DEC-004` | Notifications | V1 is email-first with an internal notification event log. In-app notifications are designed for later unless a surface explicitly needs them. | Email covers V1 production needs with less UI/state complexity. |\n| `DEC-005` | CRM source of truth | HubSpot is the primary CRM for leads, pipeline, sales activity, and renewals. B2BEA Supabase owns website profiles and operational entities. | HubSpot should own CRM workflow; the website should own profile/workspace/product data. |\n| `DEC-006` | Vendor and company analytics exports | V1 allows bounded own-account exports only. No raw platform-wide data, cross-account comparisons, or sensitive user-level data unless explicitly consented and permitted. | Keeps analytics useful while protecting privacy and platform data. |"
    },
    {
      "title": "Roles",
      "level": 2,
      "body": "| Role | Description | Access Boundary |\n|---|---|---|\n| `anonymous` | Unauthenticated public visitor. | Public content, ungated forms, public surveys, vendor/person/job/event pages, signup/login. |\n| `member` | Authenticated individual with a profile. | Own profile, own learning, own survey responses, member resources according to entitlements. |\n| `pro_member` | Member with paid/pro entitlement. | Pro gated resources, eligible academy/content/event benefits. |\n| `vendor_admin` | Vendor user who manages a vendor account. | Own vendor profile submissions, vendor team, content submissions, leads/analytics/billing when enabled. |\n| `vendor_member` | Vendor team member with limited vendor workspace access. | Vendor workspace sections assigned by vendor admin. |\n| `company_admin` | Practitioner company user who manages company access. | Own company employees, seats, academy/careers access, company entitlements, team reporting. |\n| `company_employee` | Employee under a practitioner company account. | Assigned academy/career/resources benefits, own profile and progress. |\n| `author` | Content contributor. | Own drafts/submissions where enabled; public publishing controlled by B2BEA admin/editorial workflow. |\n| `b2bea_admin` | Trusted B2BEA core admin team. | Full internal operations for V1; simple team trust model with audit for material changes. |\n| `system` | Automations, scheduled jobs, integrations. | Narrow service actions for notifications, analytics, imports, syncs, and lifecycle events. |"
    },
    {
      "title": "Permission Matrix",
      "level": 2,
      "body": "| Area | Anonymous | Member | Pro Member | Vendor Admin | Company Admin | B2BEA Admin |\n|---|---|---|---|---|---|---|\n| Public pages and directories | read | read | read | read | read | create/update/publish/archive |\n| Custom HTML landing/resource pages | read when published | read by gate | read by gate | none unless sponsor workflow | none unless assigned | import/preview/publish/archive/rollback |\n| Sanity standard pages | read when published | read by gate | read by gate | submit where enabled | none | create/update/preview/schedule/publish/archive |\n| Member profile | read public projection only | read/update own | read/update own | read own person only | read own person only | read/update/support |\n| Vendor profile | read published | read published | read published | submit updates for own vendor | read published | create/update/approve/publish/archive |\n| Vendor content submissions | none | none | none | create/update own submissions | none | review/approve/reject/publish/archive |\n| Company workspace | none | none unless employee | none unless employee | none | manage own company | create/update/support/audit |\n| Academy courses | browse public catalog | enroll/take if entitled | enroll/take if entitled | manage vendor-submitted courses when enabled | assign entitled courses | create/update/enroll/manage |\n| Surveys | take public surveys | take assigned/member surveys | take assigned/member surveys | view vendor-owned results if enabled | assign/view company results | create/publish/analyze/export |\n| Jobs and careers | read published jobs/apply where public | apply/manage own activity | apply/manage own activity | none unless sponsor/employer flow | create/update own job postings when enabled | create/review/publish/archive |\n| Events and sponsorship | read/register public events | register/manage own registrations | register/manage eligible benefits | sponsor/manage own sponsorship assets | register team where enabled | create/manage/publish/export |\n| Billing and memberships | start checkout/application | manage own membership where enabled | manage own membership | manage own vendor billing | manage company billing/contact | support/manage/administer |\n| Analytics and reporting | none | own history only | own history only | own vendor analytics/leads | own company/team analytics | platform analytics/export |"
    },
    {
      "title": "Lifecycle Matrix",
      "level": 2,
      "body": "| Entity | Owner | Source Of Truth | States | Public Visibility | Approval Rule |\n|---|---|---|---|---|---|\n| Sanity standard page | `b2bea_admin` | Sanity | `draft`, `preview`, `scheduled`, `published`, `archived` | Published only. | Core admin can publish directly; audit material public changes. |\n| Custom HTML landing/resource page | `b2bea_admin` | Code/import registry | `draft`, `preview`, `published`, `archived`, `rolled_back` | Published only. | Core admin can publish directly; rollback/archive required. |\n| Article/resource/guide/report | `b2bea_admin` or author/vendor by submission | Sanity plus Supabase tracking as needed | `draft`, `submitted`, `in_review`, `approved`, `scheduled`, `published`, `rejected`, `archived` | Published only. | Vendor/author submissions require B2BEA review. |\n| Vendor profile | `vendor_admin` plus `b2bea_admin` | Supabase | `unclaimed`, `claimed`, `update_submitted`, `in_review`, `approved`, `published`, `rejected`, `archived` | Approved/published fields only. | Vendor changes submit for admin approval before public projection changes. |\n| Member profile | `member` | Supabase | `incomplete`, `active`, `public_profile_enabled`, `hidden`, `suspended` | Public projection only when enabled/eligible. | Member edits own profile; public display rules validated by system. |\n| Company workspace/account | `company_admin` plus `b2bea_admin` | Supabase | `prospect`, `active`, `suspended`, `expired`, `archived` | Private workspace only in V1. No public practitioner company profiles. | Company admin manages own workspace within entitlement limits; no public profile publishing in V1. |\n| Company employee seat | `company_admin` | Supabase | `invited`, `active`, `removed`, `expired` | Private. | Company admin manages seats within purchased/assigned entitlement. |\n| Course | `b2bea_admin` | Supabase/Sanity decision needed | `draft`, `preview`, `published`, `retired`, `archived` | Catalog visibility by status and entitlement. | Core admin can publish directly. |\n| Enrollment/course assignment | `member`, `company_admin`, or `b2bea_admin` | Supabase | `assigned`, `enrolled`, `in_progress`, `completed`, `expired`, `revoked` | Private to learner/company/admin. | Assignment must pass entitlement checks. |\n| Certificate | `member` plus `b2bea_admin` | Supabase | `eligible`, `issued`, `revoked`, `expired` | Private unless member shares/public enabled. | System/admin issues only when completion criteria pass. |\n| Survey | `b2bea_admin` | Supabase | `draft`, `preview`, `published`, `closed`, `archived` | Published surveys according to audience. | Core admin can publish; audience and result visibility required. |\n| Survey response | Respondent | Supabase | `started`, `submitted`, `invalidated`, `deleted` | Private/aggregated unless explicit results display. | Respondent can submit; admin can analyze/export according to privacy rules. |\n| Form | `b2bea_admin` | Supabase or Sanity decision needed | `draft`, `preview`, `published`, `closed`, `archived` | Published only. | Core admin can publish directly. |\n| Form submission | Submitter plus `b2bea_admin` | Supabase | `submitted`, `triaged`, `assigned`, `in_progress`, `resolved`, `spam`, `archived` | Private. | Admin reviews and assigns. |\n| Job posting | `b2bea_admin` or `company_admin` | Supabase | `draft`, `submitted`, `in_review`, `published`, `closed`, `rejected`, `archived` | Published only. | Company-created jobs require B2BEA admin review before public publishing in V1. |\n| Event | `b2bea_admin` | Supabase/Sanity decision needed | `draft`, `preview`, `published`, `registration_open`, `sold_out`, `completed`, `archived` | Published and registration states. | Core admin can publish directly. |\n| Vendor sponsorship | `vendor_admin` plus `b2bea_admin` | Supabase | `draft`, `submitted`, `in_review`, `approved`, `active`, `fulfilled`, `rejected`, `archived` | Active/approved sponsor assets only. | Vendor submissions require B2BEA approval. |\n| Notification | `system` | Supabase plus provider logs | `queued`, `sent`, `delivered`, `failed`, `suppressed` | Private to recipient/admin logs. | Triggered by lifecycle events and user preferences. |\n| Lead/opportunity | `b2bea_admin` | HubSpot primary CRM; B2BEA Supabase stores site intake/submission references as needed | `new`, `assigned`, `contacted`, `qualified`, `converted`, `lost`, `archived` | Private admin only. | Internal sales/admin workflow in HubSpot; B2BEA.org routes qualified intake to CRM. |"
    },
    {
      "title": "Enforcement Rules",
      "level": 2,
      "body": "- Public read paths can be static/client-rendered when data is already public.\n- Any mutation by members, vendors, companies, or anonymous users needs server-side validation and ownership checks.\n- Entitlement decisions should not rely only on client-side checks.\n- Vendor/company/member data updates must validate ownership before write.\n- Public projection changes should be auditable even when the core admin team can publish directly.\n- Billing, membership, course access, survey assignment, and company seats require explicit entitlement checks.\n- Export actions require role checks and audit events because they can expose sensitive data."
    },
    {
      "title": "Unresolved Decisions",
      "level": 2,
      "body": "No major permission/lifecycle decisions remain open at this level. Deeper specs may add implementation-level decisions."
    },
    {
      "title": "Next Artifacts",
      "level": 2,
      "body": "- `design-system-spec`\n- `publishing-model-spec`\n- `data-model-spec`\n- `surface-specs`\n- `security-privacy-spec`"
    }
  ],
  "html_path": "artifacts/2026-05-06-b2bea-org-permission-lifecycle-matrix-67d0d78e54.html",
  "json_path": "artifacts/2026-05-06-b2bea-org-permission-lifecycle-matrix-67d0d78e54.json"
}