Skip to content

Product-Guide Workspaces — PRODUCT

Status: [CURRENT-CANONICAL] — NEW-S244 Wave 0. Reserved-seat spec for the product_guide application type satellite. Phase 1 deliverable per RATIFIED-S243 Item 15 (docs/plans/phase-0-investigation/pre-s244-project-feedback.md line 53 + docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md §5 row “product-guide-workspaces” line 494).

product_guide_workspaces is the reserved Phase 1 satellite table for the product_guide application type — one of six baseline application_types per Q-OQR1-03 (docs/plans/phase-0-investigation/architecture/04-workspace-types.md §3.2 line 77). At v1 apply time the satellite ships as a reserved seat (PK + FK + RLS only per docs/specs/reserved-workspace-seats/PRODUCT.md S-1..S-8); per-app columns are added via ALTER TABLE at the product-guide feature build cycle, not in the Q-OQR1-16 combined-PR migration. This spec ratifies the seat shape and names the existing product-guide-adjacent code surfaces in the repo that the feature-build cycle will integrate against.

  1. When the Q-OQR1-16 combined-PR migration applies (PLAN.md §4.2 T2 sub-task 7), product_guide_workspaces exists in the public schema with only the columns required for a reserved seat per docs/specs/reserved-workspace-seats/PRODUCT.md S-2 + S-3 — id uuid PRIMARY KEY DEFAULT gen_random_uuid() and workspace_id uuid NOT NULL UNIQUE REFERENCES workspaces(id) ON DELETE CASCADE. No application-specific columns exist at this point.

  2. Row-level security is enabled on the table at creation time via the rls_auto_enable() event trigger per docs/specs/rls-pattern/PRODUCT.md P-1, and the standard 3-role grants block is applied via grant_standard_public_table_access('public.product_guide_workspaces'::regclass) per docs/specs/reserved-workspace-seats/PRODUCT.md S-6 (anon SELECT; authenticated + service_role full CRUD). Both must hold immediately after the migration commits — RLS-without-grants returns 42501 permission denied from the Data API per RLS-PATTERN P-3.

  3. Each row in product_guide_workspaces is 1:1 with a row in workspaces where workspaces.application_type_id resolves to the application_types.key='product_guide' row (per Q-OQR1-113-A satellite-per-application_type cardinality and architecture/04-workspace-types.md §4.1 line 95). The UNIQUE constraint on workspace_id enforces this cardinality.

  4. When the parent workspaces row is deleted, the satellite row cascades automatically (per ON DELETE CASCADE). Deleting a satellite row does not affect the parent workspace (no reverse cascade) — same shape as procurement_workspaces and the other reserved seats.

  5. Row visibility is governed by inheritance through the workspace_id FK — a tenant role can read or write a product_guide_workspaces row iff it has access to the parent workspaces row, via a per-seat RLS policy that delegates to workspaces via JOIN-or-EXISTS per docs/specs/reserved-workspace-seats/PRODUCT.md S-5. No separate tenant_id column is added to the satellite.

  1. Per-application-type column lists (whatever shape product-guide-specific fields take — e.g. product_id, guide_section_set, layout config) are not added at the Phase 1 migration. They land via ALTER TABLE public.product_guide_workspaces ADD COLUMN ... migrations authored alongside the product-guide feature spec at feature-build time (per architecture/04-workspace-types.md §4.2 line 110 + docs/specs/reserved-workspace-seats/PRODUCT.md S-7).

  2. The reserved-seat invariants in docs/specs/reserved-workspace-seats/PRODUCT.md S-1 through S-8 apply verbatim to this seat — this PRODUCT.md does not re-state them; the cross-reference is load-bearing. If those invariants change, this seat changes with them.

  3. The naming convention product_guide_workspaces is frozen at S240 per docs/specs/reserved-workspace-seats/PRODUCT.md S-8 + architecture/04-workspace-types.md §3.2 line 77. Renaming requires a separate ratification cycle (precedent: bid_workspaces → procurement_workspaces per 0.9-decision-graph.md §11.3 row 4).

Integration with existing product-guide-adjacent code

Section titled “Integration with existing product-guide-adjacent code”
  1. The repo already carries product-guide-related code and data distinct from this satellite. The existing surface is content-side, not application-type-side:

    • guides table (supabase/migrations/20260416102457_pre_squash_reconciliation.sql:3804-3813) — carries a guide_type CHECK column with 'product' as one of five allowed values ('sector', 'product', 'company', 'research', 'custom'). Rows with guide_type='product' are the three live Phew product guides — Advanced Audits, LMS, Websites — per docs/specs/p0-product-guide-section-alignment-spec.md lines 22-26 + docs/specs/p0-product-guide-section-alignment-spec.md line 121.
    • guide_sections table (supabase/migrations/20260422174420_wire_product_guide_sections.sql, 20260422174117_add_research_feed_to_product_guides.sql) — 19+1 sections wired per product guide (S189 WP4 + WP5).
    • lib/intelligence/guide-generator.ts:50 — auto-generates guide_type='research' guides for intelligence workspaces (not product); shows how guides bind to workspaces today via workspace_id on the generator’s caller chain.
    • lib/guide-section-mapping.ts:118-126 — domain-filtered guide-section lookup; references guides.domain_filter and guides.is_published.
    • lib/mcp/tools/guides.ts:52-105 — MCP tools (list_guides, get_guide, create_guide, update_guide) operate on the guides table with guide_type as a filter parameter.
    • docs/ontology/25-application-type.md:20-22 + 50 — names product_guide as a baseline core-provenance application type with label “Product Guide”.
    • docs/specs/p0-product-guide-section-alignment-spec.md — section-alignment spec governs the content shape of guides/guide_sections rows where guide_type='product'; orthogonal to this satellite.
  2. The existing guides.guide_type='product' rows are content records — they bind to workspaces via guide_id on consumer tables (e.g. intelligence flow per lib/intelligence/guide-generator.ts:90-150), not via a satellite row. The new product_guide_workspaces satellite is the application-type seat for workspaces themselves; the two integrate at feature-build time but are independent objects today.

  3. No data migration is performed at Phase 1 — the satellite ships empty. Backfill (if any — e.g. populating product_guide_workspaces rows for any existing workspaces.application_type_id → 'product_guide' rows) is a feature-build-cycle deliverable. As of S243 no production workspaces.type rows carry a product-guide value (production carries only 4 intelligence rows verified S234 per architecture/04-workspace-types.md §2.2 line 40); the feature-build cycle creates them when product-guide workspaces become a user-facing concept.

  • Per-app column shape — owned by the future product-guide feature PRODUCT/TECH spec. This spec does not constrain what columns the feature spec adds.
  • Product-guide content behaviour — section taxonomy, ROI/Impact handling, IMPACT-of-If-Not-Now, FAQs, layer nesting, and the rest of docs/specs/p0-product-guide-section-alignment-spec.md scope. That spec covers the guides/guide_sections content model; nothing about the workspace-satellite seat.
  • guidesproduct_guide_workspaces integration shape — how a workspace with application_type='product_guide' references its associated guides row(s), and whether that reference lives on the satellite as a typed column (e.g. primary_guide_id uuid REFERENCES guides(id)) or stays loose. Deferred to feature build.
  • guide_type CV alignment — the existing guides.guide_type='product' CHECK constraint vs. the new application_types.key='product_guide' row. Whether these collapse, alias, or coexist is a feature-build decision. Open question: at feature build, evaluate whether guide_type retires in favour of application_types-driven discrimination (similar to the workspaces.typeworkspaces.application_type_id collapse per Q-OQR1-01).
  • State machine — per-application state machines live in lib/<application_key>/ per Q-OQR1-05. lib/product_guide/ does not yet exist; not in scope for the reserved-seat spec.
  • Admin UI — workspace-settings surface per application type is v1.1 admin-UI scope per Q-OQR1-13.
  • MCP tooling for product_guide_workspaceslib/mcp/tools/ exposure decisions are feature-build scope. The existing lib/mcp/tools/guides.ts continues to operate on guides rows independent of this satellite.
  • RATIFIED-S243 Item 15 — NEW Phase 1 spec ratification (docs/plans/phase-0-investigation/pre-s244-project-feedback.md line 53; PLAN.md §5 row 494 + Wave 0 ordering at §8 line 588).
  • RATIFIED-S240 — reserved seats pattern + S-1..S-8 invariants (docs/specs/reserved-workspace-seats/PRODUCT.md).
  • RATIFIED-S239 — RLS pattern P-1..P-5 (docs/specs/rls-pattern/PRODUCT.md).
  • RATIFIED-S235 — application_types Option (c) hybrid + 6 baseline core-provenance rows including product_guide (Q-OQR1-01 + Q-OQR1-03; architecture/04-workspace-types.md §3 line 67 + ontology docs/ontology/25-application-type.md line 20).
  • RATIFIED-S235 — satellite-per-application_type cardinality + naming pattern (Q-OQR1-113-A; architecture/04-workspace-types.md §4.1).
  • Existing-code anchors (current state, not ratifications)lib/mcp/tools/guides.ts, lib/intelligence/guide-generator.ts, lib/guide-section-mapping.ts, supabase/migrations/20260416102457_pre_squash_reconciliation.sql:3804-3813 (guides schema), supabase/migrations/20260422174420_wire_product_guide_sections.sql, docs/specs/p0-product-guide-section-alignment-spec.md.

End of PRODUCT spec. Implementation references in ./TECH.md.