# Padrões Azure - MORPH Framework

## 💰 Filosofia de Custos

> **Free tier primeiro. Aprovação explícita para upgrade.**

| Nível | Limite | Requer |
|-------|--------|--------|
| Sem aprovação | Free tier apenas | Nada |
| Com aprovação | Até $10/mês | Confirmação |
| Acima de $10 | Justificativa detalhada | ADR |

---

## 🌐 Hosting: App Service vs Container Apps

### Matriz de Decisão

| Critério | App Service (Free F1) | Container Apps (Consumption) |
|----------|----------------------|------------------------------|
| **Custo** | ✅ $0/mês | ⚠️ ~$5/mês |
| **RAM** | 1GB | Configurável (0.5Gi min) |
| **Storage** | 1GB | Ephemeral |
| **CPU** | ⚠️ 60 min/dia | ✅ Ilimitado |
| **Disponibilidade** | ⚠️ Sleep após 20min | ✅ Scale-to-zero sem sleep |
| **SSL Customizado** | ❌ Não (apenas *.azurewebsites.net) | ✅ Sim, gratuito |
| **Scale Out** | ❌ Não | ✅ Auto-scaling |
| **Blazor Server** | ✅ Suporte nativo | ✅ Via Docker |
| **Deploy** | ✅ Direto (ZIP, Git) | ⚠️ Requer container |

### Quando Usar App Service Free

**✅ Cenários Ideais:**
- Protótipos e MVPs de baixo tráfego
- Aplicações de uso interno (horário comercial)
- Demos e POCs
- Apps que toleram cold start (20 min sleep)
- Orçamento zero absoluto

**❌ Não Usar Quando:**
- Necessita estar sempre disponível (24/7)
- Tráfego imprevisível ou spikes
- Mais de 60 min de CPU/dia
- Precisa de SSL customizado
- Requer auto-scaling

### Quando Usar Container Apps

**✅ Cenários Ideais:**
- Produção com disponibilidade 24/7
- Auto-scaling baseado em demanda
- SSL customizado necessário
- Arquitetura microserviços
- Background jobs com Hangfire (minReplicas: 1)
- Apps que precisam estar sempre "quentes"

**❌ Não Usar Quando:**
- Orçamento zero obrigatório
- Tráfego extremamente baixo (< 100 req/dia)
- MVP simples sem requisitos de SLA

### Estratégia Híbrida

```
Dev/Staging:    App Service Free F1
Production:     Container Apps Consumption
```

**Benefícios:**
- 💰 Economia em ambientes não críticos
- 🚀 Performance garantida em produção
- 🔄 Fácil migração (mesma stack .NET)

---

## 📋 Stack Padrão Aprovado

| Recurso | Tier | Custo | Quando Usar |
|---------|------|-------|-------------|
| **App Service** | Free F1 | $0 | MVP, protótipos, dev/staging |
| **Container Apps** | Consumption | ~$0-5/mês | Produção, auto-scaling |
| **Azure SQL** | Free 32GB | $0 | Database |
| **ACR** | Basic | ~$5/mês | Container registry (apenas com CA) |
| **App Insights** | Free 5GB | $0 | Logs e métricas |
| **Azure OpenAI** | gpt-4o-mini | ~$2-10/mês | Análises AI |

**Custo total típico:**
- **App Service Stack:** $0-2/mês (sem ACR)
- **Container Apps Stack:** $7-20/mês (com ACR)

### ⚠️ Requer Aprovação

| Recurso | Custo | Alternativa Free |
|---------|-------|------------------|
| Azure Functions | ~$0-5/mês | Hangfire |
| Service Bus | ~$10/mês | Queue em SQL |
| Cosmos DB | ~$25/mês | Azure SQL JSON |
| Redis Cache | ~$15/mês | In-memory |

---

## 🌐 App Service Free Tier

### Configuração Obrigatória
```bicep
resource appService 'Microsoft.Web/sites@2022-03-01' = {
  name: 'app-${projectName}-${environment}'
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
    siteConfig: {
      netFrameworkVersion: 'v8.0'
      alwaysOn: false        # ⚠️ OBRIGATÓRIO no Free tier
      minTlsVersion: '1.2'
    }
  }
}

resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: 'plan-${projectName}-${environment}'
  location: location
  sku: {
    name: 'F1'               # Free tier
    tier: 'Free'
  }
}
```

### Limitações Importantes
- ⚠️ **CPU**: Apenas 60 minutos/dia (não contínuos)
- ⚠️ **Sleep**: App dorme após 20 minutos de inatividade
- ⚠️ **SSL**: Apenas `*.azurewebsites.net` (sem domínio customizado)
- ⚠️ **Escala**: Sem scale-out (apenas 1 instância)
- ✅ **Memória**: 1GB RAM
- ✅ **Storage**: 1GB disco

### Deploy
```bash
# Via Azure CLI
az webapp up --name app-myproject-dev --runtime "DOTNET:8.0"

# Via GitHub Actions
- task: AzureWebApp@1
  inputs:
    azureSubscription: 'Azure-Connection'
    appName: 'app-myproject-dev'
    package: '$(Build.ArtifactStagingDirectory)/**/*.zip'
```

### Quando Migrar para Container Apps
Se você observar:
- 🔴 CPU quota esgotada frequentemente
- 🔴 Cold starts afetando UX
- 🔴 Necessidade de SSL customizado
- 🔴 Tráfego crescendo (>1000 req/dia)

**→ Considere migrar para Container Apps Consumption**

---

## 🐳 Container Apps

### Configuração Obrigatória
```yaml
properties:
  template:
    scale:
      minReplicas: 0      # ⚠️ OBRIGATÓRIO: scale-to-zero
      maxReplicas: 2
    containers:
      - name: app
        resources:
          cpu: 0.25       # Mínimo
          memory: 0.5Gi   # Mínimo
```

### Scale-to-Zero
- ✅ **OBRIGATÓRIO** para dev/staging
- ⚠️ Em prod com Hangfire: `minReplicas: 1`
- 💰 Economia: ~80% vs always-on

---

## 🗄️ Azure SQL Free Tier

```
- 32 GB storage
- 100,000 vCore seconds/month
- Serverless compute
- Auto-pause after 1 hour idle
```

### Práticas
- ✅ Usar Managed Identity
- ✅ TDE habilitado (default)
- ❌ Não criar índices em excesso

---

## 🤖 Azure OpenAI

### Modelo Padrão: gpt-4o-mini

| Modelo | Custo Input | Custo Output | Usar |
|--------|-------------|--------------|------|
| **gpt-4o-mini** | $0.15/1M | $0.60/1M | ✅ PADRÃO |
| gpt-4o | $2.50/1M | $10/1M | Com aprovação |
| gpt-4 | $30/1M | $60/1M | ❌ NUNCA |

### Otimização
```csharp
var settings = new OpenAIPromptExecutionSettings
{
    MaxTokens = 500,  // Limitar resposta
    Temperature = 0.3 // Mais determinístico
};
```

---

## 🔐 Segurança

### Managed Identity (Preferido)
```csharp
// Para Azure SQL
"Authentication=Active Directory Managed Identity;"

// Para Azure OpenAI
var credential = new DefaultAzureCredential();
```

### Key Vault
Usar apenas para:
- Secrets de serviços externos
- API keys de terceiros

---

## 📛 Naming Conventions

```
{tipo}-{projeto}-{ambiente}

Exemplos:
- rg-myproject-dev          # Resource Group
- app-myproject-dev         # App Service
- plan-myproject-dev        # App Service Plan
- ca-myproject-dev          # Container App
- sql-myproject-dev         # SQL Server
- sqldb-myproject-dev       # SQL Database
- acr-myproject             # Container Registry
- appi-myproject-dev        # App Insights
- kv-myproject-dev          # Key Vault
```

| Ambiente | Sufixo | Características |
|----------|--------|-----------------|
| Development | -dev | Scale-to-zero, free tier |
| Staging | -stg | Scale-to-zero, free tier |
| Production | -prod | Min 1 replica |

---

## 🚀 Azure DevOps Pipelines

### Estratégia de Ambientes

**2 ambientes:**
- **Staging**: Desenvolvimento + QA (branch: `staging`)
  - Developers rodam projeto LOCAL
  - Acessam recursos REMOTOS staging
  - Deploy automático via pipeline

- **Produção**: Ambiente crítico (branch: `main`/`master`)
  - Deploy via pipeline com aprovação manual
  - Always-on, monitoramento 24/7

### Estrutura de Pipelines

```
.azure/pipelines/
├── staging-pipeline.yml      # Branch: staging
├── prod-pipeline.yml         # Branch: main/master
├── pipeline-variables.yml    # Variáveis compartilhadas
└── templates/
    ├── build-dotnet.yml
    ├── deploy-container-app.yml
    └── infra-deploy.yml
```

### Pipeline Staging

```yaml
# staging-pipeline.yml
trigger:
  branches:
    include: [staging]

variables:
  - template: pipeline-variables.yml
  - name: environment
    value: 'staging'
  - name: hostingType
    value: 'containerapp'

stages:
  - stage: Build
  - stage: DeployInfra
  - stage: BuildContainer
  - stage: DeployApp
    jobs:
      - deployment: DeployAppJob
        environment: 'staging'  # No approval
```

### Pipeline Production

```yaml
# prod-pipeline.yml
trigger:
  branches:
    include: [main, master]

variables:
  - template: pipeline-variables.yml
  - name: environment
    value: 'prod'
  - name: hostingType
    value: 'containerapp'

stages:
  - stage: Build
  - stage: SecurityScan
  - stage: DeployInfra
  - stage: BuildContainer
  - stage: DeployApp
    jobs:
      - deployment: DeployAppJob
        environment: 'production'  # Approval required
```

### Workload Identity (Sem Secrets)

Ao invés de Service Principals com secrets, use Workload Identity Federation:

```bash
# Criar App Registration com Federated Credential
az ad app create --display-name "myapp-prod-pipeline"

# Configurar federated credential
az ad app federated-credential create \
  --id <APP_ID> \
  --parameters @federated-credential.json
```

**Vantagens:**
- ✅ Sem secrets para gerenciar
- ✅ Rotação automática de tokens
- ✅ Mais seguro
- ✅ Auditoria melhorada

**Documentação completa:** `.azure/docs/azure-devops-setup.md`

---

## ✅ Checklist de Deploy

### Antes
- [ ] Testes passando
- [ ] Migrations aplicadas
- [ ] Secrets no Key Vault
- [ ] Managed Identity configurada

### Após
- [ ] Health check OK
- [ ] Logs no App Insights
- [ ] Funcionalidade testada
- [ ] Custos verificados
