@polymorphism-tech/morph-spec 4.13.0 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CLAUDE.md +7 -7
  2. package/README.md +9 -7
  3. package/claude-plugin.json +1 -1
  4. package/docs/CHEATSHEET.md +6 -7
  5. package/docs/QUICKSTART.md +1 -1
  6. package/framework/agents/ai-agents/ai-system-architect.md +2 -0
  7. package/framework/agents/ai-agents/vector-search-expert.md +233 -0
  8. package/framework/agents/architecture/seo-growth-hacker.md +2 -0
  9. package/framework/agents/architecture/standards-architect.md +3 -0
  10. package/framework/agents/backend/dotnet-senior.md +3 -0
  11. package/framework/agents/backend/ef-modeler.md +2 -0
  12. package/framework/agents/backend/hangfire-orchestrator.md +2 -0
  13. package/framework/agents/backend/ms-agent-expert.md +2 -0
  14. package/framework/agents/backend/supabase-expert.md +256 -0
  15. package/framework/agents/frontend/css-specialist.md +2 -0
  16. package/framework/agents/frontend/nextjs-expert.md +3 -0
  17. package/framework/agents/frontend/ui-ux-designer.md +3 -1
  18. package/framework/agents/infrastructure/infra-architect.md +3 -0
  19. package/framework/agents/integrations/asaas-financial.md +2 -0
  20. package/framework/agents/integrations/clerk-auth.md +2 -0
  21. package/framework/agents/integrations/resend-email.md +2 -0
  22. package/framework/agents.json +1077 -1040
  23. package/framework/commands/morph-apply.md +0 -2
  24. package/framework/commands/morph-preflight.md +192 -247
  25. package/framework/commands/morph-proposal.md +210 -238
  26. package/framework/commands/morph-status.md +72 -92
  27. package/framework/phases.json +162 -162
  28. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +1 -1
  29. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +2 -2
  30. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +1 -1
  31. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +1 -1
  32. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
  33. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
  34. package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -170
  35. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
  36. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  37. package/package.json +1 -1
  38. package/src/utils/agents-installer.js +58 -18
  39. package/framework/agents/integrations/hangfire-integration.md +0 -69
package/CLAUDE.md CHANGED
@@ -51,16 +51,16 @@ No build step — pure ESM JavaScript, runs directly via Node.js 18+.
51
51
  - `installers/` — Agents, skills, hooks installers for target projects
52
52
  - **`src/utils/`** — Shared utilities (logger, banner, file-copier, claude-settings-manager, etc.)
53
53
  - **`framework/`** — Metadata installed into target projects (READ-ONLY at runtime):
54
- - `agents.json` (v4.0.0, 46 agents in 4 tiers)
55
- - `phases.json` (8 phases + sync)
56
- - `standards/STANDARDS.json` (86 entries)
57
- - `hooks/claude-code/` — Hook scripts (10 hooks, fail-open design)
54
+ - `agents.json` (v4.0.0)
55
+ - `phases.json` (7 phases incl. sync)
56
+ - `standards/STANDARDS.json`
57
+ - `hooks/claude-code/` — Hook scripts (fail-open design)
58
58
  - `skills/` — Morph skills (level-0-meta + level-1-workflows)
59
59
  - `templates/` — Handlebars templates for code generation
60
60
 
61
61
  ### Key Architectural Patterns
62
62
 
63
- **Dual-layer phase tracking:** Phase is derived from filesystem (`derivePhase()` scans for highest-numbered phase folder) — state.json only overrides for lightweight phases (setup, clarify, sync).
63
+ **Dual-layer phase tracking:** Phase is derived from filesystem (`derivePhase()` scans for highest-numbered phase folder) — state.json only overrides for lightweight phases (sync).
64
64
 
65
65
  **Output schema as single source of truth:** `src/core/paths/output-schema.js` defines all output types. Run `npm run generate` after modifying it to update derived reference files.
66
66
 
@@ -70,12 +70,12 @@ No build step — pure ESM JavaScript, runs directly via Node.js 18+.
70
70
 
71
71
  **Atomic state writes:** `state-manager.js` writes to a process-ID temp file then renames, preventing corruption from concurrent CLI invocations.
72
72
 
73
- **Stack-aware filtering:** Assets declare `stacks: ['dotnet', 'blazor']` in YAML frontmatter. `setup-infra.js` reads `config.json → project.stack`, splits into tags, and installs only matching assets. `stacks: ['*']` = universal.
73
+ **Stack-aware filtering:** Assets declare `stacks: ['dotnet']` in YAML frontmatter. `setup-infra.js` reads `config.json → project.stack`, splits into tags, and installs only matching assets. `stacks: ['*']` = universal.
74
74
 
75
75
  ### Phase Sequence
76
76
 
77
77
  ```
78
- proposal → setup → [uiux] → design → clarify → plan → tasks → implement → [sync]
78
+ proposal → [uiux] → design → plan → tasks → implement → [sync]
79
79
  ```
80
80
 
81
81
  Phases in brackets are optional. Approval gates exist at: proposal, design, plan, tasks, uiux.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > Spec-driven development framework for multi-stack projects. Turns feature requests into implementation-ready code through structured, AI-orchestrated phases.
4
4
 
5
5
  **Package:** `@polymorphism-tech/morph-spec`
6
- **Version:** 4.13.0
6
+ **Version:** 4.15.0
7
7
  **Requires:** Node.js 18+, Claude Code
8
8
 
9
9
  ---
@@ -88,7 +88,7 @@ your-project/
88
88
  Features move through structured phases. Some are optional depending on feature type.
89
89
 
90
90
  ```
91
- proposal → setup → [uiux] → design → clarify → tasks → implement → [sync]
91
+ proposal → [uiux] → design → plan → tasks → implement → [sync]
92
92
  ```
93
93
 
94
94
  Phases in brackets are optional. `uiux` applies to UI-heavy features. `sync` is a post-implementation reconciliation step.
@@ -101,14 +101,16 @@ Phases in brackets are optional. `uiux` applies to UI-heavy features. `sync` is
101
101
  | Proposal | `0-proposal/` | `proposal.md` |
102
102
  | UI/UX | `1-ui/` | `design-system.md`, `mockups.md`, `components.md`, `flows.md` |
103
103
  | Design | `2-design/` | `spec.md`, `contracts.cs`, `decisions.md` |
104
- | Tasks | `3-tasks/` | `tasks.md` |
105
- | Implement | `4-implement/` | `recap.md` |
104
+ | Plan | `3-plan/` | `plan.md` |
105
+ | Tasks | `4-tasks/` | `tasks.md` |
106
+ | Implement | `5-implement/` | `recap.md` |
106
107
 
107
108
 
108
109
  ### Approval gates
109
110
 
110
- - **Design gate** — Spec must be approved before moving to Tasks.
111
- - **Implementation gate** — Task list must be approved before implementation starts.
111
+ - **Design gate** — Spec must be approved before moving to Plan.
112
+ - **Plan gate** — Plan must be approved before moving to Tasks.
113
+ - **Tasks gate** — Task list must be approved before implementation starts.
112
114
 
113
115
  Check gate status:
114
116
 
@@ -362,4 +364,4 @@ Code generated by morph-spec (contracts, templates, implementation output) belon
362
364
 
363
365
  ---
364
366
 
365
- *morph-spec v4.13.0 by [Polymorphism Tech](https://polymorphism.tech)*
367
+ *morph-spec v4.15.0 by [Polymorphism Tech](https://polymorphism.tech)*
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "morph-spec",
3
- "version": "4.13.0",
3
+ "version": "4.15.0",
4
4
  "displayName": "MORPH-SPEC Framework",
5
5
  "description": "Spec-driven development with 38 agents and 8-phase workflow for .NET/Blazor/Next.js/Azure",
6
6
  "publisher": "polymorphism-tech",
@@ -17,7 +17,7 @@ morph-spec --version
17
17
  ## Phase workflow
18
18
 
19
19
  ```
20
- proposal → setup → [uiux] → design → clarify → tasks → implement → [sync]
20
+ proposal → [uiux] → design → plan → tasks → implement → [sync]
21
21
  ```
22
22
 
23
23
  Phases in brackets are optional.
@@ -25,13 +25,12 @@ Phases in brackets are optional.
25
25
  | Phase | Directory | Output files | Gate |
26
26
  |-------|-----------|--------------|------|
27
27
  | proposal | `0-proposal/` | `proposal.md` | ✅ Approval |
28
- | setup | *(no output)* | context loaded | — |
29
28
  | uiux *(optional)* | `1-ui/` | `design-system.md`, `mockups.md`, `components.md`, `flows.md` | ✅ Approval |
30
29
  | design | `2-design/` | `spec.md`, `contracts.cs`, `decisions.md` | ✅ Approval |
31
- | clarify | `2-design/` | spec updated | — |
32
- | tasks | `3-tasks/` | `tasks.md` | ✅ Approval |
33
- | implement | `4-implement/` | code + `recap.md` | — |
34
- | sync *(optional)* | `.morph/context/` | standards updated | — |
30
+ | plan | `3-plan/` | `plan.md` | ✅ Approval |
31
+ | tasks | `4-tasks/` | `tasks.md` | ✅ Approval |
32
+ | implement | `5-implement/` | code + `recap.md` | — |
33
+ | sync *(optional)* | — | standards updated | — |
35
34
 
36
35
  ---
37
36
 
@@ -197,4 +196,4 @@ These files are never edited directly. Use CLI commands or `morph-spec update` i
197
196
 
198
197
  ---
199
198
 
200
- *morph-spec v4.13.0 by Polymorphism Tech*
199
+ *morph-spec v4.15.0 by Polymorphism Tech*
@@ -197,4 +197,4 @@ morph-spec doctor
197
197
 
198
198
  ---
199
199
 
200
- *morph-spec v4.13.0 by Polymorphism Tech*
200
+ *morph-spec v4.15.0 by Polymorphism Tech*
@@ -2,6 +2,8 @@
2
2
  name: ai-system-architect
3
3
  description: AI System Architect specialist for designing multi-agent systems, LLM orchestration, RAG pipelines, and Semantic Kernel patterns. Use when designing AI agent architectures, implementing LLM-powered features, building RAG pipelines, or integrating Microsoft Agent Framework.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
+ color: orange
6
+ effort: high
5
7
  ---
6
8
 
7
9
  # AI System Architect
@@ -0,0 +1,233 @@
1
+ ---
2
+ name: vector-search-expert
3
+ description: Vector Search & RAG specialist for embedding pipelines, pgvector indexes, semantic search, hybrid search, and retrieval-augmented generation. Use when implementing embedding generation, vector similarity search, RAG pipelines, or hybrid full-text + vector search.
4
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
+ color: yellow
6
+ effort: medium
7
+ ---
8
+
9
+ # Vector Search & RAG Specialist
10
+
11
+ Expert in embedding pipelines, pgvector, semantic search, and retrieval-augmented generation.
12
+
13
+ > **Ref:** `framework/standards/backend/database/vector-search-rag.md` — Chunking, embedding, retrieval patterns
14
+
15
+ ---
16
+
17
+ ## Embedding Pipeline
18
+
19
+ ```
20
+ Documents → Chunking → Embedding → pgvector Storage → Retrieval → LLM
21
+ ```
22
+
23
+ ### Chunking Strategies
24
+
25
+ | Strategy | Method | Best For | Chunk Size |
26
+ |----------|--------|----------|------------|
27
+ | **Paragraph** | Split by `\n\n` | General text | 200-500 tokens |
28
+ | **Markdown Headers** | Split by `#`, `##` | Documentation | Variable |
29
+ | **Token-based** | Fixed token windows | Uniform chunks | 256-512 tokens |
30
+ | **Semantic** | Cosine similarity threshold | Highest quality | Variable |
31
+
32
+ **Always overlap:** 10-20% overlap between chunks prevents context loss at boundaries.
33
+
34
+ ```csharp
35
+ // Simple paragraph chunker
36
+ public static IEnumerable<string> ChunkByParagraph(string text, int maxTokens = 500)
37
+ {
38
+ var paragraphs = text.Split("\n\n", StringSplitOptions.RemoveEmptyEntries);
39
+ var current = new StringBuilder();
40
+ var currentTokens = 0;
41
+
42
+ foreach (var para in paragraphs)
43
+ {
44
+ var paraTokens = EstimateTokens(para);
45
+ if (currentTokens + paraTokens > maxTokens && current.Length > 0)
46
+ {
47
+ yield return current.ToString().Trim();
48
+ current.Clear();
49
+ currentTokens = 0;
50
+ }
51
+ current.AppendLine(para);
52
+ currentTokens += paraTokens;
53
+ }
54
+ if (current.Length > 0) yield return current.ToString().Trim();
55
+ }
56
+ ```
57
+
58
+ ---
59
+
60
+ ## Embedding Generation
61
+
62
+ ```csharp
63
+ // Using Microsoft.Extensions.AI
64
+ public class EmbeddingService(IEmbeddingGenerator<string, Embedding<float>> generator)
65
+ {
66
+ public async Task<float[]> GenerateAsync(string text, CancellationToken ct = default)
67
+ {
68
+ var result = await generator.GenerateAsync([text], cancellationToken: ct);
69
+ return result[0].Vector.ToArray();
70
+ }
71
+
72
+ public async Task<IReadOnlyList<float[]>> GenerateBatchAsync(
73
+ IEnumerable<string> texts, CancellationToken ct = default)
74
+ {
75
+ var result = await generator.GenerateAsync(texts.ToList(), cancellationToken: ct);
76
+ return result.Select(e => e.Vector.ToArray()).ToList();
77
+ }
78
+ }
79
+
80
+ // Registration
81
+ builder.Services.AddEmbeddingGenerator(b => b
82
+ .UseOpenTelemetry()
83
+ .UseLogging()
84
+ .Use(new OpenAIEmbeddingGenerator(
85
+ new OpenAIClient(apiKey),
86
+ "text-embedding-3-small"))); // 1536 dimensions
87
+ ```
88
+
89
+ ---
90
+
91
+ ## pgvector Storage & Search
92
+
93
+ ### Table schema
94
+
95
+ ```sql
96
+ CREATE TABLE public.embeddings (
97
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
98
+ source_id UUID NOT NULL,
99
+ source_type TEXT NOT NULL, -- 'document', 'faq', 'article'
100
+ chunk_index INT NOT NULL,
101
+ content TEXT NOT NULL,
102
+ embedding vector(1536) NOT NULL,
103
+ metadata JSONB DEFAULT '{}'::jsonb,
104
+ created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
105
+ UNIQUE(source_id, chunk_index)
106
+ );
107
+
108
+ -- HNSW index (fast, recommended for < 1M vectors)
109
+ CREATE INDEX idx_embeddings_hnsw ON public.embeddings
110
+ USING hnsw (embedding vector_cosine_ops)
111
+ WITH (m = 16, ef_construction = 64);
112
+
113
+ -- IVFFlat index (better for > 1M vectors)
114
+ -- CREATE INDEX idx_embeddings_ivf ON public.embeddings
115
+ -- USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
116
+ ```
117
+
118
+ ### Similarity search
119
+
120
+ ```sql
121
+ -- Cosine similarity (1 = identical, 0 = unrelated)
122
+ SELECT id, content, metadata,
123
+ 1 - (embedding <=> $1::vector) AS similarity
124
+ FROM public.embeddings
125
+ WHERE 1 - (embedding <=> $1::vector) > 0.78
126
+ ORDER BY embedding <=> $1::vector
127
+ LIMIT 5;
128
+ ```
129
+
130
+ ### Hybrid search (vector + full-text)
131
+
132
+ ```sql
133
+ -- Combine vector similarity with PostgreSQL full-text search
134
+ CREATE OR REPLACE FUNCTION hybrid_search(
135
+ query_text TEXT,
136
+ query_embedding vector(1536),
137
+ match_count INT DEFAULT 5,
138
+ vector_weight FLOAT DEFAULT 0.7,
139
+ text_weight FLOAT DEFAULT 0.3
140
+ )
141
+ RETURNS TABLE (id UUID, content TEXT, score FLOAT)
142
+ LANGUAGE plpgsql AS $$
143
+ BEGIN
144
+ RETURN QUERY
145
+ WITH vector_results AS (
146
+ SELECT e.id, e.content,
147
+ 1 - (e.embedding <=> query_embedding) AS vscore
148
+ FROM public.embeddings e
149
+ ORDER BY e.embedding <=> query_embedding
150
+ LIMIT match_count * 3
151
+ ),
152
+ text_results AS (
153
+ SELECT e.id, e.content,
154
+ ts_rank(to_tsvector('english', e.content), plainto_tsquery('english', query_text)) AS tscore
155
+ FROM public.embeddings e
156
+ WHERE to_tsvector('english', e.content) @@ plainto_tsquery('english', query_text)
157
+ LIMIT match_count * 3
158
+ )
159
+ SELECT COALESCE(v.id, t.id),
160
+ COALESCE(v.content, t.content),
161
+ (COALESCE(v.vscore, 0) * vector_weight + COALESCE(t.tscore, 0) * text_weight) AS score
162
+ FROM vector_results v
163
+ FULL OUTER JOIN text_results t ON v.id = t.id
164
+ ORDER BY score DESC
165
+ LIMIT match_count;
166
+ END;
167
+ $$;
168
+ ```
169
+
170
+ ---
171
+
172
+ ## RAG Tool for Agent Framework
173
+
174
+ ```csharp
175
+ public class KnowledgeBaseTool(
176
+ EmbeddingService embeddings,
177
+ ISupabaseClient supabase)
178
+ {
179
+ [Description("Search the knowledge base for relevant information")]
180
+ public async Task<string> SearchAsync(
181
+ [Description("Natural language search query")] string query,
182
+ [Description("Maximum results to return")] int topK = 5,
183
+ CancellationToken ct = default)
184
+ {
185
+ var embedding = await embeddings.GenerateAsync(query, ct);
186
+
187
+ var results = await supabase.Rpc("match_embeddings", new
188
+ {
189
+ query_embedding = embedding,
190
+ match_threshold = 0.78,
191
+ match_count = topK
192
+ }, ct);
193
+
194
+ return string.Join("\n\n---\n\n",
195
+ results.Select(r => $"[Score: {r.Similarity:F2}]\n{r.Content}"));
196
+ }
197
+ }
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Index Selection Guide
203
+
204
+ | Vectors | Recommended | Why |
205
+ |---------|-------------|-----|
206
+ | < 10K | No index (sequential scan) | Index overhead not worth it |
207
+ | 10K - 1M | HNSW (m=16, ef=64) | Fast, good recall |
208
+ | 1M+ | IVFFlat (lists=sqrt(n)) | Lower memory, acceptable recall |
209
+
210
+ ### Tuning HNSW
211
+
212
+ - `m` (connections per node): higher = better recall, more memory. Default 16.
213
+ - `ef_construction` (build-time search depth): higher = better index, slower build. Default 64.
214
+ - `ef_search` (query-time): `SET hnsw.ef_search = 100;` for better recall at query time.
215
+
216
+ ---
217
+
218
+ ## Checklist
219
+
220
+ - [ ] Chunking strategy selected and tested with real data
221
+ - [ ] Chunk overlap configured (10-20%)
222
+ - [ ] Embedding model chosen (text-embedding-3-small for cost, text-embedding-3-large for quality)
223
+ - [ ] pgvector extension enabled
224
+ - [ ] HNSW or IVFFlat index created based on vector count
225
+ - [ ] Similarity threshold tuned (start at 0.78, adjust by domain)
226
+ - [ ] Hybrid search implemented if full-text relevance matters
227
+ - [ ] Batch embedding for initial ingestion (not one-by-one)
228
+ - [ ] RLS policies on embeddings table
229
+ - [ ] Source tracking (source_id + source_type) for updates/deletes
230
+
231
+ ---
232
+
233
+ *MORPH-SPEC by Polymorphism Tech*
@@ -2,6 +2,8 @@
2
2
  name: seo-growth-hacker
3
3
  description: SEO and Growth specialist for technical SEO, Core Web Vitals optimization, content strategy, and organic growth for SaaS and landing pages. Use when optimizing for search engine ranking, improving Lighthouse scores, implementing SEO for Next.js pages, or planning content-driven growth.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
+ color: pink
6
+ effort: medium
5
7
  ---
6
8
 
7
9
  # SEO Growth Hacker
@@ -2,6 +2,9 @@
2
2
  name: standards-architect
3
3
  description: Standards Architect (Tier 1 Orchestrator) that enforces MORPH-SPEC naming conventions, coding standards, and cross-cutting compliance across all outputs. Always active in MORPH-SPEC workflows. Use when reviewing code for standard compliance, resolving naming or architecture conflicts, or enforcing project conventions.
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
+ color: red
6
+ effort: high
7
+ permissionMode: acceptEdits
5
8
  ---
6
9
 
7
10
  # Standards Architect
@@ -4,6 +4,9 @@ description: Senior .NET engineer and Backend Squad Leader for VSA (Vertical Sli
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  stacks:
6
6
  - dotnet
7
+ color: blue
8
+ effort: medium
9
+ permissionMode: acceptEdits
7
10
  ---
8
11
 
9
12
  # .NET Senior Engineer
@@ -4,6 +4,8 @@ description: Entity Framework Modeler specialist for database schema design, EF
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  stacks:
6
6
  - dotnet
7
+ color: teal
8
+ effort: medium
7
9
  ---
8
10
 
9
11
  # EF Modeler
@@ -4,6 +4,8 @@ description: Hangfire Orchestrator specialist for background job design, recurri
4
4
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  stacks:
6
6
  - hangfire
7
+ color: teal
8
+ effort: medium
7
9
  ---
8
10
 
9
11
  # Hangfire Orchestrator
@@ -5,6 +5,8 @@ allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
5
  stacks:
6
6
  - semantic-kernel
7
7
  - ms-agents
8
+ color: yellow
9
+ effort: medium
8
10
  ---
9
11
 
10
12
  # Agent Framework Expert
@@ -0,0 +1,256 @@
1
+ ---
2
+ name: supabase-expert
3
+ description: Supabase & PostgreSQL specialist for RLS policies, auth integration, pgvector, Realtime subscriptions, Edge Functions, and migration management. Use when designing database schemas, implementing Row Level Security, setting up auth flows, or working with pgvector embeddings.
4
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
+ stacks:
6
+ - supabase
7
+ color: teal
8
+ effort: medium
9
+ ---
10
+
11
+ # Supabase & PostgreSQL Specialist
12
+
13
+ Expert in Supabase auth, Row Level Security, Realtime, Edge Functions, and pgvector.
14
+
15
+ > **Ref:** `framework/standards/infrastructure/supabase/` — RLS, auth, storage, pgvector standards
16
+
17
+ ## Connection Pooling
18
+
19
+ ```
20
+ # Direct connection (migrations only)
21
+ postgresql://postgres:[password]@db.[project].supabase.co:5432/postgres
22
+
23
+ # PgBouncer (application — ALWAYS use this)
24
+ postgresql://postgres.[project]:[password]@aws-0-[region].pooler.supabase.com:6543/postgres
25
+ ```
26
+
27
+ **Rule:** Application code ALWAYS connects via PgBouncer (port 6543). Direct connections (port 5432) only for migrations and schema changes.
28
+
29
+ ---
30
+
31
+ ## Row Level Security (RLS)
32
+
33
+ ### Enable RLS on every table
34
+
35
+ ```sql
36
+ ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
37
+ ```
38
+
39
+ ### Common RLS Patterns
40
+
41
+ ```sql
42
+ -- User owns the row
43
+ CREATE POLICY "Users can view own documents"
44
+ ON public.documents FOR SELECT
45
+ USING (auth.uid() = user_id);
46
+
47
+ -- User can insert own rows
48
+ CREATE POLICY "Users can insert own documents"
49
+ ON public.documents FOR INSERT
50
+ WITH CHECK (auth.uid() = user_id);
51
+
52
+ -- User can update own rows
53
+ CREATE POLICY "Users can update own documents"
54
+ ON public.documents FOR UPDATE
55
+ USING (auth.uid() = user_id)
56
+ WITH CHECK (auth.uid() = user_id);
57
+
58
+ -- User can delete own rows
59
+ CREATE POLICY "Users can delete own documents"
60
+ ON public.documents FOR DELETE
61
+ USING (auth.uid() = user_id);
62
+
63
+ -- Service role bypass (for backend API)
64
+ CREATE POLICY "Service role full access"
65
+ ON public.documents FOR ALL
66
+ USING (auth.role() = 'service_role');
67
+
68
+ -- Team-based access
69
+ CREATE POLICY "Team members can view"
70
+ ON public.documents FOR SELECT
71
+ USING (
72
+ team_id IN (
73
+ SELECT team_id FROM public.team_members
74
+ WHERE user_id = auth.uid()
75
+ )
76
+ );
77
+ ```
78
+
79
+ ### RLS with Clerk JWT (custom claims)
80
+
81
+ ```sql
82
+ -- Extract Clerk user ID from JWT
83
+ CREATE OR REPLACE FUNCTION auth.clerk_user_id()
84
+ RETURNS TEXT AS $$
85
+ SELECT coalesce(
86
+ current_setting('request.jwt.claims', true)::json->>'sub',
87
+ ''
88
+ );
89
+ $$ LANGUAGE sql STABLE;
90
+
91
+ -- Use in RLS policies
92
+ CREATE POLICY "Clerk users own rows"
93
+ ON public.documents FOR ALL
94
+ USING (clerk_user_id = auth.clerk_user_id());
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Migrations
100
+
101
+ ```bash
102
+ # Create new migration
103
+ npx supabase migration new create_documents_table
104
+
105
+ # Apply locally
106
+ npx supabase db reset
107
+
108
+ # Push to remote
109
+ npx supabase db push
110
+
111
+ # Diff local vs remote
112
+ npx supabase db diff --use-migra
113
+
114
+ # Lint for common issues
115
+ npx supabase db lint --level warning
116
+ ```
117
+
118
+ ### Migration file structure
119
+
120
+ ```sql
121
+ -- supabase/migrations/20240101000000_create_documents_table.sql
122
+
123
+ CREATE TABLE public.documents (
124
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
125
+ user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
126
+ title TEXT NOT NULL,
127
+ content TEXT,
128
+ created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
129
+ updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
130
+ );
131
+
132
+ -- Always enable RLS
133
+ ALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;
134
+
135
+ -- Always add indexes for filtered columns
136
+ CREATE INDEX idx_documents_user_id ON public.documents(user_id);
137
+ CREATE INDEX idx_documents_created_at ON public.documents(created_at DESC);
138
+
139
+ -- RLS policies
140
+ CREATE POLICY "Users manage own documents"
141
+ ON public.documents FOR ALL
142
+ USING (auth.uid() = user_id)
143
+ WITH CHECK (auth.uid() = user_id);
144
+ ```
145
+
146
+ ---
147
+
148
+ ## pgvector (Embeddings)
149
+
150
+ ### Setup
151
+
152
+ ```sql
153
+ CREATE EXTENSION IF NOT EXISTS vector;
154
+
155
+ CREATE TABLE public.embeddings (
156
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
157
+ document_id UUID REFERENCES public.documents(id) ON DELETE CASCADE,
158
+ content TEXT NOT NULL,
159
+ embedding vector(1536) NOT NULL, -- OpenAI text-embedding-3-small
160
+ metadata JSONB DEFAULT '{}'::jsonb,
161
+ created_at TIMESTAMPTZ DEFAULT now() NOT NULL
162
+ );
163
+
164
+ -- HNSW index for fast similarity search (cosine distance)
165
+ CREATE INDEX idx_embeddings_vector ON public.embeddings
166
+ USING hnsw (embedding vector_cosine_ops)
167
+ WITH (m = 16, ef_construction = 64);
168
+ ```
169
+
170
+ ### Similarity search function
171
+
172
+ ```sql
173
+ CREATE OR REPLACE FUNCTION match_embeddings(
174
+ query_embedding vector(1536),
175
+ match_threshold FLOAT DEFAULT 0.78,
176
+ match_count INT DEFAULT 5
177
+ )
178
+ RETURNS TABLE (
179
+ id UUID,
180
+ content TEXT,
181
+ metadata JSONB,
182
+ similarity FLOAT
183
+ )
184
+ LANGUAGE plpgsql AS $$
185
+ BEGIN
186
+ RETURN QUERY
187
+ SELECT
188
+ e.id,
189
+ e.content,
190
+ e.metadata,
191
+ 1 - (e.embedding <=> query_embedding) AS similarity
192
+ FROM public.embeddings e
193
+ WHERE 1 - (e.embedding <=> query_embedding) > match_threshold
194
+ ORDER BY e.embedding <=> query_embedding
195
+ LIMIT match_count;
196
+ END;
197
+ $$;
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Realtime Subscriptions
203
+
204
+ ```typescript
205
+ // Subscribe to changes on a table
206
+ const channel = supabase
207
+ .channel('documents-changes')
208
+ .on('postgres_changes',
209
+ { event: '*', schema: 'public', table: 'documents', filter: `user_id=eq.${userId}` },
210
+ (payload) => {
211
+ console.log('Change:', payload.eventType, payload.new);
212
+ }
213
+ )
214
+ .subscribe();
215
+
216
+ // Cleanup
217
+ channel.unsubscribe();
218
+ ```
219
+
220
+ **Rule:** Always filter subscriptions by user/team — never subscribe to full table changes.
221
+
222
+ ---
223
+
224
+ ## Storage (File Uploads)
225
+
226
+ ```sql
227
+ -- Create bucket
228
+ INSERT INTO storage.buckets (id, name, public)
229
+ VALUES ('avatars', 'avatars', true);
230
+
231
+ -- RLS for storage
232
+ CREATE POLICY "Users upload own avatar"
233
+ ON storage.objects FOR INSERT
234
+ WITH CHECK (
235
+ bucket_id = 'avatars' AND
236
+ auth.uid()::text = (storage.foldername(name))[1]
237
+ );
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Checklist
243
+
244
+ - [ ] PgBouncer (port 6543) used for all application connections
245
+ - [ ] RLS enabled on ALL public tables
246
+ - [ ] RLS policies cover SELECT, INSERT, UPDATE, DELETE
247
+ - [ ] Service role policy exists for backend API access
248
+ - [ ] Migrations use `npx supabase migration new` (not manual SQL)
249
+ - [ ] Indexes on all frequently filtered columns
250
+ - [ ] pgvector: HNSW index with appropriate m/ef_construction values
251
+ - [ ] Realtime subscriptions filtered by user/team
252
+ - [ ] Storage buckets have RLS policies
253
+
254
+ ---
255
+
256
+ *MORPH-SPEC by Polymorphism Tech*