@polymorphism-tech/morph-spec 4.16.0 → 4.18.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 (107) hide show
  1. package/CLAUDE.md +36 -0
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +3 -0
  4. package/bin/task-manager.js +999 -962
  5. package/claude-plugin.json +1 -1
  6. package/docs/CHEATSHEET.md +1 -1
  7. package/docs/QUICKSTART.md +1 -1
  8. package/framework/agents/ai-agents/vector-search-expert.md +247 -233
  9. package/framework/agents/backend/ms-agent-expert.md +1 -1
  10. package/framework/agents/backend/neon-expert.md +379 -0
  11. package/framework/agents/frontend/gsap-animator.md +131 -0
  12. package/framework/agents/integrations/neon-auth.md +151 -0
  13. package/framework/agents.json +1183 -1085
  14. package/framework/commands/morph-preflight.md +200 -192
  15. package/framework/hooks/claude-code/session-start/inject-morph-context.js +1 -1
  16. package/framework/rules/gsap-standards.md +13 -0
  17. package/framework/rules/neon-auth-standards.md +13 -0
  18. package/framework/rules/neon-standards.md +26 -0
  19. package/framework/skills/level-0-meta/mcp-registry.json +1 -1
  20. package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +472 -472
  21. package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +1 -1
  22. package/framework/skills/level-0-meta/morph-init/SKILL.md +12 -12
  23. package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +5 -5
  24. package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +5 -5
  25. package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +7 -7
  26. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +24 -24
  27. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +12 -12
  28. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +9 -9
  29. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
  30. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
  31. package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -143
  32. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
  33. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  34. package/framework/standards/STANDARDS.json +197 -116
  35. package/framework/standards/ai-agents/production.md +1 -0
  36. package/framework/standards/ai-agents/setup.md +3 -2
  37. package/framework/standards/ai-agents/workflows.md +1 -0
  38. package/framework/standards/architecture/vertical-slice/vertical-slice.md +4 -4
  39. package/framework/standards/backend/database/postgresql/database.md +63 -83
  40. package/framework/standards/backend/dotnet/scalar-ui.md +172 -172
  41. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +274 -274
  42. package/framework/standards/backend/integrations/asaas/asaas-api.md +2 -2
  43. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +364 -0
  44. package/framework/standards/frontend/design-system/animations.md +9 -0
  45. package/framework/standards/frontend/gsap/gsap-core.md +463 -0
  46. package/framework/standards/frontend/gsap/gsap-plugins.md +294 -0
  47. package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +318 -0
  48. package/framework/standards/frontend/nextjs/motion-patterns.md +1 -0
  49. package/framework/standards/frontend/nextjs/nextjs-patterns.md +47 -37
  50. package/framework/standards/infrastructure/docker/easypanel-deploy.md +4 -8
  51. package/framework/standards/infrastructure/neon/neon-pgrag.md +239 -0
  52. package/framework/standards/infrastructure/neon/neon-pgvector.md +236 -0
  53. package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +310 -0
  54. package/framework/standards/infrastructure/neon/neon-setup.md +186 -0
  55. package/framework/standards/integration/mcp/mcp-tools.md +32 -34
  56. package/framework/templates/README.md +20 -20
  57. package/framework/templates/REGISTRY.json +54 -101
  58. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  59. package/framework/templates/code/dotnet/backend/repository.cs +148 -148
  60. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +2 -2
  61. package/framework/templates/code/dotnet/database/vector-entity.cs +93 -0
  62. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +1 -1
  63. package/framework/templates/code/sql/{supabase-migration.sql → postgresql-migration.sql} +12 -21
  64. package/framework/templates/code/sql/{supabase-migration.template.sql → postgresql-migration.template.sql} +13 -18
  65. package/framework/templates/code/sql/{rls-policy.sql → postgresql-rls-policy.sql} +6 -9
  66. package/framework/templates/code/typescript/contracts.ts +167 -168
  67. package/framework/templates/context/CONTEXT.md +3 -3
  68. package/framework/templates/docs/proposal.md +6 -6
  69. package/framework/templates/docs/ui-components.md +1 -1
  70. package/framework/templates/feature/decisions.md +122 -121
  71. package/framework/templates/feature/recap.md +145 -145
  72. package/framework/templates/feature/tasks.md +199 -199
  73. package/framework/templates/frontend/nextjs/gsap-scroll-section.tsx.hbs +44 -0
  74. package/framework/templates/infrastructure/docker/docker-compose.template.yml +50 -67
  75. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  76. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  77. package/framework/templates/infrastructure/docker/easypanel.template.json +46 -54
  78. package/framework/templates/infrastructure/github/README.md +56 -56
  79. package/framework/templates/integrations/neon-auth-config.cs +133 -0
  80. package/framework/templates/integrations/semantic-kernel-neon.cs +125 -0
  81. package/framework/workflows/README.md +1 -1
  82. package/framework/workflows/docs/full-morph.md +69 -69
  83. package/package.json +1 -1
  84. package/src/commands/agents/dispatch-agents.js +19 -15
  85. package/src/commands/state/advance-phase.js +5 -0
  86. package/src/commands/tasks/task.js +3 -0
  87. package/src/core/state/state-manager.js +45 -1
  88. package/src/core/templates/template-registry.js +1 -66
  89. package/src/lib/detectors/index.js +4 -4
  90. package/src/lib/generators/architecture-scanner.js +639 -640
  91. package/src/lib/installers/mcp-installer.js +1 -1
  92. package/src/lib/tasks/task-classifier.js +15 -1
  93. package/src/lib/tasks/test-runner.js +5 -1
  94. package/src/lib/validators/content/content-validator.js +9 -10
  95. package/src/lib/validators/validation-runner.js +7 -5
  96. package/framework/agents/backend/supabase-expert.md +0 -256
  97. package/framework/agents/integrations/clerk-auth.md +0 -109
  98. package/framework/rules/clerk-standards.md +0 -13
  99. package/framework/rules/supabase-standards.md +0 -29
  100. package/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -290
  101. package/framework/standards/infrastructure/supabase/mcp-setup.md +0 -142
  102. package/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
  103. package/framework/standards/infrastructure/supabase/supabase-custom-jwt.md +0 -206
  104. package/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
  105. package/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
  106. package/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
  107. package/framework/templates/integrations/clerk-config.cs +0 -217
@@ -26,7 +26,7 @@ export function loadMcpRegistry() {
26
26
  /**
27
27
  * Filter MCPs by stack relevance
28
28
  * @param {Object} registry - Full MCP registry
29
- * @param {string} stack - Detected project stack (e.g., 'nextjs-supabase', 'blazor')
29
+ * @param {string} stack - Detected project stack (e.g., 'nextjs-neon', 'blazor')
30
30
  * @returns {Object} Filtered map of mcpName → mcpEntry
31
31
  */
32
32
  export function filterByStack(registry, stack) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Task classifier — identifies test/validation tasks by title.
2
+ * Task classifier — identifies test/validation and infrastructure tasks by title.
3
3
  */
4
4
 
5
5
  const TEST_TASK_PATTERN = /\b(tests?|testing|specs?|coverage|e2e|unit|integration|integra[cç][aã]o|valida[cç][aã]o|cobertura|testes?)\b/i;
@@ -14,3 +14,17 @@ export function isTestTask(taskTitle) {
14
14
  if (!taskTitle) return false;
15
15
  return TEST_TASK_PATTERN.test(taskTitle);
16
16
  }
17
+
18
+ const INFRA_TASK_PATTERN = /\b(infrastructure|infra|cleanup|migration|migra[cç][aã]o|config|setup|ci\/cd|devops|deploy|docker|packages?|dependencies|tags)\b/i;
19
+
20
+ /**
21
+ * Returns true if the task title indicates an infrastructure/cleanup/migration task.
22
+ * Used to skip contract validation and suppress breaking change warnings.
23
+ *
24
+ * @param {string} taskTitle
25
+ * @returns {boolean}
26
+ */
27
+ export function isInfrastructureTask(taskTitle) {
28
+ if (!taskTitle) return false;
29
+ return INFRA_TASK_PATTERN.test(taskTitle);
30
+ }
@@ -68,9 +68,13 @@ export function runTestSuite(projectPath = '.', opts = {}) {
68
68
  });
69
69
  return { passed: true, output: output ?? '', exitCode: 0 };
70
70
  } catch (err) {
71
+ const output = (err.stdout || '') + (err.stderr || '');
72
+ const BUILD_FAIL = /Build FAILED|error MSB\d+|error CS\d+|Could not find.*\.csproj/i;
73
+ const buildFailed = BUILD_FAIL.test(output);
71
74
  return {
72
75
  passed: false,
73
- output: (err.stdout || '') + (err.stderr || ''),
76
+ buildFailed,
77
+ output,
74
78
  exitCode: err.status ?? 1
75
79
  };
76
80
  }
@@ -23,18 +23,17 @@ export function validateSpecContent(specPath) {
23
23
 
24
24
  const content = readFileSync(specPath, 'utf8');
25
25
 
26
- // Required sections for a complete spec (prefix-match to handle variants like
27
- // "## Functional Requirements" and "## Technical Architecture")
26
+ // Required sections (flexible regex handles numbered variants like '## 1. Overview')
28
27
  const requiredSections = [
29
- '## Overview',
30
- '## Functional Requirements',
31
- '## Technical',
32
- '## Data Model',
28
+ { label: '## Overview', pattern: /^##\s+(?:\d+\.?\s+)?Overview/i },
29
+ { label: '## Functional Requirements', pattern: /^##\s+(?:\d+\.?\s+)?Functional Requirements/i },
30
+ { label: '## Technical', pattern: /^##\s+(?:\d+\.?\s+)?Technical/i },
31
+ { label: '## Data Model', pattern: /^##\s+(?:\d+\.?\s+)?Data Model/i },
33
32
  ];
34
33
 
35
34
  const lines = content.split('\n');
36
- const missing = requiredSections.filter(section =>
37
- !lines.some(line => line.startsWith(section))
35
+ const missing = requiredSections.filter(s =>
36
+ !lines.some(line => s.pattern.test(line))
38
37
  );
39
38
 
40
39
  // Additional quality checks
@@ -44,8 +43,8 @@ export function validateSpecContent(specPath) {
44
43
  // Missing sections are warnings, not errors — not every spec needs all sections
45
44
  // (e.g., frontend-only features may not have Data Model, CLI tools may not have Technical Architecture)
46
45
  if (missing.length > 0) {
47
- missing.forEach(section => {
48
- warnings.push(`Missing recommended section: ${section}`);
46
+ missing.forEach(s => {
47
+ warnings.push(`Missing recommended section: ${s.label}`);
49
48
  });
50
49
  }
51
50
 
@@ -119,11 +119,13 @@ export async function runValidation(projectPath, featureName, options = {}) {
119
119
  }
120
120
 
121
121
  // Always run contract compliance if the contracts file exists (stack-aware)
122
- const _profileForContracts = getStackProfile(projectPath);
123
- const contractsType = resolveContractsOutputType(_profileForContracts.stack);
124
- const contractsPath = getAbsoluteOutputPath(projectPath, featureName, contractsType);
125
- if (existsSync(contractsPath) && !_profileForContracts.isNextjs) {
126
- validatorIds.push('contract-compliance');
122
+ if (!options.skipContracts) {
123
+ const _profileForContracts = getStackProfile(projectPath);
124
+ const contractsType = resolveContractsOutputType(_profileForContracts.stack);
125
+ const contractsPath = getAbsoluteOutputPath(projectPath, featureName, contractsType);
126
+ if (existsSync(contractsPath) && !_profileForContracts.isNextjs) {
127
+ validatorIds.push('contract-compliance');
128
+ }
127
129
  }
128
130
 
129
131
  // Deduplicate
@@ -1,256 +0,0 @@
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*
@@ -1,109 +0,0 @@
1
- ---
2
- name: clerk-auth
3
- description: Clerk Auth specialist for Clerk SDK integration, social login, JWT session management, and user management in Next.js and .NET projects. Use when integrating Clerk authentication, implementing social login flows, managing user sessions with Clerk JWT, or protecting routes with Clerk middleware.
4
- allowed-tools: Read, Write, Edit, Bash, Glob, Grep
5
- stacks:
6
- - clerk
7
- color: teal
8
- effort: medium
9
- ---
10
-
11
- # Clerk Auth
12
-
13
- Autenticação SaaS com Clerk para .NET e Next.js. SDK: `Clerk.Net.AspNetCore.Security` (.NET) / `@clerk/nextjs` (Next.js).
14
-
15
- ## Setup
16
-
17
- ```csharp
18
- // appsettings.json
19
- { "Clerk": { "SecretKey": "${CLERK_SECRET_KEY}", "PublishableKey": "pk_test_xxx" } }
20
-
21
- // Program.cs
22
- builder.Services.AddClerk(builder.Configuration);
23
- builder.Services.AddAuthentication(ClerkAuthenticationDefaults.AuthenticationScheme)
24
- .AddClerk(o => { o.Authority = "https://clerk.{instance}.com"; o.ValidAudiences = ["your-app-id"]; });
25
- builder.Services.AddAuthorization();
26
- app.UseAuthentication();
27
- app.UseAuthorization();
28
- ```
29
-
30
- ## Protected Endpoints
31
-
32
- ```csharp
33
- // Minimal API
34
- app.MapGet("/api/profile", async (ClaimsPrincipal user, IClerkClient clerk) =>
35
- {
36
- var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);
37
- if (userId is null) return Results.Unauthorized();
38
- var u = await clerk.Users.GetUserAsync(userId);
39
- return Results.Ok(new { u.Id, Email = u.EmailAddresses.FirstOrDefault()?.EmailAddress });
40
- }).RequireAuthorization();
41
-
42
- // Controller: same pattern with [Authorize] + User.FindFirstValue()
43
- // Role-based: [Authorize(Roles = "admin")]
44
- ```
45
-
46
- ## Next.js Integration
47
-
48
- ```tsx
49
- // middleware.ts
50
- import { clerkMiddleware } from '@clerk/nextjs/server';
51
- export default clerkMiddleware();
52
- export const config = { matcher: ['/((?!.*\\..*|_next).*)', '/'] };
53
-
54
- // Protected page
55
- import { auth } from '@clerk/nextjs/server';
56
- export default async function DashboardPage() {
57
- const { userId } = await auth();
58
- if (!userId) redirect('/sign-in');
59
- return <Dashboard />;
60
- }
61
-
62
- // Client component
63
- 'use client';
64
- import { useUser } from '@clerk/nextjs';
65
- const { user, isLoaded } = useUser();
66
- ```
67
-
68
- ## Client Operations (.NET)
69
-
70
- ```csharp
71
- var user = await _clerk.Users.GetUserAsync(userId); // Get
72
- var users = await _clerk.Users.GetUserListAsync(new() { Limit = 10 }); // List
73
- await _clerk.Users.UpdateUserMetadataAsync(userId, new() // Update metadata
74
- { PublicMetadata = new Dictionary<string, object> { ["plan"] = "pro" } });
75
- await _clerk.Users.DeleteUserAsync(userId); // Delete
76
- ```
77
-
78
- ## Webhooks
79
-
80
- ```csharp
81
- [ApiController, Route("api/webhooks/clerk")]
82
- public class ClerkWebhookController(IUserService users) : ControllerBase
83
- {
84
- [HttpPost]
85
- public async Task<IActionResult> Handle([FromBody] ClerkWebhookPayload payload)
86
- {
87
- switch (payload.Type)
88
- {
89
- case "user.created": await users.SyncUserAsync(payload.Data); break;
90
- case "user.updated": await users.UpdateUserAsync(payload.Data); break;
91
- case "user.deleted": await users.DeleteUserAsync(payload.Data.Id); break;
92
- }
93
- return Ok();
94
- }
95
- }
96
- ```
97
-
98
- ## Checklist
99
-
100
- - [ ] Secret Key in environment variables (not hardcoded)
101
- - [ ] Authentication scheme configured
102
- - [ ] Authorization policies defined
103
- - [ ] Webhook endpoint + signature validation
104
- - [ ] Redirect after login configured
105
- - [ ] Error handling for expired sessions
106
-
107
- ---
108
-
109
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,13 +0,0 @@
1
- ---
2
- paths:
3
- - "**/Auth/**"
4
- - "**/auth/**"
5
- - "**/Identity/**"
6
- - "**/Clerk/**"
7
- stacks:
8
- - dotnet
9
- ---
10
-
11
- # Clerk Authentication Standards
12
-
13
- @.morph/framework/standards/backend/integrations/clerk/clerk-auth.md
@@ -1,29 +0,0 @@
1
- ---
2
- paths:
3
- - "**/*.sql"
4
- - "**/supabase/**"
5
- - "**/migrations/**"
6
- stacks:
7
- - supabase
8
- ---
9
-
10
- # Supabase & PostgreSQL Standards
11
-
12
- @.morph/framework/standards/infrastructure/supabase/supabase-auth.md
13
- @.morph/framework/standards/infrastructure/supabase/supabase-rls.md
14
- @.morph/framework/standards/infrastructure/supabase/supabase-storage.md
15
- @.morph/framework/standards/infrastructure/supabase/supabase-pgvector.md
16
- @.morph/framework/standards/infrastructure/supabase/mcp-setup.md
17
- @.morph/framework/standards/infrastructure/supabase/supabase-custom-jwt.md
18
- @.morph/framework/standards/backend/database/postgresql/database.md
19
-
20
- ## SQL & Migration Templates
21
-
22
- | Template | Path | Purpose |
23
- |----------|------|---------|
24
- | Migration (full) | `.morph/framework/templates/code/sql/supabase-migration.template.sql` | RLS + indexes |
25
- | Migration (simple) | `.morph/framework/templates/code/sql/supabase-migration.sql` | Basic migration |
26
- | RLS Policy | `.morph/framework/templates/code/sql/rls-policy.sql` | Row Level Security |
27
- | TS Types | `.morph/framework/templates/code/typescript/contracts.ts` | Supabase DB types |
28
-
29
- Read the template to see the exact pattern for migrations, RLS policies, and type generation.