@polymorphism-tech/morph-spec 4.3.4 → 4.3.6

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 (164) hide show
  1. package/.morph/.morphversion +5 -0
  2. package/.morph/config/agents.json +948 -0
  3. package/.morph/config/config.json +9 -9
  4. package/.morph/project/context/README.md +17 -0
  5. package/.morph/project/context/detection-log.md +16 -0
  6. package/.morph/project/standards/inferred.md +59 -0
  7. package/.morph/standards/ai-agents/blazor-ui.md +364 -0
  8. package/.morph/standards/ai-agents/production.md +415 -0
  9. package/.morph/standards/ai-agents/setup.md +418 -0
  10. package/.morph/standards/ai-agents/team-orchestration.md +479 -0
  11. package/.morph/standards/ai-agents/workflows.md +354 -0
  12. package/.morph/standards/architecture/ddd/aggregates.md +120 -0
  13. package/.morph/standards/architecture/ddd/entities.md +99 -0
  14. package/.morph/standards/architecture/ddd/value-objects.md +124 -0
  15. package/.morph/standards/backend/api/minimal-api.md +494 -0
  16. package/.morph/standards/backend/api/rest.md +492 -0
  17. package/.morph/standards/backend/api/validation.md +88 -0
  18. package/.morph/standards/backend/authentication/passkeys.md +428 -0
  19. package/.morph/standards/backend/database/ef-core.md +199 -0
  20. package/.morph/standards/backend/database/migrations.md +393 -0
  21. package/.morph/standards/backend/database/postgresql/database.md +352 -0
  22. package/.morph/standards/backend/database/repository-patterns.md +528 -0
  23. package/.morph/standards/backend/database/vector-search-rag.md +541 -0
  24. package/.morph/standards/backend/dotnet/async.md +366 -0
  25. package/.morph/standards/backend/dotnet/core.md +117 -0
  26. package/.morph/standards/backend/dotnet/di.md +439 -0
  27. package/.morph/standards/backend/dotnet/program-cs-checklist.md +92 -0
  28. package/.morph/standards/backend/integrations/asaas/asaas-api.md +216 -0
  29. package/.morph/standards/backend/integrations/clerk/clerk-auth.md +290 -0
  30. package/.morph/standards/backend/integrations/hangfire/hangfire-jobs.md +350 -0
  31. package/.morph/standards/backend/integrations/resend/resend-email.md +385 -0
  32. package/.morph/standards/context/analytics.md +96 -0
  33. package/.morph/standards/context/bundles.md +110 -0
  34. package/.morph/standards/context/priming.md +78 -0
  35. package/.morph/standards/core/architecture.md +185 -0
  36. package/.morph/standards/core/coding.md +214 -0
  37. package/.morph/standards/core/git-branching-strategy.md +403 -0
  38. package/.morph/standards/core/git.md +185 -0
  39. package/.morph/standards/core/testing.md +295 -0
  40. package/.morph/standards/data/nosql/blob-storage.md +102 -0
  41. package/.morph/standards/data/nosql/cache/redis.md +97 -0
  42. package/.morph/standards/data/nosql/cosmos-db.md +118 -0
  43. package/.morph/standards/data/vector-search/azure-ai-search.md +121 -0
  44. package/.morph/standards/data/vector-search/rag-chunking.md +104 -0
  45. package/.morph/standards/frontend/blazor/design-checklist.md +222 -0
  46. package/.morph/standards/frontend/blazor/fluent-ui-setup.md +595 -0
  47. package/.morph/standards/frontend/blazor/fluent-ui.md +137 -0
  48. package/.morph/standards/frontend/blazor/html-conversion.md +184 -0
  49. package/.morph/standards/frontend/blazor/lifecycle.md +195 -0
  50. package/.morph/standards/frontend/blazor/pitfalls.md +198 -0
  51. package/.morph/standards/frontend/blazor/state.md +191 -0
  52. package/.morph/standards/frontend/design-system/animations.md +151 -0
  53. package/.morph/standards/frontend/design-system/naming.md +64 -0
  54. package/.morph/standards/frontend/nextjs/nextjs-patterns.md +198 -0
  55. package/.morph/standards/infrastructure/azure/azure.md +624 -0
  56. package/.morph/standards/infrastructure/azure/bicep/bicep-patterns.md +422 -0
  57. package/.morph/standards/infrastructure/azure/devops/azure-devops-setup.md +516 -0
  58. package/.morph/standards/infrastructure/azure/devops/local-development.md +520 -0
  59. package/.morph/standards/infrastructure/azure/services/functions.md +486 -0
  60. package/.morph/standards/infrastructure/azure/services/service-bus.md +459 -0
  61. package/.morph/standards/infrastructure/azure/services/storage.md +407 -0
  62. package/.morph/standards/infrastructure/docker/easypanel-deploy.md +196 -0
  63. package/.morph/standards/infrastructure/supabase/mcp-setup.md +252 -0
  64. package/.morph/standards/infrastructure/supabase/supabase-auth.md +176 -0
  65. package/.morph/standards/infrastructure/supabase/supabase-pgvector.md +169 -0
  66. package/.morph/standards/infrastructure/supabase/supabase-rls.md +184 -0
  67. package/.morph/standards/infrastructure/supabase/supabase-storage.md +153 -0
  68. package/.morph/standards/integration/api/graphql.md +91 -0
  69. package/.morph/standards/integration/api/grpc.md +114 -0
  70. package/.morph/standards/integration/api/rest-design.md +95 -0
  71. package/.morph/standards/integration/event-driven/cqrs.md +101 -0
  72. package/.morph/standards/integration/event-driven/event-sourcing.md +124 -0
  73. package/.morph/standards/integration/event-driven/service-bus.md +95 -0
  74. package/.morph/standards/observability/logging.md +131 -0
  75. package/.morph/standards/observability/metrics.md +121 -0
  76. package/.morph/standards/observability/monitoring.md +114 -0
  77. package/.morph/standards/observability/tracing.md +132 -0
  78. package/.morph/standards/workflows/parallel-execution.md +112 -0
  79. package/.morph/standards/workflows/thread-management.md +113 -0
  80. package/.morph/templates/.idea/morph-templates.xml +92 -0
  81. package/.morph/templates/.vscode/morph-templates.code-snippets +186 -0
  82. package/.morph/templates/IDE-SNIPPETS.md +266 -0
  83. package/.morph/templates/README.md +814 -0
  84. package/.morph/templates/REGISTRY.json +1677 -0
  85. package/.morph/templates/code/dotnet/backend/repository.cs +141 -0
  86. package/.morph/templates/code/dotnet/backend/service.cs +139 -0
  87. package/.morph/templates/code/dotnet/contracts/Commands.cs +74 -0
  88. package/.morph/templates/code/dotnet/contracts/Entities.cs +25 -0
  89. package/.morph/templates/code/dotnet/contracts/Queries.cs +74 -0
  90. package/.morph/templates/code/dotnet/contracts/README.md +74 -0
  91. package/.morph/templates/code/dotnet/contracts/api-contracts.cs +173 -0
  92. package/.morph/templates/code/dotnet/contracts/contracts.cs +217 -0
  93. package/.morph/templates/code/dotnet/database/migration.cs +83 -0
  94. package/.morph/templates/code/dotnet/frontend/component.razor +239 -0
  95. package/.morph/templates/code/dotnet/jobs/agent.cs +163 -0
  96. package/.morph/templates/code/dotnet/jobs/job.cs +171 -0
  97. package/.morph/templates/code/dotnet/test.cs +239 -0
  98. package/.morph/templates/code/sql/rls-policy.sql +57 -0
  99. package/.morph/templates/code/sql/supabase-migration.sql +100 -0
  100. package/.morph/templates/code/sql/supabase-migration.template.sql +113 -0
  101. package/.morph/templates/code/typescript/contracts.ts +168 -0
  102. package/.morph/templates/context/CONTEXT-FEATURE.md +276 -0
  103. package/.morph/templates/context/CONTEXT.md +181 -0
  104. package/.morph/templates/docs/proposal.md +182 -0
  105. package/.morph/templates/docs/spec.md +149 -0
  106. package/.morph/templates/examples/design-system-examples.md +357 -0
  107. package/.morph/templates/examples/spec-examples.md +90 -0
  108. package/.morph/templates/feature/decisions.md +187 -0
  109. package/.morph/templates/feature/recap.md +146 -0
  110. package/.morph/templates/feature/tasks.md +199 -0
  111. package/.morph/templates/infrastructure/azure/Dockerfile.example +82 -0
  112. package/.morph/templates/infrastructure/azure/README.md +286 -0
  113. package/.morph/templates/infrastructure/azure/app-insights.bicep +63 -0
  114. package/.morph/templates/infrastructure/azure/app-service.bicep +164 -0
  115. package/.morph/templates/infrastructure/azure/container-app-env.bicep +49 -0
  116. package/.morph/templates/infrastructure/azure/container-app.bicep +156 -0
  117. package/.morph/templates/infrastructure/azure/deploy-checklist.md +426 -0
  118. package/.morph/templates/infrastructure/azure/deploy.ps1 +229 -0
  119. package/.morph/templates/infrastructure/azure/deploy.sh +208 -0
  120. package/.morph/templates/infrastructure/azure/key-vault.bicep +91 -0
  121. package/.morph/templates/infrastructure/azure/main.bicep +189 -0
  122. package/.morph/templates/infrastructure/azure/parameters.dev.json +29 -0
  123. package/.morph/templates/infrastructure/azure/parameters.prod.json +29 -0
  124. package/.morph/templates/infrastructure/azure/parameters.staging.json +29 -0
  125. package/.morph/templates/infrastructure/azure/sql-database.bicep +103 -0
  126. package/.morph/templates/infrastructure/azure/storage.bicep +106 -0
  127. package/.morph/templates/infrastructure/docker/Dockerfile.template +58 -0
  128. package/.morph/templates/infrastructure/docker/docker-compose.template.yml +67 -0
  129. package/.morph/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -0
  130. package/.morph/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -0
  131. package/.morph/templates/infrastructure/docker/easypanel.template.json +54 -0
  132. package/.morph/templates/infrastructure/github/README.md +593 -0
  133. package/.morph/templates/infrastructure/github/actions/azure-auth/action.yml.hbs +22 -0
  134. package/.morph/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -0
  135. package/.morph/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -0
  136. package/.morph/templates/infrastructure/github/workflows/deploy-azure-app-service.yml.hbs +61 -0
  137. package/.morph/templates/infrastructure/github/workflows/deploy-easypanel.yml.hbs +31 -0
  138. package/.morph/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -0
  139. package/.morph/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -0
  140. package/.morph/templates/integrations/asaas-client.cs +387 -0
  141. package/.morph/templates/integrations/asaas-webhook.cs +351 -0
  142. package/.morph/templates/integrations/azure-identity-config.cs +288 -0
  143. package/.morph/templates/integrations/clerk-config.cs +258 -0
  144. package/.morph/templates/meta-prompts/fusion/fusion-agent.md +76 -0
  145. package/.morph/templates/meta-prompts/fusion/fusion-aggregator.md +100 -0
  146. package/.morph/templates/meta-prompts/hops/hop-retry.md +78 -0
  147. package/.morph/templates/meta-prompts/hops/hop-validation.md +97 -0
  148. package/.morph/templates/meta-prompts/hops/hop-wrapper.md +36 -0
  149. package/.morph/templates/meta-prompts/parallel-workers/parallel-coordinator.md +113 -0
  150. package/.morph/templates/meta-prompts/parallel-workers/parallel-worker.md +80 -0
  151. package/.morph/templates/meta-prompts/squad-leaders/backend-squad.md +90 -0
  152. package/.morph/templates/meta-prompts/squad-leaders/frontend-squad.md +126 -0
  153. package/.morph/templates/meta-prompts/squad-leaders/squad-leader.md +43 -0
  154. package/.morph/templates/meta-prompts/validators/checkpoint-validator.md +107 -0
  155. package/.morph/templates/meta-prompts/validators/pre-commit-validator.md +95 -0
  156. package/.morph/templates/saas/subscription.cs +347 -0
  157. package/.morph/templates/saas/tenant.cs +338 -0
  158. package/.morph/templates/state.template.json +17 -0
  159. package/.morph/templates/ui/FluentDesignTheme.cs +149 -0
  160. package/.morph/templates/ui/MudTheme.cs +281 -0
  161. package/.morph/templates/ui/design-system.css +226 -0
  162. package/bin/morph-spec.js +1 -1
  163. package/package.json +1 -1
  164. package/src/commands/project/update.js +185 -46
@@ -0,0 +1,286 @@
1
+ # MORPH-SPEC - Templates Bicep
2
+
3
+ Templates de infraestrutura para Azure com suporte a App Service e Container Apps.
4
+
5
+ ---
6
+
7
+ ## 🚀 Quick Start
8
+
9
+ ### 1. App Service Free (Desenvolvimento - $0/mês)
10
+
11
+ ```bash
12
+ # Deploy infraestrutura com App Service Free
13
+ az deployment group create \
14
+ --resource-group rg-myapp-dev \
15
+ --template-file main.bicep \
16
+ --parameters @parameters.dev.json \
17
+ --parameters appName=myapp
18
+ ```
19
+
20
+ ### 2. Container Apps (Produção - $5-15/mês)
21
+
22
+ ```bash
23
+ # Build e push imagem para ACR
24
+ az acr build \
25
+ --registry acrXXXX \
26
+ --image myapp:v1.0.0 \
27
+ --file Dockerfile \
28
+ .
29
+
30
+ # Deploy infraestrutura com Container Apps
31
+ az deployment group create \
32
+ --resource-group rg-myapp-prod \
33
+ --template-file main.bicep \
34
+ --parameters @parameters.prod.json \
35
+ --parameters appName=myapp
36
+ ```
37
+
38
+ ---
39
+
40
+ ## 📁 Estrutura de Arquivos
41
+
42
+ ```
43
+ infra/
44
+ ├── main.bicep # Entry point com lógica condicional
45
+ ├── parameters.dev.json # Params dev (App Service Free)
46
+ ├── parameters.prod.json # Params prod (Container Apps)
47
+ ├── app-service.bicep # Template App Service
48
+ ├── container-app.bicep # Template Container App
49
+ ├── container-app-env.bicep # Container Apps Environment
50
+ ├── sql-database.bicep # Azure SQL Database
51
+ ├── storage.bicep # Storage Account
52
+ ├── key-vault.bicep # Key Vault
53
+ └── app-insights.bicep # Application Insights
54
+ ```
55
+
56
+ ---
57
+
58
+ ## ⚙️ Parâmetros Principais
59
+
60
+ ### main.bicep
61
+
62
+ | Parâmetro | Tipo | Default | Descrição |
63
+ |-----------|------|---------|-----------|
64
+ | `environment` | string | `dev` | Ambiente (dev, staging, prod) |
65
+ | `appName` | string | **required** | Nome da aplicação (3-15 chars) |
66
+ | `location` | string | `resourceGroup().location` | Região Azure |
67
+ | `hostingType` | string | `appservice` | Tipo de hosting (`appservice` ou `containerapp`) |
68
+ | `appServiceSku` | string | `F1` | SKU do App Service (F1, B1, S1, P1v2) |
69
+ | `containerImage` | string | `mcr.microsoft.com/hello-world:latest` | Imagem Docker (apenas Container Apps) |
70
+ | `sqlAdminPassword` | securestring | **required** | Senha do SQL Server |
71
+
72
+ ---
73
+
74
+ ## 🌐 Escolhendo o Hosting Type
75
+
76
+ ### App Service (`hostingType: appservice`)
77
+
78
+ **Usar quando:**
79
+ - ✅ Orçamento zero (Free F1)
80
+ - ✅ MVP ou protótipo
81
+ - ✅ Tráfego baixo (<100 req/dia)
82
+ - ✅ App tolerante a cold starts (20 min sleep)
83
+ - ✅ Deploy simplificado (sem Docker)
84
+
85
+ **SKUs disponíveis:**
86
+ - `F1` (Free): $0/mês - 1GB RAM, 60 min CPU/dia, sleep após 20min
87
+ - `B1` (Basic): $13/mês - 1.75GB RAM, always-on
88
+ - `S1` (Standard): $70/mês - 1.75GB RAM, auto-scale, slots
89
+ - `P1v2` (Premium): $85/mês - 3.5GB RAM, melhor performance
90
+
91
+ ### Container Apps (`hostingType: containerapp`)
92
+
93
+ **Usar quando:**
94
+ - ✅ Produção com SLA 24/7
95
+ - ✅ Auto-scaling baseado em demanda
96
+ - ✅ SSL customizado necessário
97
+ - ✅ Background jobs (Hangfire)
98
+ - ✅ Arquitetura microserviços
99
+
100
+ **Custo:** $0-15/mês (scale-to-zero + consumo)
101
+
102
+ ---
103
+
104
+ ## 📝 Configuração por Ambiente
105
+
106
+ ### Development (parameters.dev.json)
107
+
108
+ ```json
109
+ {
110
+ "environment": { "value": "dev" },
111
+ "hostingType": { "value": "appservice" },
112
+ "appServiceSku": { "value": "F1" }
113
+ }
114
+ ```
115
+
116
+ **Infraestrutura:**
117
+ - App Service Free F1
118
+ - Azure SQL Free (32GB)
119
+ - App Insights Free (5GB)
120
+
121
+ **Custo total:** $0/mês
122
+
123
+ ### Staging (parameters.staging.json)
124
+
125
+ ```json
126
+ {
127
+ "environment": { "value": "staging" },
128
+ "hostingType": { "value": "containerapp" },
129
+ "minReplicas": { "value": 0 } // scale-to-zero
130
+ }
131
+ ```
132
+
133
+ **Infraestrutura:**
134
+ - Container Apps (scale-to-zero)
135
+ - Azure SQL Free (32GB)
136
+ - ACR Basic
137
+ - App Insights Free
138
+
139
+ **Custo total:** $5-10/mês
140
+
141
+ ### Production (parameters.prod.json)
142
+
143
+ ```json
144
+ {
145
+ "environment": { "value": "prod" },
146
+ "hostingType": { "value": "containerapp" },
147
+ "minReplicas": { "value": 1 } // always-on
148
+ }
149
+ ```
150
+
151
+ **Infraestrutura:**
152
+ - Container Apps (min 1 replica)
153
+ - Azure SQL Free (ou pago se necessário)
154
+ - ACR Basic
155
+ - App Insights (pode ultrapassar free tier)
156
+
157
+ **Custo total:** $10-20/mês
158
+
159
+ ---
160
+
161
+ ## 🔧 Customização
162
+
163
+ ### Adicionar variáveis de ambiente
164
+
165
+ **App Service:**
166
+ ```bicep
167
+ module appService 'app-service.bicep' = {
168
+ params: {
169
+ envVars: {
170
+ MY_CUSTOM_VAR: 'value'
171
+ ANOTHER_VAR: 'another-value'
172
+ }
173
+ }
174
+ }
175
+ ```
176
+
177
+ **Container Apps:**
178
+ ```bicep
179
+ module containerApp 'container-app.bicep' = {
180
+ params: {
181
+ envVars: [
182
+ {
183
+ name: 'MY_CUSTOM_VAR'
184
+ value: 'value'
185
+ }
186
+ ]
187
+ }
188
+ }
189
+ ```
190
+
191
+ ### Usar secrets do Key Vault
192
+
193
+ ```bicep
194
+ param sqlAdminPassword string {
195
+ reference: {
196
+ keyVault: {
197
+ id: '/subscriptions/.../providers/Microsoft.KeyVault/vaults/kv-myapp'
198
+ }
199
+ secretName: 'sql-admin-password'
200
+ }
201
+ }
202
+ ```
203
+
204
+ ---
205
+
206
+ ## 🔄 Migração App Service → Container Apps
207
+
208
+ Ver guia completo em: `../../standards/migration-guide.md`
209
+
210
+ **Resumo:**
211
+ 1. Criar Dockerfile
212
+ 2. Implementar health checks
213
+ 3. Build e push para ACR
214
+ 4. Atualizar `parameters.json` → `hostingType: containerapp`
215
+ 5. Redeploy
216
+ 6. Testar
217
+ 7. Cutover DNS
218
+
219
+ ---
220
+
221
+ ## 📊 Outputs Gerados
222
+
223
+ Após deploy, os seguintes outputs são gerados:
224
+
225
+ ```bash
226
+ # Obter URL da aplicação
227
+ az deployment group show \
228
+ -g rg-myapp-dev \
229
+ -n deployment-name \
230
+ --query properties.outputs.appUrl.value
231
+
232
+ # Obter connection string SQL
233
+ az deployment group show \
234
+ -g rg-myapp-dev \
235
+ -n deployment-name \
236
+ --query properties.outputs.sqlConnectionString.value
237
+
238
+ # Obter App Insights connection string
239
+ az deployment group show \
240
+ -g rg-myapp-dev \
241
+ -n deployment-name \
242
+ --query properties.outputs.appInsightsConnectionString.value
243
+ ```
244
+
245
+ ---
246
+
247
+ ## 🆘 Troubleshooting
248
+
249
+ ### Erro: "The template deployment 'X' is not valid"
250
+
251
+ Validar template:
252
+ ```bash
253
+ az deployment group validate \
254
+ --resource-group rg-myapp-dev \
255
+ --template-file main.bicep \
256
+ --parameters @parameters.dev.json
257
+ ```
258
+
259
+ ### Erro: "SKU not available in this location"
260
+
261
+ Verificar SKUs disponíveis:
262
+ ```bash
263
+ az appservice list-locations --sku F1
264
+ ```
265
+
266
+ ### Deploy muito lento
267
+
268
+ Container Apps pode levar 5-10 minutos no primeiro deploy. Use `--no-wait` para não bloquear:
269
+ ```bash
270
+ az deployment group create \
271
+ ... \
272
+ --no-wait
273
+ ```
274
+
275
+ ---
276
+
277
+ ## 📚 Referências
278
+
279
+ - [Bicep Documentation](https://learn.microsoft.com/azure/azure-resource-manager/bicep/)
280
+ - [App Service Bicep Reference](https://learn.microsoft.com/azure/templates/microsoft.web/sites)
281
+ - [Container Apps Bicep Reference](https://learn.microsoft.com/azure/templates/microsoft.app/containerapps)
282
+ - [Azure CLI Reference](https://learn.microsoft.com/cli/azure/)
283
+
284
+ ---
285
+
286
+ *MORPH-SPEC by Polymorphism Tech*
@@ -0,0 +1,63 @@
1
+ // ==============================================================================
2
+ // MORPH-SPEC - Application Insights
3
+ // Azure Application Insights for monitoring and telemetry
4
+ // ==============================================================================
5
+
6
+ @description('Application Insights name')
7
+ param name string
8
+
9
+ @description('Location')
10
+ param location string
11
+
12
+ @description('Tags')
13
+ param tags object = {}
14
+
15
+ @description('Log Analytics Workspace ID')
16
+ param logAnalyticsWorkspaceId string
17
+
18
+ @description('Application type')
19
+ @allowed(['web', 'other'])
20
+ param applicationType string = 'web'
21
+
22
+ @description('Retention in days')
23
+ @minValue(30)
24
+ @maxValue(730)
25
+ param retentionInDays int = 90
26
+
27
+ // ==============================================================================
28
+ // APPLICATION INSIGHTS
29
+ // ==============================================================================
30
+
31
+ resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
32
+ name: name
33
+ location: location
34
+ tags: tags
35
+ kind: applicationType
36
+ properties: {
37
+ Application_Type: applicationType
38
+ WorkspaceResourceId: logAnalyticsWorkspaceId
39
+ IngestionMode: 'LogAnalytics'
40
+ publicNetworkAccessForIngestion: 'Enabled'
41
+ publicNetworkAccessForQuery: 'Enabled'
42
+ RetentionInDays: retentionInDays
43
+ }
44
+ }
45
+
46
+ // ==============================================================================
47
+ // OUTPUTS
48
+ // ==============================================================================
49
+
50
+ @description('Application Insights ID')
51
+ output id string = appInsights.id
52
+
53
+ @description('Application Insights name')
54
+ output name string = appInsights.name
55
+
56
+ @description('Instrumentation Key')
57
+ output instrumentationKey string = appInsights.properties.InstrumentationKey
58
+
59
+ @description('Connection String')
60
+ output connectionString string = appInsights.properties.ConnectionString
61
+
62
+ @description('App ID')
63
+ output appId string = appInsights.properties.AppId
@@ -0,0 +1,164 @@
1
+ // ==============================================================================
2
+ // MORPH-SPEC - App Service
3
+ // Azure App Service with Free F1 tier support
4
+ // ==============================================================================
5
+
6
+ @description('App Service name')
7
+ param name string
8
+
9
+ @description('Location')
10
+ param location string
11
+
12
+ @description('Tags')
13
+ param tags object = {}
14
+
15
+ @description('App Service Plan SKU (F1, B1, S1, P1v2)')
16
+ @allowed(['F1', 'B1', 'S1', 'P1v2', 'P2v2'])
17
+ param sku string = 'F1'
18
+
19
+ @description('App Insights connection string')
20
+ param appInsightsConnectionString string = ''
21
+
22
+ @description('.NET version')
23
+ @allowed(['v6.0', 'v7.0', 'v8.0'])
24
+ param dotnetVersion string = 'v8.0'
25
+
26
+ @description('Always On (not available on Free tier)')
27
+ param alwaysOn bool = false
28
+
29
+ @description('Environment variables')
30
+ param envVars object = {}
31
+
32
+ // ==============================================================================
33
+ // VARIABLES
34
+ // ==============================================================================
35
+
36
+ var skuTiers = {
37
+ F1: 'Free'
38
+ B1: 'Basic'
39
+ S1: 'Standard'
40
+ P1v2: 'PremiumV2'
41
+ P2v2: 'PremiumV2'
42
+ }
43
+
44
+ var planName = 'plan-${name}'
45
+
46
+ // Merge default env vars with custom ones
47
+ var defaultEnvVars = {
48
+ ASPNETCORE_ENVIRONMENT: 'Production'
49
+ APPLICATIONINSIGHTS_CONNECTION_STRING: appInsightsConnectionString
50
+ }
51
+
52
+ var mergedEnvVars = union(defaultEnvVars, envVars)
53
+
54
+ // ==============================================================================
55
+ // APP SERVICE PLAN
56
+ // ==============================================================================
57
+
58
+ resource appServicePlan 'Microsoft.Web/serverfarms@2022-09-01' = {
59
+ name: planName
60
+ location: location
61
+ tags: tags
62
+ sku: {
63
+ name: sku
64
+ tier: skuTiers[sku]
65
+ }
66
+ kind: 'linux'
67
+ properties: {
68
+ reserved: true // Required for Linux
69
+ }
70
+ }
71
+
72
+ // ==============================================================================
73
+ // APP SERVICE
74
+ // ==============================================================================
75
+
76
+ resource appService 'Microsoft.Web/sites@2022-09-01' = {
77
+ name: name
78
+ location: location
79
+ tags: tags
80
+ kind: 'app,linux'
81
+ identity: {
82
+ type: 'SystemAssigned'
83
+ }
84
+ properties: {
85
+ serverFarmId: appServicePlan.id
86
+ httpsOnly: true
87
+ siteConfig: {
88
+ linuxFxVersion: 'DOTNETCORE|${dotnetVersion}'
89
+ alwaysOn: alwaysOn
90
+ minTlsVersion: '1.2'
91
+ ftpsState: 'Disabled'
92
+ http20Enabled: true
93
+ healthCheckPath: '/health'
94
+ appSettings: [for key in objectKeys(mergedEnvVars): {
95
+ name: key
96
+ value: mergedEnvVars[key]
97
+ }]
98
+ cors: {
99
+ allowedOrigins: [
100
+ 'https://portal.azure.com'
101
+ ]
102
+ supportCredentials: false
103
+ }
104
+ }
105
+ clientAffinityEnabled: false // Recommended for stateless apps
106
+ }
107
+ }
108
+
109
+ // ==============================================================================
110
+ // DEPLOYMENT SLOT (Only for non-Free tiers)
111
+ // ==============================================================================
112
+
113
+ resource stagingSlot 'Microsoft.Web/sites/slots@2022-09-01' = if (sku != 'F1') {
114
+ name: 'staging'
115
+ parent: appService
116
+ location: location
117
+ tags: tags
118
+ kind: 'app,linux'
119
+ identity: {
120
+ type: 'SystemAssigned'
121
+ }
122
+ properties: {
123
+ serverFarmId: appServicePlan.id
124
+ httpsOnly: true
125
+ siteConfig: {
126
+ linuxFxVersion: 'DOTNETCORE|${dotnetVersion}'
127
+ alwaysOn: alwaysOn
128
+ minTlsVersion: '1.2'
129
+ ftpsState: 'Disabled'
130
+ http20Enabled: true
131
+ healthCheckPath: '/health'
132
+ appSettings: [for key in objectKeys(mergedEnvVars): {
133
+ name: key
134
+ value: mergedEnvVars[key]
135
+ }]
136
+ }
137
+ clientAffinityEnabled: false
138
+ }
139
+ }
140
+
141
+ // ==============================================================================
142
+ // OUTPUTS
143
+ // ==============================================================================
144
+
145
+ @description('App Service ID')
146
+ output id string = appService.id
147
+
148
+ @description('App Service name')
149
+ output name string = appService.name
150
+
151
+ @description('App Service URL')
152
+ output url string = 'https://${appService.properties.defaultHostName}'
153
+
154
+ @description('App Service default hostname')
155
+ output defaultHostName string = appService.properties.defaultHostName
156
+
157
+ @description('App Service Plan ID')
158
+ output planId string = appServicePlan.id
159
+
160
+ @description('App Service Managed Identity Principal ID')
161
+ output principalId string = appService.identity.principalId
162
+
163
+ @description('Staging slot URL (if available)')
164
+ output stagingUrl string = sku != 'F1' ? 'https://${stagingSlot.properties.defaultHostName}' : ''
@@ -0,0 +1,49 @@
1
+ // ==============================================================================
2
+ // MORPH-SPEC - Container Apps Environment
3
+ // Azure Container Apps managed environment
4
+ // ==============================================================================
5
+
6
+ @description('Environment name')
7
+ param name string
8
+
9
+ @description('Location')
10
+ param location string
11
+
12
+ @description('Tags')
13
+ param tags object = {}
14
+
15
+ @description('Log Analytics Workspace ID')
16
+ param logAnalyticsWorkspaceId string
17
+
18
+ // ==============================================================================
19
+ // CONTAINER APPS ENVIRONMENT
20
+ // ==============================================================================
21
+
22
+ resource containerAppEnv 'Microsoft.App/managedEnvironments@2023-05-01' = {
23
+ name: name
24
+ location: location
25
+ tags: tags
26
+ properties: {
27
+ appLogsConfiguration: {
28
+ destination: 'log-analytics'
29
+ logAnalyticsConfiguration: {
30
+ customerId: reference(logAnalyticsWorkspaceId, '2022-10-01').customerId
31
+ sharedKey: listKeys(logAnalyticsWorkspaceId, '2022-10-01').primarySharedKey
32
+ }
33
+ }
34
+ zoneRedundant: false
35
+ }
36
+ }
37
+
38
+ // ==============================================================================
39
+ // OUTPUTS
40
+ // ==============================================================================
41
+
42
+ @description('Container Apps Environment ID')
43
+ output id string = containerAppEnv.id
44
+
45
+ @description('Container Apps Environment name')
46
+ output name string = containerAppEnv.name
47
+
48
+ @description('Default domain')
49
+ output defaultDomain string = containerAppEnv.properties.defaultDomain
@@ -0,0 +1,156 @@
1
+ // ==============================================================================
2
+ // MORPH-SPEC - Container App
3
+ // Azure Container Apps with ingress and auto-scaling
4
+ // ==============================================================================
5
+
6
+ @description('App name')
7
+ param name string
8
+
9
+ @description('Location')
10
+ param location string
11
+
12
+ @description('Tags')
13
+ param tags object = {}
14
+
15
+ @description('Container App Environment ID')
16
+ param environmentId string
17
+
18
+ @description('Container image')
19
+ param containerImage string
20
+
21
+ @description('App Insights connection string')
22
+ param appInsightsConnectionString string = ''
23
+
24
+ @description('CPU cores (0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0)')
25
+ param cpu string = '0.25'
26
+
27
+ @description('Memory (0.5Gi, 1Gi, 1.5Gi, 2Gi, 3Gi, 4Gi)')
28
+ param memory string = '0.5Gi'
29
+
30
+ @description('Minimum replicas (0 = scale to zero)')
31
+ param minReplicas int = 0
32
+
33
+ @description('Maximum replicas')
34
+ param maxReplicas int = 3
35
+
36
+ @description('Target port')
37
+ param targetPort int = 8080
38
+
39
+ @description('Environment variables')
40
+ param envVars array = []
41
+
42
+ // ==============================================================================
43
+ // CONTAINER APP
44
+ // ==============================================================================
45
+
46
+ var secrets = appInsightsConnectionString != '' ? [
47
+ {
48
+ name: 'appinsights-connection-string'
49
+ value: appInsightsConnectionString
50
+ }
51
+ ] : []
52
+
53
+ var defaultEnvVars = appInsightsConnectionString != '' ? [
54
+ {
55
+ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
56
+ secretRef: 'appinsights-connection-string'
57
+ }
58
+ {
59
+ name: 'ASPNETCORE_ENVIRONMENT'
60
+ value: 'Production'
61
+ }
62
+ ] : [
63
+ {
64
+ name: 'ASPNETCORE_ENVIRONMENT'
65
+ value: 'Production'
66
+ }
67
+ ]
68
+
69
+ resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
70
+ name: name
71
+ location: location
72
+ tags: tags
73
+ properties: {
74
+ managedEnvironmentId: environmentId
75
+ configuration: {
76
+ ingress: {
77
+ external: true
78
+ targetPort: targetPort
79
+ transport: 'http'
80
+ allowInsecure: false
81
+ traffic: [
82
+ {
83
+ latestRevision: true
84
+ weight: 100
85
+ }
86
+ ]
87
+ }
88
+ secrets: secrets
89
+ }
90
+ template: {
91
+ containers: [
92
+ {
93
+ name: name
94
+ image: containerImage
95
+ resources: {
96
+ cpu: json(cpu)
97
+ memory: memory
98
+ }
99
+ env: concat(defaultEnvVars, envVars)
100
+ probes: [
101
+ {
102
+ type: 'Liveness'
103
+ httpGet: {
104
+ path: '/health'
105
+ port: targetPort
106
+ }
107
+ initialDelaySeconds: 10
108
+ periodSeconds: 30
109
+ failureThreshold: 3
110
+ }
111
+ {
112
+ type: 'Readiness'
113
+ httpGet: {
114
+ path: '/health/ready'
115
+ port: targetPort
116
+ }
117
+ initialDelaySeconds: 5
118
+ periodSeconds: 10
119
+ failureThreshold: 3
120
+ }
121
+ ]
122
+ }
123
+ ]
124
+ scale: {
125
+ minReplicas: minReplicas
126
+ maxReplicas: maxReplicas
127
+ rules: [
128
+ {
129
+ name: 'http-scale'
130
+ http: {
131
+ metadata: {
132
+ concurrentRequests: '100'
133
+ }
134
+ }
135
+ }
136
+ ]
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ // ==============================================================================
143
+ // OUTPUTS
144
+ // ==============================================================================
145
+
146
+ @description('Container App ID')
147
+ output id string = containerApp.id
148
+
149
+ @description('Container App name')
150
+ output name string = containerApp.name
151
+
152
+ @description('Container App URL')
153
+ output url string = 'https://${containerApp.properties.configuration.ingress.fqdn}'
154
+
155
+ @description('Container App FQDN')
156
+ output fqdn string = containerApp.properties.configuration.ingress.fqdn