@polymorphism-tech/morph-spec 1.0.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 (83) hide show
  1. package/README.md +279 -0
  2. package/bin/morph-spec.js +53 -0
  3. package/content/.claude/commands/morph-apply.md +66 -0
  4. package/content/.claude/commands/morph-archive.md +79 -0
  5. package/content/.claude/commands/morph-costs.md +206 -0
  6. package/content/.claude/commands/morph-infra.md +209 -0
  7. package/content/.claude/commands/morph-proposal.md +60 -0
  8. package/content/.claude/commands/morph-status.md +71 -0
  9. package/content/.claude/settings.local.json +15 -0
  10. package/content/.claude/skills/infra/bicep-architect.md +419 -0
  11. package/content/.claude/skills/infra/container-specialist.md +437 -0
  12. package/content/.claude/skills/infra/devops-engineer.md +405 -0
  13. package/content/.claude/skills/integrations/asaas-financial.md +333 -0
  14. package/content/.claude/skills/integrations/azure-identity.md +309 -0
  15. package/content/.claude/skills/integrations/clerk-auth.md +290 -0
  16. package/content/.claude/skills/specialists/azure-architect.md +142 -0
  17. package/content/.claude/skills/specialists/cost-guardian.md +110 -0
  18. package/content/.claude/skills/specialists/ef-modeler.md +200 -0
  19. package/content/.claude/skills/specialists/hangfire-orchestrator.md +245 -0
  20. package/content/.claude/skills/specialists/ms-agent-expert.md +209 -0
  21. package/content/.claude/skills/specialists/po-pm-advisor.md +197 -0
  22. package/content/.claude/skills/specialists/standards-architect.md +78 -0
  23. package/content/.claude/skills/specialists/ui-ux-designer.md +325 -0
  24. package/content/.claude/skills/stacks/dotnet-blazor.md +352 -0
  25. package/content/.claude/skills/stacks/dotnet-nextjs.md +402 -0
  26. package/content/.claude/skills/stacks/shopify.md +445 -0
  27. package/content/.morph/archive/.gitkeep +25 -0
  28. package/content/.morph/config/agents.json +149 -0
  29. package/content/.morph/config/config.template.json +96 -0
  30. package/content/.morph/examples/api-nextjs/README.md +241 -0
  31. package/content/.morph/examples/api-nextjs/contracts.ts +307 -0
  32. package/content/.morph/examples/api-nextjs/spec.md +399 -0
  33. package/content/.morph/examples/api-nextjs/tasks.md +168 -0
  34. package/content/.morph/examples/micro-saas/README.md +125 -0
  35. package/content/.morph/examples/micro-saas/contracts.cs +358 -0
  36. package/content/.morph/examples/micro-saas/decisions.md +246 -0
  37. package/content/.morph/examples/micro-saas/spec.md +236 -0
  38. package/content/.morph/examples/micro-saas/tasks.md +150 -0
  39. package/content/.morph/examples/multi-agent/README.md +309 -0
  40. package/content/.morph/examples/multi-agent/contracts.cs +433 -0
  41. package/content/.morph/examples/multi-agent/spec.md +479 -0
  42. package/content/.morph/examples/multi-agent/tasks.md +185 -0
  43. package/content/.morph/features/.gitkeep +25 -0
  44. package/content/.morph/project.md +159 -0
  45. package/content/.morph/specs/.gitkeep +20 -0
  46. package/content/.morph/standards/architecture.md +190 -0
  47. package/content/.morph/standards/azure.md +184 -0
  48. package/content/.morph/standards/coding.md +342 -0
  49. package/content/.morph/templates/agent.cs +172 -0
  50. package/content/.morph/templates/component.razor +239 -0
  51. package/content/.morph/templates/contracts.cs +217 -0
  52. package/content/.morph/templates/decisions.md +106 -0
  53. package/content/.morph/templates/infra/app-insights.bicep +63 -0
  54. package/content/.morph/templates/infra/container-app-env.bicep +49 -0
  55. package/content/.morph/templates/infra/container-app.bicep +156 -0
  56. package/content/.morph/templates/infra/key-vault.bicep +91 -0
  57. package/content/.morph/templates/infra/main.bicep +155 -0
  58. package/content/.morph/templates/infra/parameters.dev.json +23 -0
  59. package/content/.morph/templates/infra/parameters.prod.json +23 -0
  60. package/content/.morph/templates/infra/sql-database.bicep +103 -0
  61. package/content/.morph/templates/infra/storage.bicep +106 -0
  62. package/content/.morph/templates/integrations/asaas-client.cs +387 -0
  63. package/content/.morph/templates/integrations/asaas-webhook.cs +351 -0
  64. package/content/.morph/templates/integrations/azure-identity-config.cs +288 -0
  65. package/content/.morph/templates/integrations/clerk-config.cs +258 -0
  66. package/content/.morph/templates/job.cs +171 -0
  67. package/content/.morph/templates/migration.cs +83 -0
  68. package/content/.morph/templates/proposal.md +155 -0
  69. package/content/.morph/templates/recap.md +105 -0
  70. package/content/.morph/templates/repository.cs +141 -0
  71. package/content/.morph/templates/saas/subscription.cs +347 -0
  72. package/content/.morph/templates/saas/tenant.cs +338 -0
  73. package/content/.morph/templates/service.cs +139 -0
  74. package/content/.morph/templates/spec.md +147 -0
  75. package/content/.morph/templates/tasks.md +235 -0
  76. package/content/.morph/templates/test.cs +239 -0
  77. package/content/CLAUDE.md +318 -0
  78. package/package.json +50 -0
  79. package/src/commands/doctor.js +132 -0
  80. package/src/commands/init.js +121 -0
  81. package/src/commands/update.js +84 -0
  82. package/src/utils/file-copier.js +50 -0
  83. package/src/utils/logger.js +32 -0
@@ -0,0 +1,258 @@
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 Microsoft.AspNetCore.Components.Authorization;
8
+ using System.Security.Claims;
9
+
10
+ namespace {{Namespace}}.Infrastructure.Auth;
11
+
12
+ // ==============================================================================
13
+ // OPTIONS
14
+ // ==============================================================================
15
+
16
+ public class ClerkOptions
17
+ {
18
+ public const string SectionName = "Clerk";
19
+
20
+ /// <summary>
21
+ /// Clerk Secret Key (starts with sk_)
22
+ /// </summary>
23
+ public string SecretKey { get; set; } = string.Empty;
24
+
25
+ /// <summary>
26
+ /// Clerk Publishable Key (starts with pk_)
27
+ /// </summary>
28
+ public string PublishableKey { get; set; } = string.Empty;
29
+
30
+ /// <summary>
31
+ /// Clerk Frontend API URL
32
+ /// </summary>
33
+ public string FrontendApi { get; set; } = string.Empty;
34
+ }
35
+
36
+ // ==============================================================================
37
+ // SERVICE EXTENSIONS
38
+ // ==============================================================================
39
+
40
+ public static class ClerkServiceExtensions
41
+ {
42
+ /// <summary>
43
+ /// Adiciona autenticação Clerk ao projeto
44
+ /// Requer: Clerk.Net.AspNetCore.Security
45
+ /// </summary>
46
+ public static IServiceCollection AddClerkAuthentication(
47
+ this IServiceCollection services,
48
+ IConfiguration configuration)
49
+ {
50
+ services.Configure<ClerkOptions>(configuration.GetSection(ClerkOptions.SectionName));
51
+
52
+ // Opção 1: Usando Clerk.Net SDK oficial
53
+ // services.AddClerk(configuration);
54
+
55
+ // Opção 2: Configuração manual com JWT
56
+ services.AddAuthentication("Clerk")
57
+ .AddJwtBearer("Clerk", options =>
58
+ {
59
+ var clerkOptions = configuration.GetSection(ClerkOptions.SectionName).Get<ClerkOptions>()!;
60
+
61
+ options.Authority = clerkOptions.FrontendApi;
62
+ options.TokenValidationParameters = new()
63
+ {
64
+ ValidateIssuer = true,
65
+ ValidateAudience = false,
66
+ ValidateLifetime = true,
67
+ ValidateIssuerSigningKey = true,
68
+ NameClaimType = ClaimTypes.NameIdentifier
69
+ };
70
+ });
71
+
72
+ services.AddAuthorization();
73
+
74
+ return services;
75
+ }
76
+
77
+ /// <summary>
78
+ /// Adiciona Clerk para Blazor Server
79
+ /// </summary>
80
+ public static IServiceCollection AddClerkBlazor(
81
+ this IServiceCollection services,
82
+ IConfiguration configuration)
83
+ {
84
+ services.AddClerkAuthentication(configuration);
85
+ services.AddScoped<AuthenticationStateProvider, ClerkAuthenticationStateProvider>();
86
+ services.AddCascadingAuthenticationState();
87
+
88
+ return services;
89
+ }
90
+ }
91
+
92
+ // ==============================================================================
93
+ // AUTHENTICATION STATE PROVIDER (Blazor)
94
+ // ==============================================================================
95
+
96
+ public class ClerkAuthenticationStateProvider : AuthenticationStateProvider
97
+ {
98
+ private readonly IHttpContextAccessor _httpContextAccessor;
99
+
100
+ public ClerkAuthenticationStateProvider(IHttpContextAccessor httpContextAccessor)
101
+ {
102
+ _httpContextAccessor = httpContextAccessor;
103
+ }
104
+
105
+ public override Task<AuthenticationState> GetAuthenticationStateAsync()
106
+ {
107
+ var user = _httpContextAccessor.HttpContext?.User ?? new ClaimsPrincipal();
108
+ return Task.FromResult(new AuthenticationState(user));
109
+ }
110
+
111
+ public void NotifyAuthenticationStateChanged()
112
+ {
113
+ NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
114
+ }
115
+ }
116
+
117
+ // ==============================================================================
118
+ // CLERK USER SERVICE
119
+ // ==============================================================================
120
+
121
+ public interface IClerkUserService
122
+ {
123
+ Task<ClerkUser?> GetCurrentUserAsync(CancellationToken ct = default);
124
+ Task<ClerkUser?> GetUserByIdAsync(string userId, CancellationToken ct = default);
125
+ Task UpdateUserMetadataAsync(string userId, Dictionary<string, object> metadata, CancellationToken ct = default);
126
+ }
127
+
128
+ public class ClerkUserService : IClerkUserService
129
+ {
130
+ private readonly HttpClient _httpClient;
131
+ private readonly IHttpContextAccessor _httpContextAccessor;
132
+ private readonly ILogger<ClerkUserService> _logger;
133
+
134
+ public ClerkUserService(
135
+ HttpClient httpClient,
136
+ IHttpContextAccessor httpContextAccessor,
137
+ ILogger<ClerkUserService> logger)
138
+ {
139
+ _httpClient = httpClient;
140
+ _httpContextAccessor = httpContextAccessor;
141
+ _logger = logger;
142
+ }
143
+
144
+ public async Task<ClerkUser?> GetCurrentUserAsync(CancellationToken ct = default)
145
+ {
146
+ var userId = _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);
147
+ if (string.IsNullOrEmpty(userId)) return null;
148
+
149
+ return await GetUserByIdAsync(userId, ct);
150
+ }
151
+
152
+ public async Task<ClerkUser?> GetUserByIdAsync(string userId, CancellationToken ct = default)
153
+ {
154
+ try
155
+ {
156
+ var response = await _httpClient.GetAsync($"users/{userId}", ct);
157
+
158
+ if (!response.IsSuccessStatusCode)
159
+ {
160
+ _logger.LogWarning("Failed to get Clerk user {UserId}: {Status}", userId, response.StatusCode);
161
+ return null;
162
+ }
163
+
164
+ return await response.Content.ReadFromJsonAsync<ClerkUser>(ct);
165
+ }
166
+ catch (Exception ex)
167
+ {
168
+ _logger.LogError(ex, "Error getting Clerk user {UserId}", userId);
169
+ return null;
170
+ }
171
+ }
172
+
173
+ public async Task UpdateUserMetadataAsync(string userId, Dictionary<string, object> metadata, CancellationToken ct = default)
174
+ {
175
+ var request = new { public_metadata = metadata };
176
+ var response = await _httpClient.PatchAsJsonAsync($"users/{userId}", request, ct);
177
+ response.EnsureSuccessStatusCode();
178
+ }
179
+ }
180
+
181
+ // ==============================================================================
182
+ // CLERK USER MODEL
183
+ // ==============================================================================
184
+
185
+ public record ClerkUser
186
+ {
187
+ public string Id { get; init; } = string.Empty;
188
+ public string? FirstName { get; init; }
189
+ public string? LastName { get; init; }
190
+ public string? ImageUrl { get; init; }
191
+ public List<ClerkEmailAddress>? EmailAddresses { get; init; }
192
+ public string? PrimaryEmailAddressId { get; init; }
193
+ public Dictionary<string, object>? PublicMetadata { get; init; }
194
+ public long CreatedAt { get; init; }
195
+ public long UpdatedAt { get; init; }
196
+
197
+ public string? PrimaryEmail => EmailAddresses?
198
+ .FirstOrDefault(e => e.Id == PrimaryEmailAddressId)?.EmailAddress;
199
+
200
+ public string FullName => $"{FirstName} {LastName}".Trim();
201
+ }
202
+
203
+ public record ClerkEmailAddress
204
+ {
205
+ public string Id { get; init; } = string.Empty;
206
+ public string EmailAddress { get; init; } = string.Empty;
207
+ public bool Verified { get; init; }
208
+ }
209
+
210
+ // ==============================================================================
211
+ // MIDDLEWARE PIPELINE
212
+ // ==============================================================================
213
+
214
+ public static class ClerkMiddlewareExtensions
215
+ {
216
+ public static IApplicationBuilder UseClerkAuthentication(this IApplicationBuilder app)
217
+ {
218
+ app.UseAuthentication();
219
+ app.UseAuthorization();
220
+ return app;
221
+ }
222
+ }
223
+
224
+ // ==============================================================================
225
+ // APPSETTINGS EXAMPLE
226
+ // ==============================================================================
227
+
228
+ /*
229
+ {
230
+ "Clerk": {
231
+ "SecretKey": "sk_test_xxxxx",
232
+ "PublishableKey": "pk_test_xxxxx",
233
+ "FrontendApi": "https://your-app.clerk.accounts.dev"
234
+ }
235
+ }
236
+ */
237
+
238
+ // ==============================================================================
239
+ // PROGRAM.CS EXAMPLE
240
+ // ==============================================================================
241
+
242
+ /*
243
+ // Program.cs
244
+ var builder = WebApplication.CreateBuilder(args);
245
+
246
+ // Add Clerk authentication
247
+ builder.Services.AddClerkAuthentication(builder.Configuration);
248
+ // Or for Blazor:
249
+ // builder.Services.AddClerkBlazor(builder.Configuration);
250
+
251
+ var app = builder.Build();
252
+
253
+ app.UseClerkAuthentication();
254
+
255
+ app.MapControllers().RequireAuthorization();
256
+
257
+ app.Run();
258
+ */
@@ -0,0 +1,171 @@
1
+ // ============================================================
2
+ // HANGFIRE JOB TEMPLATE
3
+ // Generated by MORPH Framework
4
+ // ============================================================
5
+
6
+ using Hangfire;
7
+ using Microsoft.Extensions.Logging;
8
+
9
+ namespace MyProject.Application.Features.{Feature}.Jobs;
10
+
11
+ /// <summary>
12
+ /// Background job for processing {Feature}.
13
+ /// Uses Hangfire for scheduling and retry handling.
14
+ /// </summary>
15
+ public class {Feature}ProcessorJob(
16
+ I{Feature}Service service,
17
+ I{Feature}AnalyzerAgent analyzer,
18
+ ILogger<{Feature}ProcessorJob> logger) : I{Feature}ProcessorJob
19
+ {
20
+ /// <summary>
21
+ /// Executes the {Feature} processing job.
22
+ /// </summary>
23
+ /// <param name="id">The {Feature} ID to process</param>
24
+ /// <param name="cancellationToken">Cancellation token</param>
25
+ [AutomaticRetry(Attempts = 3, DelaysInSeconds = new[] { 60, 300, 900 })]
26
+ [Queue("default")]
27
+ [JobDisplayName("{Feature} Processing - ID: {0}")]
28
+ public async Task ExecuteAsync(int id, CancellationToken cancellationToken)
29
+ {
30
+ logger.LogInformation("Starting {Feature} processing for ID {Id}", id);
31
+
32
+ try
33
+ {
34
+ // Get the entity
35
+ var item = await service.GetByIdAsync(id, cancellationToken);
36
+ if (item is null)
37
+ {
38
+ logger.LogWarning("{Feature} with ID {Id} not found, skipping", id);
39
+ return;
40
+ }
41
+
42
+ // Check if already processed
43
+ if (item.Status == {Feature}Status.Completed)
44
+ {
45
+ logger.LogInformation("{Feature} {Id} already completed, skipping", id);
46
+ return;
47
+ }
48
+
49
+ // Perform analysis (if applicable)
50
+ var analysisData = new {Feature}Data(item.Name);
51
+ var analysis = await analyzer.AnalyzeAsync(analysisData, cancellationToken);
52
+
53
+ logger.LogInformation(
54
+ "{Feature} {Id} analyzed. Confidence: {Confidence:P0}",
55
+ id, analysis.ConfidenceScore);
56
+
57
+ // Update status
58
+ // Note: You might need to add a method to update with analysis results
59
+ // await service.CompleteWithAnalysisAsync(id, analysis, cancellationToken);
60
+
61
+ logger.LogInformation("Completed {Feature} processing for ID {Id}", id);
62
+ }
63
+ catch (Exception ex)
64
+ {
65
+ logger.LogError(ex, "Failed to process {Feature} {Id}", id);
66
+ throw; // Re-throw to trigger Hangfire retry
67
+ }
68
+ }
69
+ }
70
+
71
+ // ============================================================
72
+ // RECURRING JOB CONFIGURATION
73
+ // ============================================================
74
+ //
75
+ // For scheduled/recurring jobs, configure in Program.cs:
76
+ //
77
+ // // Run every hour
78
+ // RecurringJob.AddOrUpdate<I{Feature}ProcessorJob>(
79
+ // "{feature}-processor",
80
+ // job => job.ExecuteAsync(0, CancellationToken.None),
81
+ // Cron.Hourly);
82
+ //
83
+ // // Run daily at midnight
84
+ // RecurringJob.AddOrUpdate<I{Feature}ProcessorJob>(
85
+ // "{feature}-daily-processor",
86
+ // job => job.ExecuteAsync(0, CancellationToken.None),
87
+ // Cron.Daily);
88
+ //
89
+ // // Custom cron expression (every 15 minutes)
90
+ // RecurringJob.AddOrUpdate<I{Feature}ProcessorJob>(
91
+ // "{feature}-frequent-processor",
92
+ // job => job.ExecuteAsync(0, CancellationToken.None),
93
+ // "*/15 * * * *");
94
+ //
95
+ // ============================================================
96
+
97
+ // ============================================================
98
+ // BATCH JOB TEMPLATE
99
+ // ============================================================
100
+
101
+ /// <summary>
102
+ /// Batch job for processing multiple {Feature}s.
103
+ /// </summary>
104
+ public class {Feature}BatchProcessorJob(
105
+ I{Feature}Service service,
106
+ I{Feature}ProcessorJob itemProcessor,
107
+ ILogger<{Feature}BatchProcessorJob> logger)
108
+ {
109
+ /// <summary>
110
+ /// Processes all pending {Feature}s.
111
+ /// </summary>
112
+ [AutomaticRetry(Attempts = 1)]
113
+ [Queue("batch")]
114
+ [JobDisplayName("{Feature} Batch Processing")]
115
+ public async Task ProcessAllPendingAsync(CancellationToken cancellationToken)
116
+ {
117
+ logger.LogInformation("Starting batch processing for pending {Feature}s");
118
+
119
+ var items = await service.GetAllAsync(cancellationToken);
120
+ var pending = items.Where(x => x.Status == {Feature}Status.Pending).ToList();
121
+
122
+ logger.LogInformation("Found {Count} pending {Feature}s to process", pending.Count);
123
+
124
+ foreach (var item in pending)
125
+ {
126
+ // Enqueue individual processing jobs
127
+ BackgroundJob.Enqueue<I{Feature}ProcessorJob>(
128
+ job => job.ExecuteAsync(item.Id, CancellationToken.None));
129
+ }
130
+
131
+ logger.LogInformation("Enqueued {Count} processing jobs", pending.Count);
132
+ }
133
+ }
134
+
135
+ // ============================================================
136
+ // HANGFIRE CONFIGURATION
137
+ // ============================================================
138
+ //
139
+ // In Program.cs:
140
+ //
141
+ // // Add Hangfire services
142
+ // builder.Services.AddHangfire(config => config
143
+ // .SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
144
+ // .UseSimpleAssemblyNameTypeSerializer()
145
+ // .UseRecommendedSerializerSettings()
146
+ // .UseSqlServerStorage(connectionString, new SqlServerStorageOptions
147
+ // {
148
+ // CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
149
+ // SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
150
+ // QueuePollInterval = TimeSpan.Zero,
151
+ // UseRecommendedIsolationLevel = true,
152
+ // DisableGlobalLocks = true
153
+ // }));
154
+ //
155
+ // builder.Services.AddHangfireServer(options =>
156
+ // {
157
+ // options.Queues = new[] { "default", "batch" };
158
+ // options.WorkerCount = Environment.ProcessorCount * 2;
159
+ // });
160
+ //
161
+ // // Register jobs
162
+ // builder.Services.AddScoped<I{Feature}ProcessorJob, {Feature}ProcessorJob>();
163
+ // builder.Services.AddScoped<{Feature}BatchProcessorJob>();
164
+ //
165
+ // // In app pipeline
166
+ // app.UseHangfireDashboard("/hangfire", new DashboardOptions
167
+ // {
168
+ // Authorization = new[] { new HangfireAuthorizationFilter() }
169
+ // });
170
+ //
171
+ // ============================================================
@@ -0,0 +1,83 @@
1
+ // ============================================================
2
+ // EF CORE MIGRATION TEMPLATE
3
+ // Generated by MORPH Framework
4
+ // ============================================================
5
+
6
+ using Microsoft.EntityFrameworkCore.Migrations;
7
+
8
+ #nullable disable
9
+
10
+ namespace MyProject.Infrastructure.Data.Migrations;
11
+
12
+ /// <inheritdoc />
13
+ public partial class Add{Feature} : Migration
14
+ {
15
+ /// <inheritdoc />
16
+ protected override void Up(MigrationBuilder migrationBuilder)
17
+ {
18
+ migrationBuilder.CreateTable(
19
+ name: "{Feature}s",
20
+ columns: table => new
21
+ {
22
+ Id = table.Column<int>(type: "int", nullable: false)
23
+ .Annotation("SqlServer:Identity", "1, 1"),
24
+ Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
25
+ Status = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
26
+ CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false,
27
+ defaultValueSql: "GETUTCDATE()"),
28
+ UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true)
29
+ },
30
+ constraints: table =>
31
+ {
32
+ table.PrimaryKey("PK_{Feature}s", x => x.Id);
33
+ });
34
+
35
+ // Indexes
36
+ migrationBuilder.CreateIndex(
37
+ name: "IX_{Feature}s_Name",
38
+ table: "{Feature}s",
39
+ column: "Name");
40
+
41
+ migrationBuilder.CreateIndex(
42
+ name: "IX_{Feature}s_Status",
43
+ table: "{Feature}s",
44
+ column: "Status");
45
+
46
+ migrationBuilder.CreateIndex(
47
+ name: "IX_{Feature}s_CreatedAt",
48
+ table: "{Feature}s",
49
+ column: "CreatedAt");
50
+ }
51
+
52
+ /// <inheritdoc />
53
+ protected override void Down(MigrationBuilder migrationBuilder)
54
+ {
55
+ migrationBuilder.DropTable(
56
+ name: "{Feature}s");
57
+ }
58
+ }
59
+
60
+ // ============================================================
61
+ // HOW TO CREATE A MIGRATION
62
+ // ============================================================
63
+ //
64
+ // 1. Add your entity to AppDbContext:
65
+ //
66
+ // public DbSet<{Feature}> {Feature}s => Set<{Feature}>();
67
+ //
68
+ // 2. Add your configuration:
69
+ //
70
+ // protected override void OnModelCreating(ModelBuilder modelBuilder)
71
+ // {
72
+ // modelBuilder.ApplyConfiguration(new {Feature}Configuration());
73
+ // }
74
+ //
75
+ // 3. Run migration command:
76
+ //
77
+ // dotnet ef migrations add Add{Feature} -p src/MyProject.Infrastructure -s src/MyProject.Web
78
+ //
79
+ // 4. Apply migration:
80
+ //
81
+ // dotnet ef database update -p src/MyProject.Infrastructure -s src/MyProject.Web
82
+ //
83
+ // ============================================================
@@ -0,0 +1,155 @@
1
+ # Feature Proposal: {FEATURE_NAME}
2
+
3
+ > Proposta para nova feature. Este documento descreve O QUE e POR QUÊ.
4
+ > Para detalhes técnicos, veja `spec.md`.
5
+
6
+ ## Metadata
7
+
8
+ | Field | Value |
9
+ |-------|-------|
10
+ | **Proposed** | {date} |
11
+ | **Author** | {name} |
12
+ | **Status** | Draft / Under Review / Approved / Rejected |
13
+ | **Priority** | High / Medium / Low |
14
+
15
+ ---
16
+
17
+ ## Problem Statement
18
+
19
+ ### What is the problem?
20
+
21
+ {Descreva o problema que esta feature resolve. Seja específico.}
22
+
23
+ ### Who is affected?
24
+
25
+ {Quem sofre com este problema? Usuários finais? Desenvolvedores? Operações?}
26
+
27
+ ### What is the impact?
28
+
29
+ {Qual o impacto de NÃO resolver este problema?}
30
+ - Perda de produtividade: {X}
31
+ - Custo: {X}
32
+ - Satisfação do usuário: {X}
33
+
34
+ ---
35
+
36
+ ## Proposed Solution
37
+
38
+ ### Overview
39
+
40
+ {Descreva a solução proposta em 2-3 parágrafos}
41
+
42
+ ### Key Features
43
+
44
+ 1. **{Feature 1}** - {breve descrição}
45
+ 2. **{Feature 2}** - {breve descrição}
46
+ 3. **{Feature 3}** - {breve descrição}
47
+
48
+ ### User Journey
49
+
50
+ ```
51
+ 1. Usuário {ação inicial}
52
+ 2. Sistema {resposta}
53
+ 3. Usuário {próxima ação}
54
+ 4. Sistema {resultado final}
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Success Metrics
60
+
61
+ Como saberemos que esta feature foi um sucesso?
62
+
63
+ | Metric | Current | Target |
64
+ |--------|---------|--------|
65
+ | {Metric 1} | {X} | {Y} |
66
+ | {Metric 2} | {X} | {Y} |
67
+
68
+ ---
69
+
70
+ ## Scope
71
+
72
+ ### In Scope
73
+
74
+ - {Item 1 que está incluído}
75
+ - {Item 2 que está incluído}
76
+ - {Item 3 que está incluído}
77
+
78
+ ### Out of Scope
79
+
80
+ - {Item 1 que NÃO está incluído}
81
+ - {Item 2 que NÃO está incluído}
82
+
83
+ ### Future Considerations
84
+
85
+ - {Item que pode ser adicionado depois}
86
+
87
+ ---
88
+
89
+ ## Risks & Concerns
90
+
91
+ | Risk | Likelihood | Impact | Mitigation |
92
+ |------|------------|--------|------------|
93
+ | {Risk 1} | High/Med/Low | High/Med/Low | {Como mitigar} |
94
+ | {Risk 2} | High/Med/Low | High/Med/Low | {Como mitigar} |
95
+
96
+ ---
97
+
98
+ ## Dependencies
99
+
100
+ - [ ] {Dependency 1} - {status}
101
+ - [ ] {Dependency 2} - {status}
102
+
103
+ ---
104
+
105
+ ## Estimated Effort
106
+
107
+ | Phase | Estimate |
108
+ |-------|----------|
109
+ | Design & Spec | {X}h |
110
+ | Implementation | {X}h |
111
+ | Testing | {X}h |
112
+ | **Total** | **{X}h** |
113
+
114
+ ---
115
+
116
+ ## Cost Impact
117
+
118
+ | Resource | Monthly Cost |
119
+ |----------|--------------|
120
+ | Compute | ${X} |
121
+ | Storage | ${X} |
122
+ | AI/API | ${X} |
123
+ | **Total** | **${X}/month** |
124
+
125
+ ⚠️ **Requires Approval:** {Yes/No}
126
+
127
+ ---
128
+
129
+ ## Questions & Clarifications
130
+
131
+ 1. {Pergunta 1 que precisa de resposta}
132
+ 2. {Pergunta 2 que precisa de resposta}
133
+
134
+ ---
135
+
136
+ ## Approval
137
+
138
+ | Role | Name | Decision | Date |
139
+ |------|------|----------|------|
140
+ | Product Owner | | Pending | |
141
+ | Tech Lead | | Pending | |
142
+ | Cost Guardian | | Pending | |
143
+
144
+ ---
145
+
146
+ ## Next Steps
147
+
148
+ Once approved:
149
+ 1. Create detailed `spec.md` with technical design
150
+ 2. Break down into `tasks.md`
151
+ 3. Begin implementation
152
+
153
+ ---
154
+
155
+ *Created with MORPH Framework*