maestro-bundle 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.
Files changed (60) hide show
  1. package/README.md +91 -0
  2. package/package.json +25 -0
  3. package/src/cli.mjs +212 -0
  4. package/templates/bundle-ai-agents/.spec/constitution.md +33 -0
  5. package/templates/bundle-ai-agents/AGENTS.md +140 -0
  6. package/templates/bundle-ai-agents/skills/agent-orchestration/SKILL.md +132 -0
  7. package/templates/bundle-ai-agents/skills/api-design/SKILL.md +100 -0
  8. package/templates/bundle-ai-agents/skills/clean-architecture/SKILL.md +99 -0
  9. package/templates/bundle-ai-agents/skills/context-engineering/SKILL.md +98 -0
  10. package/templates/bundle-ai-agents/skills/database-modeling/SKILL.md +59 -0
  11. package/templates/bundle-ai-agents/skills/docker-containerization/SKILL.md +114 -0
  12. package/templates/bundle-ai-agents/skills/eval-testing/SKILL.md +115 -0
  13. package/templates/bundle-ai-agents/skills/memory-management/SKILL.md +106 -0
  14. package/templates/bundle-ai-agents/skills/prompt-engineering/SKILL.md +66 -0
  15. package/templates/bundle-ai-agents/skills/rag-pipeline/SKILL.md +128 -0
  16. package/templates/bundle-ai-agents/skills/testing-strategy/SKILL.md +95 -0
  17. package/templates/bundle-base/AGENTS.md +118 -0
  18. package/templates/bundle-base/skills/branch-strategy/SKILL.md +42 -0
  19. package/templates/bundle-base/skills/code-review/SKILL.md +54 -0
  20. package/templates/bundle-base/skills/commit-pattern/SKILL.md +58 -0
  21. package/templates/bundle-data-pipeline/.spec/constitution.md +32 -0
  22. package/templates/bundle-data-pipeline/AGENTS.md +115 -0
  23. package/templates/bundle-data-pipeline/skills/data-preprocessing/SKILL.md +75 -0
  24. package/templates/bundle-data-pipeline/skills/docker-containerization/SKILL.md +114 -0
  25. package/templates/bundle-data-pipeline/skills/feature-engineering/SKILL.md +76 -0
  26. package/templates/bundle-data-pipeline/skills/mlops-pipeline/SKILL.md +77 -0
  27. package/templates/bundle-data-pipeline/skills/model-training/SKILL.md +68 -0
  28. package/templates/bundle-data-pipeline/skills/rag-pipeline/SKILL.md +128 -0
  29. package/templates/bundle-frontend-spa/.spec/constitution.md +32 -0
  30. package/templates/bundle-frontend-spa/AGENTS.md +107 -0
  31. package/templates/bundle-frontend-spa/skills/authentication/SKILL.md +90 -0
  32. package/templates/bundle-frontend-spa/skills/component-design/SKILL.md +115 -0
  33. package/templates/bundle-frontend-spa/skills/e2e-testing/SKILL.md +101 -0
  34. package/templates/bundle-frontend-spa/skills/integration-api/SKILL.md +95 -0
  35. package/templates/bundle-frontend-spa/skills/react-patterns/SKILL.md +130 -0
  36. package/templates/bundle-frontend-spa/skills/responsive-layout/SKILL.md +65 -0
  37. package/templates/bundle-frontend-spa/skills/state-management/SKILL.md +86 -0
  38. package/templates/bundle-jhipster-microservices/.spec/constitution.md +37 -0
  39. package/templates/bundle-jhipster-microservices/AGENTS.md +307 -0
  40. package/templates/bundle-jhipster-microservices/skills/ci-cd-pipeline/SKILL.md +112 -0
  41. package/templates/bundle-jhipster-microservices/skills/clean-architecture/SKILL.md +99 -0
  42. package/templates/bundle-jhipster-microservices/skills/ddd-tactical/SKILL.md +138 -0
  43. package/templates/bundle-jhipster-microservices/skills/jhipster-angular/SKILL.md +97 -0
  44. package/templates/bundle-jhipster-microservices/skills/jhipster-docker-k8s/SKILL.md +183 -0
  45. package/templates/bundle-jhipster-microservices/skills/jhipster-entities/SKILL.md +87 -0
  46. package/templates/bundle-jhipster-microservices/skills/jhipster-gateway/SKILL.md +96 -0
  47. package/templates/bundle-jhipster-microservices/skills/jhipster-kafka/SKILL.md +145 -0
  48. package/templates/bundle-jhipster-microservices/skills/jhipster-registry/SKILL.md +83 -0
  49. package/templates/bundle-jhipster-microservices/skills/jhipster-service/SKILL.md +131 -0
  50. package/templates/bundle-jhipster-microservices/skills/testing-strategy/SKILL.md +95 -0
  51. package/templates/bundle-jhipster-monorepo/.spec/constitution.md +32 -0
  52. package/templates/bundle-jhipster-monorepo/AGENTS.md +227 -0
  53. package/templates/bundle-jhipster-monorepo/skills/clean-architecture/SKILL.md +99 -0
  54. package/templates/bundle-jhipster-monorepo/skills/ddd-tactical/SKILL.md +138 -0
  55. package/templates/bundle-jhipster-monorepo/skills/jhipster-angular/SKILL.md +166 -0
  56. package/templates/bundle-jhipster-monorepo/skills/jhipster-entities/SKILL.md +141 -0
  57. package/templates/bundle-jhipster-monorepo/skills/jhipster-liquibase/SKILL.md +95 -0
  58. package/templates/bundle-jhipster-monorepo/skills/jhipster-security/SKILL.md +89 -0
  59. package/templates/bundle-jhipster-monorepo/skills/jhipster-spring/SKILL.md +155 -0
  60. package/templates/bundle-jhipster-monorepo/skills/testing-strategy/SKILL.md +95 -0
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: ddd-tactical
3
+ description: Implementar padrões táticos do DDD - Entities, Value Objects, Aggregates, Domain Events, Repositories e Domain Services. Use quando for modelar domínio, criar entidades ricas, ou aplicar DDD no código.
4
+ ---
5
+
6
+ # DDD Tático
7
+
8
+ ## Value Objects
9
+
10
+ Imutáveis, comparados por valor, contêm validação.
11
+
12
+ ```python
13
+ @dataclass(frozen=True)
14
+ class Email:
15
+ value: str
16
+
17
+ def __post_init__(self):
18
+ if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', self.value):
19
+ raise InvalidEmailException(self.value)
20
+
21
+ @dataclass(frozen=True)
22
+ class ComplianceScore:
23
+ value: float
24
+
25
+ def __post_init__(self):
26
+ if not 0 <= self.value <= 100:
27
+ raise ValueError("Score deve ser entre 0 e 100")
28
+
29
+ def is_passing(self) -> bool:
30
+ return self.value >= 80.0
31
+
32
+ def __str__(self) -> str:
33
+ return f"{self.value:.1f}%"
34
+ ```
35
+
36
+ ## Entities
37
+
38
+ Identidade única, mutáveis, contêm comportamento.
39
+
40
+ ```python
41
+ class Task:
42
+ def __init__(self, id: TaskId, description: str, agent_type: AgentType):
43
+ self._id = id
44
+ self._description = description
45
+ self._agent_type = agent_type
46
+ self._status = TaskStatus.PENDING
47
+ self._started_at: datetime | None = None
48
+ self._completed_at: datetime | None = None
49
+
50
+ def start(self) -> None:
51
+ if self._status != TaskStatus.PENDING:
52
+ raise TaskNotPendingException(self._id)
53
+ self._status = TaskStatus.IN_PROGRESS
54
+ self._started_at = datetime.now()
55
+
56
+ def complete(self, result: TaskResult) -> None:
57
+ if self._status != TaskStatus.IN_PROGRESS:
58
+ raise TaskNotInProgressException(self._id)
59
+ self._status = TaskStatus.COMPLETED
60
+ self._completed_at = datetime.now()
61
+
62
+ @property
63
+ def duration(self) -> timedelta | None:
64
+ if self._started_at and self._completed_at:
65
+ return self._completed_at - self._started_at
66
+ return None
67
+ ```
68
+
69
+ ## Aggregates
70
+
71
+ Cluster de entities com uma raiz que protege invariantes.
72
+
73
+ ```python
74
+ class Demand: # Aggregate Root
75
+ """Demand é a raiz. Tasks só são acessadas via Demand."""
76
+
77
+ def add_task(self, task: Task) -> None:
78
+ if len(self._tasks) >= 20:
79
+ raise TooManyTasksException("Máximo 20 tasks por demanda")
80
+ self._tasks.append(task)
81
+
82
+ def start_task(self, task_id: TaskId) -> None:
83
+ task = self._find_task(task_id)
84
+ # Verificar invariante: não ter mais de 3 tasks simultâneas
85
+ active = [t for t in self._tasks if t.status == TaskStatus.IN_PROGRESS]
86
+ if len(active) >= 3:
87
+ raise TooManyActiveTasksException()
88
+ task.start()
89
+ ```
90
+
91
+ ## Domain Events
92
+
93
+ Notificam que algo aconteceu no domínio.
94
+
95
+ ```python
96
+ @dataclass(frozen=True)
97
+ class DomainEvent:
98
+ occurred_at: datetime = field(default_factory=datetime.now)
99
+
100
+ @dataclass(frozen=True)
101
+ class TaskCompleted(DomainEvent):
102
+ task_id: TaskId
103
+ agent_id: AgentId
104
+ branch_name: str
105
+ duration_seconds: float
106
+
107
+ @dataclass(frozen=True)
108
+ class ComplianceViolationDetected(DomainEvent):
109
+ agent_id: AgentId
110
+ bundle_name: str
111
+ violations: list[str]
112
+ severity: str # "warning" | "critical"
113
+ ```
114
+
115
+ ## Domain Services
116
+
117
+ Lógica que não pertence a uma única entidade.
118
+
119
+ ```python
120
+ class TeamRecruitmentService:
121
+ def recruit_for_demand(self, demand: Demand, available: list[Agent]) -> AgentTeam:
122
+ complexity = demand.assess_complexity()
123
+ required = self._determine_roles(complexity)
124
+ team = AgentTeam()
125
+ for role in required:
126
+ agent = next((a for a in available if a.type == role and a.is_available), None)
127
+ if not agent:
128
+ raise NoAvailableAgentException(role)
129
+ team.add(agent)
130
+ return team
131
+ ```
132
+
133
+ ## Ordem de prioridade para regras
134
+
135
+ 1. **Value Object** — validação e comportamento simples
136
+ 2. **Entity** — regras que envolvem estado da entidade
137
+ 3. **Domain Service** — regras que envolvem múltiplas entidades
138
+ 4. **Use Case** — orquestração (NÃO contém regras)
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: jhipster-angular
3
+ description: Desenvolver frontend Angular no Gateway JHipster que consome múltiplos microsserviços. Use quando precisar criar telas que agregam dados de vários serviços, ou customizar o frontend do Gateway.
4
+ ---
5
+
6
+ # JHipster Angular — Microservices
7
+
8
+ ## Diferença do Monorepo
9
+
10
+ No microservices, o Angular fica no **Gateway**. Ele não sabe que existem múltiplos serviços — o Gateway roteia transparentemente.
11
+
12
+ ```
13
+ Browser → Gateway:8080/api/demands → demand-service:8081/api/demands
14
+ Browser → Gateway:8080/api/agents → agent-service:8082/api/agents
15
+ ```
16
+
17
+ Do ponto de vista do Angular, tudo é uma API só.
18
+
19
+ ## Services que agregam dados
20
+
21
+ ```typescript
22
+ // dashboard.service.ts — agrega dados de múltiplos serviços (via gateway)
23
+ @Injectable({ providedIn: 'root' })
24
+ export class DashboardService {
25
+ constructor(
26
+ private demandService: DemandService,
27
+ private agentService: AgentService,
28
+ private trackingService: TrackingService,
29
+ ) {}
30
+
31
+ getMetrics(): Observable<DashboardMetrics> {
32
+ return forkJoin({
33
+ activeDemands: this.demandService.countByStatus('IN_PROGRESS'),
34
+ activeAgents: this.agentService.countByStatus('BUSY'),
35
+ completedToday: this.trackingService.getCompletedToday(),
36
+ complianceRate: this.trackingService.getComplianceRate(),
37
+ });
38
+ }
39
+ }
40
+ ```
41
+
42
+ ## Tratamento de falha parcial
43
+
44
+ Se um serviço estiver fora do ar, mostrar o que conseguir:
45
+
46
+ ```typescript
47
+ getMetrics(): Observable<DashboardMetrics> {
48
+ return forkJoin({
49
+ activeDemands: this.demandService.countByStatus('IN_PROGRESS').pipe(
50
+ catchError(() => of({ count: -1 })) // -1 = indisponível
51
+ ),
52
+ activeAgents: this.agentService.countByStatus('BUSY').pipe(
53
+ catchError(() => of({ count: -1 }))
54
+ ),
55
+ });
56
+ }
57
+ ```
58
+
59
+ ```html
60
+ <div *ngIf="metrics.activeDemands.count >= 0; else unavailable">
61
+ {{ metrics.activeDemands.count }}
62
+ </div>
63
+ <ng-template #unavailable>
64
+ <span class="text-muted">Indisponível</span>
65
+ </ng-template>
66
+ ```
67
+
68
+ ## WebSocket para real-time
69
+
70
+ ```typescript
71
+ // No Gateway, conectar via STOMP
72
+ @Injectable({ providedIn: 'root' })
73
+ export class WebSocketService {
74
+ private stompClient: RxStomp;
75
+
76
+ connect(): void {
77
+ this.stompClient = new RxStomp();
78
+ this.stompClient.configure({
79
+ brokerURL: `ws://${location.host}/websocket`,
80
+ });
81
+ this.stompClient.activate();
82
+ }
83
+
84
+ onAgentEvent(): Observable<TrackingEvent> {
85
+ return this.stompClient.watch('/topic/tracking').pipe(
86
+ map(msg => JSON.parse(msg.body))
87
+ );
88
+ }
89
+ }
90
+ ```
91
+
92
+ ## Regras
93
+
94
+ - Frontend no Gateway, não nos serviços
95
+ - Tratar falha de serviços individuais gracefully
96
+ - Usar `forkJoin` para agregar, `catchError` para resiliência
97
+ - Lazy loading por módulo/feature
@@ -0,0 +1,183 @@
1
+ ---
2
+ name: jhipster-docker-k8s
3
+ description: Deploy de microsserviços JHipster com Docker Compose (dev) e Kubernetes/K3s (prod). Use quando precisar containerizar serviços JHipster, criar docker-compose, ou fazer deploy em K8s.
4
+ ---
5
+
6
+ # Docker & Kubernetes para JHipster Microservices
7
+
8
+ ## Docker Compose — Dev
9
+
10
+ ```bash
11
+ # Gerar docker-compose via JHipster
12
+ jhipster docker-compose
13
+
14
+ # Ou usar o gerado pelo JDL deployment
15
+ ```
16
+
17
+ ```yaml
18
+ # docker-compose/docker-compose.yml
19
+ services:
20
+ gateway:
21
+ image: gateway:latest
22
+ ports:
23
+ - "8080:8080"
24
+ environment:
25
+ - SPRING_PROFILES_ACTIVE=dev
26
+ - SPRING_CLOUD_CONSUL_HOST=consul
27
+ depends_on:
28
+ - consul
29
+ - keycloak
30
+
31
+ demand-service:
32
+ image: demand-service:latest
33
+ environment:
34
+ - SPRING_PROFILES_ACTIVE=dev
35
+ - SPRING_CLOUD_CONSUL_HOST=consul
36
+ - SPRING_DATASOURCE_URL=jdbc:postgresql://demand-db:5432/demand
37
+ depends_on:
38
+ - demand-db
39
+ - consul
40
+ - kafka
41
+
42
+ demand-db:
43
+ image: postgres:16
44
+ environment:
45
+ POSTGRES_DB: demand
46
+ POSTGRES_USER: demand
47
+ POSTGRES_PASSWORD: demand
48
+
49
+ agent-service:
50
+ image: agent-service:latest
51
+ environment:
52
+ - SPRING_PROFILES_ACTIVE=dev
53
+ - SPRING_CLOUD_CONSUL_HOST=consul
54
+ - SPRING_DATASOURCE_URL=jdbc:postgresql://agent-db:5432/agent
55
+ depends_on:
56
+ - agent-db
57
+ - consul
58
+ - kafka
59
+
60
+ agent-db:
61
+ image: postgres:16
62
+ environment:
63
+ POSTGRES_DB: agent
64
+ POSTGRES_USER: agent
65
+ POSTGRES_PASSWORD: agent
66
+
67
+ consul:
68
+ image: consul:1.15
69
+ ports:
70
+ - "8500:8500"
71
+ command: agent -server -bootstrap -ui -client=0.0.0.0
72
+
73
+ kafka:
74
+ image: confluentinc/cp-kafka:7.5.0
75
+ depends_on:
76
+ - zookeeper
77
+ ports:
78
+ - "9092:9092"
79
+ environment:
80
+ KAFKA_BROKER_ID: 1
81
+ KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
82
+ KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
83
+ KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
84
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
85
+
86
+ zookeeper:
87
+ image: confluentinc/cp-zookeeper:7.5.0
88
+ environment:
89
+ ZOOKEEPER_CLIENT_PORT: 2181
90
+
91
+ keycloak:
92
+ image: quay.io/keycloak/keycloak:23.0
93
+ ports:
94
+ - "9080:8080"
95
+ environment:
96
+ KEYCLOAK_ADMIN: admin
97
+ KEYCLOAK_ADMIN_PASSWORD: admin
98
+ command: start-dev --import-realm
99
+ volumes:
100
+ - ./keycloak-realm.json:/opt/keycloak/data/import/realm.json
101
+ ```
102
+
103
+ ## Kubernetes — Prod
104
+
105
+ ```bash
106
+ # Gerar manifests via JHipster
107
+ jhipster kubernetes
108
+ ```
109
+
110
+ ### Deployment por serviço
111
+ ```yaml
112
+ apiVersion: apps/v1
113
+ kind: Deployment
114
+ metadata:
115
+ name: demand-service
116
+ namespace: maestro
117
+ spec:
118
+ replicas: 2
119
+ selector:
120
+ matchLabels:
121
+ app: demand-service
122
+ template:
123
+ spec:
124
+ containers:
125
+ - name: demand-service
126
+ image: registry.local/demand-service:1.0.0
127
+ ports:
128
+ - containerPort: 8081
129
+ resources:
130
+ requests:
131
+ memory: "512Mi"
132
+ cpu: "500m"
133
+ limits:
134
+ memory: "1Gi"
135
+ cpu: "1000m"
136
+ readinessProbe:
137
+ httpGet:
138
+ path: /management/health/readiness
139
+ port: 8081
140
+ initialDelaySeconds: 30
141
+ livenessProbe:
142
+ httpGet:
143
+ path: /management/health/liveness
144
+ port: 8081
145
+ initialDelaySeconds: 60
146
+ env:
147
+ - name: SPRING_PROFILES_ACTIVE
148
+ value: prod
149
+ - name: SPRING_DATASOURCE_URL
150
+ valueFrom:
151
+ secretKeyRef:
152
+ name: demand-service-db
153
+ key: url
154
+ ```
155
+
156
+ ## Build de imagens
157
+
158
+ ```bash
159
+ # Build com Jib (padrão JHipster, sem Docker daemon)
160
+ ./mvnw -ntp verify -DskipTests jib:dockerBuild -Pprod
161
+
162
+ # Ou com Docker
163
+ docker build -t demand-service:1.0.0 .
164
+ ```
165
+
166
+ ## Comandos úteis
167
+
168
+ ```bash
169
+ # Dev: subir tudo
170
+ docker-compose -f docker-compose/docker-compose.yml up -d
171
+
172
+ # Dev: ver logs de um serviço
173
+ docker-compose logs -f demand-service
174
+
175
+ # Prod: deploy
176
+ kubectl apply -f k8s/
177
+
178
+ # Prod: rollback
179
+ kubectl rollout undo deployment/demand-service -n maestro
180
+
181
+ # Prod: escalar
182
+ kubectl scale deployment demand-service --replicas=3 -n maestro
183
+ ```
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: jhipster-entities
3
+ description: Criar e gerenciar entidades JHipster com JDL para microsserviços, incluindo relações cross-service e DTOs compartilhados. Use quando precisar criar entidades, definir modelo de dados, ou gerar código em microsserviços.
4
+ ---
5
+
6
+ # JHipster Entities — Microservices
7
+
8
+ ## Regra fundamental
9
+
10
+ Em microsserviços, **entidades pertencem a um único serviço**. Relacionamentos cross-service usam IDs, não foreign keys.
11
+
12
+ ## JDL com microservice assignment
13
+
14
+ ```jdl
15
+ /* demand-service entities */
16
+ entity Demand {
17
+ description TextBlob required
18
+ status DemandStatus required
19
+ priority Priority required
20
+ createdAt Instant required
21
+ }
22
+
23
+ entity Task {
24
+ description String required maxlength(500)
25
+ status TaskStatus required
26
+ agentId Long // ID do agente (outro serviço), não FK
27
+ branchName String
28
+ }
29
+
30
+ relationship OneToMany {
31
+ Demand{tasks} to Task{demand required}
32
+ }
33
+
34
+ microservice Demand, Task with demandService
35
+
36
+ /* agent-service entities */
37
+ entity Agent {
38
+ name String required
39
+ type AgentType required
40
+ status AgentStatus required
41
+ worktreePath String
42
+ }
43
+
44
+ entity AgentTeam {
45
+ demandId Long required // ID da demand (outro serviço), não FK
46
+ }
47
+
48
+ relationship ManyToMany {
49
+ AgentTeam{agents} to Agent
50
+ }
51
+
52
+ microservice Agent, AgentTeam with agentService
53
+ ```
54
+
55
+ ## Comunicação cross-service
56
+
57
+ Quando `Task` referencia `Agent` (outro serviço):
58
+
59
+ ```java
60
+ // NO demand-service — Task.java
61
+ @Entity
62
+ public class Task {
63
+ // ...
64
+ private Long agentId; // Apenas o ID, não a entidade Agent
65
+
66
+ // Para obter dados do Agent, chamar agent-service via Feign
67
+ }
68
+
69
+ // NO demand-service — DemandService
70
+ @Service
71
+ public class DemandServiceImpl {
72
+ private final AgentServiceClient agentClient;
73
+
74
+ public TaskDetailDTO getTaskDetail(Long taskId) {
75
+ Task task = taskRepository.findById(taskId).orElseThrow();
76
+ AgentDTO agent = agentClient.getAgent(task.getAgentId()); // Feign call
77
+ return new TaskDetailDTO(task, agent);
78
+ }
79
+ }
80
+ ```
81
+
82
+ ## Regras
83
+
84
+ - Entidade pertence a UM serviço
85
+ - Cross-service: guardar apenas o ID, nunca FK real
86
+ - Para exibir dados de outro serviço: Feign Client ou evento Kafka
87
+ - Nunca compartilhar entities entre serviços (duplicar DTOs se necessário)
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: jhipster-gateway
3
+ description: Configurar o JHipster Gateway com Spring Cloud Gateway, roteamento, rate limiting e frontend Angular. Use quando precisar configurar rotas do gateway, load balancing, ou CORS entre serviços.
4
+ ---
5
+
6
+ # JHipster Gateway
7
+
8
+ ## O que é
9
+
10
+ O Gateway é o ponto de entrada único. Ele roteia requests para os microsserviços, serve o frontend Angular e gerencia autenticação.
11
+
12
+ ## Roteamento
13
+
14
+ ```yaml
15
+ # application.yml
16
+ spring:
17
+ cloud:
18
+ gateway:
19
+ routes:
20
+ - id: demand-service
21
+ uri: lb://demand-service
22
+ predicates:
23
+ - Path=/api/demands/**,/api/tasks/**
24
+ - id: agent-service
25
+ uri: lb://agent-service
26
+ predicates:
27
+ - Path=/api/agents/**,/api/teams/**
28
+ - id: tracking-service
29
+ uri: lb://tracking-service
30
+ predicates:
31
+ - Path=/api/tracking/**,/api/events/**
32
+ default-filters:
33
+ - TokenRelay
34
+ ```
35
+
36
+ ## Rate Limiting no Gateway
37
+
38
+ ```yaml
39
+ spring:
40
+ cloud:
41
+ gateway:
42
+ routes:
43
+ - id: demand-service
44
+ uri: lb://demand-service
45
+ predicates:
46
+ - Path=/api/demands/**
47
+ filters:
48
+ - name: RequestRateLimiter
49
+ args:
50
+ redis-rate-limiter.replenishRate: 10
51
+ redis-rate-limiter.burstCapacity: 20
52
+ key-resolver: "#{@userKeyResolver}"
53
+ ```
54
+
55
+ ```java
56
+ @Bean
57
+ public KeyResolver userKeyResolver() {
58
+ return exchange -> Mono.just(
59
+ exchange.getRequest().getHeaders().getFirst("Authorization") != null
60
+ ? exchange.getRequest().getHeaders().getFirst("Authorization")
61
+ : exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
62
+ );
63
+ }
64
+ ```
65
+
66
+ ## CORS
67
+
68
+ ```java
69
+ @Bean
70
+ public CorsWebFilter corsFilter() {
71
+ CorsConfiguration config = new CorsConfiguration();
72
+ config.setAllowedOrigins(List.of("http://localhost:4200", "https://maestro.local"));
73
+ config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
74
+ config.setAllowedHeaders(List.of("*"));
75
+ config.setAllowCredentials(true);
76
+
77
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
78
+ source.registerCorsConfiguration("/api/**", config);
79
+ return new CorsWebFilter(source);
80
+ }
81
+ ```
82
+
83
+ ## Health check dos serviços
84
+
85
+ ```yaml
86
+ management:
87
+ endpoints:
88
+ web:
89
+ exposure:
90
+ include: health,info,gateway
91
+ endpoint:
92
+ gateway:
93
+ enabled: true
94
+ ```
95
+
96
+ Acessar `GET /actuator/gateway/routes` para ver rotas ativas.