Aplicação unificada em ASP.NET Core + Blazor WebAssembly (SPA), utilizando PostgreSQL.
Este documento é voltado para devs que precisam:
- entender rapidamente a arquitetura e os padrões do Bud,
- subir o ambiente local,
- executar fluxos principais de desenvolvimento com segurança.
- Arquitetura da aplicação
- Padrões arquiteturais adotados
- Como contribuir
- Como rodar
- Como rodar sem Docker
- Servidor MCP (Missões e Métricas)
- Deploy no Google Cloud
- Onboarding rápido (30 min)
- Testes
- Observabilidade
- Health checks
- Endpoints principais
- Sistema de Design e Tokens
O Bud segue uma arquitetura em camadas com separação explícita de responsabilidades:
- API/Host (
Bud.Server): exposição HTTP, autenticação/autorização, middleware e composição de dependências. - Application: casos de uso (
Application/UseCases/), portas de aplicação e orquestração de eventos de domínio.Application/Common: resultados e utilitários transversais.Application/Mapping: mapeamento entre read models/domínio e contratos de borda.
- Domain: conceitos de domínio, value objects e interfaces de repositório.
- Infrastructure: EF Core (
ApplicationDbContext), repositórios (Repositories/), serviços de infraestrutura (Services/) e specifications de consulta (Querying/). - Client (
Bud.Client): SPA Blazor WASM com consumo da API. - Shared (
Bud.Shared): contratos de borda compartilhados entre cliente, servidor e MCP.
- Controllers recebem requests, validam payloads (FluentValidation) e delegam para Use Cases.
Validações dependentes de dados devem passar por abstrações/repositórios, não por acesso direto de validator ao
DbContext. - Use Cases (
Application/UseCases/{Domain}/) centralizam o fluxo completo da aplicação (orquestração, autorização, notificações) e retornamResult/Result<T>(emApplication/Common/). Cada use case é uma classe com métodoExecuteAsync, injetada diretamente nos controllers (sem mediator). - Infrastructure (
Infrastructure/) contém implementações concretas:Repositories/: implementações dos repositórios (I*Repositoryficam emDomain/Repositories/).Services/: implementações de adapters (AuthService,MissionScopeResolver,MissionProgressService,NotificationRecipientResolver), com interfaces emApplication/Ports/.Querying/: specifications de consulta para filtros reutilizáveis.ApplicationDbContext,Configurations/eDbSeeder.
- Authorization (
Authorization/) contém serviços de autorização (TenantAuthorizationService,OrganizationAuthorizationService), policies, requirements e handlers. - DependencyInjection modulariza bootstrap (
BudApi,BudSecurity,BudInfrastructure,BudApplication).
- Use Cases + Repositories (Clean Architecture)
Controllers delegam para Use Cases (
Application/UseCases/), que dependem de interfaces (portas) emDomain/RepositorieseApplication/Ports. Implementações concretas ficam emInfrastructure/RepositorieseInfrastructure/Services.Domainnão depende deApplicationnem deInfrastructure. Referências:docs/adr/ADR-0002-arquitetura-ddd-estrita-e-regras-de-dependencia.md. - Policy-based Authorization (Requirement/Handler)
Regras de autorização centralizadas em policies e handlers, reduzindo condicionais espalhadas.
Referências:
docs/adr/ADR-0007-autenticacao-e-autorizacao-por-politicas.md. - Specification Pattern (consultas reutilizáveis)
Filtros de domínio encapsulados em specifications para evitar duplicação de predicados.
Referências:
src/Bud.Server/Infrastructure/Querying/. - Structured Logging (source-generated)
Logs com
[LoggerMessage]definidos localmente por componente (partial), comEventIdestável e sem catálogo central global. - Governança arquitetural por testes + ADRs
Decisões versionadas (ADR) e proteção contra regressão de fronteiras via testes de arquitetura. Referências:docs/adr/README.mdetests/Bud.Server.Tests/Architecture/ArchitectureTests.cs. - Aggregate Roots explícitas
Entidades raiz de agregado são marcadas com
IAggregateRootpara tornar boundaries verificáveis por testes. Referências:docs/adr/ADR-0003-agregados-entidades-value-objects-e-invariantes.md. - Invariantes no domínio (modelo rico)
Regras centrais de negócio são aplicadas por métodos de agregado/entidade (Create,Rename,SetScope, etc.) com tradução paraResultna camada de aplicação (Use Cases). Inclui Value Objects formais (PersonName,MissionScope,ConfidenceLevel,MetricRange) para reduzir primitive obsession. - Notification Orchestration (Application)
Orquestração de notificações centralizada em
Application/EventHandlers/(NotificationOrchestrator), desacoplada dos repositórios. - Domain Events + Unit of Work
Eventos de domínio (
IDomainEvent,IHasDomainEvents) são disparados por agregados e despachados viaIUnitOfWork/EfUnitOfWorkno commit. Handlers tipados (IDomainEventNotifier<T>) emApplication/EventHandlers/reagem a eventos comoMissionCreatedDomainEvent,MissionUpdatedDomainEvent,MissionDeletedDomainEventeMetricCheckinCreatedDomainEvent. Referências:docs/adr/ADR-0009-eventos-de-dominio-e-notificacoes.md.
Isolamento por organização (OrganizationId) com:
ITenantProviderpara resolver tenant do contexto autenticado.- Query filters globais do EF Core.
TenantRequiredMiddlewarepara reforçar seleção/autorização de tenant em/api/*.- Cabeçalho
X-Tenant-Idenviado pelo client quando uma organização específica está selecionada.
- Request chega no controller.
- Payload é validado.
- Controller chama o Use Case correspondente.
- Use Case aplica regras de autorização/orquestração e delega para repositórios/ports (via interfaces em
Domain/RepositorieseApplication/Ports). - Repositório persiste/consulta via
ApplicationDbContext. - Use Case orquestra notificações quando aplicável (via
NotificationOrchestrator). - Resultado (
Result) é mapeado para resposta HTTP.
- Unit tests: regras de negócio, validações, commands/queries e componentes de infraestrutura.
- Integration tests: ciclo HTTP completo com PostgreSQL em container.
- Architecture tests: evitam regressão de fronteira entre camadas (ex.: Use Case depender de Infrastructure diretamente), validam tenant isolation, autorização e boundaries de aggregate roots.
A camada de infraestrutura exige
IEntityTypeConfiguration<T>dedicada para todas as entidades doApplicationDbContext. - ADRs: decisões arquiteturais versionadas em
docs/adr/.
- Toda mudança arquitetural deve criar/atualizar ADR.
- ADRs seguem convenção
docs/adr/ADR-XXXX-*.md. - Índice e convenções:
docs/adr/README.md. - No PR, inclua explicitamente:
Architectural impact: yes/noADR: ADR-XXXX(quando aplicável)
Para lista atualizada de ADRs e ordem recomendada de leitura, consulte:
docs/adr/README.md.
flowchart LR
A[Bud.Client<br/>Blazor WASM] -->|HTTP + JWT + X-Tenant-Id| B[Bud.Server Controllers]
B --> C[Application<br/>Use Cases]
C --> R[Infrastructure<br/>I*Repository + Repositories]
R --> E[(PostgreSQL<br/>ApplicationDbContext)]
C --> N[NotificationOrchestrator]
N --> R
sequenceDiagram
participant U as Usuário/Client
participant C as Controller
participant UC as Use Case
participant R as Repository
participant NO as NotificationOrchestrator
participant DB as PostgreSQL
U->>C: Requisição de comando (create/update/delete)
C->>UC: Executa caso de uso
UC->>R: Persiste entidade
R->>DB: Consulta/persistência
UC->>NO: Orquestra notificações (quando aplicável)
NO->>R: Persiste notificações
C-->>U: Resposta HTTP (sucesso)
flowchart TD
O[Organization]
W[Workspace]
T[Team]
ST[SubTeam]
C[Collaborator]
M[Mission]
MO[Objective]
MM[Metric]
MC[MetricCheckin]
O --> W
W --> T
T --> ST
T --> C
O --> M
W -. escopo .-> M
T -. escopo .-> M
C -. escopo .-> M
M --> MO
MO --> MO
MO --> MM
M --> MM
MM --> MC
O --> N[Notification]
C --> N
sequenceDiagram
participant UI as Bud.Client
participant API as Bud.Server
participant SESS as SessionsController/CreateSession
participant ME as MeController/ListMyOrganizations
participant TENANT as TenantRequiredMiddleware
participant CTRL as Controller
UI->>API: POST /api/sessions
API->>SESS: Valida e autentica por e-mail
SESS-->>UI: JWT + dados básicos da sessão
UI->>API: GET /api/me/organizations
API->>ME: Lista organizações do usuário autenticado
ME-->>UI: Lista de organizações disponíveis
UI->>UI: Usuário seleciona organização (ou "TODOS")
UI->>API: Request com Authorization: Bearer + X-Tenant-Id (opcional)
API->>TENANT: Valida autenticação e tenant selecionado
TENANT->>CTRL: Libera acesso conforme policies
CTRL-->>UI: Resposta filtrada por tenant
sequenceDiagram
participant UI as Bud.Client / Caller
participant API as ASP.NET Core Pipeline
participant AUTH as AuthN/AuthZ
participant TENANT as TenantRequiredMiddleware
participant CTRL as Controller
participant VAL as FluentValidation
participant UC as Use Case
participant REPO as Repository
participant DB as ApplicationDbContext/PostgreSQL
UI->>API: HTTP Request
API->>AUTH: Valida JWT/policies
AUTH->>TENANT: Valida contexto de tenant (quando aplicável)
TENANT->>CTRL: Encaminha request autorizado
CTRL->>VAL: Valida payload
alt Payload inválido
VAL-->>CTRL: Erros de validação
CTRL-->>UI: 400 ValidationProblemDetails (pt-BR)
else Payload válido
CTRL->>UC: Executa caso de uso
UC->>REPO: Consulta/persistência
REPO->>DB: EF Core
UC-->>CTRL: Result
CTRL-->>UI: 2xx/4xx/5xx + ProblemDetails quando aplicável
end
flowchart TD
A[Request recebido] --> B{JWT válido?}
B -- Não --> C[401 Não autenticado]
B -- Sim --> D{Tenant exigido e selecionado?}
D -- Não --> E[403 Tenant obrigatório]
D -- Sim --> F{Payload válido?}
F -- Não --> G[400 ValidationProblemDetails]
F -- Sim --> H{Entidade existe?}
H -- Não --> I[404 NotFound]
H -- Sim --> J{Conflito de regra?}
J -- Sim --> K[409 Conflict]
J -- Não --> L[2xx Sucesso]
flowchart TB
subgraph Host["Bud.Server Host"]
Controllers
Middleware
DependencyInjection
end
subgraph App["Application"]
UseCases["Use Cases"]
Ports["Ports (IAuthService, etc.)"]
end
subgraph Domain["Domain"]
RepoInterfaces["Interfaces (I*Repository)"]
ValueObjects
end
subgraph Infra["Infrastructure"]
Repositories
Services["Services (adapters)"]
Specifications["Querying/Specifications"]
DbContext
end
Controllers --> UseCases
UseCases --> RepoInterfaces
UseCases --> Ports
Repositories -.-> RepoInterfaces
Services -.-> Ports
Repositories --> DbContext
Repositories --> Specifications
DependencyInjection --> Controllers
DependencyInjection --> UseCases
DependencyInjection --> Repositories
flowchart LR
subgraph Client["Bud.Client (Blazor WASM)"]
UI["Pages + Layout"]
ApiClient["ApiClient + TenantDelegatingHandler"]
end
subgraph Api["Bud.Server (API/Aplicação)"]
Controllers["Controllers"]
UseCases["Use Cases"]
Authz["AuthN/AuthZ + Policies"]
end
subgraph DomainLayer["Domain"]
RepoInterfaces["Interfaces (I*Repository)"]
end
subgraph Infra["Infrastructure"]
Repos["Repositories"]
Db["ApplicationDbContext"]
Pg["PostgreSQL"]
end
UI --> ApiClient
ApiClient --> Controllers
Controllers --> UseCases
UseCases --> RepoInterfaces
Repos -.-> RepoInterfaces
Controllers --> Authz
Repos --> Db
Db --> Pg
Fluxo recomendado de contribuição para manter qualidade arquitetural e consistência:
- Crie uma branch curta e focada no objetivo da mudança.
- Escreva/atualize testes antes da implementação (TDD: Red -> Green -> Refactor).
- Implemente seguindo os padrões do projeto:
- Controllers -> Use Cases -> Repositories (via interfaces em Domain/Repositories)
- autorização por policies/handlers
- mensagens de erro/validação em pt-BR
- Atualize documentação OpenAPI (summary/description/status/errors) quando alterar contratos.
- Se houver mudança arquitetural, atualize/crie ADR em
docs/adr/. - Rode a suíte de testes aplicável e valide Swagger/health checks.
- Abra PR com impacto arquitetural explícito e referência de ADR (quando aplicável).
docker compose up --build- App (UI + API):
http://localhost:8080 - Swagger (ambiente Development):
http://localhost:8080/swagger
- Os serviços
webemcpusamdotnet watchno ambiente local via Docker Compose. - Para Docker Desktop (macOS/Windows), o compose habilita
DOTNET_USE_POLLING_FILE_WATCHER=1para detecção estável de mudanças em volumes montados. - No
web, o run usaWasmEnableHotReload=truepara habilitar hot reload do Blazor WASM nesse fluxo local. - O build continua usando caches de NuGet e compilação via volumes nomeados para acelerar o ciclo.
Se você encontrar assets antigos no browser, faça hard refresh. Se persistir, limpe volumes e recompile:
docker compose down -v
docker compose up --buildPré-requisitos:
- .NET SDK 10
- PostgreSQL 16+
Comandos:
dotnet restore
dotnet build
dotnet run --project src/Bud.ServerO repositório inclui um servidor MCP HTTP em src/Bud.Mcp, que consome a API do Bud.Server.
No transporte HTTP do MCP, o endpoint raiz delega o processamento para IMcpRequestProcessor/McpRequestProcessor,
mantendo Program.cs focado em composição e roteamento.
No ambiente local via Docker Compose:
- API + frontend:
http://localhost:8080 - MCP:
http://localhost:8081
O Bud.Mcp lê configuração na seguinte ordem:
appsettings.jsonappsettings.{DOTNET_ENVIRONMENT}.json- variáveis de ambiente (override)
Chaves suportadas:
BudMcp:ApiBaseUrl(ouBUD_API_BASE_URL)BudMcp:UserEmail(ouBUD_USER_EMAIL) opcional, para login automático no bootBudMcp:DefaultTenantId(ouBUD_DEFAULT_TENANT_ID)BudMcp:HttpTimeoutSeconds(ouBUD_HTTP_TIMEOUT_SECONDS)BudMcp:SessionIdleTtlMinutes(ouBUD_SESSION_IDLE_TTL_MINUTES)
docker compose up --buildO serviço mcp é criado no compose usando:
Dockerfile(targetdev-mcp-web)dotnet watchpara recarregar alterações locais automaticamenteDOTNET_ENVIRONMENT=Development(usasrc/Bud.Mcp/appsettings.Development.json)BUD_API_BASE_URL=http://web:8080para chamadas internas aoBud.Server- mapeamento de porta
8081:8080para evitar conflito com oweb
Health checks do MCP local:
curl -i http://localhost:8081/health/live
curl -i http://localhost:8081/health/readyExemplo de initialize no endpoint MCP:
curl -s http://localhost:8081/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize"}'A resposta inclui o header MCP-Session-Id, que deve ser enviado nas chamadas seguintes (tools/list, tools/call, etc.).
Fluxo obrigatório para atualizar catálogo MCP:
dotnet run --project src/Bud.Mcp/Bud.Mcp.csproj -- generate-tool-catalog
dotnet run --project src/Bud.Mcp/Bud.Mcp.csproj -- check-tool-catalog --fail-on-diffRegras importantes do catálogo:
- As ferramentas de domínio (
mission_*,mission_objective_*,mission_metric_*,metric_checkin_*) são carregadas exclusivamente do arquivosrc/Bud.Mcp/Tools/Generated/mcp-tool-catalog.json. - O
Bud.Mcpfalha na inicialização se o catálogo estiver ausente, inválido, vazio ou sem ferramentas de domínio obrigatórias. - O comando
check-tool-catalog --fail-on-difftambém valida o contrato mínimo de camposrequiredpor ferramenta e retorna erro quando houver quebra de contrato.
Se estiver rodando local com DOTNET_ENVIRONMENT=Development, defina:
BUD_API_BASE_URL=http://localhost:8080.
auth_loginauth_whoamitenant_list_availabletenant_set_currentsession_bootstraphelp_list_actionshelp_action_schemamission_create,mission_get,mission_list,mission_update,mission_deletemission_metric_create,mission_metric_get,mission_metric_list,mission_metric_update,mission_metric_deletemetric_checkin_create,metric_checkin_get,metric_checkin_list,metric_checkin_update,metric_checkin_delete
Nota: as tools
mission_objective_*existem no catálogo gerado (mcp-tool-catalog.json) mas ainda não estão implementadas emMcpToolService. Serão ativadas quando o wiring for adicionado.
prompts/listé suportado para compatibilidade de clientes MCP e retorna lista vazia quando não há prompts publicados.auth_loginretornawhoami,requiresTenantForDomainToolsenextStepspara orientar o agente nos próximos passos.session_bootstrapretorna snapshot de sessão (whoami,availableTenants, tenant atual) estarterSchemaspara fluxos de criação.help_action_schemaretornarequired,inputSchemaeexamplepara uma ação específica (ou todas as ações, quandoactionnão é informado).- Em erro de validação da API, o MCP retorna
statusCode,title,detaileerrorspor campo quando disponível.
Scripts disponíveis:
scripts/gcp-bootstrap.sh: prepara infraestrutura base (APIs, Artifact Registry, Cloud SQL, service account, secrets, permissões do Cloud Build).scripts/gcp-deploy-web.sh: deploy doBud.Server(com migração EF Core via Cloud Run Job).scripts/gcp-deploy-mcp.sh: deploy doBud.McpHTTP.scripts/gcp-deploy-all.sh: executa deploy completo (Bud.Server+Bud.Mcp).
Observação: os scripts de deploy remoto usam Cloud Build para gerar imagens no GCP (não dependem de docker build local).
Pré-requisitos (primeira vez): projeto GCP criado, billing vinculado, usuário com role Owner. Ver DEPLOY.md para detalhes.
Fluxo recomendado:
cp .env.example .env.gcp # ajustar PROJECT_ID
./scripts/gcp-bootstrap.sh
./scripts/gcp-deploy-all.shDeploy sem migração (quando o schema não mudou):
./scripts/gcp-deploy-all.sh --skip-migrationDeploy por serviço:
./scripts/gcp-deploy-web.sh
./scripts/gcp-deploy-web.sh --skip-migration
./scripts/gcp-deploy-mcp.shPara detalhes operacionais, pré-requisitos e troubleshooting, consulte DEPLOY.md.
Objetivo: validar ponta a ponta (auth, tenant, CRUD básico e leitura) em ambiente local.
Opção A (recomendada):
docker compose up --buildOpção B (sem Docker):
dotnet restore
dotnet build
dotnet run --project src/Bud.ServerDefina a URL base conforme o modo de execução:
# Com Docker Compose
export BUD_BASE_URL="http://localhost:8080"
# Sem Docker (dotnet run, profile padrão)
export BUD_BASE_URL="http://localhost:5096"curl -s -X POST "$BUD_BASE_URL/api/sessions" \
-H "Content-Type: application/json" \
-d '{"email":"admin@getbud.co"}'Copie o token da resposta e exporte:
export BUD_TOKEN="<jwt>"curl -s "$BUD_BASE_URL/api/me/organizations" \
-H "Authorization: Bearer $BUD_TOKEN"Copie um id e exporte:
export BUD_ORG_ID="<organization-id>"curl -s "$BUD_BASE_URL/api/missions?page=1&pageSize=10" \
-H "Authorization: Bearer $BUD_TOKEN" \
-H "X-Tenant-Id: $BUD_ORG_ID"curl -s -X POST "$BUD_BASE_URL/api/missions" \
-H "Authorization: Bearer $BUD_TOKEN" \
-H "X-Tenant-Id: $BUD_ORG_ID" \
-H "Content-Type: application/json" \
-d '{
"name":"Onboarding - Missão",
"description":"Validação ponta a ponta",
"startDate":"2026-01-01T00:00:00Z",
"endDate":"2026-12-31T23:59:59Z",
"status":"Planned",
"scopeType":"Organization",
"scopeId":"'"$BUD_ORG_ID"'"
}'sequenceDiagram
participant Dev as Dev
participant API as Bud.Server
Dev->>API: POST /api/sessions (email)
API-->>Dev: token JWT
Dev->>API: GET /api/me/organizations (Bearer)
API-->>Dev: organizations[]
Dev->>Dev: define BUD_ORG_ID
Dev->>API: GET /api/missions (Bearer + X-Tenant-Id)
API-->>Dev: lista paginada
Dev->>API: POST /api/missions (Bearer + X-Tenant-Id)
API-->>Dev: missão criada
- Acesse
$BUD_BASE_URL/swaggerpara executar os mesmos fluxos pela UI. - Consulte
GET /health/readypara validar PostgreSQL. - Em caso de erro 403, valide se o header
X-Tenant-Idfoi enviado (exceto cenário global admin em "TODOS").
-
Porta 8080 ocupada
Sintoma: erro ao subirdocker compose up --buildcom bind em8080.
Ação: pare o processo/serviço que está usando a porta ou altere o mapeamento nodocker-compose.yml. -
Falha de conexão com PostgreSQL
Sintoma:/health/readyretorna unhealthy para banco.
Ação: confirme se o containerdbsubiu e se a connection string está correta (ConnectionStrings:DefaultConnection). -
401/403 em endpoints protegidos
Sintoma: chamadas autenticadas falham mesmo após login.
Ação: verifiqueAuthorization: Bearer <token>e, para endpoints tenant-scoped, envieX-Tenant-Id. -
Dados/artefatos antigos no browser
Sintoma: UI não reflete mudanças recentes.
Ação: faça hard reload no navegador. Se persistir, executedocker compose down -v && docker compose up --build.
flowchart TD
A[Erro 401/403] --> B{Tem Bearer token?}
B -- Não --> C[Refaça login em /api/sessions]
B -- Sim --> D{Endpoint é tenant-scoped?}
D -- Não --> E[Validar payload/headers específicos]
D -- Sim --> F{X-Tenant-Id foi enviado?}
F -- Não --> G[Enviar X-Tenant-Id]
F -- Sim --> H{Usuário pertence ao tenant?}
H -- Não --> I[Selecionar tenant válido em /api/me/organizations]
H -- Sim --> J[Validar policy/regra de autorização do endpoint]
# suíte completa
dotnet test
# testes MCP
dotnet test tests/Bud.Mcp.Tests
# apenas unitários
dotnet test tests/Bud.Server.Tests
# apenas integração
dotnet test tests/Bud.Server.IntegrationTestsObservação:
dotnet testusaBud.slnxe executa tambémtests/Bud.Mcp.Tests.- Testes de integração usam PostgreSQL via Testcontainers.
- Use
dotnet test --nologopara saída mais limpa no terminal. - A solução usa
TreatWarningsAsErrors=true; avisos quebram build/test.
- UI interativa (Development):
http://localhost:8080/swagger - Documento OpenAPI bruto:
http://localhost:8080/openapi/v1.json - A documentação é enriquecida com:
ProducesResponseTypepor endpoint- comentários XML (
summary,response,remarks) - metadados de conteúdo (
Consumes/Produces) quando aplicável
- Para campos enum em payload JSON, a API aceita tanto
string(case-insensitive) quantonumber(compatibilidade retroativa).
O Bud 2.0 usa um sistema de tokens de design baseado no Figma Style Guide.
- Primária: Orange (#FF6B35) - CTAs, estados ativos e ações principais
- Secundária: Wine (#E838A3) - acentos, destaques e ações secundárias
- Crimson Pro: fonte serifada para títulos e destaques
- Plus Jakarta Sans: fonte sem serifa para texto e componentes de interface
Todos os valores de design (cores, tipografia, espaçamento e sombras) são definidos como propriedades CSS em src/Bud.Client/wwwroot/css/tokens.css.
Exemplo de uso:
.button {
background: var(--color-brand-primary);
padding: var(--spacing-3) var(--spacing-4);
border-radius: var(--radius-md);
font-size: var(--font-size-base);
}Veja DESIGN_TOKENS.md para:
- Referência completa de tokens
- Processo de atualização a partir do Figma
- Convenções de nomenclatura
- Boas práticas
- Development: o schema é criado automaticamente via
EnsureCreated()no startup. Para recriar após mudanças no modelo:docker compose down -v && docker compose up --build - Production: usa EF Core migrations (
dotnet-ef migrations bundle) via targetprod-migratenoDockerfile.Production. Migrations ficam emInfrastructure/Persistence/Migrations/.
O Bud usa OpenTelemetry (traces + métricas) e structured logging compatível com o Cloud Logging do GCP.
Em produção (ASPNETCORE_ENVIRONMENT=Production), os logs são emitidos em JSON single-line compatível com Cloud Logging:
- Campos:
severity,message,time,logging.googleapis.com/trace,logging.googleapis.com/spanId,eventId,category,exception. severityé mapeado deLogLevel(ex.:Information→INFO,Error→ERROR).- Em desenvolvimento, mantém o formatter padrão do console.
GCP_PROJECT_IDconfigura o formato completo do trace:projects/{id}/traces/{traceId}.
A instrumentação OTel cobre ASP.NET Core, HttpClient e EF Core. Toda configuração de exportação é via variáveis de ambiente padrão do OTel spec — sem hardcode no código:
| Variável | Descrição | Exemplo (produção) |
|---|---|---|
OTEL_SERVICE_NAME |
Nome do serviço | Bud.Server ou Bud.Mcp |
OTEL_RESOURCE_ATTRIBUTES |
Atributos de recurso | cloud.provider=gcp,cloud.platform=gcp_cloud_run |
OTEL_EXPORTER_OTLP_ENDPOINT |
Endpoint OTLP | https://telemetry.googleapis.com |
OTEL_EXPORTER_OTLP_PROTOCOL |
Protocolo | grpc |
Em dev local sem OTEL_EXPORTER_OTLP_ENDPOINT, o exporter tenta localhost:4317 e falha silenciosamente.
LogEnrichmentMiddleware(Bud.Server): injetaTraceId,SpanIdeCorrelationIdno scope de todos os logs da request.McpRequestLoggingMiddleware(Bud.Mcp): registra cada request com método, path, status code, elapsed e correlation ID.- Header
X-Correlation-Idadicionado a todas as respostas.
Ranges estáveis de EventId por domínio:
| Range | Domínio |
|---|---|
| 3100–3199 | RequestTelemetryMiddleware |
| 4000–4009 | Mission |
| 4010–4019 | Organization |
| 4020–4029 | Workspace |
| 4030–4039 | Team |
| 4040–4049 | Collaborator |
| 4050–4059 | Metric |
| 4060–4069 | MetricCheckin |
| 4070–4079 | Template |
| 4080–4089 | Objective |
| 4090–4099 | Session / Notification |
| 5000–5009 | McpRequestLoggingMiddleware (Bud.Mcp) |
Referência: docs/adr/ADR-0013-estrategia-de-observabilidade.md.
GET /health/live: liveness (sempre saudável).GET /health/ready: readiness (PostgreSQL).
Referência completa com exemplos interativos disponível em /swagger (ambiente Development).
POST /api/sessions— login por e-mail, retorna JWTDELETE /api/sessions/current— logout
GET /api/me/organizations— organizações disponíveisGET /api/me/dashboard— dashboard do colaborador autenticadoGET /api/me/missions— missões do colaborador autenticado
POST /api/organizationsGET /api/organizations— listagem paginada (?search=&page=1&pageSize=10)GET /api/organizations/{id}PATCH /api/organizations/{id}DELETE /api/organizations/{id}GET /api/organizations/{id}/workspacesGET /api/organizations/{id}/collaborators
POST /api/workspacesGET /api/workspaces— listagem paginada (?organizationId=&search=&page=1&pageSize=10)GET /api/workspaces/{id}PATCH /api/workspaces/{id}DELETE /api/workspaces/{id}GET /api/workspaces/{id}/teams
POST /api/teamsGET /api/teams— listagem paginada (?workspaceId=&parentTeamId=&search=&page=1&pageSize=10)GET /api/teams/{id}PATCH /api/teams/{id}DELETE /api/teams/{id}GET /api/teams/{id}/subteamsGET /api/teams/{id}/collaboratorsGET /api/teams/{id}/collaborators/lookupPATCH /api/teams/{id}/collaboratorsGET /api/teams/{id}/collaborators/eligible-for-assignment
POST /api/collaboratorsGET /api/collaborators— listagem paginada (?teamId=&search=&page=1&pageSize=10)GET /api/collaborators/{id}PATCH /api/collaborators/{id}DELETE /api/collaborators/{id}GET /api/collaborators/lookupGET /api/collaborators/leadersGET /api/collaborators/{id}/subordinatesGET /api/collaborators/{id}/teamsPATCH /api/collaborators/{id}/teamsGET /api/collaborators/{id}/teams/eligible-for-assignment
POST /api/missionsGET /api/missions— listagem paginadaGET /api/missions/{id}PATCH /api/missions/{id}DELETE /api/missions/{id}GET /api/missions/progressGET /api/missions/{id}/metricsGET /api/missions/{id}/objectives
POST /api/objectivesGET /api/objectives— listagem paginada (filtro pormissionId)GET /api/objectives/{id}PATCH /api/objectives/{id}DELETE /api/objectives/{id}GET /api/objectives/{objectiveId}/metricsGET /api/objectives/progress- Campo opcional nos payloads de criação/atualização:
dimension(texto livre de até 100 caracteres).
POST /api/metricsGET /api/metrics— listagem paginadaGET /api/metrics/{id}PATCH /api/metrics/{id}DELETE /api/metrics/{id}GET /api/metrics/progressPOST /api/metrics/{metricId}/checkins— cria checkinGET /api/metrics/{metricId}/checkins— lista checkins da métricaGET /api/metrics/{metricId}/checkins/{checkinId}— detalhe do checkinPATCH /api/metrics/{metricId}/checkins/{checkinId}— atualiza checkinDELETE /api/metrics/{metricId}/checkins/{checkinId}— remove checkin
POST /api/templatesGET /api/templates— listagem paginadaGET /api/templates/{id}PATCH /api/templates/{id}DELETE /api/templates/{id}- Modelos padrão semeados para a organização bootstrap (
getbud.co):BSC,Mapa Estratégico,Planejamento Estratégico Anual,OKRePDI(todos com objetivos e métricas vinculadas). - Payloads de criação/atualização também aceitam
objectives(objetivos do template) emetrics[].missionTemplateObjectiveIdpara vincular métricas a objetivos.
GET /api/notifications— listagem paginada (filtro porisRead)PATCH /api/notifications/{id}— marca como lidaPATCH /api/notifications— marca todas como lidas
Organization:
{
"name": "acme.com.br",
"ownerId": "00000000-0000-0000-0000-000000000000"
}Workspace:
{
"name": "Produto",
"organizationId": "00000000-0000-0000-0000-000000000000"
}Team:
{
"name": "Time A",
"workspaceId": "00000000-0000-0000-0000-000000000000",
"parentTeamId": null
}Collaborator:
{
"fullName": "Maria Silva",
"email": "maria@acme.com",
"teamId": "00000000-0000-0000-0000-000000000000",
"leaderId": null
}Mission:
{
"name": "Aumentar NPS",
"description": "Melhorar satisfação do cliente",
"startDate": "2026-01-01T00:00:00Z",
"endDate": "2026-03-31T23:59:59Z",
"status": "Planned",
"scopeType": "Workspace",
"scopeId": "00000000-0000-0000-0000-000000000000"
}Metric Checkin (POST /api/metrics/{metricId}/checkins):
{
"value": 42.5,
"text": null,
"checkinDate": "2026-02-07T00:00:00Z",
"note": "Evolução semanal",
"confidenceLevel": 4
}