fg-tracker-mcp 0.6.1 → 0.8.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/CHANGELOG.md +5 -0
- package/README.md +12 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/infra/cdk-graph.d.ts +35 -0
- package/dist/infra/cdk-graph.js +270 -0
- package/dist/infra/cdk-graph.js.map +1 -0
- package/dist/infra/tools.js +49 -2
- package/dist/infra/tools.js.map +1 -1
- package/dist/loadtest/routes.d.ts +52 -0
- package/dist/loadtest/routes.js +370 -0
- package/dist/loadtest/routes.js.map +1 -0
- package/dist/loadtest/scenario.d.ts +334 -0
- package/dist/loadtest/scenario.js +501 -0
- package/dist/loadtest/scenario.js.map +1 -0
- package/dist/loadtest/tools.d.ts +128 -0
- package/dist/loadtest/tools.js +378 -0
- package/dist/loadtest/tools.js.map +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +5 -1
- package/dist/server.js.map +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog — fg-tracker-mcp
|
|
2
2
|
|
|
3
|
+
## 0.8.0 — 2026-09-15
|
|
4
|
+
|
|
5
|
+
- **Simulação de ambiente** (CONTRATO.md §28.8): tools `loadtest_scan_routes` (rotas NestJS/Express/Next.js, DTOs e pistas de auth, somente leitura), `loadtest_create_scenario` (validação zod do roteiro §28.2 com caminhos dos erros, avisos de variáveis não definidas, senhas literais e efeitos externos), `loadtest_list_scenarios`, `loadtest_suggest_plan` (presets k6 smoke/load/stress/spike/soak/breakpoint, §28.3), `loadtest_get_run` (resumo, thresholds, por passo e advice) e `loadtest_start_run` (recusa sem `confirm: true`).
|
|
6
|
+
- Prompt `create-load-test` (`projectId?`, `path?`, `baseUrl?`, `goal?`).
|
|
7
|
+
|
|
3
8
|
## 0.6.0 — 2026-09-15
|
|
4
9
|
|
|
5
10
|
- Tool `infra_detect_environments { profiles?, includeRegions? }` (local, somente leitura): lê os perfis de `~/.aws/config`/`~/.aws/credentials` (+ `AWS_PROFILE` e cadeia padrão), `sts:GetCallerIdentity` por perfil (até 10), deduplica por conta, classifica o ambiente pelo nome do perfil/ARN e detecta as regiões em uso (índices do Resource Explorer ou sondagem com `ListStacks` + `GetResources`).
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ Cursor / Windsurf / Claude Desktop (JSON):
|
|
|
30
30
|
}
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Em produção, `FG_TRACKER_URL` é a URL da API mostrada no painel em **Conectar**. O domínio `https://
|
|
33
|
+
Em produção, `FG_TRACKER_URL` é a URL da API mostrada no painel em **Conectar**. O domínio `https://track-api.fortground.com.br` será o endereço definitivo; até ele entrar no ar, use a URL atual do painel.
|
|
34
34
|
|
|
35
35
|
## Variáveis de ambiente
|
|
36
36
|
|
|
@@ -49,6 +49,17 @@ Tools `track_*` (nomes inalterados), prompt `instrument-project` e resource `fg-
|
|
|
49
49
|
|
|
50
50
|
Infraestrutura AWS (0.6.0): tools `infra_*` e prompt `connect-infrastructure` — detectar contas/ambientes/regiões nas credenciais locais, conectar cada ambiente, descobrir recursos com credenciais locais (somente leitura), analisar o IaC, instrumentar, validar e gerar o PR de transferência de controle. Nenhuma tool altera recursos na AWS. Detalhes em `docs/mcp.md` → Infraestrutura.
|
|
51
51
|
|
|
52
|
+
Simulação de ambiente (0.8.0): prompt `create-load-test` e tools `loadtest_*` (CONTRATO.md §28.8):
|
|
53
|
+
|
|
54
|
+
| tool | entrada | o que faz |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `loadtest_scan_routes` | `{ path?, format? }` | local, somente leitura: rotas NestJS/Express/Next.js (método, caminho, arquivo:linha, controller, DTO, protegida?) e pistas de autenticação |
|
|
57
|
+
| `loadtest_create_scenario` | `{ projectId, scenario, description? }` | valida o roteiro (§28.2, erros com caminho do campo) e grava (`POST /v1/projects/:id/loadtest/scenarios`, ou `POST /v1/loadtest/scenarios` só com `FG_TRACKER_API_KEY`); resumo com passos, variáveis extraídas, checks e avisos de efeitos externos |
|
|
58
|
+
| `loadtest_list_scenarios` | `{ projectId }` | roteiros do projeto |
|
|
59
|
+
| `loadtest_suggest_plan` | `{ preset, vus?, targetRps?, duration? }` | puro: plano k6 (§28.3) para smoke/load/stress/spike/soak/breakpoint |
|
|
60
|
+
| `loadtest_get_run` | `{ projectId, runId, generateAdvice? }` | resumo do run: latências, erros, checks, thresholds, por passo e sugestões da IA |
|
|
61
|
+
| `loadtest_start_run` | `{ projectId, scenarioId, baseUrl, connectionId, plan, credentialId?, environment?, confirm }` | gera carga real: recusa sem `confirm: true` e devolve o texto de confirmação (ambiente, baseUrl, pico de VUs/RPS, duração); prefira iniciar pela UI |
|
|
62
|
+
|
|
52
63
|
## Migração de stread-track-mcp
|
|
53
64
|
|
|
54
65
|
O pacote foi renomeado de `stread-track-mcp` (última versão no npm: 0.2.0) para `fg-tracker-mcp` (0.4.0). Nomes antigos continuam funcionando e serão removidos na 1.0.
|
package/dist/client.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* (chave de projeto, header `x-fg-tracker-key`) e `FG_TRACKER_TIMEOUT_MS` — com
|
|
5
5
|
* fallback para os nomes legados `STREAD_TRACK_*` (`stread-track-mcp` ≤ 0.3).
|
|
6
6
|
*/
|
|
7
|
-
/** API local do monorepo. O endereço definitivo da API será `https://
|
|
7
|
+
/** API local do monorepo. O endereço definitivo da API será `https://track-api.fortground.com.br`. */
|
|
8
8
|
export declare const DEFAULT_URL = "http://localhost:4050";
|
|
9
9
|
/** Header da chave de projeto (a API aceita também o legado `x-stread-track-key`). */
|
|
10
10
|
export declare const API_KEY_HEADER = "x-fg-tracker-key";
|
package/dist/client.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* (chave de projeto, header `x-fg-tracker-key`) e `FG_TRACKER_TIMEOUT_MS` — com
|
|
5
5
|
* fallback para os nomes legados `STREAD_TRACK_*` (`stread-track-mcp` ≤ 0.3).
|
|
6
6
|
*/
|
|
7
|
-
/** API local do monorepo. O endereço definitivo da API será `https://
|
|
7
|
+
/** API local do monorepo. O endereço definitivo da API será `https://track-api.fortground.com.br`. */
|
|
8
8
|
export const DEFAULT_URL = 'http://localhost:4050';
|
|
9
9
|
/** Header da chave de projeto (a API aceita também o legado `x-stread-track-key`). */
|
|
10
10
|
export const API_KEY_HEADER = 'x-fg-tracker-key';
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface IacGraphResource {
|
|
2
|
+
logicalId: string;
|
|
3
|
+
type: string;
|
|
4
|
+
/** Porta de entrada pública (Function URL, API, distribuição). */
|
|
5
|
+
entry?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface IacGraphEdge {
|
|
8
|
+
source: string;
|
|
9
|
+
target: string;
|
|
10
|
+
relation: string;
|
|
11
|
+
via: string;
|
|
12
|
+
}
|
|
13
|
+
export interface IacGraphStack {
|
|
14
|
+
stackName: string;
|
|
15
|
+
templateFile: string;
|
|
16
|
+
resources: IacGraphResource[];
|
|
17
|
+
edges: IacGraphEdge[];
|
|
18
|
+
}
|
|
19
|
+
/** Tipos que viram nó no diagrama (o resto é "cola": integrações, permissões, roles, logs…). */
|
|
20
|
+
export declare const NODE_TYPES: Set<string>;
|
|
21
|
+
type Json = unknown;
|
|
22
|
+
type Resources = Record<string, {
|
|
23
|
+
Type: string;
|
|
24
|
+
Properties?: Record<string, Json>;
|
|
25
|
+
}>;
|
|
26
|
+
/** Logical ids referenciados (Ref, Fn::GetAtt, Fn::Sub `${X}` / `${X.Arn}`) dentro de um valor. */
|
|
27
|
+
export declare function refsIn(value: Json, resources: Resources, out?: Set<string>): Set<string>;
|
|
28
|
+
export declare function graphFromTemplate(stackName: string, templateFile: string, template: {
|
|
29
|
+
Resources?: Resources;
|
|
30
|
+
}): IacGraphStack;
|
|
31
|
+
/** Diretórios cdk.out conhecidos a partir do app (cdk.json `output`, padrão `cdk.out`). */
|
|
32
|
+
export declare function findCloudAssemblies(root: string, appDirs: string[]): Promise<string[]>;
|
|
33
|
+
/** Stacks de um cloud assembly (manifest.json → template de cada stack, com o nome real do stack). */
|
|
34
|
+
export declare function graphsFromAssembly(dir: string): Promise<IacGraphStack[]>;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagrama declarado a partir do CloudFormation sintetizado (`cdk synth` → cdk.out, SAM/CFN templates):
|
|
3
|
+
* recursos que viram nós e as ligações entre eles (API → Lambda, fila → Lambda, Lambda → fila/tabela/bucket,
|
|
4
|
+
* regra → alvo, tópico → assinante, CloudFront → origem). Só lê arquivos; não executa o app CDK.
|
|
5
|
+
*/
|
|
6
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
7
|
+
import { basename, join } from 'node:path';
|
|
8
|
+
/** Tipos que viram nó no diagrama (o resto é "cola": integrações, permissões, roles, logs…). */
|
|
9
|
+
export const NODE_TYPES = new Set([
|
|
10
|
+
'AWS::Lambda::Function',
|
|
11
|
+
'AWS::SQS::Queue',
|
|
12
|
+
'AWS::SNS::Topic',
|
|
13
|
+
'AWS::Events::Rule',
|
|
14
|
+
'AWS::Events::EventBus',
|
|
15
|
+
'AWS::DynamoDB::Table',
|
|
16
|
+
'AWS::S3::Bucket',
|
|
17
|
+
'AWS::ApiGateway::RestApi',
|
|
18
|
+
'AWS::ApiGatewayV2::Api',
|
|
19
|
+
'AWS::CloudFront::Distribution',
|
|
20
|
+
'AWS::ElasticLoadBalancingV2::LoadBalancer',
|
|
21
|
+
'AWS::ECS::Service',
|
|
22
|
+
'AWS::StepFunctions::StateMachine',
|
|
23
|
+
'AWS::Kinesis::Stream',
|
|
24
|
+
'AWS::RDS::DBInstance',
|
|
25
|
+
'AWS::RDS::DBCluster',
|
|
26
|
+
'AWS::ElastiCache::CacheCluster',
|
|
27
|
+
'AWS::ElastiCache::ReplicationGroup',
|
|
28
|
+
'AWS::Batch::JobQueue',
|
|
29
|
+
'AWS::Cognito::UserPool',
|
|
30
|
+
]);
|
|
31
|
+
const ENTRY_TYPES = new Set(['AWS::ApiGateway::RestApi', 'AWS::ApiGatewayV2::Api', 'AWS::CloudFront::Distribution', 'AWS::ElasticLoadBalancingV2::LoadBalancer']);
|
|
32
|
+
/** Logical ids referenciados (Ref, Fn::GetAtt, Fn::Sub `${X}` / `${X.Arn}`) dentro de um valor. */
|
|
33
|
+
export function refsIn(value, resources, out = new Set()) {
|
|
34
|
+
if (Array.isArray(value)) {
|
|
35
|
+
for (const item of value)
|
|
36
|
+
refsIn(item, resources, out);
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
if (!value || typeof value !== 'object') {
|
|
40
|
+
if (typeof value === 'string')
|
|
41
|
+
for (const m of value.matchAll(/\$\{([A-Za-z0-9]+)(?:\.[A-Za-z0-9.]+)?\}/g))
|
|
42
|
+
if (resources[m[1]])
|
|
43
|
+
out.add(m[1]);
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
const obj = value;
|
|
47
|
+
if (typeof obj.Ref === 'string' && resources[obj.Ref])
|
|
48
|
+
out.add(obj.Ref);
|
|
49
|
+
const getAtt = obj['Fn::GetAtt'];
|
|
50
|
+
if (Array.isArray(getAtt) && typeof getAtt[0] === 'string' && resources[getAtt[0]])
|
|
51
|
+
out.add(getAtt[0]);
|
|
52
|
+
if (typeof getAtt === 'string') {
|
|
53
|
+
const id = getAtt.split('.')[0];
|
|
54
|
+
if (resources[id])
|
|
55
|
+
out.add(id);
|
|
56
|
+
}
|
|
57
|
+
for (const [key, child] of Object.entries(obj))
|
|
58
|
+
if (key !== 'Ref' && key !== 'Fn::GetAtt')
|
|
59
|
+
refsIn(child, resources, out);
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
function nodeRefs(value, resources) {
|
|
63
|
+
const ids = [...refsIn(value, resources)];
|
|
64
|
+
const out = new Set();
|
|
65
|
+
for (const id of ids) {
|
|
66
|
+
const type = resources[id].Type;
|
|
67
|
+
if (NODE_TYPES.has(type))
|
|
68
|
+
out.add(id);
|
|
69
|
+
// Alias/versão de Lambda apontam para a função.
|
|
70
|
+
else if (type === 'AWS::Lambda::Alias' || type === 'AWS::Lambda::Version')
|
|
71
|
+
for (const fn of nodeRefs(resources[id].Properties?.FunctionName, resources))
|
|
72
|
+
out.add(fn);
|
|
73
|
+
}
|
|
74
|
+
return [...out];
|
|
75
|
+
}
|
|
76
|
+
const ACTION_RELATION = [
|
|
77
|
+
[/^sqs:SendMessage/i, 'sends'],
|
|
78
|
+
[/^sns:Publish/i, 'publishes'],
|
|
79
|
+
[/^events:PutEvents/i, 'publishes'],
|
|
80
|
+
[/^kinesis:Put/i, 'writes'],
|
|
81
|
+
[/^states:StartExecution|^states:StartSyncExecution/i, 'starts'],
|
|
82
|
+
[/^lambda:InvokeFunction/i, 'invokes'],
|
|
83
|
+
[/^dynamodb:(PutItem|UpdateItem|DeleteItem|BatchWriteItem|TransactWriteItems|GetItem|Query|Scan|BatchGetItem|\*)/i, 'reads_writes'],
|
|
84
|
+
[/^s3:(PutObject|GetObject|DeleteObject|\*)/i, 'uses'],
|
|
85
|
+
[/^batch:SubmitJob/i, 'starts'],
|
|
86
|
+
[/^rds-data:|^rds-db:connect/i, 'reads_writes'],
|
|
87
|
+
];
|
|
88
|
+
function relationForActions(actions) {
|
|
89
|
+
for (const [re, relation] of ACTION_RELATION)
|
|
90
|
+
if (actions.some((a) => re.test(a)))
|
|
91
|
+
return relation;
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const TARGET_RELATION = {
|
|
95
|
+
'AWS::SQS::Queue': 'sends',
|
|
96
|
+
'AWS::SNS::Topic': 'publishes',
|
|
97
|
+
'AWS::Events::EventBus': 'publishes',
|
|
98
|
+
'AWS::Kinesis::Stream': 'writes',
|
|
99
|
+
'AWS::StepFunctions::StateMachine': 'starts',
|
|
100
|
+
'AWS::DynamoDB::Table': 'reads_writes',
|
|
101
|
+
'AWS::RDS::DBInstance': 'reads_writes',
|
|
102
|
+
'AWS::RDS::DBCluster': 'reads_writes',
|
|
103
|
+
'AWS::ElastiCache::CacheCluster': 'reads_writes',
|
|
104
|
+
'AWS::ElastiCache::ReplicationGroup': 'reads_writes',
|
|
105
|
+
'AWS::S3::Bucket': 'uses',
|
|
106
|
+
'AWS::Lambda::Function': 'invokes',
|
|
107
|
+
'AWS::Batch::JobQueue': 'starts',
|
|
108
|
+
};
|
|
109
|
+
export function graphFromTemplate(stackName, templateFile, template) {
|
|
110
|
+
const resources = template.Resources ?? {};
|
|
111
|
+
const edges = new Map();
|
|
112
|
+
const add = (source, target, relation, via) => {
|
|
113
|
+
if (!source || !target || source === target)
|
|
114
|
+
return;
|
|
115
|
+
if (!NODE_TYPES.has(resources[source]?.Type ?? '') || !NODE_TYPES.has(resources[target]?.Type ?? ''))
|
|
116
|
+
return;
|
|
117
|
+
edges.set(`${source}|${target}|${relation}`, { source, target, relation, via });
|
|
118
|
+
};
|
|
119
|
+
const entries = new Set();
|
|
120
|
+
// Role → funções/serviços que a assumem (para as policies do IAM).
|
|
121
|
+
const roleUsers = new Map();
|
|
122
|
+
for (const [id, r] of Object.entries(resources)) {
|
|
123
|
+
const p = r.Properties ?? {};
|
|
124
|
+
if (r.Type === 'AWS::Lambda::Function' || r.Type === 'AWS::StepFunctions::StateMachine') {
|
|
125
|
+
for (const role of refsIn(p.Role ?? p.RoleArn, resources))
|
|
126
|
+
roleUsers.set(role, [...(roleUsers.get(role) ?? []), id]);
|
|
127
|
+
}
|
|
128
|
+
if (r.Type === 'AWS::ECS::TaskDefinition') {
|
|
129
|
+
const services = Object.entries(resources).filter(([, s]) => s.Type === 'AWS::ECS::Service' && refsIn(s.Properties?.TaskDefinition, resources).has(id)).map(([sid]) => sid);
|
|
130
|
+
for (const role of refsIn(p.TaskRoleArn, resources))
|
|
131
|
+
roleUsers.set(role, [...(roleUsers.get(role) ?? []), ...services]);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
for (const [id, r] of Object.entries(resources)) {
|
|
135
|
+
const p = r.Properties ?? {};
|
|
136
|
+
switch (r.Type) {
|
|
137
|
+
case 'AWS::Lambda::EventSourceMapping':
|
|
138
|
+
for (const src of nodeRefs(p.EventSourceArn, resources))
|
|
139
|
+
for (const fn of nodeRefs(p.FunctionName, resources))
|
|
140
|
+
add(src, fn, 'triggers', 'EventSourceMapping');
|
|
141
|
+
break;
|
|
142
|
+
case 'AWS::ApiGatewayV2::Integration':
|
|
143
|
+
for (const api of nodeRefs(p.ApiId, resources))
|
|
144
|
+
for (const target of nodeRefs(p.IntegrationUri, resources))
|
|
145
|
+
add(api, target, 'invokes', 'Integration');
|
|
146
|
+
break;
|
|
147
|
+
case 'AWS::ApiGateway::Method':
|
|
148
|
+
for (const api of nodeRefs(p.RestApiId, resources))
|
|
149
|
+
for (const target of nodeRefs(p.Integration?.Uri, resources))
|
|
150
|
+
add(api, target, 'invokes', 'Method');
|
|
151
|
+
break;
|
|
152
|
+
case 'AWS::SNS::Subscription':
|
|
153
|
+
for (const topic of nodeRefs(p.TopicArn, resources))
|
|
154
|
+
for (const target of nodeRefs(p.Endpoint, resources))
|
|
155
|
+
add(topic, target, 'publishes', 'Subscription');
|
|
156
|
+
break;
|
|
157
|
+
case 'AWS::Lambda::Url':
|
|
158
|
+
for (const fn of nodeRefs(p.TargetFunctionArn, resources))
|
|
159
|
+
entries.add(fn);
|
|
160
|
+
break;
|
|
161
|
+
case 'AWS::Events::Rule':
|
|
162
|
+
for (const target of p.Targets ?? [])
|
|
163
|
+
for (const t of nodeRefs(target.Arn, resources))
|
|
164
|
+
add(id, t, 'targets', 'Rule');
|
|
165
|
+
for (const bus of nodeRefs(p.EventBusName, resources))
|
|
166
|
+
add(bus, id, 'routes_to', 'Rule');
|
|
167
|
+
break;
|
|
168
|
+
case 'AWS::SQS::Queue':
|
|
169
|
+
for (const dlq of nodeRefs(p.RedrivePolicy, resources))
|
|
170
|
+
add(id, dlq, 'routes_to', 'RedrivePolicy');
|
|
171
|
+
break;
|
|
172
|
+
case 'AWS::S3::Bucket':
|
|
173
|
+
for (const target of nodeRefs(p.NotificationConfiguration, resources))
|
|
174
|
+
add(id, target, 'triggers', 'Notification');
|
|
175
|
+
break;
|
|
176
|
+
case 'AWS::CloudFront::Distribution':
|
|
177
|
+
for (const origin of nodeRefs(p.DistributionConfig?.Origins, resources))
|
|
178
|
+
add(id, origin, 'origin', 'Origin');
|
|
179
|
+
break;
|
|
180
|
+
case 'AWS::Lambda::Function':
|
|
181
|
+
for (const target of nodeRefs(p.Environment?.Variables, resources))
|
|
182
|
+
add(id, target, TARGET_RELATION[resources[target].Type] ?? 'depends_on', 'Environment');
|
|
183
|
+
for (const dlq of nodeRefs(p.DeadLetterConfig, resources))
|
|
184
|
+
add(id, dlq, 'routes_to', 'DeadLetterConfig');
|
|
185
|
+
break;
|
|
186
|
+
case 'AWS::StepFunctions::StateMachine':
|
|
187
|
+
for (const target of nodeRefs(p.DefinitionString ?? p.Definition ?? p.DefinitionSubstitutions, resources))
|
|
188
|
+
add(id, target, TARGET_RELATION[resources[target].Type] ?? 'invokes', 'Definition');
|
|
189
|
+
break;
|
|
190
|
+
case 'AWS::IAM::Policy': {
|
|
191
|
+
const users = [...refsIn(p.Roles, resources)].flatMap((role) => roleUsers.get(role) ?? []);
|
|
192
|
+
if (users.length === 0)
|
|
193
|
+
break;
|
|
194
|
+
const statements = p.PolicyDocument?.Statement ?? [];
|
|
195
|
+
for (const statement of statements) {
|
|
196
|
+
const s = statement;
|
|
197
|
+
if (s.Effect && s.Effect !== 'Allow')
|
|
198
|
+
continue;
|
|
199
|
+
const actions = (Array.isArray(s.Action) ? s.Action : [s.Action]).filter((a) => typeof a === 'string');
|
|
200
|
+
const relation = relationForActions(actions);
|
|
201
|
+
if (!relation)
|
|
202
|
+
continue;
|
|
203
|
+
for (const target of nodeRefs(s.Resource, resources))
|
|
204
|
+
for (const user of users)
|
|
205
|
+
add(user, target, relation, 'IAM');
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
default:
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const nodeResources = Object.entries(resources)
|
|
214
|
+
.filter(([, r]) => NODE_TYPES.has(r.Type))
|
|
215
|
+
.map(([logicalId, r]) => ({ logicalId, type: r.Type, ...(ENTRY_TYPES.has(r.Type) || entries.has(logicalId) ? { entry: true } : {}) }));
|
|
216
|
+
return { stackName, templateFile, resources: nodeResources, edges: [...edges.values()] };
|
|
217
|
+
}
|
|
218
|
+
/** Diretórios cdk.out conhecidos a partir do app (cdk.json `output`, padrão `cdk.out`). */
|
|
219
|
+
export async function findCloudAssemblies(root, appDirs) {
|
|
220
|
+
const dirs = new Set();
|
|
221
|
+
for (const dir of appDirs) {
|
|
222
|
+
const appDir = join(root, dir);
|
|
223
|
+
let output = 'cdk.out';
|
|
224
|
+
try {
|
|
225
|
+
const cdkJson = JSON.parse(await readFile(join(appDir, 'cdk.json'), 'utf8'));
|
|
226
|
+
if (typeof cdkJson.output === 'string')
|
|
227
|
+
output = cdkJson.output;
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
/* sem cdk.json */
|
|
231
|
+
}
|
|
232
|
+
dirs.add(join(appDir, output));
|
|
233
|
+
}
|
|
234
|
+
dirs.add(join(root, 'cdk.out'));
|
|
235
|
+
const found = [];
|
|
236
|
+
for (const dir of dirs) {
|
|
237
|
+
try {
|
|
238
|
+
await readFile(join(dir, 'manifest.json'), 'utf8');
|
|
239
|
+
found.push(dir);
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
/* não sintetizado */
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return found;
|
|
246
|
+
}
|
|
247
|
+
/** Stacks de um cloud assembly (manifest.json → template de cada stack, com o nome real do stack). */
|
|
248
|
+
export async function graphsFromAssembly(dir) {
|
|
249
|
+
const manifest = JSON.parse(await readFile(join(dir, 'manifest.json'), 'utf8'));
|
|
250
|
+
const out = [];
|
|
251
|
+
for (const [id, artifact] of Object.entries(manifest.artifacts ?? {})) {
|
|
252
|
+
if (artifact.type !== 'aws:cloudformation:stack' || !artifact.properties?.templateFile)
|
|
253
|
+
continue;
|
|
254
|
+
const file = join(dir, artifact.properties.templateFile);
|
|
255
|
+
try {
|
|
256
|
+
const template = JSON.parse(await readFile(file, 'utf8'));
|
|
257
|
+
out.push(graphFromTemplate(artifact.properties.stackName ?? id, file, template));
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
/* template ilegível */
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Nested stacks / assemblies aninhados (stages) ficam em subdiretórios assembly-*.
|
|
264
|
+
for (const entry of await readdir(dir, { withFileTypes: true }).catch(() => [])) {
|
|
265
|
+
if (entry.isDirectory() && basename(entry.name).startsWith('assembly-'))
|
|
266
|
+
out.push(...(await graphsFromAssembly(join(dir, entry.name))));
|
|
267
|
+
}
|
|
268
|
+
return out;
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=cdk-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdk-graph.js","sourceRoot":"","sources":["../../src/infra/cdk-graph.ts"],"names":[],"mappings":"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"}
|
package/dist/infra/tools.js
CHANGED
|
@@ -10,6 +10,7 @@ import { TrackApiError } from '../client.js';
|
|
|
10
10
|
import { compact, guard, json, text } from '../format.js';
|
|
11
11
|
import { ENVIRONMENT_LABEL, describeAwsError, detectEnvironments, detectRegionsInUse, discoverAws, readStackOutputs, serviceLabel } from './aws.js';
|
|
12
12
|
import { DOC_PATH, GUARD_PATH, GUARD_SCRIPT, HANDOVER_DIR, HANDOVER_README, LOCK_PATH, PATCH_PATH, buildHandoverEdits, formatChanges, handoverDoc, handoverReadme, lockFile, writeHandoverFiles, } from './handover.js';
|
|
13
|
+
import { findCloudAssemblies, graphsFromAssembly } from './cdk-graph.js';
|
|
13
14
|
import { analyzeIac, formatIac } from './iac.js';
|
|
14
15
|
import { buildInstrumentPlan } from './instrument.js';
|
|
15
16
|
const projectIdSchema = z.string().uuid().describe('ID (uuid) do projeto — veja track_list_projects');
|
|
@@ -146,7 +147,16 @@ export function registerInfraTools(server, client, version) {
|
|
|
146
147
|
];
|
|
147
148
|
let deployCommand = null;
|
|
148
149
|
if (tpl.body !== undefined && tpl.body !== null) {
|
|
149
|
-
|
|
150
|
+
// Compacto: o `--template-file` do AWS CLI aceita até 51.200 bytes e o template (com o runner de carga inline) passa disso indentado.
|
|
151
|
+
const compactJson = (raw) => {
|
|
152
|
+
try {
|
|
153
|
+
return JSON.stringify(JSON.parse(raw));
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return raw; // YAML ou texto não-JSON: grava como veio
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const body = typeof tpl.body === 'string' ? compactJson(tpl.body) : JSON.stringify(tpl.body);
|
|
150
160
|
const suffix = environment ?? (connectionId ? connectionId.slice(0, 8) : 'aws');
|
|
151
161
|
const file = join(process.cwd(), `fg-tracker-connection-${suffix}.json`);
|
|
152
162
|
await writeFile(file, body.endsWith('\n') ? body : `${body}\n`, 'utf8');
|
|
@@ -330,6 +340,43 @@ export function registerInfraTools(server, client, version) {
|
|
|
330
340
|
inputSchema: { path: z.string().optional().describe('Caminho do repositório (default: diretório atual)') },
|
|
331
341
|
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
332
342
|
}, async ({ path }) => guard(async () => text(formatIac(await analyzeIac(await resolveRoot(path))))));
|
|
343
|
+
/* 4b ---------------- diagrama do IaC ---------------- */
|
|
344
|
+
server.registerTool('infra_publish_iac', {
|
|
345
|
+
title: 'Montar o diagrama a partir do CDK',
|
|
346
|
+
description: 'Lê o CloudFormation sintetizado do app CDK (manifest.json + *.template.json do `cdk.out`, inclusive `output` customizado no cdk.json) e envia ao FG Tracker os serviços e o fluxo entre eles: API Gateway → Lambda, SQS → Lambda (event source), Lambda → SQS/SNS/DynamoDB/S3 (variáveis de ambiente e grants do IAM), EventBridge → alvo, SNS → assinante, CloudFront → origem. POST .../infra/iac. O diagrama passa a mostrar esse fluxo e o escopo do projeto vira esses stacks; estado, saúde, réplicas e tráfego vêm da AWS e do SDK. Não executa o app: se não houver cdk.out, peça ao usuário para rodar `npx cdk synth` (ou rode com aprovação) e chame de novo.',
|
|
347
|
+
inputSchema: {
|
|
348
|
+
projectId: projectIdSchema,
|
|
349
|
+
path: z.string().optional().describe('Caminho do repositório (default: diretório atual)'),
|
|
350
|
+
stacks: z.array(z.string().min(1)).max(100).optional().describe('Só estes stacks (default: todos os do cdk.out)'),
|
|
351
|
+
},
|
|
352
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
353
|
+
}, async ({ projectId, path, stacks }) => guard(async () => {
|
|
354
|
+
const root = await resolveRoot(path);
|
|
355
|
+
const analysis = await analyzeIac(root);
|
|
356
|
+
const assemblies = await findCloudAssemblies(root, analysis.cdkApps.map((app) => app.dir));
|
|
357
|
+
if (assemblies.length === 0) {
|
|
358
|
+
return text([
|
|
359
|
+
'Nenhum `cdk.out` encontrado (manifest.json).',
|
|
360
|
+
analysis.cdkApps.length
|
|
361
|
+
? `Rode \`npx cdk synth\` em ${analysis.cdkApps.map((app) => `\`${app.dir || '.'}\``).join(', ')} (peça aprovação ao usuário: executa o app CDK localmente, sem implantar nada) e chame infra_publish_iac de novo.`
|
|
362
|
+
: 'O repositório não tem app CDK reconhecido (cdk.json).',
|
|
363
|
+
].join('\n'));
|
|
364
|
+
}
|
|
365
|
+
const graphs = (await Promise.all(assemblies.map((dir) => graphsFromAssembly(dir)))).flat().filter((g) => !g.stackName.startsWith('fg-tracker-') && (!stacks?.length || stacks.includes(g.stackName)));
|
|
366
|
+
const unique = new Map(graphs.map((g) => [g.stackName, g]));
|
|
367
|
+
if (unique.size === 0)
|
|
368
|
+
return text('Nenhum stack no cdk.out corresponde ao filtro.');
|
|
369
|
+
const payload = [...unique.values()].map((g) => ({ stackName: g.stackName, resources: g.resources.slice(0, 2000), edges: g.edges.slice(0, 5000) }));
|
|
370
|
+
const result = await client.post(`${base(projectId)}/iac`, { stacks: payload }).catch(wrapInfra);
|
|
371
|
+
const lines = [
|
|
372
|
+
`Diagrama do IaC enviado: ${result.stacks} stack(s), ${result.resources} serviço(s), ${result.edges} ligação(ões); ${result.matchedEdges} já casadas com recursos descobertos na AWS.`,
|
|
373
|
+
...payload.map((g) => `- ${g.stackName}: ${g.resources.length} serviços, ${g.edges.length} ligações (${[...new Set(g.edges.map((e) => e.relation))].join(', ') || 'sem ligações'})`),
|
|
374
|
+
result.matchedEdges < result.edges
|
|
375
|
+
? 'As ligações restantes aparecem quando a descoberta pela role encontrar os recursos (ela roda em até 1 minuto; stacks ainda não implantados ficam de fora).'
|
|
376
|
+
: '',
|
|
377
|
+
].filter(Boolean);
|
|
378
|
+
return text(lines.join('\n'));
|
|
379
|
+
}));
|
|
333
380
|
/* 5 ---------------- atribuir recursos ---------------- */
|
|
334
381
|
server.registerTool('infra_assign_resources', {
|
|
335
382
|
title: 'Confirmar recursos do projeto',
|
|
@@ -687,7 +734,7 @@ export function connectInfrastructurePrompt(args, endpoint) {
|
|
|
687
734
|
b. Mostre o comando \`aws cloudformation deploy ... --profile <perfil> --region <região>\` e **peça confirmação**; com o "sim", rode-o e espere terminar.
|
|
688
735
|
c. \`infra_verify_connection { projectId, connectionId, profile }\` — se falhar, explique o status e corrija antes de seguir.
|
|
689
736
|
d. \`infra_discover { projectId, profile, regions }\` com as regiões da conexão.
|
|
690
|
-
4. **Analisar o IaC** — \`infra_analyze_iac { path }\`: apps CDK, stacks, assets, CI. Relacione cada stack do repositório aos stacks descobertos (por ambiente).
|
|
737
|
+
4. **Analisar o IaC e montar o diagrama** — \`infra_analyze_iac { path }\`: apps CDK, stacks, assets, CI. Relacione cada stack do repositório aos stacks descobertos (por ambiente). Em seguida \`infra_publish_iac { projectId, path }\`: o fluxo entre os serviços (API → Lambda → fila → worker, Lambda → tabela/bucket) vem do CloudFormation sintetizado; sem \`cdk.out\`, peça aprovação para rodar \`npx cdk synth\` (não implanta nada) e repita.
|
|
691
738
|
5. **Confirmar recursos** — proponha o que pertence ao projeto e o que é compartilhado (VPC, bancos de outros times, buckets comuns). **Peça confirmação** e só então \`infra_assign_resources { include, exclude }\`.
|
|
692
739
|
6. **Instrumentar** — \`infra_instrument { projectId, path }\`; aplique os patches de código (SDK, clientes AWS, pools, reporter ECS, camada nas Lambdas, \`wrapLambda\`) no repositório, em edits mínimos. Não implante.
|
|
693
740
|
7. **Validar** — \`infra_validate { projectId }\` e \`infra_get_diagram\`; resuma as notas por pilar e as 3–5 recomendações mais importantes.
|