@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
@@ -1,153 +0,0 @@
1
- # Supabase Storage Standard
2
-
3
- > **Scope:** nextjs-supabase
4
- > **Layer:** 2 (on keyword)
5
- > **Keywords:** supabase, storage, bucket, upload, file storage
6
- > **Load When:** supabase storage keywords detected
7
-
8
- Stack: Next.js 15 + Supabase + .NET Backend
9
-
10
- ## Core Rules
11
-
12
- - ALWAYS use RLS policies on storage.objects for access control
13
- - NEVER serve private files without signed URLs
14
- - ALWAYS validate file type and size before upload
15
- - Public buckets: anyone can read, still need auth for write
16
- - Private buckets: require signed URLs or authenticated access
17
-
18
- ## Bucket Configuration
19
-
20
- ```sql
21
- -- Public bucket (avatars, logos)
22
- INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
23
- VALUES ('avatars', 'avatars', true, 2097152, ARRAY['image/jpeg','image/png','image/webp']);
24
-
25
- -- Private bucket (documents, reports)
26
- INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
27
- VALUES ('documents', 'documents', false, 10485760, ARRAY['application/pdf','image/jpeg','image/png']);
28
- ```
29
-
30
- | Setting | Public Bucket | Private Bucket |
31
- |---------|--------------|----------------|
32
- | Read access | Anyone via URL | Signed URL or auth required |
33
- | Write access | RLS policy required | RLS policy required |
34
- | Use case | Avatars, public images | Documents, reports |
35
-
36
- ## Storage RLS Policies
37
-
38
- ```sql
39
- -- Users upload/view/delete in their own folder
40
- CREATE POLICY "user_upload" ON storage.objects FOR INSERT
41
- WITH CHECK (bucket_id = 'documents' AND (storage.foldername(name))[1] = auth.uid()::text);
42
-
43
- CREATE POLICY "user_select" ON storage.objects FOR SELECT
44
- USING (bucket_id = 'documents' AND (storage.foldername(name))[1] = auth.uid()::text);
45
-
46
- CREATE POLICY "user_delete" ON storage.objects FOR DELETE
47
- USING (bucket_id = 'documents' AND (storage.foldername(name))[1] = auth.uid()::text);
48
-
49
- -- Public bucket: anyone reads, auth users upload to own folder
50
- CREATE POLICY "public_read" ON storage.objects FOR SELECT
51
- USING (bucket_id = 'avatars');
52
-
53
- CREATE POLICY "auth_upload_avatar" ON storage.objects FOR INSERT
54
- WITH CHECK (bucket_id = 'avatars' AND (storage.foldername(name))[1] = auth.uid()::text);
55
- ```
56
-
57
- ## Path Naming Convention
58
-
59
- ```
60
- {bucket}/{user_id}/{category}/{filename}
61
- avatars/{user_id}/profile.webp
62
- documents/{user_id}/invoices/2026-01-invoice.pdf
63
- ```
64
-
65
- First folder segment = user_id (enables simple RLS). Use lowercase, hyphens, include extension.
66
-
67
- ## Upload Patterns
68
-
69
- ### Browser Upload (Next.js)
70
-
71
- ```ts
72
- async function uploadFile(file: File, userId: string) {
73
- if (file.size > 10 * 1024 * 1024) throw new Error("File too large");
74
- const allowedTypes = ["application/pdf", "image/jpeg", "image/png"];
75
- if (!allowedTypes.includes(file.type)) throw new Error("Invalid type");
76
-
77
- const path = `${userId}/uploads/${Date.now()}-${file.name}`;
78
- const { data, error } = await supabase.storage
79
- .from("documents")
80
- .upload(path, file, { cacheControl: "3600", upsert: false, contentType: file.type });
81
- if (error) throw error;
82
- return data.path;
83
- }
84
- ```
85
-
86
- ### Server Upload (.NET)
87
-
88
- ```csharp
89
- public sealed class StorageService(Supabase.Client client, ILogger<StorageService> logger)
90
- {
91
- private static readonly string[] AllowedTypes = ["application/pdf", "image/jpeg", "image/png"];
92
-
93
- public async Task<string> UploadAsync(
94
- string bucket, string path, Stream stream,
95
- string contentType, CancellationToken ct = default)
96
- {
97
- if (!AllowedTypes.Contains(contentType))
98
- throw new ValidationException($"Invalid content type: {contentType}");
99
- var response = await client.Storage.From(bucket)
100
- .Upload(stream, path, new FileOptions { ContentType = contentType, Upsert = false });
101
- return response;
102
- }
103
- }
104
- ```
105
-
106
- ## Download and Signed URLs
107
-
108
- ```ts
109
- // Public bucket: direct URL
110
- const { data } = supabase.storage.from("avatars").getPublicUrl("user-id/profile.webp");
111
-
112
- // Private bucket: signed URL (time-limited)
113
- const { data } = await supabase.storage
114
- .from("documents").createSignedUrl("user-id/report.pdf", 3600); // 1 hour
115
-
116
- // Download file content (returns Blob)
117
- const { data } = await supabase.storage.from("documents").download("user-id/report.pdf");
118
- ```
119
-
120
- ## Image Transformations
121
-
122
- ```ts
123
- const { data } = supabase.storage.from("avatars").getPublicUrl("user-id/photo.jpg", {
124
- transform: { width: 200, height: 200, resize: "cover", quality: 80 },
125
- });
126
- ```
127
-
128
- | Parameter | Options | Default |
129
- |-----------|---------|---------|
130
- | `width` / `height` | 1-2500 px | original |
131
- | `resize` | cover, contain, fill | cover |
132
- | `quality` | 20-100 | 80 |
133
- | `format` | origin, avif, webp | origin |
134
-
135
- ## File Validation
136
-
137
- | Check | Client-Side | Server-Side | Bucket Config |
138
- |-------|------------|-------------|---------------|
139
- | File size | `file.size` | Stream length | `file_size_limit` |
140
- | MIME type | `file.type` | Content-Type | `allowed_mime_types` |
141
- | Extension | File name | File name | -- |
142
-
143
- Always validate at all three levels. Client-side can be bypassed.
144
-
145
- ## Common Mistakes
146
-
147
- | Wrong | Right | Why |
148
- |-------|-------|-----|
149
- | No RLS on storage.objects | Policies for each bucket | Anyone can read/write without policies |
150
- | Private files via public URL | `createSignedUrl()` | Private bucket returns 403 without auth |
151
- | User-provided filename as-is | Sanitize + timestamp prefix | Path traversal attacks, collisions |
152
- | `upsert: true` by default | `upsert: false` | Prevents accidental file overwrites |
153
- | Files without user folder | `{user_id}/...` path pattern | Cannot write simple RLS policies |
@@ -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
- */