fg-tracker-mcp 0.11.0 → 0.12.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 CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog — fg-tracker-mcp
2
2
 
3
+ ## 0.12.0
4
+
5
+ Tools por permissão do token pessoal e escrita pelo MCP (PR B da proposta de tokens com permissões; a API e o painel vieram no PR #35). Requer a API com permissões por recurso (`credential.scopes` em `GET /v1/auth/me`, `API_KEY_PROJECT_MISMATCH`); nenhuma rota nova na API.
6
+
7
+ - **Tools por permissão.** Com token `fgt_…`, o MCP lê `credential.scopes` ao iniciar (até 5 s) e só registra as tools que o token cobre (mapa em `src/permissions.ts`); token restrito a projetos não registra `tracker_create_project`. Sessão registra todas. Se a leitura falhar (API fora do ar, token revogado, API anterior às permissões), só as de leitura são registradas: falha de introspecção nunca libera escrita. `FG_TRACKER_READ_ONLY=1` continua valendo por cima. A API segue decidindo cada chamada.
8
+ - **`tracker_status`**: diz qual credencial governa a escrita (sem valores), as permissões lidas no início × as de agora, as tools ocultas e o motivo, e pede para reiniciar o cliente MCP quando as permissões ou os projetos do token mudaram (a lista de tools só muda no reinício). `credential.scopes`, `permissions` e `writeCredential` no `structuredContent`.
9
+ - **Sem fallback para a chave.** `loadtest_create_scenario` e `infra_discover` deixam de repetir a escrita com `FG_TRACKER_API_KEY` quando o token é recusado (401, 403 e, no discover, 404): com `FG_TRACKER_TOKEN`, a recusa é final. A chave só vale sem token, só nessas duas tools e só no projeto dela (o `projectId` vai no corpo; 400 `API_KEY_PROJECT_MISMATCH` vira "a chave é de outro projeto, nada foi gravado"; uma API anterior que grave no projeto da chave é detectada pelo `projectId` da resposta do roteiro). Cada requisição leva uma credencial só: a chave não viaja mais nas chamadas do Bearer.
10
+ - **403 claros** pelo `code` da API: permissão que falta (`falta a permissão "Monitores: excluir" neste token`), operação só do painel, papel (`seu papel neste projeto é viewer`), projeto fora do token, token restrito criando projeto e falta de associação. Mensagens de erro mascaram `stk_…`/`fgt_…`.
11
+ - **Tools novas** (sem alias `track_*`):
12
+ - issues: `tracker_update_issue` (resolver, "resolver no próximo release", ignorar até data ou até escalar, reabrir, atribuir com o membro conferido antes, priorizar) e `tracker_list_members` (sem telefone);
13
+ - monitores: `tracker_create_monitor`, `tracker_update_monitor` (pausar, agenda, ambiente do monitor antigo antes do 1º check-in), `tracker_run_monitor`, `tracker_delete_monitor`;
14
+ - alertas: `tracker_list_alert_rules` (com a severidade mínima por canal), `tracker_create_alert_rule`, `tracker_update_alert_rule` (config mesclada com a gravada), `tracker_delete_alert_rule`, `tracker_ack_alert_event`, `tracker_update_alert_delivery`;
15
+ - projeto: `tracker_update_project` (limiares, repositório, regras de dono com `memberId` conferido — `addOwnershipRules`/`removeOwnershipRules` mesclam com a lista completa da API, `ownershipRules` substitui —, autoatribuição; `tracker_update_allowed_origins` continua) e `tracker_delete_project`;
16
+ - `tracker_delete_sourcemaps`; `loadtest_update_scenario`, `loadtest_delete_scenario`, `loadtest_stop_run`; `infra_update_finding`, `infra_delete_connection`.
17
+ - **Exclusões**: `destructiveHint: true` e `confirm` obrigatório com o nome ou slug do recurso (texto, nunca booleano), conferido contra o recurso lido na API antes do DELETE; a descrição manda perguntar ao usuário antes. O cliente HTTP recusa caminhos com segmento `.` ou `..` (o `fetch` os normalizaria para outra rota: `…/sourcemaps/..` viraria a exclusão do projeto), e `tracker_delete_sourcemaps` recusa essas releases e apaga também releases fora das 100 que a API lista.
18
+ - `infra_validate` passa a mostrar o id de cada achado aberto (texto e `findings`) e `infra_get_diagram` o de cada conexão (texto e `connections`), para `infra_update_finding` e `infra_delete_connection`.
19
+ - `tracker_list_alert_rules` respeita `FG_TRACKER_MAX_ITEMS` (`total`, `returned`, `truncated`).
20
+ - `tracker_list_environments` passa a declarar também `releases:read` (lê `/release-environments`).
21
+ - Documentação: tokens `fgt_` com as permissões necessárias, modelos do painel, precedência de credenciais, edição e reinício; a instalação recomendada deixa de pôr `FG_TRACKER_READ_ONLY=1` por padrão (continua como opção de só leitura).
22
+ - `tools/list` (sessão): 87 tools e ~168 KB no padrão, 66 e ~139 KB sem aliases; token Agente MCP sem aliases, 47 e ~108 KB; Somente leitura sem aliases, 34 e ~84 KB.
23
+ - Testes: registro por permissão, sessão, `FG_TRACKER_READ_ONLY`, introspecção que falha, suficiência de cada tool contra o mapa de rotas da API, permissão reduzida depois de iniciar, papel viewer, projetos restritos, exclusões com `confirm` errado e certo, nenhuma rota da chave com token recusado (401, 403, 404) e modo só com a chave; E2E com a API real em `apps/api/test/mcp-permissions.cases.cjs`.
24
+
3
25
  ## 0.11.0
4
26
 
5
27
  Diagnóstico sem painel (revisão de 15/10/2026, T3). Todas as ferramentas novas usam rotas de leitura com `@ReadScope()` (funcionam com token pessoal `fgt_…`). As de janela absoluta, ordenação e comparação dependem da API desta mesma entrega (CONTRATO §4 "Janelas absolutas" e "Comparação", §18); com uma API anterior elas avisam (`windowIgnored`, `filtersApplied: false`, "API ignorou sort") ou explicam o caminho alternativo, e as demais continuam funcionando.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # fg-tracker-mcp
2
2
 
3
- Servidor [MCP](https://modelcontextprotocol.io) (stdio) do FG Tracker para agentes de código (Claude Code, Cursor, Windsurf, Claude Desktop): projetos, métricas, traces, issues com commits suspeitos, releases, monitores, provedores externos, logs, slow queries, eventos de alerta e guia de instrumentação, com respostas estruturadas (`structuredContent`) e evidência verificável para diagnosticar sem o painel. Documentação completa: `docs/mcp.md` no repositório.
3
+ Servidor [MCP](https://modelcontextprotocol.io) (stdio) do FG Tracker para agentes de código (Claude Code, Cursor, Windsurf, Claude Desktop): projetos, métricas, traces, issues com commits suspeitos, releases, monitores, provedores externos, logs, slow queries, eventos de alerta e guia de instrumentação, com respostas estruturadas (`structuredContent`) e evidência verificável para diagnosticar sem o painel — e, com as permissões do token, triagem de issues, monitores, regras de alerta e configurações do projeto. Documentação completa: `docs/mcp.md` no repositório.
4
4
 
5
5
  ## Instalação
6
6
 
@@ -9,8 +9,8 @@ Claude Code:
9
9
  ```bash
10
10
  claude mcp add fg-tracker \
11
11
  -e FG_TRACKER_URL=http://localhost:4050 \
12
- -e FG_TRACKER_TOKEN=fgt_<seu_token_de_leitura> \
13
- -e FG_TRACKER_READ_ONLY=1 \
12
+ -e FG_TRACKER_TOKEN=fgt_<seu_token> \
13
+ -e FG_TRACKER_LEGACY_TOOL_NAMES=0 \
14
14
  -- npx -y fg-tracker-mcp
15
15
  ```
16
16
 
@@ -24,15 +24,15 @@ Cursor / Windsurf / Claude Desktop (JSON):
24
24
  "args": ["-y", "fg-tracker-mcp"],
25
25
  "env": {
26
26
  "FG_TRACKER_URL": "http://localhost:4050",
27
- "FG_TRACKER_TOKEN": "fgt_<seu_token_de_leitura>",
28
- "FG_TRACKER_READ_ONLY": "1"
27
+ "FG_TRACKER_TOKEN": "fgt_<seu_token>",
28
+ "FG_TRACKER_LEGACY_TOOL_NAMES": "0"
29
29
  }
30
30
  }
31
31
  }
32
32
  }
33
33
  ```
34
34
 
35
- Gere o token em **Conectar → Usar MCP → Gerar token de leitura para o MCP** (ou em **Conta → Tokens de acesso**). É a configuração recomendada: o token só lê, e `FG_TRACKER_READ_ONLY=1` esconde do agente as tools que escrevem. Para o agente criar projetos, registrar releases, mexer em infraestrutura ou iniciar testes de carga, use a configuração com a sessão (sem `FG_TRACKER_READ_ONLY`); `tracker_status` avisa quando a credencial é uma sessão. Detalhes em `docs/mcp.md` → Token de leitura.
35
+ Gere o token em **Conectar → Usar MCP → Gerar token para o MCP** (ou em **Conta → Tokens de acesso**) e marque só o que o agente precisa: o modelo **Agente MCP** lê tudo e cria e edita projetos, issues, releases, monitores e alertas, sem excluir; **Somente leitura** serve para diagnóstico; exclusões, infraestrutura AWS e testes de carga entram pela matriz (ou **Acesso total**). O MCP lê as permissões do token ao iniciar (`GET /v1/auth/me`) e só registra as tools que elas cobrem; a API confere cada chamada, dentro do seu papel em cada projeto. **Editou as permissões? Reinicie o cliente MCP** para a lista de tools mudar (`tracker_status` avisa). Para nunca expor escrita, acrescente `FG_TRACKER_READ_ONLY=1`. Detalhes em `docs/mcp.md` → Token pessoal.
36
36
 
37
37
  Em produção, `FG_TRACKER_URL` é a URL da API mostrada no painel em **Conectar**. O endereço de produção da API é `https://tracker-api.fortground.com.br` (o antigo `track-api.fortground.com.br` continua respondendo).
38
38
 
@@ -41,11 +41,11 @@ Em produção, `FG_TRACKER_URL` é a URL da API mostrada no painel em **Conectar
41
41
  | variável | default | uso |
42
42
  |---|---|---|
43
43
  | `FG_TRACKER_URL` | `http://localhost:4050` | URL base da API |
44
- | `FG_TRACKER_TOKEN` | — | `Authorization: Bearer`: token pessoal de leitura `fgt_…` (painel → Conta → Tokens de acesso; não cai com logout) ou token de sessão, necessário só para as tools que escrevem — projetos, métricas, traces, issues, logs |
45
- | `FG_TRACKER_API_KEY` | — | chave de projeto (`x-fg-tracker-key`) — opcional, só ingestão |
44
+ | `FG_TRACKER_TOKEN` | — | `Authorization: Bearer`: token pessoal `fgt_…` com as permissões necessárias (painel → Conta → Tokens de acesso; não cai com logout) ou token de sessão — projetos, métricas, traces, issues, logs e toda escrita |
45
+ | `FG_TRACKER_API_KEY` | — | chave de projeto (`x-fg-tracker-key`) — opcional; só sem `FG_TRACKER_TOKEN`, `loadtest_create_scenario` e `infra_discover` gravam por ela, no projeto dela. Com token, nunca é usada |
46
46
  | `FG_TRACKER_TIMEOUT_MS` | `15000` | timeout das chamadas HTTP |
47
47
  | `FG_TRACKER_MAX_ITEMS` | `200` | teto de itens da lista principal de cada tool (1 a 1000) |
48
- | `FG_TRACKER_READ_ONLY` | desligado | `1`: só as tools de leitura (`readOnlyHint: true`) são registradas |
48
+ | `FG_TRACKER_READ_ONLY` | desligado | `1`: só as tools de leitura (`readOnlyHint: true`) são registradas, mesmo com um token que escreve |
49
49
  | `FG_TRACKER_WEB_URL` | derivada da API | URL do painel nos links das respostas (`tracker-api.*` → `tracker.*`) |
50
50
  | `FG_TRACKER_LEGACY_TOOL_NAMES` | ligado | `0` desliga os aliases obsoletos `track_*` |
51
51
 
@@ -53,6 +53,8 @@ Os nomes antigos `STREAD_TRACK_*` continuam lidos quando o nome novo está ausen
53
53
 
54
54
  ## Tools, prompt e resource
55
55
 
56
+ Escrita (0.12): `tracker_update_issue` e `tracker_list_members` (triagem: resolver, "resolver no próximo release", ignorar, atribuir, priorizar), `tracker_create_monitor`, `tracker_update_monitor`, `tracker_run_monitor`, `tracker_delete_monitor`, `tracker_list_alert_rules`, `tracker_create_alert_rule`, `tracker_update_alert_rule`, `tracker_delete_alert_rule`, `tracker_ack_alert_event`, `tracker_update_alert_delivery`, `tracker_update_project`, `tracker_delete_project`, `tracker_delete_sourcemaps`, `loadtest_update_scenario`, `loadtest_delete_scenario`, `loadtest_stop_run`, `infra_update_finding` e `infra_delete_connection`. Toda exclusão tem `destructiveHint: true` e exige `confirm` com o nome ou slug do recurso, conferido antes do DELETE. Com `FG_TRACKER_TOKEN`, a recusa do token é final (sem nova tentativa pela chave `stk_`). Detalhes em `docs/mcp.md` → Escrita e exclusões.
57
+
56
58
  Diagnóstico (0.11): toda tool de leitura tem `outputSchema` e devolve `structuredContent` (o texto continua igual); as de análise trazem `evidence[]` (`traceId`, `spanId?`, métrica, valor e janela) apontando para traces existentes, mais links para o painel e para os recursos `fg-tracker://trace/{traceId}` e `fg-tracker://issue/{issueId}`. Tools novas: `tracker_compare` (duas janelas ou releases: onde o tempo cresceu, com cobertura de spans brutos), `tracker_get_endpoint` (detalhe e traces mais lentos de uma rota), `tracker_list_queries` (slow queries com o trace e o span da execução mais lenta), `tracker_log_stats` (histograma e facetas de logs), `tracker_list_alert_events` (histórico de alertas, destinatários mascarados) e `tracker_list_environments`; métricas, traces e logs aceitam `from`/`to` ISO; `tracker_list_traces` ordena por duração e filtra por span filho (`hasSpan`); `tracker_get_monitor` mostra o atraso de cada execução. Prompts das jornadas: `investigar-regressao-p95`, `investigar-query-lenta`, `investigar-job-atrasado`, `investigar-erro-distribuido` e `confirmar-correcao`. Detalhes em `docs/mcp.md` → Saída estruturada e Jornadas de diagnóstico.
57
59
 
58
60
  Tools `tracker_*` (até a 0.9, `track_*`), prompt `instrument-project` e resource `fg-tracker://docs/quickstart`. Os nomes `track_*` continuam registrados como aliases obsoletos (a versão seguinte os desliga por padrão e a 1.0 os remove); `FG_TRACKER_LEGACY_TOOL_NAMES=0` deixa só os nomes novos.
@@ -68,11 +70,14 @@ Simulação de ambiente (0.8.0): prompt `create-load-test` e tools `loadtest_*`
68
70
  | tool | entrada | o que faz |
69
71
  |---|---|---|
70
72
  | `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 |
71
- | `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 |
73
+ | `loadtest_create_scenario` | `{ projectId, scenario, description? }` | valida o roteiro (§28.2, erros com caminho do campo) e grava (`POST /v1/projects/:id/loadtest/scenarios` com o token, cuja recusa é final; `POST /v1/loadtest/scenarios` só quando não há `FG_TRACKER_TOKEN`, no projeto da chave); resumo com passos, variáveis extraídas, checks e avisos de efeitos externos |
74
+ | `loadtest_update_scenario` | `{ projectId, scenarioId, name?, description?, scenario? }` | atualiza o roteiro (documento validado antes do `PUT`) |
75
+ | `loadtest_delete_scenario` | `{ projectId, scenarioId, confirm }` | exclui o roteiro; `confirm` = nome |
72
76
  | `loadtest_list_scenarios` | `{ projectId }` | roteiros do projeto |
73
77
  | `loadtest_suggest_plan` | `{ preset, vus?, targetRps?, duration? }` | puro: plano k6 (§28.3) para smoke/load/stress/spike/soak/breakpoint |
74
78
  | `loadtest_get_run` | `{ projectId, runId, generateAdvice? }` | resumo do run: latências, erros, checks, thresholds, por passo e sugestões da IA |
75
79
  | `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 |
80
+ | `loadtest_stop_run` | `{ projectId, runId }` | para a simulação (na fila, aborta; rodando, os executores param no próximo relatório) |
76
81
 
77
82
  ## Migração de stread-track-mcp
78
83
 
package/dist/cli.js CHANGED
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Entrada do binário `fg-tracker-mcp` (alias obsoleto: `stread-track-mcp`): sobe o servidor MCP em stdio.
4
- * Env: FG_TRACKER_URL (default http://localhost:4050), FG_TRACKER_TOKEN (fgt_… ou sessão), FG_TRACKER_API_KEY,
4
+ * Env: FG_TRACKER_URL (default http://localhost:4050), FG_TRACKER_TOKEN (fgt_… com permissões, ou sessão), FG_TRACKER_API_KEY,
5
5
  * FG_TRACKER_TIMEOUT_MS, FG_TRACKER_READ_ONLY, FG_TRACKER_WEB_URL — os nomes legados STREAD_TRACK_*
6
6
  * continuam valendo como fallback.
7
7
  */
8
8
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
9
  import { configFromEnv, TrackClient } from './client.js';
10
+ import { resolveToolAccess } from './permissions.js';
10
11
  import { createServer, readOnlyFromEnv, SERVER_NAME, SERVER_VERSION } from './server.js';
11
12
  const argv = process.argv.slice(2);
12
13
  if (argv.includes('--help') || argv.includes('-h')) {
@@ -18,16 +19,18 @@ if (argv.includes('--help') || argv.includes('-h')) {
18
19
  '',
19
20
  'Variáveis de ambiente:',
20
21
  ' FG_TRACKER_URL URL da API (default http://localhost:4050)',
21
- ' FG_TRACKER_TOKEN token pessoal de leitura fgt_… (recomendado: painel → Conta → Tokens de acesso) ou de sessão (Authorization: Bearer)',
22
- ' FG_TRACKER_API_KEY chave de projeto (x-fg-tracker-key) — opcional, só ingestão',
22
+ ' FG_TRACKER_TOKEN token pessoal fgt_… (painel → Conta → Tokens de acesso) com as permissões necessárias, ou sessão (Authorization: Bearer).',
23
+ ' Com token pessoal, só as ferramentas que as permissões dele cobrem são registradas (lidas ao iniciar; reinicie ao editar o token)',
24
+ ' FG_TRACKER_API_KEY chave de projeto (x-fg-tracker-key) — opcional; sem FG_TRACKER_TOKEN, grava roteiros e snapshots só no projeto dela',
23
25
  ' FG_TRACKER_TIMEOUT_MS timeout das chamadas HTTP (default 15000)',
24
- ' FG_TRACKER_READ_ONLY=1 só registra ferramentas de leitura (esconde criar projeto, releases, infraestrutura, testes de carga)',
26
+ ' FG_TRACKER_READ_ONLY=1 só registra ferramentas de leitura (esconde toda ferramenta que cria, edita ou exclui), mesmo com permissões de escrita',
25
27
  ' FG_TRACKER_WEB_URL URL do painel para os links (default: derivada de FG_TRACKER_URL, ex. tracker-api.* → tracker.*)',
26
28
  ' FG_TRACKER_LEGACY_TOOL_NAMES=0 não registra os aliases obsoletos track_* das ferramentas tracker_*',
27
29
  ' (os nomes antigos STREAD_TRACK_* ainda são lidos como fallback; serão removidos na 1.0)',
28
30
  '',
29
31
  'Instalação no Claude Code:',
30
- ' claude mcp add fg-tracker -e FG_TRACKER_URL=http://localhost:4050 -e FG_TRACKER_TOKEN=fgt_... -e FG_TRACKER_READ_ONLY=1 -- npx -y fg-tracker-mcp',
32
+ ' claude mcp add fg-tracker -e FG_TRACKER_URL=http://localhost:4050 -e FG_TRACKER_TOKEN=fgt_... -- npx -y fg-tracker-mcp',
33
+ ' (só diagnóstico, sem nenhuma escrita: acrescente -e FG_TRACKER_READ_ONLY=1)',
31
34
  '',
32
35
  ].join('\n'));
33
36
  process.exit(0);
@@ -38,14 +41,22 @@ if (argv.includes('--version') || argv.includes('-v')) {
38
41
  }
39
42
  const config = configFromEnv();
40
43
  const client = new TrackClient(config);
41
- const server = createServer({ client });
44
+ // Permissões do token antes de registrar as ferramentas (GET /v1/auth/me, até 5 s). Falha =
45
+ // só as de leitura; a API continua decidindo cada chamada.
46
+ const access = await resolveToolAccess(client);
47
+ const server = createServer({ client, access });
42
48
  // stdout é o canal JSON-RPC: qualquer diagnóstico vai para stderr.
43
49
  const invoked = process.argv[1]?.split(/[\\/]/).pop() ?? '';
44
50
  if (invoked.startsWith('stread-track-')) {
45
51
  console.error(`[fg-tracker-mcp] "${invoked}" está obsoleto: use "fg-tracker-mcp" (o alias será removido na 1.0).`);
46
52
  }
47
- const credential = { access_token: 'pessoal (leitura)', session: 'de sessão (lê e escreve; prefira um fgt_ de leitura)', none: 'ausente' }[client.credentialKind];
48
- console.error(`[fg-tracker-mcp] API ${config.baseUrl} · token ${credential} · apiKey ${config.apiKey ? 'ok' : 'ausente'}${readOnlyFromEnv() ? ' · somente leitura' : ''}`);
53
+ const credential = {
54
+ token: `pessoal (${access.scopes?.length ?? 0} permissões)`,
55
+ 'token-unverified': `pessoal (permissões não lidas: só leitura${access.error ? `; ${access.error}` : ''})`,
56
+ session: 'de sessão (faz tudo o que você faz no painel; prefira um fgt_ com só o necessário)',
57
+ none: 'ausente',
58
+ }[access.mode];
59
+ console.error(`[fg-tracker-mcp] API ${config.baseUrl} · token ${credential} · apiKey ${config.apiKey ? (client.hasToken ? 'definida (não usada: o token decide)' : 'ok') : 'ausente'}${readOnlyFromEnv() ? ' · somente leitura' : ''}`);
49
60
  const transport = new StdioServerTransport();
50
61
  await server.connect(transport);
51
62
  const shutdown = () => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEzF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB;QACE,GAAG,WAAW,QAAQ,cAAc,uCAAuC;QAC3E,EAAE;QACF,uFAAuF;QACvF,+BAA+B;QAC/B,EAAE;QACF,wBAAwB;QACxB,qEAAqE;QACrE,+IAA+I;QAC/I,sFAAsF;QACtF,oEAAoE;QACpE,gIAAgI;QAChI,2HAA2H;QAC3H,uGAAuG;QACvG,2FAA2F;QAC3F,EAAE;QACF,4BAA4B;QAC5B,oJAAoJ;QACpJ,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AACD,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,cAAc,IAAI,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;AAC/B,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;AACvC,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAExC,mEAAmE;AACnE,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;AAC5D,IAAI,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;IACxC,OAAO,CAAC,KAAK,CAAC,qBAAqB,OAAO,uEAAuE,CAAC,CAAC;AACrH,CAAC;AACD,MAAM,UAAU,GAAG,EAAE,YAAY,EAAE,mBAAmB,EAAE,OAAO,EAAE,sDAAsD,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AAClK,OAAO,CAAC,KAAK,CAAC,wBAAwB,MAAM,CAAC,OAAO,YAAY,UAAU,aAAa,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,GAAG,eAAe,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAE3K,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC,MAAM,QAAQ,GAAG,GAAS,EAAE;IAC1B,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC,CAAC;AACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  /**
2
2
  * Cliente HTTP mínimo para a API do FG Tracker (docs/CONTRATO.md §4, §8, §11).
3
- * Lê `FG_TRACKER_URL`, `FG_TRACKER_TOKEN` (Bearer: token pessoal de leitura `fgt_…`
4
- * ou token de sessão), `FG_TRACKER_API_KEY` (chave de projeto, header
3
+ * Lê `FG_TRACKER_URL`, `FG_TRACKER_TOKEN` (Bearer: token pessoal `fgt_…` com as permissões
4
+ * marcadas no painel, ou token de sessão), `FG_TRACKER_API_KEY` (chave de projeto, header
5
5
  * `x-fg-tracker-key`), `FG_TRACKER_TIMEOUT_MS` e `FG_TRACKER_WEB_URL` — com
6
6
  * fallback para os nomes legados `STREAD_TRACK_*` (`stread-track-mcp` ≤ 0.3).
7
+ *
8
+ * Cada requisição leva uma credencial só: o Bearer nas rotas de usuário (o padrão) e a chave
9
+ * apenas nas rotas da chave (`auth: 'key'`), que as ferramentas só usam sem FG_TRACKER_TOKEN.
7
10
  */
8
11
  /** API local do monorepo. Em produção a API é `https://tracker-api.fortground.com.br`. */
9
12
  export declare const DEFAULT_URL = "http://localhost:4050";
@@ -23,11 +26,24 @@ export interface TrackClientConfig {
23
26
  webUrl?: string;
24
27
  }
25
28
  export type QueryValue = string | number | boolean | undefined | null;
29
+ /** Campos de uma recusa 403 da API (CONTRATO.md §8.1, "Erros"). */
30
+ export interface ApiErrorDetails {
31
+ requiredScope?: string | null;
32
+ requiredPermission?: string | null;
33
+ sessionOnly?: boolean;
34
+ role?: string;
35
+ requiredRoles?: string[];
36
+ }
26
37
  export declare class TrackApiError extends Error {
27
38
  readonly status: number | undefined;
28
39
  readonly path: string;
29
40
  readonly hint?: string | undefined;
30
- constructor(message: string, status: number | undefined, path: string, hint?: string | undefined);
41
+ /** `code` do corpo de erro da API (ex.: TOKEN_SCOPE_INSUFFICIENT), quando houver. */
42
+ readonly code?: string | undefined;
43
+ readonly details: ApiErrorDetails;
44
+ constructor(message: string, status: number | undefined, path: string, hint?: string | undefined,
45
+ /** `code` do corpo de erro da API (ex.: TOKEN_SCOPE_INSUFFICIENT), quando houver. */
46
+ code?: string | undefined, details?: ApiErrorDetails);
31
47
  /** Mensagem amigável pronta para devolver ao agente. */
32
48
  describe(): string;
33
49
  }
@@ -42,29 +58,50 @@ export declare function webUrlFor(baseUrl: string): string | null;
42
58
  export declare const WINDOW_HEADER = "x-fg-tracker-window";
43
59
  /** Cabeçalho com os parâmetros extras que a rota aplicou (ex.: `traces-sort,traces-has-span`). */
44
60
  export declare const CAPABILITIES_HEADER = "x-fg-tracker-capabilities";
45
- /** Prefixo dos tokens pessoais de leitura (CONTRATO.md §8.1). */
61
+ /** Prefixo dos tokens pessoais (CONTRATO.md §8.1). */
46
62
  export declare const ACCESS_TOKEN_PREFIX = "fgt_";
63
+ /**
64
+ * Esconde valores de credencial num texto que vai para o agente: chave de projeto `stk_…` e
65
+ * token pessoal `fgt_…`. As mensagens de erro da API não ecoam segredos; isto é a segunda linha.
66
+ */
67
+ export declare function redactSecrets(value: string): string;
47
68
  /** Tipo da credencial de `FG_TRACKER_TOKEN`, pelo prefixo (sem chamar a API). */
48
69
  export type CredentialKind = 'access_token' | 'session' | 'none';
70
+ /**
71
+ * Segmento "." ou ".." (também `%2e`) num caminho: o `fetch` (WHATWG URL) o normaliza e a
72
+ * requisição vai para outra rota — `DELETE …/sourcemaps/..` viraria `DELETE /v1/projects/:id`.
73
+ */
74
+ export declare function hasDotSegment(path: string): boolean;
75
+ /** Credencial de uma requisição: Bearer (rotas de usuário) ou a chave de projeto (rotas da chave). */
76
+ export type RequestAuth = 'bearer' | 'key';
49
77
  export declare class TrackClient {
50
78
  readonly config: TrackClientConfig;
51
79
  constructor(config: TrackClientConfig);
52
80
  get baseUrl(): string;
53
81
  get hasToken(): boolean;
54
- /** `FG_TRACKER_TOKEN` é um token pessoal de leitura (não uma sessão). */
82
+ /** `FG_TRACKER_TOKEN` é um token pessoal `fgt_…` (não uma sessão). */
55
83
  get hasAccessToken(): boolean;
56
84
  get credentialKind(): CredentialKind;
57
85
  /** Painel para links (`FG_TRACKER_WEB_URL` ou derivado da API); `null` se desconhecido. */
58
86
  get webUrl(): string | null;
59
87
  get hasApiKey(): boolean;
60
- /** Headers de autenticação: Bearer (token pessoal ou sessão) e/ou chave de projeto. */
88
+ /**
89
+ * Headers de autenticação de uma requisição: o Bearer (token pessoal ou sessão) nas rotas de
90
+ * usuário, ou só a chave de projeto nas rotas da chave. Nunca os dois: a chave não viaja nas
91
+ * chamadas que o Bearer decide.
92
+ */
61
93
  private authHeaders;
62
- request<T = unknown>(method: 'GET' | 'POST' | 'PATCH' | 'DELETE', path: string, options?: {
94
+ request<T = unknown>(method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE', path: string, options?: {
63
95
  query?: Record<string, QueryValue>;
64
96
  body?: unknown;
65
97
  headers?: Record<string, string>;
66
98
  onResponse?: (res: Response) => void;
99
+ auth?: RequestAuth;
100
+ timeoutMs?: number;
67
101
  }): Promise<T>;
102
+ private unauthorizedHint;
103
+ /** Dica de uma recusa 403 conforme o `code` e a permissão exigida que a API devolve. */
104
+ private forbiddenHint;
68
105
  get<T = unknown>(path: string, query?: Record<string, QueryValue>): Promise<T>;
69
106
  /**
70
107
  * GET de uma leitura com janela: devolve também a janela absoluta que a API confirmou no
@@ -81,6 +118,10 @@ export declare class TrackClient {
81
118
  }>;
82
119
  post<T = unknown>(path: string, body?: unknown): Promise<T>;
83
120
  patch<T = unknown>(path: string, body?: unknown): Promise<T>;
121
+ put<T = unknown>(path: string, body?: unknown): Promise<T>;
122
+ delete<T = unknown>(path: string): Promise<T>;
123
+ /** POST numa rota da chave de projeto (`x-fg-tracker-key`), sem o Bearer. */
124
+ postWithKey<T = unknown>(path: string, body?: unknown): Promise<T>;
84
125
  }
85
126
  export type RangeKey = '15m' | '1h' | '6h' | '24h' | '7d' | '30d';
86
127
  export declare const RANGE_KEYS: readonly RangeKey[];
package/dist/client.js CHANGED
@@ -1,9 +1,12 @@
1
1
  /**
2
2
  * Cliente HTTP mínimo para a API do FG Tracker (docs/CONTRATO.md §4, §8, §11).
3
- * Lê `FG_TRACKER_URL`, `FG_TRACKER_TOKEN` (Bearer: token pessoal de leitura `fgt_…`
4
- * ou token de sessão), `FG_TRACKER_API_KEY` (chave de projeto, header
3
+ * Lê `FG_TRACKER_URL`, `FG_TRACKER_TOKEN` (Bearer: token pessoal `fgt_…` com as permissões
4
+ * marcadas no painel, ou token de sessão), `FG_TRACKER_API_KEY` (chave de projeto, header
5
5
  * `x-fg-tracker-key`), `FG_TRACKER_TIMEOUT_MS` e `FG_TRACKER_WEB_URL` — com
6
6
  * fallback para os nomes legados `STREAD_TRACK_*` (`stread-track-mcp` ≤ 0.3).
7
+ *
8
+ * Cada requisição leva uma credencial só: o Bearer nas rotas de usuário (o padrão) e a chave
9
+ * apenas nas rotas da chave (`auth: 'key'`), que as ferramentas só usam sem FG_TRACKER_TOKEN.
7
10
  */
8
11
  /** API local do monorepo. Em produção a API é `https://tracker-api.fortground.com.br`. */
9
12
  export const DEFAULT_URL = 'http://localhost:4050';
@@ -20,11 +23,17 @@ export class TrackApiError extends Error {
20
23
  status;
21
24
  path;
22
25
  hint;
23
- constructor(message, status, path, hint) {
26
+ code;
27
+ details;
28
+ constructor(message, status, path, hint,
29
+ /** `code` do corpo de erro da API (ex.: TOKEN_SCOPE_INSUFFICIENT), quando houver. */
30
+ code, details = {}) {
24
31
  super(message);
25
32
  this.status = status;
26
33
  this.path = path;
27
34
  this.hint = hint;
35
+ this.code = code;
36
+ this.details = details;
28
37
  this.name = 'TrackApiError';
29
38
  }
30
39
  /** Mensagem amigável pronta para devolver ao agente. */
@@ -84,12 +93,43 @@ function isConnectionError(err) {
84
93
  export const WINDOW_HEADER = 'x-fg-tracker-window';
85
94
  /** Cabeçalho com os parâmetros extras que a rota aplicou (ex.: `traces-sort,traces-has-span`). */
86
95
  export const CAPABILITIES_HEADER = 'x-fg-tracker-capabilities';
87
- /** Prefixo dos tokens pessoais de leitura (CONTRATO.md §8.1). */
96
+ /** Prefixo dos tokens pessoais (CONTRATO.md §8.1). */
88
97
  export const ACCESS_TOKEN_PREFIX = 'fgt_';
98
+ /**
99
+ * Esconde valores de credencial num texto que vai para o agente: chave de projeto `stk_…` e
100
+ * token pessoal `fgt_…`. As mensagens de erro da API não ecoam segredos; isto é a segunda linha.
101
+ */
102
+ export function redactSecrets(value) {
103
+ return value.replace(/\b(stk|fgt)_[A-Za-z0-9_-]{6,}/g, '$1_…');
104
+ }
89
105
  function extractCode(body) {
90
106
  const code = body && typeof body === 'object' ? body.code : undefined;
91
107
  return typeof code === 'string' ? code : undefined;
92
108
  }
109
+ function extractDetails(body) {
110
+ if (!body || typeof body !== 'object')
111
+ return {};
112
+ const b = body;
113
+ const details = {};
114
+ if (typeof b.requiredScope === 'string' || b.requiredScope === null)
115
+ details.requiredScope = b.requiredScope;
116
+ if (typeof b.requiredPermission === 'string' || b.requiredPermission === null)
117
+ details.requiredPermission = b.requiredPermission;
118
+ if (typeof b.sessionOnly === 'boolean')
119
+ details.sessionOnly = b.sessionOnly;
120
+ if (typeof b.role === 'string')
121
+ details.role = b.role;
122
+ if (Array.isArray(b.requiredRoles))
123
+ details.requiredRoles = b.requiredRoles.map(String);
124
+ return details;
125
+ }
126
+ /**
127
+ * Segmento "." ou ".." (também `%2e`) num caminho: o `fetch` (WHATWG URL) o normaliza e a
128
+ * requisição vai para outra rota — `DELETE …/sourcemaps/..` viraria `DELETE /v1/projects/:id`.
129
+ */
130
+ export function hasDotSegment(path) {
131
+ return path.split('?')[0].split('/').some((segment) => /^(?:\.|%2e){1,2}$/i.test(segment));
132
+ }
93
133
  function extractMessage(body, fallback) {
94
134
  if (body && typeof body === 'object') {
95
135
  const m = body.message;
@@ -113,7 +153,7 @@ export class TrackClient {
113
153
  get hasToken() {
114
154
  return Boolean(this.config.token);
115
155
  }
116
- /** `FG_TRACKER_TOKEN` é um token pessoal de leitura (não uma sessão). */
156
+ /** `FG_TRACKER_TOKEN` é um token pessoal `fgt_…` (não uma sessão). */
117
157
  get hasAccessToken() {
118
158
  return Boolean(this.config.token?.startsWith(ACCESS_TOKEN_PREFIX));
119
159
  }
@@ -127,19 +167,30 @@ export class TrackClient {
127
167
  get hasApiKey() {
128
168
  return Boolean(this.config.apiKey);
129
169
  }
130
- /** Headers de autenticação: Bearer (token pessoal ou sessão) e/ou chave de projeto. */
131
- authHeaders(extra) {
170
+ /**
171
+ * Headers de autenticação de uma requisição: o Bearer (token pessoal ou sessão) nas rotas de
172
+ * usuário, ou só a chave de projeto nas rotas da chave. Nunca os dois: a chave não viaja nas
173
+ * chamadas que o Bearer decide.
174
+ */
175
+ authHeaders(auth, extra) {
132
176
  const headers = { accept: 'application/json', ...extra };
133
- if (this.config.token)
177
+ if (auth === 'key') {
178
+ if (this.config.apiKey)
179
+ headers[API_KEY_HEADER] = this.config.apiKey;
180
+ }
181
+ else if (this.config.token) {
134
182
  headers.authorization = `Bearer ${this.config.token}`;
135
- if (this.config.apiKey)
136
- headers[API_KEY_HEADER] = this.config.apiKey;
183
+ }
137
184
  return headers;
138
185
  }
139
186
  async request(method, path, options = {}) {
187
+ if (hasDotSegment(path)) {
188
+ throw new TrackApiError(`Recusado: ${method} ${path} tem um segmento "." ou "..", que mudaria a rota chamada. Nada foi enviado.`, undefined, path);
189
+ }
140
190
  const url = `${this.config.baseUrl}${path}${buildQuery(options.query)}`;
141
- const headers = this.authHeaders(options.headers);
142
- let init = { method, headers, signal: AbortSignal.timeout(this.config.timeoutMs ?? 15_000) };
191
+ const auth = options.auth ?? 'bearer';
192
+ const headers = this.authHeaders(auth, options.headers);
193
+ let init = { method, headers, signal: AbortSignal.timeout(options.timeoutMs ?? this.config.timeoutMs ?? 15_000) };
143
194
  if (options.body !== undefined) {
144
195
  headers['content-type'] = 'application/json';
145
196
  init = { ...init, body: JSON.stringify(options.body) };
@@ -172,26 +223,58 @@ export class TrackClient {
172
223
  options.onResponse?.(res);
173
224
  return body;
174
225
  }
175
- const message = extractMessage(body, `${res.status} ${res.statusText}`);
226
+ const message = redactSecrets(extractMessage(body, `${res.status} ${res.statusText}`));
227
+ const code = extractCode(body);
228
+ const details = extractDetails(body);
229
+ const fail = (summary, hint) => {
230
+ throw new TrackApiError(summary, res.status, path, hint, code, details);
231
+ };
176
232
  switch (res.status) {
177
233
  case 401:
178
- throw new TrackApiError(`Não autenticado (401) em ${method} ${path}: ${message}`, 401, path, this.hasAccessToken
179
- ? 'o token pessoal do FG_TRACKER_TOKEN expirou, foi revogado ou a conta está inativa — crie outro no painel (Conta → Tokens de acesso) e atualize FG_TRACKER_TOKEN.'
180
- : this.config.token
181
- ? 'a sessão do FG_TRACKER_TOKEN expirou ou foi encerrada — crie um token de leitura no painel (Conta → Tokens de acesso), que não cai com logout, e defina FG_TRACKER_TOKEN com ele.'
182
- : 'defina FG_TRACKER_TOKEN com um token de leitura do FG Tracker (painel → Conta → Tokens de acesso, `fgt_…`). Para ingestão use FG_TRACKER_API_KEY.');
234
+ return fail(`Não autenticado (401) em ${method} ${path}: ${message}`, auth === 'key' ? 'a FG_TRACKER_API_KEY não é a chave de um projeto (stk_…): copie FG_TRACKER_KEY no painel, em Conectar.' : this.unauthorizedHint());
183
235
  case 403:
184
- throw new TrackApiError(`Sem permissão (403) em ${method} ${path}: ${message}`, 403, path, extractCode(body) === 'TOKEN_SCOPE_INSUFFICIENT'
185
- ? 'o FG_TRACKER_TOKEN é um token pessoal somente leitura e esta operação altera dados ou lê dados que o token não cobre. Faça a operação pelo painel ou configure o MCP com uma sessão (painel → Conectar → Usar MCP → Copiar configuração com minha sessão).'
186
- : this.hasAccessToken
187
- ? 'o usuário do token não é membro ativo deste projeto, ou o token foi restrito a outros projetos (Conta → Tokens de acesso).'
188
- : 'o usuário do FG_TRACKER_TOKEN não é membro deste projeto. Peça a um owner/admin para convidá-lo em /members.');
236
+ return fail(`Sem permissão (403) em ${method} ${path}: ${message}`, this.forbiddenHint(method, path, code, details));
189
237
  case 404:
190
- throw new TrackApiError(`Não encontrado (404) em ${method} ${path}: ${message}`, 404, path);
238
+ return fail(`Não encontrado (404) em ${method} ${path}: ${message}`);
191
239
  case 400:
192
- throw new TrackApiError(`Requisição inválida (400) em ${method} ${path}: ${message}`, 400, path);
240
+ if (code === 'API_KEY_PROJECT_MISMATCH') {
241
+ return fail(`Recusado (400) em ${method} ${path}: a FG_TRACKER_API_KEY é de outro projeto, não do projectId pedido. Nada foi gravado.`, 'sem FG_TRACKER_TOKEN, as ferramentas que gravam pela chave só valem no projeto dela: use o projectId da chave, troque FG_TRACKER_API_KEY pela chave do projeto certo ou configure FG_TRACKER_TOKEN.');
242
+ }
243
+ return fail(`Requisição inválida (400) em ${method} ${path}: ${message}`);
244
+ default:
245
+ return fail(`Erro ${res.status} em ${method} ${path}: ${message}`);
246
+ }
247
+ }
248
+ unauthorizedHint() {
249
+ if (this.hasAccessToken)
250
+ return 'o token pessoal do FG_TRACKER_TOKEN expirou, foi revogado ou a conta está inativa — crie outro no painel (Conta → Tokens de acesso), com as permissões de que o agente precisa, e atualize FG_TRACKER_TOKEN. A recusa é final: o MCP não tenta de novo com outra credencial.';
251
+ if (this.config.token)
252
+ return 'a sessão do FG_TRACKER_TOKEN expirou ou foi encerrada — crie um token pessoal no painel (Conta → Tokens de acesso), que não cai com logout, e defina FG_TRACKER_TOKEN com ele.';
253
+ return 'defina FG_TRACKER_TOKEN com um token pessoal do FG Tracker (painel → Conta → Tokens de acesso, `fgt_…`). Para ingestão use FG_TRACKER_API_KEY.';
254
+ }
255
+ /** Dica de uma recusa 403 conforme o `code` e a permissão exigida que a API devolve. */
256
+ forbiddenHint(method, path, code, details) {
257
+ switch (code) {
258
+ case 'TOKEN_SCOPE_INSUFFICIENT':
259
+ if (details.sessionOnly)
260
+ return 'esta operação só pode ser feita com a sessão do painel: tokens pessoais não a fazem com nenhuma permissão. Peça ao usuário para fazê-la no painel.';
261
+ return details.requiredPermission
262
+ ? `falta a permissão "${details.requiredPermission}" neste token. O usuário pode marcá-la em Conta → Tokens de acesso → editar; a lista de ferramentas do MCP só muda depois de reiniciar o cliente MCP.`
263
+ : 'o token não tem a permissão que esta operação exige (Conta → Tokens de acesso → editar; reinicie o cliente MCP depois).';
264
+ case 'PROJECT_ROLE_INSUFFICIENT':
265
+ return `seu papel neste projeto é ${details.role ?? 'outro'}${details.requiredRoles?.length ? `, e a ação exige ${details.requiredRoles.join(' ou ')}` : ''}. Nenhum token faz mais do que o papel: peça a um owner ou admin do projeto.`;
266
+ case 'TOKEN_PROJECT_SCOPE':
267
+ return method === 'POST' && path === '/v1/projects'
268
+ ? 'um token restrito a projetos não cria projeto. Use um token válido para todos os projetos (com "Projetos: criar e editar") ou a sessão do painel.'
269
+ : 'o token não vale para este projeto: ele foi restrito a outros projetos (Conta → Tokens de acesso → projetos do token).';
270
+ case 'PROJECT_ACCESS_DENIED':
271
+ return 'o usuário da credencial não é membro ativo deste projeto. Peça a um owner/admin para convidá-lo.';
272
+ case 'EMAIL_VERIFICATION_REQUIRED':
273
+ return 'confirme o e-mail da conta no painel antes de continuar.';
193
274
  default:
194
- throw new TrackApiError(`Erro ${res.status} em ${method} ${path}: ${message}`, res.status, path);
275
+ return this.hasAccessToken
276
+ ? 'o usuário do token não tem acesso a este projeto ou o token não cobre esta operação (Conta → Tokens de acesso).'
277
+ : 'o usuário do FG_TRACKER_TOKEN não tem acesso a este projeto ou a esta operação. Peça a um owner/admin.';
195
278
  }
196
279
  }
197
280
  get(path, query) {
@@ -222,6 +305,16 @@ export class TrackClient {
222
305
  patch(path, body) {
223
306
  return this.request('PATCH', path, { body });
224
307
  }
308
+ put(path, body) {
309
+ return this.request('PUT', path, { body });
310
+ }
311
+ delete(path) {
312
+ return this.request('DELETE', path);
313
+ }
314
+ /** POST numa rota da chave de projeto (`x-fg-tracker-key`), sem o Bearer. */
315
+ postWithKey(path, body) {
316
+ return this.request('POST', path, { body, auth: 'key' });
317
+ }
225
318
  }
226
319
  export const RANGE_KEYS = ['15m', '1h', '6h', '24h', '7d', '30d'];
227
320
  export const RANGE_SECONDS = {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Confirmação das exclusões (docs/mcp.md, "Exclusões"): toda ferramenta que exclui recebe
3
+ * `confirm` com o nome ou o slug do recurso, conferido contra o recurso lido na API antes de
4
+ * qualquer efeito. Um booleano não basta: o agente teria de repetir o nome que o usuário viu.
5
+ */
6
+ import { z } from 'zod';
7
+ import { type ToolText } from './format.js';
8
+ export declare const confirmSchema: z.ZodString;
9
+ /** Texto padrão da descrição das ferramentas que excluem. */
10
+ export declare const DELETE_GUIDANCE = "ANTES de chamar, mostre ao usu\u00E1rio o que ser\u00E1 exclu\u00EDdo e pergunte se deseja continuar; s\u00F3 chame depois de um \"sim\" expl\u00EDcito, com `confirm` igual ao nome (ou slug) que ele confirmou. Sem isso, ou com outro valor, nada \u00E9 exclu\u00EDdo.";
11
+ /**
12
+ * `null` quando `confirm` é um dos identificadores aceitos (comparação exata, sem espaços nas
13
+ * pontas); senão o resultado de erro para o agente, sem nenhuma chamada de escrita feita.
14
+ */
15
+ export declare function refuseUnconfirmed(confirm: string, accepted: Array<string | null | undefined>, what: string): ToolText | null;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Confirmação das exclusões (docs/mcp.md, "Exclusões"): toda ferramenta que exclui recebe
3
+ * `confirm` com o nome ou o slug do recurso, conferido contra o recurso lido na API antes de
4
+ * qualquer efeito. Um booleano não basta: o agente teria de repetir o nome que o usuário viu.
5
+ */
6
+ import { z } from 'zod';
7
+ import { text } from './format.js';
8
+ export const confirmSchema = z
9
+ .string()
10
+ .trim()
11
+ .min(1)
12
+ .max(300)
13
+ .describe('Nome ou slug EXATO do recurso, que o usuário confirmou nesta conversa. Pergunte antes; nunca preencha por conta própria');
14
+ /** Texto padrão da descrição das ferramentas que excluem. */
15
+ export const DELETE_GUIDANCE = 'ANTES de chamar, mostre ao usuário o que será excluído e pergunte se deseja continuar; só chame depois de um "sim" explícito, com `confirm` igual ao nome (ou slug) que ele confirmou. Sem isso, ou com outro valor, nada é excluído.';
16
+ /**
17
+ * `null` quando `confirm` é um dos identificadores aceitos (comparação exata, sem espaços nas
18
+ * pontas); senão o resultado de erro para o agente, sem nenhuma chamada de escrita feita.
19
+ */
20
+ export function refuseUnconfirmed(confirm, accepted, what) {
21
+ const values = [...new Set(accepted.filter((value) => typeof value === 'string' && value.trim().length > 0).map((value) => value.trim()))];
22
+ if (values.includes(confirm.trim()))
23
+ return null;
24
+ return {
25
+ ...text([
26
+ `Recusado: nada foi excluído. confirm "${confirm.slice(0, 120)}" não é ${values.length > 1 ? 'o nome nem o slug' : 'o identificador'} de ${what}.`,
27
+ `Mostre ao usuário o que será excluído (${what}) e pergunte se deseja continuar. Só repita com confirm igual a ${values.map((value) => `"${value}"`).join(' ou ')} depois de um "sim" explícito dele nesta conversa.`,
28
+ ].join('\n')),
29
+ isError: true,
30
+ };
31
+ }
32
+ //# sourceMappingURL=confirm.js.map