@polymorphism-tech/morph-spec 4.17.0 → 4.19.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 (70) hide show
  1. package/CLAUDE.md +36 -0
  2. package/README.md +2 -2
  3. package/bin/task-manager.js +12 -0
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/agents/architecture/architecture-expert.md +86 -0
  8. package/framework/agents/architecture/morph-spec-architect.md +66 -0
  9. package/framework/agents/architecture/packages-validator.md +77 -0
  10. package/framework/agents/architecture/security-expert.md +67 -0
  11. package/framework/agents/backend/ms-agent-expert.md +1 -1
  12. package/framework/agents/backend/neon-expert.md +9 -27
  13. package/framework/agents/frontend/design-system-validator.md +88 -0
  14. package/framework/agents/frontend/nextjs-component-validator.md +85 -0
  15. package/framework/agents/frontend/{ui-ux-designer.md → ui-designer.md} +31 -0
  16. package/framework/agents/integrations/neon-auth.md +151 -0
  17. package/framework/agents.json +22 -14
  18. package/framework/hooks/claude-code/post-tool-use/dispatch.js +39 -0
  19. package/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +78 -44
  20. package/framework/hooks/claude-code/post-tool-use/loop-detect.js +103 -0
  21. package/framework/hooks/claude-code/session-start/inject-morph-context.js +21 -2
  22. package/framework/hooks/claude-code/stop/validate-completion.js +48 -1
  23. package/framework/hooks/shared/activity-logger.js +56 -1
  24. package/framework/hooks/shared/build-check.js +79 -0
  25. package/framework/hooks/shared/payload-utils.js +39 -0
  26. package/framework/hooks/shared/session-snapshot.js +105 -0
  27. package/framework/phases.json +1 -1
  28. package/framework/rules/neon-auth-standards.md +13 -0
  29. package/framework/rules/neon-standards.md +1 -0
  30. package/framework/skills/level-0-meta/mcp-registry.json +34 -1
  31. package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +3 -3
  32. package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +1 -1
  33. package/framework/skills/level-0-meta/morph-init/SKILL.md +4 -4
  34. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +1 -1
  35. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +11 -1
  36. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +12 -1
  37. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
  38. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
  39. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +119 -11
  40. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  41. package/framework/standards/STANDARDS.json +13 -9
  42. package/framework/standards/ai-agents/production.md +5 -2
  43. package/framework/standards/ai-agents/setup.md +13 -14
  44. package/framework/standards/ai-agents/workflows.md +8 -6
  45. package/framework/standards/backend/database/postgresql/database.md +5 -5
  46. package/framework/standards/backend/database/vector-search-rag.md +1 -1
  47. package/framework/standards/backend/integrations/asaas/asaas-api.md +1 -1
  48. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +364 -0
  49. package/framework/standards/frontend/nextjs/nextjs-patterns.md +9 -9
  50. package/framework/templates/README.md +2 -2
  51. package/framework/templates/REGISTRY.json +5 -5
  52. package/framework/templates/code/dotnet/jobs/agent.cs +0 -1
  53. package/framework/templates/code/sql/postgresql-migration.sql +10 -10
  54. package/framework/templates/code/sql/postgresql-migration.template.sql +12 -14
  55. package/framework/templates/code/sql/postgresql-rls-policy.sql +6 -9
  56. package/framework/templates/feature/decisions.md +8 -7
  57. package/framework/templates/integrations/neon-auth-config.cs +133 -0
  58. package/framework/workflows/docs/full-morph.md +1 -1
  59. package/package.json +1 -1
  60. package/src/commands/mcp/mcp-setup.js +21 -0
  61. package/src/commands/project/init.js +11 -0
  62. package/src/lib/contracts/sprint-contract-generator.js +137 -0
  63. package/src/lib/detectors/index.js +2 -2
  64. package/src/lib/generators/architecture-scanner.js +2 -3
  65. package/src/lib/installers/mcp-installer.js +25 -0
  66. package/src/utils/hooks-installer.js +12 -1
  67. package/framework/agents/integrations/clerk-auth.md +0 -109
  68. package/framework/rules/clerk-standards.md +0 -13
  69. package/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -292
  70. package/framework/templates/integrations/clerk-config.cs +0 -217
@@ -1,292 +0,0 @@
1
- # Clerk Authentication Integration Standard
2
-
3
- > **Scope:** universal
4
- > **Layer:** 2 (on keyword)
5
- > **Keywords:** clerk, auth, authentication, nextjs, user management
6
- > **Load When:** clerk authentication keywords detected
7
-
8
- Modern authentication and user management for Next.js applications.
9
-
10
- ---
11
-
12
- ## Overview
13
-
14
- Clerk provides:
15
- - Pre-built UI components (SignIn, SignUp, UserProfile)
16
- - Social auth (Google, GitHub, etc.)
17
- - Multi-factor authentication
18
- - Session management
19
- - User metadata and organizations
20
-
21
- **Primary Use Case:** Next.js 15 + App Router
22
-
23
- ---
24
-
25
- ## Core Principles
26
-
27
- 1. **Server-First**: Use server-side auth checks with `auth()` helper
28
- 2. **Route Protection**: Middleware-based protection for private routes
29
- 3. **Type Safety**: Use Clerk's TypeScript types
30
- 4. **Edge Compatible**: Works with Edge Runtime
31
-
32
- ---
33
-
34
- ## Installation & Setup
35
-
36
- ### Install Packages
37
-
38
- ```bash
39
- npm install @clerk/nextjs
40
- ```
41
-
42
- ### Environment Variables
43
-
44
- ```bash
45
- # .env.local
46
- NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
47
- CLERK_SECRET_KEY=sk_test_...
48
- NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
49
- NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
50
- NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
51
- NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/onboarding
52
- ```
53
-
54
- ### Root Layout Wrapper
55
-
56
- ```typescript
57
- // app/layout.tsx
58
- import { ClerkProvider } from '@clerk/nextjs';
59
-
60
- export default function RootLayout({ children }: { children: React.ReactNode }) {
61
- return (
62
- <ClerkProvider>
63
- <html lang="en">
64
- <body>{children}</body>
65
- </html>
66
- </ClerkProvider>
67
- );
68
- }
69
- ```
70
-
71
- ### Middleware Protection
72
-
73
- ```typescript
74
- // middleware.ts
75
- import { authMiddleware } from '@clerk/nextjs';
76
-
77
- export default authMiddleware({
78
- publicRoutes: ['/', '/api/webhooks/clerk'],
79
- ignoredRoutes: ['/api/public']
80
- });
81
-
82
- export const config = {
83
- matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
84
- };
85
- ```
86
-
87
- ---
88
-
89
- ## Common Patterns
90
-
91
- ### Sign In Page
92
-
93
- ```typescript
94
- // app/sign-in/[[...sign-in]]/page.tsx
95
- import { SignIn } from '@clerk/nextjs';
96
-
97
- export default function SignInPage() {
98
- return (
99
- <div className="flex items-center justify-center min-h-screen">
100
- <SignIn />
101
- </div>
102
- );
103
- }
104
- ```
105
-
106
- ### Server-Side Auth Check
107
-
108
- ```typescript
109
- // app/dashboard/page.tsx
110
- import { auth } from '@clerk/nextjs';
111
- import { redirect } from 'next/navigation';
112
-
113
- export default async function DashboardPage() {
114
- const { userId } = auth();
115
-
116
- if (!userId) {
117
- redirect('/sign-in');
118
- }
119
-
120
- return <div>Dashboard for user {userId}</div>;
121
- }
122
- ```
123
-
124
- ### Client Component with User Data
125
-
126
- ```typescript
127
- // components/UserProfile.tsx
128
- 'use client';
129
- import { useUser } from '@clerk/nextjs';
130
-
131
- export function UserProfile() {
132
- const { user, isLoaded, isSignedIn } = useUser();
133
-
134
- if (!isLoaded) return <div>Loading...</div>;
135
- if (!isSignedIn) return <div>Not signed in</div>;
136
-
137
- return (
138
- <div>
139
- <p>Welcome, {user.firstName}!</p>
140
- <p>Email: {user.primaryEmailAddress?.emailAddress}</p>
141
- </div>
142
- );
143
- }
144
- ```
145
-
146
- ### API Route Protection
147
-
148
- ```typescript
149
- // app/api/protected/route.ts
150
- import { auth } from '@clerk/nextjs';
151
-
152
- export async function GET() {
153
- const { userId } = auth();
154
-
155
- if (!userId) {
156
- return new Response('Unauthorized', { status: 401 });
157
- }
158
-
159
- // Fetch user-specific data
160
- const data = await fetchUserData(userId);
161
-
162
- return Response.json(data);
163
- }
164
- ```
165
-
166
- ---
167
-
168
- ## Webhook Integration
169
-
170
- ### Setup Webhook Endpoint
171
-
172
- ```typescript
173
- // app/api/webhooks/clerk/route.ts
174
- import { Webhook } from 'svix';
175
- import { headers } from 'next/headers';
176
-
177
- export async function POST(req: Request) {
178
- const WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET!;
179
-
180
- const headerPayload = headers();
181
- const svix_id = headerPayload.get('svix-id');
182
- const svix_timestamp = headerPayload.get('svix-timestamp');
183
- const svix_signature = headerPayload.get('svix-signature');
184
-
185
- if (!svix_id || !svix_timestamp || !svix_signature) {
186
- return new Response('Missing svix headers', { status: 400 });
187
- }
188
-
189
- const payload = await req.json();
190
- const body = JSON.stringify(payload);
191
-
192
- const wh = new Webhook(WEBHOOK_SECRET);
193
-
194
- let evt;
195
- try {
196
- evt = wh.verify(body, {
197
- 'svix-id': svix_id,
198
- 'svix-timestamp': svix_timestamp,
199
- 'svix-signature': svix_signature,
200
- });
201
- } catch (err) {
202
- return new Response('Invalid signature', { status: 400 });
203
- }
204
-
205
- // Handle events
206
- switch (evt.type) {
207
- case 'user.created':
208
- await handleUserCreated(evt.data);
209
- break;
210
- case 'user.updated':
211
- await handleUserUpdated(evt.data);
212
- break;
213
- case 'user.deleted':
214
- await handleUserDeleted(evt.data);
215
- break;
216
- }
217
-
218
- return new Response('OK');
219
- }
220
- ```
221
-
222
- ---
223
-
224
- ## Neon Integration
225
-
226
- ### Sync Users to Neon PostgreSQL (via EF Core / Npgsql)
227
-
228
- ```csharp
229
- // Services/ClerkUserSyncService.cs
230
- public sealed class ClerkUserSyncService(IDbContextFactory<AppDbContext> dbFactory)
231
- {
232
- public async Task HandleUserCreatedAsync(ClerkUserData userData, CancellationToken ct)
233
- {
234
- await using var db = await dbFactory.CreateDbContextAsync(ct);
235
-
236
- db.Profiles.Add(new Profile
237
- {
238
- ClerkUserId = userData.Id,
239
- Email = userData.EmailAddresses[0].EmailAddress,
240
- FirstName = userData.FirstName,
241
- LastName = userData.LastName,
242
- AvatarUrl = userData.ImageUrl
243
- });
244
-
245
- await db.SaveChangesAsync(ct);
246
- }
247
- }
248
- ```
249
-
250
- ---
251
-
252
- ## Best Practices
253
-
254
- ### Custom Claims
255
-
256
- ```typescript
257
- // Add custom claims in Clerk Dashboard or via API
258
- const { sessionClaims } = auth();
259
- const role = sessionClaims?.metadata?.role as string;
260
-
261
- if (role !== 'admin') {
262
- return new Response('Forbidden', { status: 403 });
263
- }
264
- ```
265
-
266
- ### Organizations
267
-
268
- ```typescript
269
- import { auth } from '@clerk/nextjs';
270
-
271
- const { orgId, orgRole } = auth();
272
-
273
- if (!orgId) {
274
- redirect('/create-organization');
275
- }
276
-
277
- if (orgRole !== 'admin') {
278
- return <div>Admin access required</div>;
279
- }
280
- ```
281
-
282
- ---
283
-
284
- ## References
285
-
286
- - [Clerk Next.js Documentation](https://clerk.com/docs/nextjs)
287
- - [Clerk API Reference](https://clerk.com/docs/reference/backend-api)
288
- - [Webhooks Guide](https://clerk.com/docs/integrations/webhooks)
289
-
290
- ---
291
-
292
- *MORPH-SPEC by Polymorphism Tech*
@@ -1,217 +0,0 @@
1
- // ==============================================================================
2
- // MORPH-SPEC - Clerk Authentication Configuration Template
3
- // Configuração de autenticação com Clerk para .NET
4
- // ==============================================================================
5
-
6
- using Microsoft.AspNetCore.Authentication;
7
- using System.Security.Claims;
8
-
9
- namespace {{Namespace}}.Infrastructure.Auth;
10
-
11
- // ==============================================================================
12
- // OPTIONS
13
- // ==============================================================================
14
-
15
- public class ClerkOptions
16
- {
17
- public const string SectionName = "Clerk";
18
-
19
- /// <summary>
20
- /// Clerk Secret Key (starts with sk_)
21
- /// </summary>
22
- public string SecretKey { get; set; } = string.Empty;
23
-
24
- /// <summary>
25
- /// Clerk Publishable Key (starts with pk_)
26
- /// </summary>
27
- public string PublishableKey { get; set; } = string.Empty;
28
-
29
- /// <summary>
30
- /// Clerk Frontend API URL
31
- /// </summary>
32
- public string FrontendApi { get; set; } = string.Empty;
33
- }
34
-
35
- // ==============================================================================
36
- // SERVICE EXTENSIONS
37
- // ==============================================================================
38
-
39
- public static class ClerkServiceExtensions
40
- {
41
- /// <summary>
42
- /// Adiciona autenticação Clerk ao projeto
43
- /// Requer: Clerk.Net.AspNetCore.Security
44
- /// </summary>
45
- public static IServiceCollection AddClerkAuthentication(
46
- this IServiceCollection services,
47
- IConfiguration configuration)
48
- {
49
- services.Configure<ClerkOptions>(configuration.GetSection(ClerkOptions.SectionName));
50
-
51
- // Opção 1: Usando Clerk.Net SDK oficial
52
- // services.AddClerk(configuration);
53
-
54
- // Opção 2: Configuração manual com JWT
55
- services.AddAuthentication("Clerk")
56
- .AddJwtBearer("Clerk", options =>
57
- {
58
- var clerkOptions = configuration.GetSection(ClerkOptions.SectionName).Get<ClerkOptions>()!;
59
-
60
- options.Authority = clerkOptions.FrontendApi;
61
- options.TokenValidationParameters = new()
62
- {
63
- ValidateIssuer = true,
64
- ValidateAudience = false,
65
- ValidateLifetime = true,
66
- ValidateIssuerSigningKey = true,
67
- NameClaimType = ClaimTypes.NameIdentifier
68
- };
69
- });
70
-
71
- services.AddAuthorization();
72
-
73
- return services;
74
- }
75
-
76
- }
77
-
78
- // ==============================================================================
79
- // CLERK USER SERVICE
80
- // ==============================================================================
81
-
82
- public interface IClerkUserService
83
- {
84
- Task<ClerkUser?> GetCurrentUserAsync(CancellationToken ct = default);
85
- Task<ClerkUser?> GetUserByIdAsync(string userId, CancellationToken ct = default);
86
- Task UpdateUserMetadataAsync(string userId, Dictionary<string, object> metadata, CancellationToken ct = default);
87
- }
88
-
89
- public class ClerkUserService : IClerkUserService
90
- {
91
- private readonly HttpClient _httpClient;
92
- private readonly IHttpContextAccessor _httpContextAccessor;
93
- private readonly ILogger<ClerkUserService> _logger;
94
-
95
- public ClerkUserService(
96
- HttpClient httpClient,
97
- IHttpContextAccessor httpContextAccessor,
98
- ILogger<ClerkUserService> logger)
99
- {
100
- _httpClient = httpClient;
101
- _httpContextAccessor = httpContextAccessor;
102
- _logger = logger;
103
- }
104
-
105
- public async Task<ClerkUser?> GetCurrentUserAsync(CancellationToken ct = default)
106
- {
107
- var userId = _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);
108
- if (string.IsNullOrEmpty(userId)) return null;
109
-
110
- return await GetUserByIdAsync(userId, ct);
111
- }
112
-
113
- public async Task<ClerkUser?> GetUserByIdAsync(string userId, CancellationToken ct = default)
114
- {
115
- try
116
- {
117
- var response = await _httpClient.GetAsync($"users/{userId}", ct);
118
-
119
- if (!response.IsSuccessStatusCode)
120
- {
121
- _logger.LogWarning("Failed to get Clerk user {UserId}: {Status}", userId, response.StatusCode);
122
- return null;
123
- }
124
-
125
- return await response.Content.ReadFromJsonAsync<ClerkUser>(ct);
126
- }
127
- catch (Exception ex)
128
- {
129
- _logger.LogError(ex, "Error getting Clerk user {UserId}", userId);
130
- return null;
131
- }
132
- }
133
-
134
- public async Task UpdateUserMetadataAsync(string userId, Dictionary<string, object> metadata, CancellationToken ct = default)
135
- {
136
- var request = new { public_metadata = metadata };
137
- var response = await _httpClient.PatchAsJsonAsync($"users/{userId}", request, ct);
138
- response.EnsureSuccessStatusCode();
139
- }
140
- }
141
-
142
- // ==============================================================================
143
- // CLERK USER MODEL
144
- // ==============================================================================
145
-
146
- public record ClerkUser
147
- {
148
- public string Id { get; init; } = string.Empty;
149
- public string? FirstName { get; init; }
150
- public string? LastName { get; init; }
151
- public string? ImageUrl { get; init; }
152
- public List<ClerkEmailAddress>? EmailAddresses { get; init; }
153
- public string? PrimaryEmailAddressId { get; init; }
154
- public Dictionary<string, object>? PublicMetadata { get; init; }
155
- public long CreatedAt { get; init; }
156
- public long UpdatedAt { get; init; }
157
-
158
- public string? PrimaryEmail => EmailAddresses?
159
- .FirstOrDefault(e => e.Id == PrimaryEmailAddressId)?.EmailAddress;
160
-
161
- public string FullName => $"{FirstName} {LastName}".Trim();
162
- }
163
-
164
- public record ClerkEmailAddress
165
- {
166
- public string Id { get; init; } = string.Empty;
167
- public string EmailAddress { get; init; } = string.Empty;
168
- public bool Verified { get; init; }
169
- }
170
-
171
- // ==============================================================================
172
- // MIDDLEWARE PIPELINE
173
- // ==============================================================================
174
-
175
- public static class ClerkMiddlewareExtensions
176
- {
177
- public static IApplicationBuilder UseClerkAuthentication(this IApplicationBuilder app)
178
- {
179
- app.UseAuthentication();
180
- app.UseAuthorization();
181
- return app;
182
- }
183
- }
184
-
185
- // ==============================================================================
186
- // APPSETTINGS EXAMPLE
187
- // ==============================================================================
188
-
189
- /*
190
- {
191
- "Clerk": {
192
- "SecretKey": "sk_test_xxxxx",
193
- "PublishableKey": "pk_test_xxxxx",
194
- "FrontendApi": "https://your-app.clerk.accounts.dev"
195
- }
196
- }
197
- */
198
-
199
- // ==============================================================================
200
- // PROGRAM.CS EXAMPLE
201
- // ==============================================================================
202
-
203
- /*
204
- // Program.cs
205
- var builder = WebApplication.CreateBuilder(args);
206
-
207
- // Add Clerk authentication
208
- builder.Services.AddClerkAuthentication(builder.Configuration);
209
-
210
- var app = builder.Build();
211
-
212
- app.UseClerkAuthentication();
213
-
214
- app.MapControllers().RequireAuthorization();
215
-
216
- app.Run();
217
- */