Product-Guide Workspaces — TECH
Product-Guide Workspaces — TECH
Section titled “Product-Guide Workspaces — TECH”Status:
[CURRENT-CANONICAL]— NEW-S244 Wave 0. Companion toPRODUCT.md. Phase 1 reserved-seat scope only; per-app columns deferred to product-guide feature build.
How to use this doc
Section titled “How to use this doc”This file carries implementation references for the Phase 1 reserved seat. Each T-N entry inherits the corresponding S-N invariant from ./PRODUCT.md + the parent docs/specs/reserved-workspace-seats/PRODUCT.md S-1..S-8. T-N entries below cover only what’s specific to the product_guide_workspaces seat — they do not re-state the generic reserved-seat DDL pattern (cross-ref to RWS TECH T-1..T-8 for that).
Each T-N entry contains:
- Current state: code / migration file:line that today implements the invariant, or “greenfield” if no code exists.
- Target state: what the platform must do after the Phase 1 migration applies.
- Gate: any STILL-OPEN dependency.
- Validation: how the invariant is verified.
Source-of-truth pointers
Section titled “Source-of-truth pointers”./PRODUCT.md— Phase 1 reserved-seat invariants (cross-refs to RWS S-1..S-8).docs/specs/reserved-workspace-seats/{PRODUCT,TECH}.md— parent spec for the reserved-seat pattern; S-1..S-8 invariants + T-1..T-8 implementation references.docs/specs/id-38-rls-pattern/{PRODUCT,TECH}.md— RLS auto-enable + grants-helper pattern.docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md§4.2 T2 sub-task 7 — combined-PR migration scope landing the 5 reserved satellite seats.docs/plans/phase-0-investigation/architecture/04-workspace-types.md§3.2 + §4.2 — application_types instance table + per-application-type satellite pattern.docs/ontology/25-application-type.md—product_guideas baselinecore-provenance application type.
Audience
Section titled “Audience”Engineers writing the Phase 1 reserved-seats migration (T2 sub-task 7) for the product_guide_workspaces row of that migration; future product-guide feature-spec authors planning the per-app ALTER TABLE pattern.
T-1 — Satellite shape (reserved seat only) (implements S-1, S-2, S-3 via PRODUCT.md invariants 1, 3, 4)
Section titled “T-1 — Satellite shape (reserved seat only) (implements S-1, S-2, S-3 via PRODUCT.md invariants 1, 3, 4)”Current state: Greenfield. The table product_guide_workspaces does not exist in either staging (turayklvaunphgbgscat) or production (rovrymhhffssilaftdwd) schemas as of S243. Confirmed by absence from supabase/types/database.types.ts (auto-generated; never hand-edited per CLAUDE.md “Supabase & Schema”).
Target state: The migration landing the 5 reserved seats (PLAN.md §4.2 T2 sub-task 7) creates product_guide_workspaces in the same transaction as the other 4 reserved seats per docs/specs/reserved-workspace-seats/TECH.md T-1 BEGIN/COMMIT envelope. Shape:
CREATE TABLE public.product_guide_workspaces ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), workspace_id uuid NOT NULL UNIQUE REFERENCES workspaces(id) ON DELETE CASCADE, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now());Identical shape to the other 4 reserved seats per docs/specs/reserved-workspace-seats/TECH.md T-1 (lines 41-62 of that doc — intelligence_workspaces, sales_proposal_workspaces, product_guide_workspaces, competitor_research_workspaces, training_onboarding_workspaces all share the shell shape).
Lands in: Same migration as the other 4 reserved seats (Q-OQR1-16 combined PR per PLAN.md §4.2 T2 sub-task 7) — filename per Supabase migration timestamp convention. Single migration creates all 5 in one transaction.
Gate: RLS-PATTERN combined migration (supabase/migrations/20260514150238_enable_rls_auto_event_trigger_and_grants_pattern.sql) MUST apply first so the rls_auto_enable() event trigger + grant_standard_public_table_access(regclass) helper exist when this migration runs. Per PLAN.md §8 Wave 1, this is already DONE-S239 (verified S243 — docs/specs/phase-1-kickoff-scoping-s243.md §3).
Validation:
- Apply migration to staging; assert
SELECT count(*) FROM information_schema.tables WHERE table_schema='public' AND table_name = 'product_guide_workspaces'returns1. - Assert column shape:
SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_name='product_guide_workspaces' ORDER BY ordinal_positionreturns the 4-row shape above (id + workspace_id + created_at + updated_at; no per-app columns). - Confirm FK + UNIQUE:
SELECT constraint_name, constraint_type FROM information_schema.table_constraints WHERE table_name='product_guide_workspaces'returns the PK + the FK + the UNIQUE onworkspace_id. - Cascade test: insert a workspace + matching satellite row; delete workspace; assert satellite row count drops to 0.
T-2 — Feature-build ALTER path (implements PRODUCT.md invariant 6 + S-7)
Section titled “T-2 — Feature-build ALTER path (implements PRODUCT.md invariant 6 + S-7)”Current state: No lib/product_guide/, no app/product_guide/, no feature-spec directory. The product-guide-feature build cycle has not begun.
Target state: When the product-guide feature spec ships, its TECH.md owns a migration of the form:
ALTER TABLE public.product_guide_workspaces ADD COLUMN <product_guide_specific_col_1> <type> [NULL | NOT NULL] [DEFAULT ...];-- repeat per per-app column as the feature spec dictates.This spec does not constrain the column list. The reserved-seat invariant is that the seat shell remains the FK target while column lists evolve per-application — never re-create the table, never DROP TABLE + CREATE TABLE per docs/specs/reserved-workspace-seats/TECH.md T-7 (line 199-201).
Gate: Product-guide feature spec drafting (out of scope for Phase 1). Per CLAUDE.md “Supabase & Schema”: new columns adding PL/pgSQL helper functions need SET search_path = public, extensions + per-function REVOKE EXECUTE ... FROM anon; blocks — feature spec must carry these patterns.
Validation:
- Per-feature-spec; not validated at Phase 1.
- v1.1 candidate CI guard per
docs/specs/reserved-workspace-seats/TECH.mdT-7: extendmigration-revoke-guard.yml(or sibling workflow) to lint forCREATE TABLE public.product_guide_workspacesoutside the v1 reserved-seats migration file.
T-3 — RLS auto-enable + grants helper (implements PRODUCT.md invariant 2 + S-4 + S-6)
Section titled “T-3 — RLS auto-enable + grants helper (implements PRODUCT.md invariant 2 + S-4 + S-6)”Current state: Greenfield seat. The auto-RLS event trigger from RLS-PATTERN P-1/T-1 is applied per PLAN.md §8 Wave 1 (DONE-S239); the grants helper from RLS-PATTERN T-2 is available.
Target state: Two things must hold immediately after CREATE TABLE public.product_guide_workspaces returns:
pg_class.relrowsecurity = truefor the new table — set by therls_auto_enable()event trigger firing on theCREATE TABLEcommand tag per RLS-PATTERN P-1.- The standard 3-role grants (anon SELECT; authenticated full CRUD; service_role full CRUD) are applied via
SELECT grant_standard_public_table_access('public.product_guide_workspaces'::regclass);per RWS S-6 + RLS-PATTERN P-2.
Migration order per docs/specs/reserved-workspace-seats/TECH.md T-6 line 180-185:
CREATE TABLE public.product_guide_workspaces (...);ALTER TABLE public.product_guide_workspaces ENABLE ROW LEVEL SECURITY; -- belt-and-braces per RWS S-4SELECT grant_standard_public_table_access('public.product_guide_workspaces'::regclass);-- per-seat RLS policies follow per T-4 belowThe explicit ALTER TABLE ... ENABLE ROW LEVEL SECURITY is idempotent against the event-trigger enable, but acts as a fall-back if migration order inverts — per RWS T-4 line 116-126.
Gate: RLS-PATTERN combined migration applied (DONE-S239 — supabase/migrations/20260514150238_enable_rls_auto_event_trigger_and_grants_pattern.sql). No further gate at Phase 1.
Validation:
- Apply migration to staging; assert
SELECT relrowsecurity FROM pg_class WHERE relname = 'product_guide_workspaces'returnstrue. - Assert grants per RWS TECH T-6:
SELECT grantee, privilege_type FROM information_schema.role_table_grants WHERE table_name = 'product_guide_workspaces'returns the 3-role pattern (anon SELECT; authenticated SELECT/INSERT/UPDATE/DELETE; service_role SELECT/INSERT/UPDATE/DELETE). - Negative-case (per implementation-readiness audit P4 fix): an unprivileged tenant cannot SELECT from
product_guide_workspacesfor a workspace they do not own — Data API returns42501 permission denied, not silent empty result.
T-4 — Per-tenant RLS policies (implements S-5)
Section titled “T-4 — Per-tenant RLS policies (implements S-5)”Current state: Greenfield. Pattern precedent will land on the post-rename procurement_workspaces (per PLAN.md §4.2 T2 sub-task 4) — JOIN-or-EXISTS delegation through workspace_id to the parent workspaces row’s tenant scope.
Target state: The seat carries 4 RLS policies (select, insert, update, delete) delegating to the parent workspaces row per RWS TECH T-5 (lines 141-160). Policy shape (SELECT example):
CREATE POLICY product_guide_workspaces_selectON public.product_guide_workspacesFOR SELECTUSING ( EXISTS ( SELECT 1 FROM workspaces w WHERE w.id = product_guide_workspaces.workspace_id AND ( -- delegated to workspaces' own RLS USING clause (role-based via get_user_role() -- per CLAUDE.md "Supabase & Schema"); exact predicate matches workspaces-level pattern ) ));Identical pattern across all 5 reserved seats — 20 policy statements total (5 seats × 4 policies) per RWS TECH T-5 line 163.
Gate: None — workspaces table RLS policies are stable in current production schema.
Validation:
- Per-seat: connect as
authenticatedrole with tenant A; insert workspace + matching satellite for tenant A; assert satellite visible. Switch to tenant B; assert satellite not visible. - Test fixture from procurement seat post-rename will provide the migration test scaffold — copy across the 5 reserved seats per RWS TECH T-5 line 168.
T-5 — Existing-code integration anchor (no Phase 1 binding)
Section titled “T-5 — Existing-code integration anchor (no Phase 1 binding)”Current state: The repo carries product-guide-adjacent code distinct from this satellite. Integration shape is feature-build scope; this T-5 names the anchors so feature-build planning has the inventory.
| File / artefact | Line refs | What it does | Integration shape |
|---|---|---|---|
supabase/migrations/20260416102457_pre_squash_reconciliation.sql | 3804-3813 | Defines public.guides table with guide_type CHECK column allowing 'product' value (5-value CV: sector, product, company, research, custom) | Feature spec resolves whether guide_type CV retires/aliases vs application_types.key discrimination. Content-side vs application-type-side disambiguation. |
supabase/migrations/20260422174420_wire_product_guide_sections.sql | (S189 WP4) | Wires 19 sections per product guide row; populates subtopic_filter | Out of Phase 1 scope; section-shape governed by docs/specs/p0-product-guide-section-alignment-spec.md. |
supabase/migrations/20260422174117_add_research_feed_to_product_guides.sql | (S189 WP5) | Adds 20th “Research Feed” section to product guides | Same — content-side; orthogonal to satellite seat. |
lib/mcp/tools/guides.ts | 52-105, 237-283, 356-548, 680 | MCP tools list_guides, get_guide, create_guide, update_guide; guide_type is a filter parameter | Feature spec decides whether product_guide_workspaces rows surface as a separate MCP tool (list_product_guide_workspaces etc.) or whether existing guides.ts tools extend to join through the satellite. |
lib/intelligence/guide-generator.ts | 33-150 | Auto-generates guide_type='research' guides for intelligence workspaces; sets guide_id on intelligence_workspaces (via workspaces.domain_metadata JSONB per S243 audit) | Direct precedent for how a workspace satellite may reference a guides row at feature-build time. The Shape B promotion guide_id is one of two fields the intelligence-workspaces spec ratifies as typed columns (per PLAN.md §4.2 T2 sub-task 8 + S243 Item 12). Product-guide feature spec may follow the same pattern (or differ — feature-spec call). |
lib/guide-section-mapping.ts | 82-139 | Domain-filtered guide-section lookup; reads guides.domain_filter + guides.is_published | Out of Phase 1 scope; will integrate at feature-build only if section-aware UX surfaces for product-guide workspaces. |
scripts/seed-phew-guides.ts | 388-390 | Seeds the live Phew product guide rows (“Advanced Audits Product Guide” etc.) | Existing-state evidence — three live guide_type='product' rows exist (Advanced Audits, LMS, Websites) per docs/specs/p0-product-guide-section-alignment-spec.md line 121. Confirms guides content-side coexists with the empty Phase 1 satellite. |
docs/ontology/25-application-type.md | 20-22, 50 | Names product_guide (label “Product Guide”) as baseline core-provenance application type | Direct cross-reference — the application_types seed row key='product_guide' is what workspaces.application_type_id FKs to; this satellite is its sibling. |
docs/specs/p0-product-guide-section-alignment-spec.md | (full doc) | Pre-launch spec governing content shape of guides/guide_sections rows where guide_type='product' | Orthogonal — content-model spec for the guides table; this PRODUCT.md/TECH.md is the workspace-satellite seat. The two integrate at feature-build time but are independent at Phase 1. |
Target state: No Phase 1 binding. Per docs/specs/reserved-workspace-seats/TECH.md T-7 line 198, the reserved seat exists as a stable FK target while the feature-build cycle adds typed columns. If the feature-build cycle decides to expose primary_guide_id uuid REFERENCES guides(id) on the satellite (one plausible shape — mirroring intelligence_workspaces.guide_id per S243 Item 12 Shape B promotion), that ALTER lands in the feature TECH.md, not here.
Gate: Feature-spec drafting — owns the integration shape. This anchor table is a roadmap, not a constraint.
Validation:
- Phase 1 only validates the seat shell (T-1, T-3, T-4). Integration shape validation lands at feature-build.
T-6 — Naming convention frozen (implements S-8)
Section titled “T-6 — Naming convention frozen (implements S-8)”Current state: Name documented at architecture/04-workspace-types.md §3.2 line 77, docs/ontology/25-application-type.md line 50, and docs/specs/reserved-workspace-seats/PRODUCT.md S-1 + S-8.
Target state: Migration creates the table verbatim as public.product_guide_workspaces — underscore-separated, singular product_guide matching application_types.key='product_guide' per Q-OQR1-113-A.
Gate: None — name is settled. Rename requires separate ratification cycle.
Validation:
- Migration file diff vs
architecture/04-workspace-types.md§3.2 line 77 +PRODUCT.mdS-1 name list.
T-N gap flags
Section titled “T-N gap flags”-
Gap flag GF-1 —
guides.guide_type='product'vsapplication_types.key='product_guide'collapse decision (DEFERRED to feature build). The existing 5-valueguide_typeCV (sector,product,company,research,custom) overlaps in intent withapplication_types.keyfor at least two values (product↔product_guide;research↔intelligencePhase-1-only research-flow generation; arguablysector↔intelligenceif sector guides are an intelligence-flow surface). Phase 1 does not resolve this — both CVs coexist. The product-guide feature spec at build time must rule on whetherguide_typeretires (similar toworkspaces.type → workspaces.application_type_idper Q-OQR1-01) or stays as a content-side discriminator. Category (construction-guide §5.2): Ratification needed (product-owner judgement call: collapse vs coexist). Sources checked:supabase/migrations/20260416102457_pre_squash_reconciliation.sql:3804-3813(5-value CV),docs/ontology/25-application-type.md(product_guidebaseline),0.9-decision-graph.md§11.3 row 1 (Q-OQR1-01 precedent). Prerequisite work: product-guide feature PRODUCT spec ratification on the collapse vs coexist decision. Construction-guide §5.3 format:[STILL-OPEN — gates on product-guide feature spec ratification]. -
Gap flag GF-2 — Backfill for any pre-existing
workspaces.application_type_id='product_guide'rows. As of S243, 0 prodworkspacesrows carry a product-guide application type (only 4intelligencerows verified S234 perarchitecture/04-workspace-types.md§2.2 line 40). If feature-build cycle precedes any product-guide workspace creation, backfill is null; if feature-build cycle happens after some workspaces are created withapplication_type='product_guide'(e.g. via admin UI v1.1 or migration), the feature TECH.md must include aINSERT INTO product_guide_workspaces (workspace_id) SELECT id FROM workspaces WHERE application_type_id = (SELECT id FROM application_types WHERE key='product_guide')backfill step. Phase 1 does not pre-empt this — feature spec owns. Category (construction-guide §5.2): Tech spec needed (the backfill SQL is a feature-spec implementation detail conditional on sequencing). Sources checked:architecture/04-workspace-types.md§2.2 (4-intel rows / 0-product-guide rows audit),pre-s244-project-feedback.mdItem 15 (NEW Phase 1 specs),application_typesseed list in T2 sub-task 1. Prerequisite work: product-guide feature TECH spec drafting at feature-build kickoff. Construction-guide §5.3 format:[STILL-OPEN — gates on feature-build sequencing relative to first product-guide workspace creation]. -
GF-3 — MCP tool integration shape for
product_guide_workspaces. The existinglib/mcp/tools/guides.ts:52-105MCP tools (list_guidesetc.) operate onguides. Whether the feature build exposes the satellite via a separatelist_product_guide_workspacestool, or extendsguides.tsto JOIN through, or surfaces a unified workspace-listing tool that includes satellite columns — open. Category (construction-guide §5.2): Tech spec needed (MCP surface decisions live in TECH territory; the feature TECH spec selects one of the three shapes). Sources checked:lib/mcp/tools/guides.ts:52-105, 237-283, 356-548, 680(existing surface),06-mcp-tooling.md(architecture sub-doc surface), product-guide feature spec (not yet drafted). Prerequisite work: product-guide feature TECH spec MCP-surface decision at feature-build kickoff. Construction-guide §5.3 format:[STILL-OPEN — gates on product-guide feature MCP scope decision].
Cross-doc cross-references
Section titled “Cross-doc cross-references”| Doc | What it references |
|---|---|
./PRODUCT.md | Phase 1 reserved-seat invariants (delegates S-1..S-8 to RWS PRODUCT.md). |
docs/specs/reserved-workspace-seats/{PRODUCT,TECH}.md | Parent reserved-seat spec; this seat is one of five it covers. |
docs/specs/id-38-rls-pattern/{PRODUCT,TECH}.md | RLS auto-enable + grants-helper pattern this seat leverages. |
docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md §4.2 T2 sub-task 7 + §5 row “product-guide-workspaces” + §8 Wave 0 ordering | Implementation sequencing — this spec lands Wave 0; migration lands Wave 2 T2. |
docs/plans/phase-0-investigation/architecture/04-workspace-types.md §3.2 + §4.2 | Pattern substrate; names the satellite verbatim. |
docs/ontology/25-application-type.md line 20-22 + 50 | application_types.key='product_guide' row binding. |
docs/specs/p0-product-guide-section-alignment-spec.md | Orthogonal content-model spec for guides.guide_type='product' rows; integration deferred to feature build. |
Future docs/specs/product-guide/{PRODUCT,TECH}.md (or equivalent feature-spec path) | Owner of per-app column lists + integration shape with guides/guide_sections. |
docs/reference/SCHEMA-QUICK-REFERENCE.md §workspaces | Post-apply update — add the new satellite row alongside the other 4 reserved seats. |
Source-doc supersession
Section titled “Source-doc supersession”Not applicable — NEW spec. No predecessor.
Heritage docs feeding this sub-doc
Section titled “Heritage docs feeding this sub-doc”| Doc | Date | Status | Useful for |
|---|---|---|---|
docs/specs/reserved-workspace-seats/{PRODUCT,TECH}.md | 15/05/2026 (S240 NEW) | [CURRENT-CANONICAL] for the reserved-seat pattern. | S-1..S-8 invariants inherited verbatim; T-1..T-8 implementation patterns referenced inline. |
docs/plans/phase-0-investigation/architecture/04-workspace-types.md §3.2 + §4.2 | 14-15/05/2026 (S239 + S240 ratifications) | [CURRENT-CANONICAL] for the satellite pattern + S240 upfront-seats decision + the product_guide baseline application type row. | Substrate for T-1 (seat shape) + T-6 (naming). |
docs/specs/id-31-canonical-pipeline-implementation-plan/PLAN.md §4.2 + §5 + §8 | 18/05/2026 + 20/05/2026 S243 ratifications | [CURRENT-CANONICAL] for the Wave 0 spec drafting requirement + Wave 2 migration sequencing. | Substrate for the Wave 0 gate identification + T-2 deferral framing. |
docs/plans/phase-0-investigation/pre-s244-project-feedback.md Item 15 | 20/05/2026 (S243 interim) | [CURRENT-CANONICAL] for the RATIFIED-S243 Item 15 ratification of this NEW spec. | Source ratification — the only doc that mandates this spec’s existence. |
docs/specs/rls-pattern/{PRODUCT,TECH}.md | 14/05/2026 (S239 NEW) | [CURRENT-CANONICAL] for RLS auto-enable + grants pattern. | T-3 leverage. |
docs/ontology/25-application-type.md | (S235 ratified) | [CURRENT-CANONICAL] for product_guide baseline application type row. | T-6 cross-ref + GF-1 collapse-decision substrate. |
docs/specs/p0-product-guide-section-alignment-spec.md | 23/04/2026 (S190 draft) | [CURRENT-CANONICAL] for guides.guide_type='product' content model — orthogonal to satellite seat. | T-5 existing-code anchor; GF-1 substrate. |
supabase/migrations/20260416102457_pre_squash_reconciliation.sql lines 3804-3813 | (live schema) | [CURRENT-CANONICAL] for live guides table shape with guide_type CHECK. | T-5 existing-code anchor; current-state evidence. |
lib/intelligence/guide-generator.ts lines 33-150 | (live code) | [CURRENT-CANONICAL] for the precedent pattern of workspace → guides binding (via intelligence_workspaces). | T-5 integration anchor — direct precedent feature-spec may follow. |
End of TECH spec. Numbered invariants and behaviour anchors in ./PRODUCT.md.