@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.
- package/README.md +279 -0
- package/bin/morph-spec.js +53 -0
- package/content/.claude/commands/morph-apply.md +66 -0
- package/content/.claude/commands/morph-archive.md +79 -0
- package/content/.claude/commands/morph-costs.md +206 -0
- package/content/.claude/commands/morph-infra.md +209 -0
- package/content/.claude/commands/morph-proposal.md +60 -0
- package/content/.claude/commands/morph-status.md +71 -0
- package/content/.claude/settings.local.json +15 -0
- package/content/.claude/skills/infra/bicep-architect.md +419 -0
- package/content/.claude/skills/infra/container-specialist.md +437 -0
- package/content/.claude/skills/infra/devops-engineer.md +405 -0
- package/content/.claude/skills/integrations/asaas-financial.md +333 -0
- package/content/.claude/skills/integrations/azure-identity.md +309 -0
- package/content/.claude/skills/integrations/clerk-auth.md +290 -0
- package/content/.claude/skills/specialists/azure-architect.md +142 -0
- package/content/.claude/skills/specialists/cost-guardian.md +110 -0
- package/content/.claude/skills/specialists/ef-modeler.md +200 -0
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +245 -0
- package/content/.claude/skills/specialists/ms-agent-expert.md +209 -0
- package/content/.claude/skills/specialists/po-pm-advisor.md +197 -0
- package/content/.claude/skills/specialists/standards-architect.md +78 -0
- package/content/.claude/skills/specialists/ui-ux-designer.md +325 -0
- package/content/.claude/skills/stacks/dotnet-blazor.md +352 -0
- package/content/.claude/skills/stacks/dotnet-nextjs.md +402 -0
- package/content/.claude/skills/stacks/shopify.md +445 -0
- package/content/.morph/archive/.gitkeep +25 -0
- package/content/.morph/config/agents.json +149 -0
- package/content/.morph/config/config.template.json +96 -0
- package/content/.morph/examples/api-nextjs/README.md +241 -0
- package/content/.morph/examples/api-nextjs/contracts.ts +307 -0
- package/content/.morph/examples/api-nextjs/spec.md +399 -0
- package/content/.morph/examples/api-nextjs/tasks.md +168 -0
- package/content/.morph/examples/micro-saas/README.md +125 -0
- package/content/.morph/examples/micro-saas/contracts.cs +358 -0
- package/content/.morph/examples/micro-saas/decisions.md +246 -0
- package/content/.morph/examples/micro-saas/spec.md +236 -0
- package/content/.morph/examples/micro-saas/tasks.md +150 -0
- package/content/.morph/examples/multi-agent/README.md +309 -0
- package/content/.morph/examples/multi-agent/contracts.cs +433 -0
- package/content/.morph/examples/multi-agent/spec.md +479 -0
- package/content/.morph/examples/multi-agent/tasks.md +185 -0
- package/content/.morph/features/.gitkeep +25 -0
- package/content/.morph/project.md +159 -0
- package/content/.morph/specs/.gitkeep +20 -0
- package/content/.morph/standards/architecture.md +190 -0
- package/content/.morph/standards/azure.md +184 -0
- package/content/.morph/standards/coding.md +342 -0
- package/content/.morph/templates/agent.cs +172 -0
- package/content/.morph/templates/component.razor +239 -0
- package/content/.morph/templates/contracts.cs +217 -0
- package/content/.morph/templates/decisions.md +106 -0
- package/content/.morph/templates/infra/app-insights.bicep +63 -0
- package/content/.morph/templates/infra/container-app-env.bicep +49 -0
- package/content/.morph/templates/infra/container-app.bicep +156 -0
- package/content/.morph/templates/infra/key-vault.bicep +91 -0
- package/content/.morph/templates/infra/main.bicep +155 -0
- package/content/.morph/templates/infra/parameters.dev.json +23 -0
- package/content/.morph/templates/infra/parameters.prod.json +23 -0
- package/content/.morph/templates/infra/sql-database.bicep +103 -0
- package/content/.morph/templates/infra/storage.bicep +106 -0
- package/content/.morph/templates/integrations/asaas-client.cs +387 -0
- package/content/.morph/templates/integrations/asaas-webhook.cs +351 -0
- package/content/.morph/templates/integrations/azure-identity-config.cs +288 -0
- package/content/.morph/templates/integrations/clerk-config.cs +258 -0
- package/content/.morph/templates/job.cs +171 -0
- package/content/.morph/templates/migration.cs +83 -0
- package/content/.morph/templates/proposal.md +155 -0
- package/content/.morph/templates/recap.md +105 -0
- package/content/.morph/templates/repository.cs +141 -0
- package/content/.morph/templates/saas/subscription.cs +347 -0
- package/content/.morph/templates/saas/tenant.cs +338 -0
- package/content/.morph/templates/service.cs +139 -0
- package/content/.morph/templates/spec.md +147 -0
- package/content/.morph/templates/tasks.md +235 -0
- package/content/.morph/templates/test.cs +239 -0
- package/content/CLAUDE.md +318 -0
- package/package.json +50 -0
- package/src/commands/doctor.js +132 -0
- package/src/commands/init.js +121 -0
- package/src/commands/update.js +84 -0
- package/src/utils/file-copier.js +50 -0
- package/src/utils/logger.js +32 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Project Context - {PROJECT_NAME}
|
|
2
|
+
|
|
3
|
+
> Este arquivo define o contexto do projeto para os agentes MORPH.
|
|
4
|
+
> Preencha com as informações específicas do seu projeto.
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
**Nome:** {PROJECT_NAME}
|
|
9
|
+
**Descrição:** {Breve descrição do projeto}
|
|
10
|
+
**Tipo:** Blazor Server Application
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Technical Stack
|
|
15
|
+
|
|
16
|
+
| Layer | Technology | Version |
|
|
17
|
+
|-------|------------|---------|
|
|
18
|
+
| Frontend | Blazor Server | .NET 9 |
|
|
19
|
+
| Backend | ASP.NET Core | 9.0 |
|
|
20
|
+
| Database | Azure SQL | Free Tier |
|
|
21
|
+
| ORM | Entity Framework Core | 9.0 |
|
|
22
|
+
| AI | MS Agent Framework / Semantic Kernel | Latest |
|
|
23
|
+
| Jobs | Hangfire | Latest |
|
|
24
|
+
| Hosting | Azure Container Apps | Consumption |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Architecture
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
┌─────────────────────────────────────────────────┐
|
|
32
|
+
│ Web (Blazor) │
|
|
33
|
+
├─────────────────────────────────────────────────┤
|
|
34
|
+
│ Application (Services) │
|
|
35
|
+
├─────────────────────────────────────────────────┤
|
|
36
|
+
│ Domain (Entities) │
|
|
37
|
+
├─────────────────────────────────────────────────┤
|
|
38
|
+
│ Infrastructure (EF Core) │
|
|
39
|
+
├─────────────────────────────────────────────────┤
|
|
40
|
+
│ Agents (AI Services) │
|
|
41
|
+
└─────────────────────────────────────────────────┘
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Project Structure
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
src/
|
|
48
|
+
├── {Project}.Web/ # Blazor Server
|
|
49
|
+
├── {Project}.Application/ # Services, DTOs, Commands
|
|
50
|
+
├── {Project}.Domain/ # Entities, Value Objects
|
|
51
|
+
├── {Project}.Infrastructure/ # EF Core, Repositories
|
|
52
|
+
└── {Project}.Agents/ # AI Agents
|
|
53
|
+
|
|
54
|
+
tests/
|
|
55
|
+
├── {Project}.Tests.Unit/
|
|
56
|
+
└── {Project}.Tests.Integration/
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Conventions
|
|
62
|
+
|
|
63
|
+
### Naming
|
|
64
|
+
|
|
65
|
+
- **Classes:** PascalCase (ex: `ReportScheduleService`)
|
|
66
|
+
- **Interfaces:** I + PascalCase (ex: `IReportScheduleService`)
|
|
67
|
+
- **Methods:** PascalCase, async com sufixo Async (ex: `GetByIdAsync`)
|
|
68
|
+
- **Variables:** camelCase (ex: `reportSchedule`)
|
|
69
|
+
- **Private fields:** _camelCase (ex: `_repository`)
|
|
70
|
+
|
|
71
|
+
### Code Style
|
|
72
|
+
|
|
73
|
+
- Primary constructors (C# 12+)
|
|
74
|
+
- Records para DTOs
|
|
75
|
+
- Private setters em entidades
|
|
76
|
+
- Factory methods para criação de entidades
|
|
77
|
+
- Fluent API para EF Core (nunca Data Annotations)
|
|
78
|
+
|
|
79
|
+
### Documentation
|
|
80
|
+
|
|
81
|
+
- Documentação em Português
|
|
82
|
+
- Código em Inglês
|
|
83
|
+
- XML comments em métodos públicos
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Azure Resources
|
|
88
|
+
|
|
89
|
+
| Resource | Name | Tier |
|
|
90
|
+
|----------|------|------|
|
|
91
|
+
| Resource Group | rg-{project}-{env} | - |
|
|
92
|
+
| Container App | ca-{project}-{env} | Consumption |
|
|
93
|
+
| SQL Server | sql-{project}-{env} | Free |
|
|
94
|
+
| SQL Database | sqldb-{project}-{env} | Free 32GB |
|
|
95
|
+
| App Insights | appi-{project}-{env} | Free 5GB |
|
|
96
|
+
|
|
97
|
+
### Cost Limits
|
|
98
|
+
|
|
99
|
+
- **Sem aprovação:** Free tier apenas
|
|
100
|
+
- **Com aprovação:** Até $10/mês
|
|
101
|
+
- **Acima de $10:** Requer ADR com justificativa
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Authentication & Authorization
|
|
106
|
+
|
|
107
|
+
- [ ] Azure AD / Entra ID
|
|
108
|
+
- [ ] Identity Server
|
|
109
|
+
- [ ] Custom JWT
|
|
110
|
+
- [ ] None (internal tool)
|
|
111
|
+
|
|
112
|
+
**Policies definidas:**
|
|
113
|
+
- `CanView{Feature}` - Visualização
|
|
114
|
+
- `CanManage{Feature}` - CRUD completo
|
|
115
|
+
- `IsAdmin` - Acesso total
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## External Integrations
|
|
120
|
+
|
|
121
|
+
| Service | Purpose | Auth Method |
|
|
122
|
+
|---------|---------|-------------|
|
|
123
|
+
| Azure OpenAI | AI Analysis | Managed Identity |
|
|
124
|
+
| {Service} | {Purpose} | {Method} |
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Development Guidelines
|
|
129
|
+
|
|
130
|
+
### Git Flow
|
|
131
|
+
|
|
132
|
+
- **main** - Produção
|
|
133
|
+
- **develop** - Desenvolvimento
|
|
134
|
+
- **feature/{name}** - Features
|
|
135
|
+
|
|
136
|
+
### Commit Convention
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
{type}({scope}): {message}
|
|
140
|
+
|
|
141
|
+
Types: feat, fix, docs, style, refactor, test, chore
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### PR Requirements
|
|
145
|
+
|
|
146
|
+
- [ ] Testes passando
|
|
147
|
+
- [ ] Code review aprovado
|
|
148
|
+
- [ ] Sem conflitos
|
|
149
|
+
- [ ] Linked to work item
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Notes
|
|
154
|
+
|
|
155
|
+
{Adicione notas específicas do projeto aqui}
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
*Gerado pelo MORPH Framework*
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Specs Ativas
|
|
2
|
+
|
|
3
|
+
Esta pasta contém as especificações ATIVAS do projeto.
|
|
4
|
+
Specs são extraídas de features arquivadas e representam a "verdade atual" do sistema.
|
|
5
|
+
|
|
6
|
+
## Estrutura
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
specs/
|
|
10
|
+
└── {domain}/
|
|
11
|
+
└── spec.md
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Como usar
|
|
15
|
+
|
|
16
|
+
1. Quando uma feature é arquivada, specs relevantes são extraídas para cá
|
|
17
|
+
2. Specs aqui são a referência para comportamento do sistema
|
|
18
|
+
3. Novas features podem referenciar e modificar estas specs
|
|
19
|
+
|
|
20
|
+
*Gerado pelo MORPH Framework*
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Padrões de Arquitetura - MORPH Framework
|
|
2
|
+
|
|
3
|
+
## 🏗️ Clean Architecture Simplificada
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
┌────────────────────────────────────────────────┐
|
|
7
|
+
│ Web │
|
|
8
|
+
│ (Blazor Server, Controllers) │
|
|
9
|
+
├────────────────────────────────────────────────┤
|
|
10
|
+
│ Application │
|
|
11
|
+
│ (Services, Commands, Queries, DTOs) │
|
|
12
|
+
├────────────────────────────────────────────────┤
|
|
13
|
+
│ Domain │
|
|
14
|
+
│ (Entities, Value Objects, Enums) │
|
|
15
|
+
├────────────────────────────────────────────────┤
|
|
16
|
+
│ Infrastructure │
|
|
17
|
+
│ (EF Core, External Services, Repositories) │
|
|
18
|
+
├────────────────────────────────────────────────┤
|
|
19
|
+
│ Agents │
|
|
20
|
+
│ (MS Agent Framework, AI Services) │
|
|
21
|
+
└────────────────────────────────────────────────┘
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Regras de Dependência
|
|
25
|
+
- Web → Application, Infrastructure, Agents
|
|
26
|
+
- Application → Domain
|
|
27
|
+
- Infrastructure → Domain, Application (interfaces)
|
|
28
|
+
- Agents → Domain, Application (interfaces)
|
|
29
|
+
- Domain → Nada (núcleo isolado)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 📁 Organização por Feature
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Application/
|
|
37
|
+
├── Features/
|
|
38
|
+
│ ├── Reports/
|
|
39
|
+
│ │ ├── Commands/
|
|
40
|
+
│ │ │ └── CreateReportSchedule/
|
|
41
|
+
│ │ ├── Queries/
|
|
42
|
+
│ │ │ └── GetReportSchedule/
|
|
43
|
+
│ │ ├── Services/
|
|
44
|
+
│ │ │ ├── IReportScheduleService.cs
|
|
45
|
+
│ │ │ └── ReportScheduleService.cs
|
|
46
|
+
│ │ └── DTOs/
|
|
47
|
+
│ │ └── ReportScheduleDto.cs
|
|
48
|
+
│ │
|
|
49
|
+
│ └── Users/
|
|
50
|
+
│ ├── Commands/
|
|
51
|
+
│ ├── Queries/
|
|
52
|
+
│ └── Services/
|
|
53
|
+
│
|
|
54
|
+
└── Common/
|
|
55
|
+
├── Interfaces/
|
|
56
|
+
└── Exceptions/
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🔄 CQRS Simplificado (Sem MediatR)
|
|
62
|
+
|
|
63
|
+
```csharp
|
|
64
|
+
// Application/Features/Reports/Services/IReportScheduleService.cs
|
|
65
|
+
public interface IReportScheduleService
|
|
66
|
+
{
|
|
67
|
+
// Queries
|
|
68
|
+
Task<ReportScheduleDto?> GetByIdAsync(int id);
|
|
69
|
+
Task<List<ReportScheduleDto>> GetAllAsync();
|
|
70
|
+
|
|
71
|
+
// Commands
|
|
72
|
+
Task<ReportScheduleDto> CreateAsync(CreateReportScheduleRequest request);
|
|
73
|
+
Task UpdateAsync(int id, UpdateReportScheduleRequest request);
|
|
74
|
+
Task DeleteAsync(int id);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 🔐 Segurança
|
|
81
|
+
|
|
82
|
+
### Authorization - Policy-Based
|
|
83
|
+
```csharp
|
|
84
|
+
// Program.cs
|
|
85
|
+
builder.Services.AddAuthorization(options =>
|
|
86
|
+
{
|
|
87
|
+
options.AddPolicy("CanManageReports", policy =>
|
|
88
|
+
policy.RequireRole("Admin", "ReportManager"));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// No componente Blazor
|
|
92
|
+
@attribute [Authorize(Policy = "CanManageReports")]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Current User Service
|
|
96
|
+
```csharp
|
|
97
|
+
public interface ICurrentUserService
|
|
98
|
+
{
|
|
99
|
+
string? UserId { get; }
|
|
100
|
+
string? UserName { get; }
|
|
101
|
+
bool IsAuthenticated { get; }
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## ⚠️ Exception Handling
|
|
108
|
+
|
|
109
|
+
### Hierarquia
|
|
110
|
+
```csharp
|
|
111
|
+
public abstract class DomainException : Exception
|
|
112
|
+
{
|
|
113
|
+
protected DomainException(string message) : base(message) { }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public class NotFoundException : DomainException
|
|
117
|
+
{
|
|
118
|
+
public NotFoundException(string entityName, object key)
|
|
119
|
+
: base($"Entity \"{entityName}\" ({key}) was not found.") { }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public class ValidationException : DomainException
|
|
123
|
+
{
|
|
124
|
+
public IDictionary<string, string[]> Errors { get; }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Feature-specific
|
|
128
|
+
public class ReportScheduleNotFoundException : NotFoundException
|
|
129
|
+
{
|
|
130
|
+
public ReportScheduleNotFoundException(int id)
|
|
131
|
+
: base("ReportSchedule", id) { }
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 🔌 HTTP Clients com Polly
|
|
138
|
+
|
|
139
|
+
```csharp
|
|
140
|
+
services.AddHttpClient<IMemberKitClient, MemberKitClient>(client =>
|
|
141
|
+
{
|
|
142
|
+
client.BaseAddress = new Uri(configuration["MemberKit:BaseUrl"]!);
|
|
143
|
+
})
|
|
144
|
+
.AddTransientHttpErrorPolicy(p =>
|
|
145
|
+
p.WaitAndRetryAsync(3, _ => TimeSpan.FromSeconds(2)));
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 🤖 Agents como Services
|
|
151
|
+
|
|
152
|
+
```csharp
|
|
153
|
+
// Agents/DependencyInjection.cs
|
|
154
|
+
public static IServiceCollection AddAgents(this IServiceCollection services, IConfiguration configuration)
|
|
155
|
+
{
|
|
156
|
+
var builder = Kernel.CreateBuilder();
|
|
157
|
+
builder.AddAzureOpenAIChatCompletion(
|
|
158
|
+
deploymentName: "gpt-4o-mini",
|
|
159
|
+
endpoint: configuration["AzureOpenAI:Endpoint"]!,
|
|
160
|
+
apiKey: configuration["AzureOpenAI:ApiKey"]!);
|
|
161
|
+
|
|
162
|
+
services.AddSingleton(builder.Build());
|
|
163
|
+
services.AddScoped<IReportAnalyzerAgent, ReportAnalyzerAgent>();
|
|
164
|
+
|
|
165
|
+
return services;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Uso transparente nos services
|
|
169
|
+
public class ReportGeneratorJob(IReportAnalyzerAgent analyzer)
|
|
170
|
+
{
|
|
171
|
+
public async Task ExecuteAsync(int scheduleId, CancellationToken ct)
|
|
172
|
+
{
|
|
173
|
+
var analysis = await analyzer.AnalyzeAsync(data, ct);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## ✅ Checklist de Arquitetura
|
|
181
|
+
|
|
182
|
+
- [ ] Domain sem dependências externas
|
|
183
|
+
- [ ] Features organizadas por pasta
|
|
184
|
+
- [ ] Interfaces em Application, implementações em Infrastructure
|
|
185
|
+
- [ ] DTOs para comunicação entre camadas
|
|
186
|
+
- [ ] Exceptions customizadas para domínio
|
|
187
|
+
- [ ] DI via construtor (não Service Locator)
|
|
188
|
+
- [ ] Agents tratados como services
|
|
189
|
+
- [ ] Authorization via policies
|
|
190
|
+
- [ ] HTTP Clients tipados com retry
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Padrões Azure - MORPH Framework
|
|
2
|
+
|
|
3
|
+
## 💰 Filosofia de Custos
|
|
4
|
+
|
|
5
|
+
> **Free tier primeiro. Aprovação explícita para upgrade.**
|
|
6
|
+
|
|
7
|
+
| Nível | Limite | Requer |
|
|
8
|
+
|-------|--------|--------|
|
|
9
|
+
| Sem aprovação | Free tier apenas | Nada |
|
|
10
|
+
| Com aprovação | Até $10/mês | Confirmação |
|
|
11
|
+
| Acima de $10 | Justificativa detalhada | ADR |
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 📋 Stack Padrão Aprovado
|
|
16
|
+
|
|
17
|
+
| Recurso | Tier | Custo | Quando Usar |
|
|
18
|
+
|---------|------|-------|-------------|
|
|
19
|
+
| **Container Apps** | Consumption | ~$0-5/mês | Hosting principal |
|
|
20
|
+
| **Azure SQL** | Free 32GB | $0 | Database |
|
|
21
|
+
| **ACR** | Basic | ~$5/mês | Container registry |
|
|
22
|
+
| **App Insights** | Free 5GB | $0 | Logs e métricas |
|
|
23
|
+
| **Azure OpenAI** | gpt-4o-mini | ~$2-10/mês | Análises AI |
|
|
24
|
+
|
|
25
|
+
**Custo total típico: $7-20/mês**
|
|
26
|
+
|
|
27
|
+
### ⚠️ Requer Aprovação
|
|
28
|
+
|
|
29
|
+
| Recurso | Custo | Alternativa Free |
|
|
30
|
+
|---------|-------|------------------|
|
|
31
|
+
| Azure Functions | ~$0-5/mês | Hangfire |
|
|
32
|
+
| Service Bus | ~$10/mês | Queue em SQL |
|
|
33
|
+
| Cosmos DB | ~$25/mês | Azure SQL JSON |
|
|
34
|
+
| Redis Cache | ~$15/mês | In-memory |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 🐳 Container Apps
|
|
39
|
+
|
|
40
|
+
### Configuração Obrigatória
|
|
41
|
+
```yaml
|
|
42
|
+
properties:
|
|
43
|
+
template:
|
|
44
|
+
scale:
|
|
45
|
+
minReplicas: 0 # ⚠️ OBRIGATÓRIO: scale-to-zero
|
|
46
|
+
maxReplicas: 2
|
|
47
|
+
containers:
|
|
48
|
+
- name: app
|
|
49
|
+
resources:
|
|
50
|
+
cpu: 0.25 # Mínimo
|
|
51
|
+
memory: 0.5Gi # Mínimo
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Scale-to-Zero
|
|
55
|
+
- ✅ **OBRIGATÓRIO** para dev/staging
|
|
56
|
+
- ⚠️ Em prod com Hangfire: `minReplicas: 1`
|
|
57
|
+
- 💰 Economia: ~80% vs always-on
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🗄️ Azure SQL Free Tier
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
- 32 GB storage
|
|
65
|
+
- 100,000 vCore seconds/month
|
|
66
|
+
- Serverless compute
|
|
67
|
+
- Auto-pause after 1 hour idle
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Práticas
|
|
71
|
+
- ✅ Usar Managed Identity
|
|
72
|
+
- ✅ TDE habilitado (default)
|
|
73
|
+
- ❌ Não criar índices em excesso
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 🤖 Azure OpenAI
|
|
78
|
+
|
|
79
|
+
### Modelo Padrão: gpt-4o-mini
|
|
80
|
+
|
|
81
|
+
| Modelo | Custo Input | Custo Output | Usar |
|
|
82
|
+
|--------|-------------|--------------|------|
|
|
83
|
+
| **gpt-4o-mini** | $0.15/1M | $0.60/1M | ✅ PADRÃO |
|
|
84
|
+
| gpt-4o | $2.50/1M | $10/1M | Com aprovação |
|
|
85
|
+
| gpt-4 | $30/1M | $60/1M | ❌ NUNCA |
|
|
86
|
+
|
|
87
|
+
### Otimização
|
|
88
|
+
```csharp
|
|
89
|
+
var settings = new OpenAIPromptExecutionSettings
|
|
90
|
+
{
|
|
91
|
+
MaxTokens = 500, // Limitar resposta
|
|
92
|
+
Temperature = 0.3 // Mais determinístico
|
|
93
|
+
};
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 🔐 Segurança
|
|
99
|
+
|
|
100
|
+
### Managed Identity (Preferido)
|
|
101
|
+
```csharp
|
|
102
|
+
// Para Azure SQL
|
|
103
|
+
"Authentication=Active Directory Managed Identity;"
|
|
104
|
+
|
|
105
|
+
// Para Azure OpenAI
|
|
106
|
+
var credential = new DefaultAzureCredential();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Key Vault
|
|
110
|
+
Usar apenas para:
|
|
111
|
+
- Secrets de serviços externos
|
|
112
|
+
- API keys de terceiros
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 📛 Naming Conventions
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
{tipo}-{projeto}-{ambiente}
|
|
120
|
+
|
|
121
|
+
Exemplos:
|
|
122
|
+
- rg-myproject-dev # Resource Group
|
|
123
|
+
- ca-myproject-dev # Container App
|
|
124
|
+
- sql-myproject-dev # SQL Server
|
|
125
|
+
- sqldb-myproject-dev # SQL Database
|
|
126
|
+
- acr-myproject # Container Registry
|
|
127
|
+
- appi-myproject-dev # App Insights
|
|
128
|
+
- kv-myproject-dev # Key Vault
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
| Ambiente | Sufixo | Características |
|
|
132
|
+
|----------|--------|-----------------|
|
|
133
|
+
| Development | -dev | Scale-to-zero, free tier |
|
|
134
|
+
| Staging | -stg | Scale-to-zero, free tier |
|
|
135
|
+
| Production | -prod | Min 1 replica |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 🚀 Pipeline YAML
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
trigger:
|
|
143
|
+
branches:
|
|
144
|
+
include: [main, develop]
|
|
145
|
+
|
|
146
|
+
stages:
|
|
147
|
+
- stage: Build
|
|
148
|
+
jobs:
|
|
149
|
+
- job: BuildAndTest
|
|
150
|
+
steps:
|
|
151
|
+
- script: dotnet restore
|
|
152
|
+
- script: dotnet build
|
|
153
|
+
- script: dotnet test
|
|
154
|
+
- task: Docker@2
|
|
155
|
+
inputs:
|
|
156
|
+
command: buildAndPush
|
|
157
|
+
|
|
158
|
+
- stage: DeployDev
|
|
159
|
+
condition: eq(variables['Build.SourceBranch'], 'refs/heads/develop')
|
|
160
|
+
jobs:
|
|
161
|
+
- deployment: DeployToDev
|
|
162
|
+
environment: Development
|
|
163
|
+
strategy:
|
|
164
|
+
runOnce:
|
|
165
|
+
deploy:
|
|
166
|
+
steps:
|
|
167
|
+
- task: AzureContainerApps@1
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## ✅ Checklist de Deploy
|
|
173
|
+
|
|
174
|
+
### Antes
|
|
175
|
+
- [ ] Testes passando
|
|
176
|
+
- [ ] Migrations aplicadas
|
|
177
|
+
- [ ] Secrets no Key Vault
|
|
178
|
+
- [ ] Managed Identity configurada
|
|
179
|
+
|
|
180
|
+
### Após
|
|
181
|
+
- [ ] Health check OK
|
|
182
|
+
- [ ] Logs no App Insights
|
|
183
|
+
- [ ] Funcionalidade testada
|
|
184
|
+
- [ ] Custos verificados
|