@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,437 @@
|
|
|
1
|
+
# Container Specialist
|
|
2
|
+
|
|
3
|
+
Especialista em containerização com Docker e deploy para Azure Container Apps.
|
|
4
|
+
|
|
5
|
+
## Responsabilidades
|
|
6
|
+
|
|
7
|
+
1. **Criar Dockerfiles** otimizados para .NET
|
|
8
|
+
2. **Configurar Container Apps** no Azure
|
|
9
|
+
3. **Gerenciar registries** (ACR, GHCR)
|
|
10
|
+
4. **Otimizar imagens** para tamanho e performance
|
|
11
|
+
|
|
12
|
+
## Triggers
|
|
13
|
+
|
|
14
|
+
Keywords: `docker`, `container`, `containerize`, `container apps`, `acr`, `registry`, `image`
|
|
15
|
+
|
|
16
|
+
## Docker para .NET
|
|
17
|
+
|
|
18
|
+
### Dockerfile Multi-stage Otimizado
|
|
19
|
+
|
|
20
|
+
```dockerfile
|
|
21
|
+
# Dockerfile
|
|
22
|
+
# Stage 1: Build
|
|
23
|
+
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
|
|
24
|
+
WORKDIR /src
|
|
25
|
+
|
|
26
|
+
# Copy csproj files first (cache de restore)
|
|
27
|
+
COPY ["src/Web/Web.csproj", "src/Web/"]
|
|
28
|
+
COPY ["src/Application/Application.csproj", "src/Application/"]
|
|
29
|
+
COPY ["src/Domain/Domain.csproj", "src/Domain/"]
|
|
30
|
+
COPY ["src/Infrastructure/Infrastructure.csproj", "src/Infrastructure/"]
|
|
31
|
+
|
|
32
|
+
# Restore
|
|
33
|
+
RUN dotnet restore "src/Web/Web.csproj"
|
|
34
|
+
|
|
35
|
+
# Copy everything
|
|
36
|
+
COPY . .
|
|
37
|
+
|
|
38
|
+
# Build
|
|
39
|
+
WORKDIR "/src/src/Web"
|
|
40
|
+
RUN dotnet build "Web.csproj" -c Release -o /app/build
|
|
41
|
+
|
|
42
|
+
# Stage 2: Publish
|
|
43
|
+
FROM build AS publish
|
|
44
|
+
RUN dotnet publish "Web.csproj" -c Release -o /app/publish \
|
|
45
|
+
/p:UseAppHost=false \
|
|
46
|
+
/p:PublishTrimmed=false
|
|
47
|
+
|
|
48
|
+
# Stage 3: Runtime
|
|
49
|
+
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final
|
|
50
|
+
WORKDIR /app
|
|
51
|
+
|
|
52
|
+
# Security: non-root user
|
|
53
|
+
RUN addgroup -g 1000 appgroup && \
|
|
54
|
+
adduser -u 1000 -G appgroup -D appuser
|
|
55
|
+
|
|
56
|
+
# Copy published app
|
|
57
|
+
COPY --from=publish /app/publish .
|
|
58
|
+
|
|
59
|
+
# Set ownership
|
|
60
|
+
RUN chown -R appuser:appgroup /app
|
|
61
|
+
|
|
62
|
+
USER appuser
|
|
63
|
+
|
|
64
|
+
# Expose port
|
|
65
|
+
EXPOSE 8080
|
|
66
|
+
|
|
67
|
+
# Health check
|
|
68
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
69
|
+
CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
|
|
70
|
+
|
|
71
|
+
# Entry point
|
|
72
|
+
ENTRYPOINT ["dotnet", "Web.dll"]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### .dockerignore
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
# .dockerignore
|
|
79
|
+
**/.git
|
|
80
|
+
**/.vs
|
|
81
|
+
**/.vscode
|
|
82
|
+
**/bin
|
|
83
|
+
**/obj
|
|
84
|
+
**/node_modules
|
|
85
|
+
**/.idea
|
|
86
|
+
*.md
|
|
87
|
+
*.txt
|
|
88
|
+
Dockerfile*
|
|
89
|
+
docker-compose*
|
|
90
|
+
.dockerignore
|
|
91
|
+
.gitignore
|
|
92
|
+
.editorconfig
|
|
93
|
+
**/*.user
|
|
94
|
+
**/*.suo
|
|
95
|
+
**/TestResults
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Docker Compose para Dev
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
# docker-compose.yml
|
|
102
|
+
services:
|
|
103
|
+
web:
|
|
104
|
+
build:
|
|
105
|
+
context: .
|
|
106
|
+
dockerfile: Dockerfile
|
|
107
|
+
ports:
|
|
108
|
+
- "8080:8080"
|
|
109
|
+
environment:
|
|
110
|
+
- ASPNETCORE_ENVIRONMENT=Development
|
|
111
|
+
- ConnectionStrings__DefaultConnection=Server=db;Database=App;User=sa;Password=YourStrong!Passw0rd;TrustServerCertificate=true
|
|
112
|
+
depends_on:
|
|
113
|
+
db:
|
|
114
|
+
condition: service_healthy
|
|
115
|
+
networks:
|
|
116
|
+
- app-network
|
|
117
|
+
|
|
118
|
+
db:
|
|
119
|
+
image: mcr.microsoft.com/mssql/server:2022-latest
|
|
120
|
+
environment:
|
|
121
|
+
- ACCEPT_EULA=Y
|
|
122
|
+
- SA_PASSWORD=YourStrong!Passw0rd
|
|
123
|
+
ports:
|
|
124
|
+
- "1433:1433"
|
|
125
|
+
volumes:
|
|
126
|
+
- sqldata:/var/opt/mssql
|
|
127
|
+
healthcheck:
|
|
128
|
+
test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "YourStrong!Passw0rd" -Q "SELECT 1" -C
|
|
129
|
+
interval: 10s
|
|
130
|
+
timeout: 3s
|
|
131
|
+
retries: 10
|
|
132
|
+
networks:
|
|
133
|
+
- app-network
|
|
134
|
+
|
|
135
|
+
redis:
|
|
136
|
+
image: redis:7-alpine
|
|
137
|
+
ports:
|
|
138
|
+
- "6379:6379"
|
|
139
|
+
networks:
|
|
140
|
+
- app-network
|
|
141
|
+
|
|
142
|
+
networks:
|
|
143
|
+
app-network:
|
|
144
|
+
driver: bridge
|
|
145
|
+
|
|
146
|
+
volumes:
|
|
147
|
+
sqldata:
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Azure Container Registry (ACR)
|
|
151
|
+
|
|
152
|
+
### Criar ACR via Bicep
|
|
153
|
+
|
|
154
|
+
```bicep
|
|
155
|
+
// modules/acr.bicep
|
|
156
|
+
@description('ACR name')
|
|
157
|
+
param name string
|
|
158
|
+
|
|
159
|
+
@description('Location')
|
|
160
|
+
param location string
|
|
161
|
+
|
|
162
|
+
@description('Tags')
|
|
163
|
+
param tags object = {}
|
|
164
|
+
|
|
165
|
+
@description('SKU')
|
|
166
|
+
@allowed(['Basic', 'Standard', 'Premium'])
|
|
167
|
+
param sku string = 'Basic'
|
|
168
|
+
|
|
169
|
+
resource acr 'Microsoft.ContainerRegistry/registries@2023-07-01' = {
|
|
170
|
+
name: name
|
|
171
|
+
location: location
|
|
172
|
+
tags: tags
|
|
173
|
+
sku: {
|
|
174
|
+
name: sku
|
|
175
|
+
}
|
|
176
|
+
properties: {
|
|
177
|
+
adminUserEnabled: true
|
|
178
|
+
publicNetworkAccess: 'Enabled'
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
output loginServer string = acr.properties.loginServer
|
|
183
|
+
output name string = acr.name
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Commands ACR
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Criar ACR
|
|
190
|
+
az acr create --resource-group rg-myapp --name myappacr --sku Basic
|
|
191
|
+
|
|
192
|
+
# Login
|
|
193
|
+
az acr login --name myappacr
|
|
194
|
+
|
|
195
|
+
# Build e push
|
|
196
|
+
az acr build --registry myappacr --image myapp:v1 .
|
|
197
|
+
|
|
198
|
+
# Listar imagens
|
|
199
|
+
az acr repository list --name myappacr
|
|
200
|
+
|
|
201
|
+
# Listar tags
|
|
202
|
+
az acr repository show-tags --name myappacr --repository myapp
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Azure Container Apps
|
|
206
|
+
|
|
207
|
+
### Deploy via Bicep
|
|
208
|
+
|
|
209
|
+
```bicep
|
|
210
|
+
// modules/container-app.bicep
|
|
211
|
+
@description('App name')
|
|
212
|
+
param name string
|
|
213
|
+
|
|
214
|
+
@description('Location')
|
|
215
|
+
param location string
|
|
216
|
+
|
|
217
|
+
@description('Tags')
|
|
218
|
+
param tags object = {}
|
|
219
|
+
|
|
220
|
+
@description('Container App Environment ID')
|
|
221
|
+
param environmentId string
|
|
222
|
+
|
|
223
|
+
@description('Container image')
|
|
224
|
+
param containerImage string
|
|
225
|
+
|
|
226
|
+
@description('Registry server')
|
|
227
|
+
param registryServer string
|
|
228
|
+
|
|
229
|
+
@description('Registry username')
|
|
230
|
+
param registryUsername string
|
|
231
|
+
|
|
232
|
+
@description('Registry password')
|
|
233
|
+
@secure()
|
|
234
|
+
param registryPassword string
|
|
235
|
+
|
|
236
|
+
@description('Environment variables')
|
|
237
|
+
param envVars array = []
|
|
238
|
+
|
|
239
|
+
resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
|
|
240
|
+
name: name
|
|
241
|
+
location: location
|
|
242
|
+
tags: tags
|
|
243
|
+
properties: {
|
|
244
|
+
managedEnvironmentId: environmentId
|
|
245
|
+
configuration: {
|
|
246
|
+
ingress: {
|
|
247
|
+
external: true
|
|
248
|
+
targetPort: 8080
|
|
249
|
+
transport: 'http'
|
|
250
|
+
allowInsecure: false
|
|
251
|
+
traffic: [
|
|
252
|
+
{
|
|
253
|
+
latestRevision: true
|
|
254
|
+
weight: 100
|
|
255
|
+
}
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
registries: [
|
|
259
|
+
{
|
|
260
|
+
server: registryServer
|
|
261
|
+
username: registryUsername
|
|
262
|
+
passwordSecretRef: 'registry-password'
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
secrets: [
|
|
266
|
+
{
|
|
267
|
+
name: 'registry-password'
|
|
268
|
+
value: registryPassword
|
|
269
|
+
}
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
template: {
|
|
273
|
+
containers: [
|
|
274
|
+
{
|
|
275
|
+
name: name
|
|
276
|
+
image: containerImage
|
|
277
|
+
resources: {
|
|
278
|
+
cpu: json('0.25')
|
|
279
|
+
memory: '0.5Gi'
|
|
280
|
+
}
|
|
281
|
+
env: envVars
|
|
282
|
+
probes: [
|
|
283
|
+
{
|
|
284
|
+
type: 'Liveness'
|
|
285
|
+
httpGet: {
|
|
286
|
+
path: '/health'
|
|
287
|
+
port: 8080
|
|
288
|
+
}
|
|
289
|
+
initialDelaySeconds: 10
|
|
290
|
+
periodSeconds: 30
|
|
291
|
+
}
|
|
292
|
+
{
|
|
293
|
+
type: 'Readiness'
|
|
294
|
+
httpGet: {
|
|
295
|
+
path: '/health/ready'
|
|
296
|
+
port: 8080
|
|
297
|
+
}
|
|
298
|
+
initialDelaySeconds: 5
|
|
299
|
+
periodSeconds: 10
|
|
300
|
+
}
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
]
|
|
304
|
+
scale: {
|
|
305
|
+
minReplicas: 0
|
|
306
|
+
maxReplicas: 5
|
|
307
|
+
rules: [
|
|
308
|
+
{
|
|
309
|
+
name: 'http-scale'
|
|
310
|
+
http: {
|
|
311
|
+
metadata: {
|
|
312
|
+
concurrentRequests: '100'
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
output url string = 'https://${containerApp.properties.configuration.ingress.fqdn}'
|
|
323
|
+
output name string = containerApp.name
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Deploy via CLI
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
# Criar environment
|
|
330
|
+
az containerapp env create \
|
|
331
|
+
--name myapp-env \
|
|
332
|
+
--resource-group rg-myapp \
|
|
333
|
+
--location brazilsouth
|
|
334
|
+
|
|
335
|
+
# Criar container app
|
|
336
|
+
az containerapp create \
|
|
337
|
+
--name myapp \
|
|
338
|
+
--resource-group rg-myapp \
|
|
339
|
+
--environment myapp-env \
|
|
340
|
+
--image myappacr.azurecr.io/myapp:latest \
|
|
341
|
+
--registry-server myappacr.azurecr.io \
|
|
342
|
+
--registry-username myappacr \
|
|
343
|
+
--registry-password $ACR_PASSWORD \
|
|
344
|
+
--target-port 8080 \
|
|
345
|
+
--ingress external \
|
|
346
|
+
--min-replicas 0 \
|
|
347
|
+
--max-replicas 5 \
|
|
348
|
+
--cpu 0.25 \
|
|
349
|
+
--memory 0.5Gi
|
|
350
|
+
|
|
351
|
+
# Atualizar imagem
|
|
352
|
+
az containerapp update \
|
|
353
|
+
--name myapp \
|
|
354
|
+
--resource-group rg-myapp \
|
|
355
|
+
--image myappacr.azurecr.io/myapp:v2
|
|
356
|
+
|
|
357
|
+
# Ver logs
|
|
358
|
+
az containerapp logs show \
|
|
359
|
+
--name myapp \
|
|
360
|
+
--resource-group rg-myapp \
|
|
361
|
+
--follow
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Health Checks no ASP.NET
|
|
365
|
+
|
|
366
|
+
```csharp
|
|
367
|
+
// Program.cs
|
|
368
|
+
builder.Services.AddHealthChecks()
|
|
369
|
+
.AddSqlServer(
|
|
370
|
+
connectionString: builder.Configuration.GetConnectionString("Default")!,
|
|
371
|
+
name: "database",
|
|
372
|
+
tags: new[] { "ready" })
|
|
373
|
+
.AddRedis(
|
|
374
|
+
redisConnectionString: builder.Configuration.GetConnectionString("Redis")!,
|
|
375
|
+
name: "redis",
|
|
376
|
+
tags: new[] { "ready" });
|
|
377
|
+
|
|
378
|
+
app.MapHealthChecks("/health", new HealthCheckOptions
|
|
379
|
+
{
|
|
380
|
+
Predicate = _ => true,
|
|
381
|
+
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
app.MapHealthChecks("/health/ready", new HealthCheckOptions
|
|
385
|
+
{
|
|
386
|
+
Predicate = check => check.Tags.Contains("ready")
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
app.MapHealthChecks("/health/live", new HealthCheckOptions
|
|
390
|
+
{
|
|
391
|
+
Predicate = _ => false // Sempre retorna healthy
|
|
392
|
+
});
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## Otimização de Imagens
|
|
396
|
+
|
|
397
|
+
### Tamanho de Imagens
|
|
398
|
+
|
|
399
|
+
| Base Image | Tamanho |
|
|
400
|
+
|------------|---------|
|
|
401
|
+
| `aspnet:9.0` | ~220MB |
|
|
402
|
+
| `aspnet:9.0-alpine` | ~110MB |
|
|
403
|
+
| `aspnet:9.0-chiseled` | ~80MB |
|
|
404
|
+
|
|
405
|
+
### Chiseled Images (Mais Seguro)
|
|
406
|
+
|
|
407
|
+
```dockerfile
|
|
408
|
+
# Runtime minimal e seguro
|
|
409
|
+
FROM mcr.microsoft.com/dotnet/aspnet:9.0-chiseled AS final
|
|
410
|
+
WORKDIR /app
|
|
411
|
+
COPY --from=publish /app/publish .
|
|
412
|
+
USER $APP_UID
|
|
413
|
+
ENTRYPOINT ["dotnet", "Web.dll"]
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Documentação de Referência
|
|
417
|
+
|
|
418
|
+
- [Docker Documentation](https://docs.docker.com/)
|
|
419
|
+
- [Container Apps](https://learn.microsoft.com/en-us/azure/container-apps/)
|
|
420
|
+
- [ACR](https://learn.microsoft.com/en-us/azure/container-registry/)
|
|
421
|
+
- [.NET Container Images](https://learn.microsoft.com/en-us/dotnet/core/docker/)
|
|
422
|
+
|
|
423
|
+
## Checklist de Containerização
|
|
424
|
+
|
|
425
|
+
- [ ] Dockerfile multi-stage
|
|
426
|
+
- [ ] .dockerignore configurado
|
|
427
|
+
- [ ] Non-root user no container
|
|
428
|
+
- [ ] Health checks configurados
|
|
429
|
+
- [ ] Imagem base alpine ou chiseled
|
|
430
|
+
- [ ] Docker Compose para dev
|
|
431
|
+
- [ ] ACR criado e configurado
|
|
432
|
+
- [ ] Container App com scale-to-zero
|
|
433
|
+
- [ ] Probes de liveness e readiness
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
*MORPH-SPEC by Polymorphism Tech*
|