{
  "id": "2026-05-07-b2bea-org-survey-system-spec-cb785b1033",
  "scope": "redkey",
  "source_of_truth": "repo",
  "source_path": "docs/specs/2026-05-07-b2bea-org-survey-system-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.734Z",
  "artifact_type": "design_doc",
  "schema_version": "design_doc.generated.v1",
  "title": "B2BEA.org V1 Survey System Spec",
  "summary": "B2BEA.org V1 Survey System Spec Source of record: RedKey Supabase Studio artifact. Project: B2BEA.org Rebuild Project ID: a820dd0c 6cef 4133 bfbd d802fd806e44 Artifact: survey system spec Artifact ID: 823d14d7 5992 42f3 a2f4 f4738a045f7c Version: 1 Status: draft Updated: 2026 05 07T15:32:18.423567+00:00 Purpose Define the standard reusable survey/form capabi...",
  "format_source": "markdown",
  "sections": [
    {
      "title": "B2BEA.org V1 Survey System 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: `survey-system-spec`\n- Artifact ID: `823d14d7-5992-42f3-a2f4-f4738a045f7c`\n- Version: `1`\n- Status: `draft`\n- Updated: `2026-05-07T15:32:18.423567+00:00`"
    },
    {
      "title": "Purpose",
      "level": 2,
      "body": "Define the standard reusable survey/form capability separately from the maturity-assessment special flow, so B2BEA can run structured surveys without forcing all assessments into one generic model."
    },
    {
      "title": "Scope",
      "level": 2,
      "body": "```json\n{\n  \"included\": [\n    \"Admin-created standard surveys and forms\",\n    \"Question definitions and ordering\",\n    \"Audience assignment rules\",\n    \"Public/member/vendor/company respondent flows where authorized\",\n    \"Response capture and partial/progress state where needed\",\n    \"Review, export, reporting, and display permissions\",\n    \"Email-first notification events for invitations/reminders/results where approved\",\n    \"Audit trail for publish/archive/export and permission-sensitive operations\"\n  ],\n  \"excluded_or_separate\": [\n    \"Current maturity assessment special flow; it remains V1 but uses its own maturity-assessment pattern\",\n    \"Complex in-app notification center beyond email-first event log\",\n    \"Unbounded custom quiz/certification grading; academy certification has its own spec\",\n    \"Anonymous collection of sensitive data without explicit consent/policy\",\n    \"Raw platform-wide exports for vendors or companies\"\n  ]\n}\n```"
    },
    {
      "title": "Status",
      "level": 2,
      "body": "draft"
    },
    {
      "title": "Actors",
      "level": 2,
      "body": "| id | role |\n| --- | --- |\n| b2bea_admin | Creates, publishes, assigns, reviews, exports, and archives surveys/forms. |\n| anonymous_respondent | Can submit public surveys/forms only when explicitly published for anonymous access. |\n| member | Can respond to member-assigned or public surveys and view own submitted responses/results where allowed. |\n| vendor_admin | Can respond to vendor-assigned surveys and view own vendor aggregate/report outputs where allowed. |\n| company_admin | Can assign company-eligible surveys to employees and view own-company aggregate/report outputs where allowed. |\n| company_employee | Can respond to company-assigned surveys when invited/entitled. |"
    },
    {
      "title": "Capability Contracts",
      "level": 2,
      "body": "| id | actor | surface | acceptance | description |\n| --- | --- | --- | --- | --- |\n| SurveyCreateDefinition | b2bea_admin | /admin | Definition validates before publish., Question ids are stable., Owner and intended audience are required. | Create a reusable survey/form definition with title, description, purpose, owner, question set, audience, lifecycle, consent copy, and reporting policy. |\n| SurveyPublishArchive | b2bea_admin | /admin | Draft/preview is not public., Archived surveys stop accepting new responses., Lifecycle changes create audit events. | Move survey/form through draft, preview, published, paused, archived lifecycle. |\n| SurveyAssignAudience | b2bea_admin/company_admin | /admin or /company | Audience membership is server-side evaluated., Assignment has opens_at/closes_at where relevant., Company admins can only assign surveys allowed by company entitlement/policy. | Assign a published survey/form to an audience: public link, members, vendors, companies, company employees, event attendees, or a curated list. |\n| SurveyTake | respondent | public/member/vendor/company as authorized | Required questions are enforced., Respondent access is checked server-side., Submission confirmation is clear., Duplicate/retry behavior is defined. | Respondent completes questions with progress, validation, save/submit, consent, and confirmation states. |\n| SurveyReport | b2bea_admin/vendor_admin/company_admin/member | /admin, /vendor, /company, member dashboard | Admins can see full permitted results., Vendors/companies see only own-account scoped results., Sensitive respondent-level data is hidden unless explicitly permitted and consented. | View permitted results and reporting by audience, survey, question, or own-account aggregation. |\n| SurveyExport | b2bea_admin/vendor_admin/company_admin | /admin, /vendor, /company | Exports are audited., Vendor/company exports are own-account only., No raw platform-wide or sensitive user-level export without explicit policy/consent. | Export response/report data within policy boundaries. |"
    },
    {
      "title": "Target Data Model",
      "level": 2,
      "body": "```json\n{\n  \"tables_or_entities\": [\n    {\n      \"name\": \"survey_definitions\",\n      \"purpose\": \"Canonical survey/form definition and lifecycle metadata.\",\n      \"key_fields\": [\n        \"id\",\n        \"slug\",\n        \"title\",\n        \"description\",\n        \"owner_role\",\n        \"status\",\n        \"audience_policy\",\n        \"consent_text\",\n        \"reporting_policy\",\n        \"created_by\",\n        \"created_at\",\n        \"updated_at\",\n        \"published_at\",\n        \"archived_at\"\n      ]\n    },\n    {\n      \"name\": \"survey_questions\",\n      \"purpose\": \"Ordered question definitions linked to survey_definitions.\",\n      \"key_fields\": [\n        \"id\",\n        \"survey_id\",\n        \"stable_key\",\n        \"question_type\",\n        \"label\",\n        \"help_text\",\n        \"required\",\n        \"order_index\",\n        \"options_json\",\n        \"validation_json\",\n        \"show_if_json\",\n        \"sensitive_flag\"\n      ]\n    },\n    {\n      \"name\": \"survey_assignments\",\n      \"purpose\": \"Audience assignment and availability window for a survey.\",\n      \"key_fields\": [\n        \"id\",\n        \"survey_id\",\n        \"audience_type\",\n        \"audience_ref\",\n        \"opens_at\",\n        \"closes_at\",\n        \"status\",\n        \"created_by\"\n      ]\n    },\n    {\n      \"name\": \"survey_responses\",\n      \"purpose\": \"One respondent response session/submission.\",\n      \"key_fields\": [\n        \"id\",\n        \"survey_id\",\n        \"assignment_id\",\n        \"respondent_person_id\",\n        \"anonymous_token_hash\",\n        \"subject_type\",\n        \"subject_ref\",\n        \"status\",\n        \"started_at\",\n        \"submitted_at\",\n        \"consent_at\",\n        \"ip_hash\",\n        \"user_agent_hash\"\n      ]\n    },\n    {\n      \"name\": \"survey_answers\",\n      \"purpose\": \"Question-level answer storage with typed values.\",\n      \"key_fields\": [\n        \"id\",\n        \"response_id\",\n        \"question_id\",\n        \"answer_json\",\n        \"answered_at\"\n      ]\n    },\n    {\n      \"name\": \"survey_report_views\",\n      \"purpose\": \"Optional materialized/read-model reporting layer for aggregate dashboards.\",\n      \"key_fields\": [\n        \"survey_id\",\n        \"scope_type\",\n        \"scope_ref\",\n        \"question_key\",\n        \"aggregate_json\",\n        \"updated_at\"\n      ]\n    },\n    {\n      \"name\": \"survey_export_events\",\n      \"purpose\": \"Audited export requests/generation/downloads.\",\n      \"key_fields\": [\n        \"id\",\n        \"survey_id\",\n        \"requested_by\",\n        \"scope_type\",\n        \"scope_ref\",\n        \"status\",\n        \"file_ref\",\n        \"created_at\",\n        \"expires_at\"\n      ]\n    }\n  ],\n  \"implementation_note\": \"Exact SQL/migration belongs in PLAN/build phase. This spec defines target contracts, not implementation approval.\"\n}\n```"
    },
    {
      "title": "Question Model",
      "level": 2,
      "body": "```json\n{\n  \"v1_rules\": [\n    \"Every question has a stable key, label, optional help text, required flag, order, and answer validation.\",\n    \"Choice questions store stable option keys, not only display labels.\",\n    \"Conditional branching is limited in V1: show_if based on prior single_choice/boolean answers only, unless separately approved.\",\n    \"Free-text responses can be marked sensitive and excluded from non-admin exports by default.\"\n  ],\n  \"v1_question_types\": [\n    \"short_text\",\n    \"long_text\",\n    \"single_choice\",\n    \"multi_choice\",\n    \"rating_scale\",\n    \"boolean\",\n    \"email\",\n    \"url\",\n    \"number\",\n    \"date\"\n  ],\n  \"deferred_question_types\": [\n    \"file_upload\",\n    \"matrix_grid\",\n    \"rank_order\",\n    \"payment\",\n    \"signature\",\n    \"complex calculated score blocks\"\n  ]\n}\n```"
    },
    {
      "title": "Lifecycle Models",
      "level": 2,
      "body": "```json\n{\n  \"export\": [\n    \"requested\",\n    \"authorized\",\n    \"generated\",\n    \"downloaded\",\n    \"expired\",\n    \"denied\",\n    \"failed\"\n  ],\n  \"response\": [\n    \"not_started\",\n    \"in_progress\",\n    \"submitted\",\n    \"voided\",\n    \"deleted_or_redacted\"\n  ],\n  \"assignment\": [\n    \"draft\",\n    \"scheduled\",\n    \"open\",\n    \"closed\",\n    \"archived\"\n  ],\n  \"survey_definition\": [\n    \"draft\",\n    \"preview\",\n    \"published\",\n    \"paused\",\n    \"archived\"\n  ]\n}\n```"
    },
    {
      "title": "Permission Model",
      "level": 2,
      "body": "```json\n{\n  \"entitlement_keys\": [\n    \"survey.respond.public\",\n    \"survey.respond.member\",\n    \"survey.respond.vendor\",\n    \"survey.respond.company\",\n    \"survey.report.admin\",\n    \"survey.report.own_account\",\n    \"survey.export.admin\",\n    \"survey.export.own_account\"\n  ],\n  \"server_side_rules\": [\n    \"Survey definition writes require b2bea_admin/core admin permission.\",\n    \"Public surveys require status=published and anonymous_allowed=true or public assignment.\",\n    \"Member/vendor/company surveys require active user plus matching assignment/entitlement.\",\n    \"Vendor and company report/export reads are scoped to own vendor/company only.\",\n    \"Sensitive free-text/person-level exports require explicit admin permission and consent/policy basis.\",\n    \"All publish/archive/export/assignment changes create audit events.\"\n  ]\n}\n```"
    },
    {
      "title": "Acceptance Criteria",
      "level": 2,
      "body": "- Spec clearly separates standard surveys/forms from maturity assessments.\n- A developer can design survey tables, guards, and UI modules from the contracts without guessing source of truth.\n- Permission/export boundaries are explicit for public, member, vendor, company, and admin actors.\n- No implementation/build is authorized by this artifact alone; PLAN/EXEC_PLAN_REVIEW and Justin build approval remain required."
    },
    {
      "title": "Next Artifacts",
      "level": 2,
      "body": "- qa-release-readiness-spec\n- plan"
    },
    {
      "title": "Open Questions",
      "level": 2,
      "body": "| id | blocks | question |\n| --- | --- | --- |\n| SURV-OQ-001 | Exact first implementation module, not this spec. | Which existing V1 forms should migrate into survey/form system versus remain bespoke contact/application flows? |\n| SURV-OQ-002 | Content editing workflow details. | Should survey definitions live only in B2BEA Supabase, or should Sanity own public explanatory copy for standard public surveys? |\n| SURV-OQ-003 | Export/report policy. | What respondent-level data is allowed in vendor/company reporting, if any? |"
    },
    {
      "title": "Source Artifacts",
      "level": 2,
      "body": "| status | version | artifact_id | artifact_type |\n| --- | --- | --- | --- |\n| draft | 1 | 05e0ed7c-416a-4d8f-853a-bc3dfa3d64f6 | company-workspace-data-spec |\n| draft | 1 | 2f473004-9063-4fe9-8290-5cbd1b19dfb4 | data-model-spec |\n| draft | 1 | 355b3249-3af9-45a4-9c45-67777bd2d72d | entitlement-model-spec |\n| draft | 1 | 427c04a9-40b7-4e55-a642-65b2aee20b2b | page-template-spec |\n| draft | 3 | 80328220-3deb-4cf9-a68f-d440b41a38da | production-readiness-gap-register |\n| draft | 3 | 2cec821e-07ba-4aca-81fb-078f163adf44 | route-family-inventory |\n| draft | 9 | 77853042-e7a4-48bd-91a4-6e48d0484b1b | surface-specs |"
    },
    {
      "title": "Qa And Release Checks",
      "level": 2,
      "body": "- Anonymous/public survey cannot submit when survey is draft, paused, archived, or closed.\n- Unauthorized user cannot access private assignment by URL.\n- Required validation works on desktop/mobile and with keyboard input.\n- Submitted response persists and cannot be double-submitted unless policy allows updates.\n- Own-account vendor/company reports exclude other account data.\n- Exports create audit events and expire.\n- Sensitive fields are excluded from non-admin exports by default."
    },
    {
      "title": "Page Template Implications",
      "level": 2,
      "body": "| implication | page_family |\n| --- | --- |\n| Needs survey definition list, editor, assignment, report, and export admin modules. | admin_module |\n| Can share question controls and validation primitives, but retains maturity-specific scoring/result narrative. | maturity_assessment_special_flow |\n| May need vendor-scoped survey response/report widgets for assigned vendor surveys. | vendor_dashboard |\n| Future /company templates need employee assignment and own-company aggregate survey reporting. | company_workspace |"
    },
    {
      "title": "Relationship To Maturity Assessments",
      "level": 2,
      "body": "```json\n{\n  \"decision\": \"Maturity assessments are a reusable special assessment pattern, not just generic surveys. The standard survey system may share question/answer primitives, consent, response storage, and reporting components, but maturity assessments retain domain-specific scoring, result narrative, and recommendations.\",\n  \"future_alignment\": [\n    \"Use compatible question and response primitives where practical.\",\n    \"Keep maturity scoring/result models separate from simple survey reports.\",\n    \"Allow future domain maturity assessments to reuse the maturity_assessment_special_flow page family.\"\n  ],\n  \"current_v1_maturity_routes\": [\n    \"/assessments\",\n    \"/assessments/maturity\",\n    \"/assessments/maturity/take\",\n    \"/assessments/maturity/results\"\n  ]\n}\n```"
    }
  ],
  "html_path": "artifacts/2026-05-07-b2bea-org-survey-system-spec-cb785b1033.html",
  "json_path": "artifacts/2026-05-07-b2bea-org-survey-system-spec-cb785b1033.json"
}