@neetru/cli 2.28.8 → 2.29.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 +74 -1
- package/README.md +2 -1
- package/dist/commands/admin/oidc-login.d.ts +18 -0
- package/dist/commands/admin/oidc-login.js +62 -0
- package/dist/commands/admin/oidc-login.js.map +1 -1
- package/dist/commands/agent-release.d.ts +2 -0
- package/dist/commands/agent-release.js +27 -2
- package/dist/commands/agent-release.js.map +1 -1
- package/dist/commands/agent-write.d.ts +1 -0
- package/dist/commands/agent-write.js +4 -0
- package/dist/commands/agent-write.js.map +1 -1
- package/dist/commands/code.js +10 -1
- package/dist/commands/code.js.map +1 -1
- package/dist/commands/db-move.d.ts +50 -1
- package/dist/commands/db-move.js +137 -13
- package/dist/commands/db-move.js.map +1 -1
- package/dist/commands/db.js +17 -9
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/deploy.d.ts +15 -0
- package/dist/commands/deploy.js +76 -1
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/deployments.d.ts +7 -1
- package/dist/commands/deployments.js +59 -8
- package/dist/commands/deployments.js.map +1 -1
- package/dist/commands/doctor.js +12 -6
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/ops.d.ts +17 -0
- package/dist/commands/ops.js +50 -18
- package/dist/commands/ops.js.map +1 -1
- package/dist/commands/products-db.d.ts +1 -0
- package/dist/commands/products-db.js +15 -15
- package/dist/commands/products-db.js.map +1 -1
- package/dist/commands/servers.d.ts +30 -3
- package/dist/commands/servers.js +130 -8
- package/dist/commands/servers.js.map +1 -1
- package/dist/commands/vm.d.ts +2 -0
- package/dist/commands/vm.js +8 -0
- package/dist/commands/vm.js.map +1 -1
- package/dist/index.js +90 -11
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-artifact-url.d.ts +19 -0
- package/dist/lib/agent-artifact-url.js +48 -0
- package/dist/lib/agent-artifact-url.js.map +1 -0
- package/dist/lib/api-client.d.ts +11 -3
- package/dist/lib/api-client.js +55 -24
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/api-error.js +32 -1
- package/dist/lib/api-error.js.map +1 -1
- package/dist/lib/auth.d.ts +2 -9
- package/dist/lib/auth.js +34 -18
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/cli-write.d.ts +31 -0
- package/dist/lib/cli-write.js +51 -2
- package/dist/lib/cli-write.js.map +1 -1
- package/dist/lib/telemetry.d.ts +7 -0
- package/dist/lib/telemetry.js +9 -0
- package/dist/lib/telemetry.js.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,16 @@ Convenção: [Keep a Changelog](https://keepachangelog.com/) + [SemVer](https://
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [2.29.0] — 2026-10-01 (status live_unverified, db move decommission no contrato real, servers pgbouncer sync-userlist, TUI do code sob demanda)
|
|
8
|
+
|
|
7
9
|
### Adicionado
|
|
8
10
|
|
|
11
|
+
- **Suporte ao status de ambiente `live_unverified`** (`neetru-core` PR #531 — gate de saúde pós-deploy no Core, **desligado por padrão**): quando o Core aplica um deploy mas o gate ainda não confirmou a saúde do ambiente, ele pode devolver `live_unverified` em vez de `live`/`success`. O CLI agora reconhece esse status em vez de tratá-lo como genérico/desconhecido:
|
|
12
|
+
- `src/commands/deployments.ts` — `live_unverified` entra em `DEPLOY_TERMINAL` (estado final, não fica indefinidamente em polling) mas **fica fora de `DEPLOY_SUCCESS`**; nova `isDeployUnverified()` + `deployStatusLabel()` (rótulo PT-BR "no ar, saúde não confirmada" anexado ao status cru, que se mantém em inglês pra não quebrar `--json`/automação) + `colorDeployStatus()` (cor de aviso/amarelo, mesma paleta semântica do resto do CLI).
|
|
13
|
+
- **Decisão para `--wait`/espera de deploy** (`neetru deployments watch --follow`, usado também por `neetru promote execute`): `live_unverified` **não fica girando os 20min do timeout** (é terminal) e **não é tratado como falha silenciosa nem como falha real** — vira **sucesso COM AVISO, exit code 0** (`spinner.warn` + `verified:false` no `--json`), o mesmo tratamento que o probe de saúde independente do CLI (`probeDeployedHealth` em `deploy.ts`) já dá ao verdict `unverifiable`. Só `failed`/`rolled_back`/`canary_aborted` continuam saindo com exit 1.
|
|
14
|
+
- `src/commands/deploy.ts` — os caminhos síncronos `target=workspace` e `target=cloud-run` (que antes só reconheciam `resp.status === 'live'` como sucesso e tratavam qualquer outro valor como falha genérica) ganharam o mesmo ramo "sucesso com aviso" para `live_unverified`, evitando que um deploy aplicado-mas-não-confirmado fosse reportado como `Deploy failed`.
|
|
15
|
+
- Não exige mudança de contrato nem flag nova — é passivo até o Core ligar o gate (hoje desligado por padrão); devs que não tocarem nesse valor não veem diferença.
|
|
16
|
+
|
|
9
17
|
- **`neetru mobile`** — registro/gestão de Apps Mobile (iOS/Android) do produto atual, consumindo o contrato do Core (`neetru-core` PR #482 — dev-facing, self-service, mesmo padrão de `db`/`domains`).
|
|
10
18
|
- **`neetru mobile init --platform <ios|android> --redirect-uri <https://...> [...]`** — registra o app no Core (`POST /api/cli/v1/products/{slug}/mobile-apps`) e só DEPOIS grava o stub local em `.neetru/mobile.json` (mesma ordem register-antes-do-stub de `db init` — evita entrada órfã se o POST falhar). Flags condicionais por plataforma: `--bundle-id`/`--team-id` (ios), `--package-name`/`--sha-fingerprint` (repetível, android), `--name` opcional. `--redirect-uri` **precisa** ser `https://` (Universal Link/App Link, RFC 8252) — custom scheme (`meuapp://`) é rejeitado localmente e pelo Core, decisão de segurança do owner, não limitação temporária. Resposta traz o `oidcClientId` (PKCE público, sem client secret) — a saída lembra de configurar `NEETRU_MOBILE_CLIENT_ID` no app.
|
|
11
19
|
- **`neetru mobile list`** — `GET` dos apps mobile do produto atual, tabela (platform/bundle-package/status/oidcClientId) ou `--json`.
|
|
@@ -34,17 +42,82 @@ Convenção: [Keep a Changelog](https://keepachangelog.com/) + [SemVer](https://
|
|
|
34
42
|
- **`neetru db move status <migrationId>`** — estado da relocação + `verifyReport` (contagem por tabela origem vs destino) + gates.
|
|
35
43
|
- **`neetru db move confirm <migrationId> --mfa <code>`** — libera o cutover manual (`--manual-cutover`).
|
|
36
44
|
- **`neetru db move abort <migrationId> --reason "<t>"`** — dispara o rollback do estado atual (exige `--reason`; confirmação interativa pulável com `--yes`).
|
|
45
|
+
- **`neetru db move decommission <migrationId> --reason "<t>" [--retry]`** — único caminho que DESPACHA o drop da cópia ANTIGA na origem, depois de um move `done` (`POST /api/cli/v1/db/relocate/[id]/decommission`, atualizado para o contrato real da Fase 2 do Core — PR #536). **Recusado client-side** se o ledger ainda não confirma o destino (espelho da INV-DESTROY; nunca dropar quem o ledger diz ser o vivo) e se `--retry` for pedido sem uma tentativa anterior `failed`. O Core é a autoridade final: além do ledger, a trava lógica cobre **kill switch**, migração `done`, **período de observação de 7 dias** após o `done`, nenhuma migração ativa do banco e a origem nunca ter sido liberada de volta ao app. **O drop é ASSÍNCRONO** — o comando só confirma o DESPACHO (`outcome: dispatched|already_requested`, `commandId`); nunca afirma "descomissionada" (a versão anterior mentia isso). Recusas de trava voltam 409 com código estável (`RELOCATE_DISABLED`, `RELOCATE_DECOMMISSION_NOT_DONE`, `RELOCATE_DECOMMISSION_OBSERVATION_PENDING`, `RELOCATE_DECOMMISSION_LEDGER_MISMATCH`, `RELOCATE_DECOMMISSION_MIGRATION_ACTIVE`, `RELOCATE_DECOMMISSION_RETRY_NOT_ALLOWED`, `RELOCATE_SOURCE_RELEASED`) — cada um com mensagem PT-BR própria (o que significa + o que fazer, `DECOMMISSION_REFUSAL_GUIDANCE`).
|
|
46
|
+
- **`neetru db move status <migrationId>`** agora também mostra `doneAt` e o progresso do decommission da origem (`sourceDecommission.status`: `dispatched → dropped|failed`, tentativa, quando pedido/terminou, erro do agente) e `sourceDecommissionedAt` quando o drop terminou — é como se acompanha o desfecho do `decommission` assíncrono.
|
|
37
47
|
- **`neetru db where --product <slug>` / `--db <dbId>`** — READ-ONLY: mostra em qual VM o banco de um produto **vive hoje** (serverId + endpoint). Complementa `neetru db status <dbId>` (que exige o dbId) aceitando o slug do produto.
|
|
38
|
-
- **Nota:** os endpoints `/api/cli/v1/db/[id]/relocate` e `/api/cli/v1/db/relocate/[migrationId]{,/confirm,/abort}` são o contrato com o Core, construídos pelo componente irmão (Fase 2 / PR #423). Este bump entrega só a superfície CLI; o `db move` real depende do Core estar publicado com esses endpoints.
|
|
48
|
+
- **Nota:** os endpoints `/api/cli/v1/db/[id]/relocate` e `/api/cli/v1/db/relocate/[migrationId]{,/confirm,/abort,/decommission}` são o contrato com o Core, construídos pelo componente irmão (Fase 2 / PR #423, decommission assíncrono na Fase 2 / PR #536). Este bump entrega só a superfície CLI; o `db move` real depende do Core estar publicado com esses endpoints.
|
|
49
|
+
|
|
50
|
+
### Corrigido
|
|
51
|
+
|
|
52
|
+
- **`neetru code` carrega a TUI só quando ela é usada** (`bug_b1e9af59`) — `commands/code.ts` importava `lib/code-agent-tui` (ink + react + ink-text-input) estaticamente; agora é `await import()` dentro de `runInteractive`. O one-shot (`neetru code "tarefa"`) deixa de pagar a carga da TUI (medido no `dist`: `code.js` ~0,8–0,95s sem ela; a TUI sozinha 6–8,5s nesta máquina Windows).
|
|
53
|
+
- **`neetru db` carrega o `inquirer` só quando vai perguntar algo** (`bug_b1e9af59`) — era o único import estático dele no grafo de `commands/db.ts`; agora `carregarInquirer()` (`await import`) nos 8 prompts. `db list`/`db status`/`db apply --json` deixam de pagar ~0,5s de carga (A/B no `dist`, mesma carga de máquina: ~1,1–1,4s contra ~2,0–2,3s).
|
|
54
|
+
|
|
55
|
+
### Interno
|
|
56
|
+
|
|
57
|
+
- **Gate de pre-push local** (padrão da skill `neetru-pre-push` — Actions da org sem billing, o gate local É o CI): `scripts/pre-push-gate.mjs` (template da loja, sem dependências) + `.githooks/pre-push`. Etapas = as do `ci.yml`: `tsc --noEmit` → `npm test` (→ `npm run build` com `NEETRU_PREPUSH_FULL=1`); push direto pra `main` bloqueado (`NEETRU_ALLOW_MAIN_PUSH=1` pra fuga consciente); `NEETRU_SKIP_PREPUSH=1` só em emergência, com motivo no PR. O `prepare` liga `core.hooksPath=.githooks` só quando existe `.git` (arquivo ou diretório — vale em worktree) e nunca falha: não afeta `npm publish` nem quem instala o pacote do registry (lá o `prepare` nem roda).
|
|
58
|
+
- **Gate roda as etapas sem `GIT_DIR` & cia** (incidente 2026-10-01) — o git exporta variáveis de repositório para hooks; num worktree, `GIT_DIR=<repo>/.git/worktrees/<nome>`. As etapas herdavam isso e os testes que criam repo próprio num tmpdir (`git init`/`config`/`commit`) operaram no clone real (`core.bare=true`, `user.name` de teste, commit "init"). O template ganhou `sanitizeGitEnv(env)` + `GIT_REPO_ENV_VARS` (= `git rev-parse --local-env-vars` do git 2.53 + `GIT_NAMESPACE`/`GIT_QUARANTINE_PATH`, e os pares `GIT_CONFIG_KEY_n`/`VALUE_n`); transporte/credencial (`GIT_SSH*`, `GIT_ASKPASS`, `GIT_TERMINAL_PROMPT`) ficam. `pre-push-gate.test.ts`: unitário, cobertura contra o git instalado e prova de ponta a ponta com `git hook run` num worktree vítima (sem saneamento a config da vítima é alterada; pelo gate, fica intacta).
|
|
59
|
+
- **`neetru servers pgbouncer sync-userlist <serverId>`** — re-sincroniza o userlist do PgBouncer de uma VM sem SSH e sem rotacionar senha (`POST /api/cli/v1/servers/[id]/pgbouncer/sync-userlist`, Core PR #539, `agent.db.pgbouncer.sync_userlist`). Remediação de drift SASL (userlist congelado pelo `cred_rotate`): o agente relê o hash SCRAM do `pg_shadow` de cada papel Postgres **ativo** da VM (lista montada no Core a partir de `product_databases` — nunca vem do cliente) e reescreve as linhas.
|
|
60
|
+
- **`merge`** (padrão) só faz upsert dos papéis esperados — sem confirmação interativa, só admin + step-up MFA.
|
|
61
|
+
- **`--replace`** reescreve o userlist **INTEIRO** — exige `--reason` (≥10 chars, vai pro audit) fora de `--dry-run` + `confirmDestructive` (pulável com `--yes`); o Core recusa com 409 `replace_incomplete` se a lista calculada não for a COMPLETA da VM (banco em status bloqueante, migração de banco em curso ou papel fora do formato) — **nada é apagado** nesse caso.
|
|
62
|
+
- **MFA INCONDICIONAL** — ao contrário da maioria das rotas com `--dry-run` deste CLI, a rota do Core chama `requireCliStepUpMfa` **antes** de ler `dryRun` (fecha o bypass que dry-run representaria): o comando nunca repassa `dryRun` pro `resolveStepUp` padrão (que pularia o header MFA) — resolve o MFA sempre e anexa `?dryRun=true` à parte.
|
|
63
|
+
- Saída: tabela de bancos/papéis enviados + banco(s) deixado(s) de fora (`skipped`, com motivo) + `commandId` do `agent.db.drop` despachado (assíncrono — orienta `servers logs --source audit` / `servers describe` pra acompanhar); `--json` espelha o contrato cru do Core (sem `ok` — o CLI adiciona `ok:true` só na própria saída JSON).
|
|
64
|
+
- 409 `no_active_databases`/`replace_incomplete` ganham mensagem PT-BR própria (o que significa + o que fazer); 400 `invalid_param`/`invalid_json`/`reason_required` e 404 seguem o `handleApiError` genérico.
|
|
39
65
|
|
|
40
66
|
### Testes
|
|
41
67
|
|
|
68
|
+
- **`code-session.test.ts` estável** (`bug_b1e9af59`) — o import do módulo saiu do corpo do 1º teste (estourava o `testTimeout` de 10s na suíte inteira) para `beforeAll(…, 60s)`; cada teste tem o próprio `AbortController` e o mock de `apiRequest` só atende chamadas com o `signal` do teste ativo — resíduo de um teste que expirou não contamina o seguinte (a cascata no 2º teste). Mock ganhou `CliApiError` (antes qualquer erro do gateway virava "No export defined on the mock"). Novo caso de regressão do isolamento.
|
|
69
|
+
- **Suíte estável na execução completa** (`bug_b1e9af59` — gate local vermelho com 10 falhas: 8 timeouts de 10s + 2 cascatas) — 8 arquivos: `bug-fixes-2026-05-25`, `code-agent-git-tools`, `db-apply-nosql`, `db-commands`, `db-init-register-shape.regression`, `dev-context`, `high-fixes-2-9-1`, `sabatina-r1-db-flow`.
|
|
70
|
+
- **Novo `src/__tests__/helpers/isolamento.ts`**: `it` que rastreia o corpo de cada teste + `aguardarCorpoDoTeste()` como 1ª linha do `afterEach` da raiz — um corpo que expirou termina com o ambiente DELE montado antes da limpeza e do teste seguinte (sem cascata). Provado por `isolamento-helper.test.ts` (com o `it` cru do vitest a mesma prova falha).
|
|
71
|
+
- Imports pesados aquecidos em `beforeAll(…, 60s)`, fora do `testTimeout`. Em `high-fixes-2-9-1` o `vi.resetModules()` por teste foi mantido (módulos reais reavaliados por teste); o aquecimento só deixa pronto o que ele não descarta (cache de transform + pacotes externos já carregados).
|
|
72
|
+
- `code-agent-git-tools`: `gh` falso via mock de `node:child_process` (o `gh.cmd` no PATH não era achado pelo `spawnSync` sem shell no Windows — o teste chamava o **gh real**, e os casos `skipIf(!ghAvailable)` dependiam da máquina; agora sempre rodam); push para remoto **local** (repo bare); `commit.gpgsign=false`; timeout próprio por teste (30s — vários processos git reais).
|
|
73
|
+
- `bug-fixes-2026-05-25`: `neetru open` (pdv #9) **abria o navegador real** a cada execução (`rundll32 url.dll,FileProtocolHandler`) — `spawn`/`spawnSync` mockados; e `vi.restoreAllMocks()` por teste (spies de `process.cwd` no corpo nunca eram restaurados — o cwd ficava no tmpDir já apagado do teste anterior).
|
|
74
|
+
- **Todo git rodado pela suíte usa env sem `GIT_DIR` & cia e `cwd` no tmpdir** (incidente 2026-10-01 — defesa em profundidade, vale mesmo fora do gate): `helpers/git-env.ts` (`gitEnvLimpo()` a partir do `sanitizeGitEnv` do template + `exigirDirTemporario()`) em todo `spawnSync('git', …)` de `code-agent-git-tools` e `code-agent`; o repasse para o git real no mock de `child_process` de `code-agent-git-tools` também saneia (cobre o git disparado pelo código sob teste); e `setupFiles` do vitest (`setup/sem-env-de-repo-git.ts`) tira essas variáveis do `process.env` de cada worker. Prova: com `GIT_DIR` apontando para o gitdir de worktree de um repo vítima, a versão anterior dos 2 arquivos reproduziu o incidente na vítima (`core.bare=true`, `user.*` de teste, `commit.gpgsign=false`, commit "init" — o `git init --bare` do remoto local, introduzido no commit anterior, é o que gerava o `core.bare`); a nova deixa a vítima idêntica (63/63).
|
|
75
|
+
|
|
42
76
|
- **`mobile-local.test.ts`** (novo) — `@neetru/mobile-local`: migração defensiva do `.neetru/mobile.json` (entradas malformadas descartadas, upgrade sem `version`, default `status: 'active'`), round-trip `readMobileJson`/`writeMobileJson` (atômico, sem lixo `.tmp-*`), `upsertMobileApp`/`removeMobileApp`.
|
|
43
77
|
- **`mobile-commands.test.ts`** (novo) — `neetru mobile`: validação por-plataforma em `init` (ios exige bundle-id+team-id, android exige package-name+sha-fingerprint, redirect-uri precisa `https://`), ordem register-no-Core-antes-do-stub-local, **POST falho NÃO deixa `.neetru/mobile.json` órfão** (nem sobrescreve entradas pré-existentes), `list` happy-path/`--json`/erro de API, `revoke` fail-closed sem `--yes`/`--json`/TTY, header MFA (`X-Neetru-MFA-Token`) anexado no DELETE, remoção local só após sucesso remoto (DELETE falho preserva o registry).
|
|
44
78
|
- **`smoke.test.ts`** (novo, 18 testes): descoberta de rotas a partir de fixture `app/` (route groups removidos, dinâmicos pulados/avisados, `api/` excluída); alcance (pass 200, fail 500, fail em marcador de erro no corpo 200, unit de `classifyReachability`); health (pass ok JSON, warn 404, fail 503, unit de `classifyHealth`); login (warn sem afford, fail não-200); saída `--json` (shape + `ok=false` + exit 1 via ExitSentinel); smoke de prod só roda com `--prod`. `fetchImpl` e diretório de descoberta injetados — sem servidor vivo.
|
|
45
79
|
- `top-level-commands-coverage.regression.test.ts`: `smoke` adicionado a `TOP_LEVEL_COMMANDS` (autocomplete) pra acompanhar o novo comando em `index.ts`.
|
|
46
80
|
- **`vm-memory.test.ts`** (novo, 18 casos): status GET+JSON+tabela; set GET→POST com body correto + header MFA; alias `--max`; herança de teto com só `--max-old-space`; `--high`/`--confirm-shrink`/`--reason` no body; validações fail-fast (slug inválido, sem flags, `max-old-space ≥ memory-max`, `high > memory-max`, abaixo do piso, não-inteiro, slug sem teto); avisos de overcommit / encolhimento / RAM desconhecida (o Core continua sendo a autoridade fail-closed).
|
|
47
81
|
- **`db-move.test.ts`** (novo) — mocka o Core (`apiRequest`) e as deps de escrita. Cobre: (a) **sucesso** (só reporta "concluída" quando o poll chega em `done`; body/headers/MFA corretos no POST); (b) **falha com rollback** (`rolled_back` + `lastError` → "seguiu na origem" + `setSafeExitCode(1)`, sem afirmar sucesso); (c) **`--yes`** (repassa `yes:true` ao `confirmDestructive` e prossegue); (d) **`--dry-run`** (sem confirmação/MFA, `body.dryRun=true`, sem poll); (e) manual-cutover (pausa e instrui `db move confirm`); (f) guardrails de input (`--to` ausente, estratégia inválida, produto ambíguo → exit 1 sem tocar o Core); (g) `confirm`/`abort`/`status`/`where`; e os helpers PUROS (`classifyRelocation`, `validateMaxQuiesceMs`, `formatVerifyReportLines`).
|
|
82
|
+
- **`db-move.test.ts`** (atualizado — `decommission` contra o contrato real da Fase 2/PR #536): resposta `outcome: 'dispatched'` reporta "DESPACHADO" (nunca "descomissionada" — era mentira sobre um drop síncrono que não existe); `--retry` manda `retry:true` no body e é recusado client-side sem tentativa anterior `failed`; `outcome: 'already_requested'` é no-op (sem `log.success`, orienta `status`/`--retry` conforme o status da tentativa); cada código 409 (`RELOCATE_DISABLED`/`RELOCATE_DECOMMISSION_*`/`RELOCATE_SOURCE_RELEASED`) cai em `describeDecommissionRefusal`/`DECOMMISSION_REFUSAL_GUIDANCE` (mensagem do Core + o que fazer, exit 1) em vez do `handleApiError` genérico (exit 4); código 409 desconhecido só mostra a mensagem do Core; erro não-409 (5xx) ainda cai no `handleApiError`; `db move status` (texto) mostra `sourceDecommission`/`doneAt`/`sourceDecommissionedAt` quando presentes.
|
|
83
|
+
- **`servers-pgbouncer-sync.test.ts`** (novo, 11 casos) — `servers pgbouncer sync-userlist`: merge não chama `confirmDestructive`; `--replace` sem `--reason` (fora de dry-run) recusado client-side sem tocar o Core; `--replace --dry-run` sem `--reason` passa (Core também isenta em dry-run); `--replace` com `--reason` válido chama `confirmDestructive` e manda `{mode,reason}` no body; **`--dry-run` chama `resolveStepUp` SEM `dryRun` no input** (regressão-alvo: o padrão `resolveStepUp` pularia o header MFA, mas esta rota exige MFA mesmo em dry-run) + URL com `?dryRun=true`; `serverId` inválido recusado client-side; 409 `no_active_databases`/`replace_incomplete` com guidance PT-BR (exit 1, sem cair no `handleApiError` genérico); 5xx cai no `handleApiError`; saída texto (sucesso+commandId+orientação de acompanhar vs. aviso `[dry-run]` sem `log.success`).
|
|
84
|
+
- **`cli-mfa-destructive-surface.test.ts`** — nova entrada no roster: `servers pgbouncer sync-userlist` (modo `merge`) também afirma o header MFA no `apiRequest`, guardando contra alguém pular `resolveStepUp` achando que `merge` (não-destrutivo em si) dispensa MFA.
|
|
85
|
+
- **`deploy-console.test.ts`** (estendido) — classificação pura do status `live_unverified`: terminal mas nem sucesso nem falha, `isDeployUnverified`, `deployStatusLabel` (rótulo PT-BR anexado) e `colorDeployStatus` (cor de aviso).
|
|
86
|
+
- **`deploy-watch-live-unverified.test.ts`** (novo) — `runDeploymentsWatch`/`--follow` com `status: 'live_unverified'`: para no primeiro poll (não gira até os 20min), nunca chama `safeExit(1)`, `--json` emite `verified:false`; `failed` continua saindo com exit 1 (regressão). Mocka `apiRequest`/`cli-write`/`logger`/`safe-exit`/`ora` — sem `git`.
|
|
87
|
+
|
|
88
|
+
## [2.28.10] — 2026-09-29 (segurança: step-up MFA nas rotas endurecidas pela auditoria cli/v1 do Core)
|
|
89
|
+
|
|
90
|
+
> **Publicar ANTES do deploy do Core** com a auditoria cli/v1 2026-09-29 (branch `fix/cli-v1-auditoria-2026-09-29` do `neetru-core`). Sem este CLI, os comandos abaixo passam a bater `401 mfa_required` sempre. Contra o Core atual os headers MFA são ignorados (compatível).
|
|
91
|
+
|
|
92
|
+
### Segurança / Corrigido
|
|
93
|
+
|
|
94
|
+
- **`neetru agent release`** — o Core exige step-up MFA em **todos** os canais (H1: publicar release atinge a frota inteira via auto-update). Novo `--mfa-token <code>`; segue o `resolveStepUp` padrão (sessão de 1h → `--mfa-token` → prompt TOTP; fail-closed sem TTY). A URL de cada binário agora é **validada localmente** com a mesma regra do Core (`src/lib/agent-artifact-url.ts`): só `https://core.neetru.com/releases/...` ou o bucket GCS de releases (`neetru-agent-releases`, ou `NEETRU_AGENT_RELEASES_BUCKET`) — sem porta, sem credencial embutida. Fora disso: erro claro com as origens aceitas, **antes** de pedir MFA ou chamar a API. `--dry-run` segue sem MFA.
|
|
95
|
+
- **`neetru ops reg-token`** — step-up MFA obrigatório (H5) + `--mfa-token`.
|
|
96
|
+
- **`neetru ops bootstrap-admin`** — com admin existente o Core exige step-up MFA (H2). Como o CLI não sabe se já há admin, manda a sessão de 1h / `--mfa-token` se houver e, no `401 mfa_required`, prompta o TOTP e repete uma vez (em `--json`/não-TTY: fail-closed com `error: "mfa_required"`). Novo **`--reactivate`** (envia `reactivate: true`) para reativar staff desligado — sem ele o Core recusa com 409 `staff_disabled`.
|
|
97
|
+
- **`neetru ops migrate cli-keys`** — step-up MFA fora do `--dry-run` (M4) + `--mfa-token`. Dry-run segue sem MFA.
|
|
98
|
+
- **`neetru vm provision`** — step-up MFA obrigatório (M6: cada chamada cria uma VM faturada), resolvido depois da confirmação de custo + `--mfa-token`.
|
|
99
|
+
- **`neetru deploy --env prod|production`** — step-up MFA (M7, mesmo gate de `promote`) nos três alvos (vm, workspace, cloud-run), resolvido **logo antes** do `POST /api/cli/v1/deploy` (depois do build/upload, pra o TOTP não vencer no meio). Novo `--mfa-token`. `dev`/`staging` inalterados. Com `--non-interactive`/`--json` nunca prompta (fail-closed com instrução).
|
|
100
|
+
- **Mensagem do 401** — `handleApiError` distingue `401 mfa_required` ("Step-up MFA exigido: … passe --mfa-token ou rode `neetru auth mfa-session`"; `--json`: `error: "mfa_required"`) de token inválido, e mostra a `message`/`error_description` que o `requireCliAuth` do Core passou a mandar (M8). O 401 legado (`{error:"Unauthorized"}`) mantém o fallback "Execute: neetru login". Exit code segue 2. O parser do `apiRequest` passa a preferir `code` explícito ao `error` string (RFC) quando os dois vêm juntos.
|
|
101
|
+
- Não há comando `functions move|redeploy|revert` no CLI — o gate de MFA (M5) dessas rotas não tem superfície aqui.
|
|
102
|
+
|
|
103
|
+
Revisão adversarial do Core (`neetru-core` PR #512):
|
|
104
|
+
|
|
105
|
+
- **`neetru agent canary start`** — step-up MFA (start empurra a versão pra parte da frota, mesmo peso do rollback) + `--mfa-token`.
|
|
106
|
+
- **`neetru servers provision`** — MFA em **toda** provisão (M6; antes só com `--is-db-vm`).
|
|
107
|
+
- **`neetru admin database set-status`** — o Core exige MFA quando o banco está `active`/`degraded` (H3). Como o CLI não sabe o estado, usa `withStepUpRetry` (tenta; no `401 mfa_required` pede o TOTP e repete 1x) + `--mfa-token`. `archived` passou a ser recusado pelo Core nessa rota (use `db delete`).
|
|
108
|
+
- **Novo `neetru admin oidc-login rotate <clientId> --product-id <id> [--immediate]`** — `POST /api/cli/v1/products/{id}/oidc-login/rotate` com step-up MFA. Mesmo contrato do `create`: o Core **não devolve o secret** (vai pro Secret Manager e o próximo deploy o injeta server-side); a saída mostra `previousSecretValidUntil` (graça de 24h) ou, com `--immediate` (`{immediate:true}`), avisa que o secret anterior já não vale e o login cai até o próximo deploy.
|
|
109
|
+
- **`neetru ops bootstrap-admin`** sem admin existente — envia `x-bootstrap-secret` a partir de `--bootstrap-secret <valor>` ou env `NEETRU_BOOTSTRAP_SECRET` (nunca logado/impresso); com o segredo, a sessão CLI é opcional.
|
|
110
|
+
|
|
111
|
+
### Interno
|
|
112
|
+
|
|
113
|
+
- `cli-write`: `withStepUpRetry` (step-up condicional com retry único no `401 mfa_required`), `isMfaRequiredError`; `StepUpOptions` ganha `nonInteractive` e `skipSession`.
|
|
114
|
+
|
|
115
|
+
### Testes
|
|
116
|
+
|
|
117
|
+
- **`step-up-mfa-auditoria-cli-v1.test.ts`** (novo, `cli-write` real + `homedir` temporário): allowlist da URL (aceita/recusa, env do bucket); `agent release` (URL ruim → exit 1 sem MFA/API; header token/sessão; fail-closed; dry-run); `reg-token`; `bootstrap-admin` (sem 401 → 1 chamada; `--reactivate` no body; retry com prompt TOTP; sessão recusada → retry ignora a sessão; `--json` fail-closed; TOTP recusado não repete → exit 2); `migrate cli-keys` (dry-run sem header; aplicar com header; fail-closed); `vm provision`; `deploy` (`isProdEnv`, staging sem MFA, prod/production com header, `--non-interactive` não prompta mesmo com TTY); revisão #512: `agent canary start`, `servers provision` sem `--is-db-vm`, `admin database set-status` (sem 401 → sem MFA; retry com TOTP; `--json` fail-closed), `admin oidc-login rotate` (rota, body com/sem `immediate`, saída, fail-closed) e `bootstrap-admin --bootstrap-secret`/env (header enviado, valor nunca impresso, sessão opcional).
|
|
118
|
+
- `cli-mfa-destructive-surface.test.ts`: `servers provision` de app passa a exigir MFA (teste invertido); `agent canary start` e `servers provision` entram na enumeração destrutiva.
|
|
119
|
+
- **`api-error-401-shape.test.ts`** (novo): parser do 401 novo/legado/RFC/`mfa_required` via `fetch` stubado; mensagens e JSON do `handleApiError`.
|
|
120
|
+
- `ops-new-commands.test.ts` / `deploy.test.ts`: testes existentes de `migrate cli-keys` (aplicar) e `deploy --env prod` passam `mfaToken`; o de deploy afirma o header MFA no POST.
|
|
48
121
|
|
|
49
122
|
## [2.28.7] — 2026-09-07 (fix: `servers force-cleanup` sem step-up MFA — drift do P0.4)
|
|
50
123
|
|
package/README.md
CHANGED
|
@@ -199,7 +199,8 @@ neetru audit tail --json | jq 'select(.action | startswith("billing"))'
|
|
|
199
199
|
- **Tokens** salvos em `~/.config/neetru-cli/auth.json` (chmod 0600 em Unix, NTFS ACL em Windows). Desde 2.11.0 o resolver canônico (`getActiveTokenSync`) prefere esse arquivo sobre o Conf storage legado (que será removido em 2.12.0)
|
|
200
200
|
- **URL allowlist** (desde 2.11.0): `neetruApiUrl` rejeita hosts fora de `*.neetru.com` + `localhost` sem `--allow-untrusted-url` — fecha vetor de exfiltração do Bearer token
|
|
201
201
|
- **Rate-limit** por método HTTP: GET 120/min, POST/PUT/PATCH 30/min, DELETE 5/min
|
|
202
|
-
- **Step-up MFA** (TOTP) obrigatório em operações destrutivas: `--mfa-token <code>` ou prompt
|
|
202
|
+
- **Step-up MFA** (TOTP) obrigatório em operações destrutivas: sessão de 1h (`neetru auth mfa-session`), `--mfa-token <code>` ou prompt (em `--json`/sem TTY: fail-closed). Desde 2.28.10 também em `agent release` (todos os canais), `ops reg-token`, `ops bootstrap-admin` (quando já há admin; `--reactivate` reativa staff desligado), `ops migrate cli-keys` (fora do dry-run), `vm provision` e `deploy --env prod`
|
|
203
|
+
- **`agent release`** só aceita binários em `https://core.neetru.com/releases/...` ou no bucket GCS de releases (validado localmente, mesma regra do Core)
|
|
203
204
|
- **Dry-run** disponível em comandos de mutação: `--dry-run` mostra efeito SEM aplicar
|
|
204
205
|
- **Telemetry** opt-in (desde 2.11.0): habilitando `telemetry.enabled=true` o CLI emite `{command, durationMs, ok, exitCode}` anônimo via `installId` UUID. Zero token/path/email/env vazam
|
|
205
206
|
|
|
@@ -9,6 +9,24 @@ export interface OidcLoginCreateOptions {
|
|
|
9
9
|
json?: boolean;
|
|
10
10
|
}
|
|
11
11
|
export declare function runOidcLoginCreate(opts: OidcLoginCreateOptions): Promise<void>;
|
|
12
|
+
export interface OidcLoginRotateOptions {
|
|
13
|
+
productId?: string;
|
|
14
|
+
/** `--immediate` — revoga o secret anterior na hora (sem a graça de 24h). */
|
|
15
|
+
immediate?: boolean;
|
|
16
|
+
mfaToken?: string;
|
|
17
|
+
json?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* `neetru admin oidc-login rotate <clientId> --product-id <id> [--immediate]`
|
|
21
|
+
*
|
|
22
|
+
* `POST /api/cli/v1/products/{productId}/oidc-login/rotate` (H4, auditoria
|
|
23
|
+
* cli/v1 2026-09-29). Mesmo contrato de `create`: o Core NÃO devolve o
|
|
24
|
+
* `client_secret` — grava a versão nova no Secret Manager e o PRÓXIMO deploy a
|
|
25
|
+
* injeta server-side. O secret anterior segue aceito até
|
|
26
|
+
* `previousSecretValidUntil` (24h); com `--immediate` ele é revogado na hora e o
|
|
27
|
+
* login do produto fica fora até o próximo deploy. Step-up MFA obrigatório.
|
|
28
|
+
*/
|
|
29
|
+
export declare function runOidcLoginRotate(clientId: string, opts: OidcLoginRotateOptions): Promise<void>;
|
|
12
30
|
export interface OidcLoginListOptions {
|
|
13
31
|
productId?: string;
|
|
14
32
|
json?: boolean;
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* Sub-comandos:
|
|
14
14
|
* create — cria o login-client (PUBLIC/PKCE por default; --confidential p/ BFF)
|
|
15
15
|
* list — lista os login-clients do produto (mascarado, sem secret)
|
|
16
|
+
* rotate — rotaciona o client_secret (MFA; --immediate revoga o anterior na hora)
|
|
17
|
+
* rotate — rotaciona o client_secret (MFA; --immediate revoga o anterior na hora)
|
|
16
18
|
*
|
|
17
19
|
* Dois padrões de `redirect_uri` (o `/authorize` faz match EXATO byte-a-byte):
|
|
18
20
|
* - PUBLIC (PKCE client-side puro, ex.: NeetruLoginButton sem backend) → o SDK
|
|
@@ -23,6 +25,8 @@
|
|
|
23
25
|
* Endpoints (Core):
|
|
24
26
|
* GET /api/cli/v1/products/{productId}/oidc-login
|
|
25
27
|
* POST /api/cli/v1/products/{productId}/oidc-login
|
|
28
|
+
* POST /api/cli/v1/products/{productId}/oidc-login/rotate
|
|
29
|
+
* POST /api/cli/v1/products/{productId}/oidc-login/rotate
|
|
26
30
|
*/
|
|
27
31
|
import chalk from 'chalk';
|
|
28
32
|
import ora from 'ora';
|
|
@@ -111,6 +115,64 @@ export async function runOidcLoginCreate(opts) {
|
|
|
111
115
|
' bater com o que o SDK envia (PKCE client-side puro = a ORIGIN do produto).'));
|
|
112
116
|
console.log();
|
|
113
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* `neetru admin oidc-login rotate <clientId> --product-id <id> [--immediate]`
|
|
120
|
+
*
|
|
121
|
+
* `POST /api/cli/v1/products/{productId}/oidc-login/rotate` (H4, auditoria
|
|
122
|
+
* cli/v1 2026-09-29). Mesmo contrato de `create`: o Core NÃO devolve o
|
|
123
|
+
* `client_secret` — grava a versão nova no Secret Manager e o PRÓXIMO deploy a
|
|
124
|
+
* injeta server-side. O secret anterior segue aceito até
|
|
125
|
+
* `previousSecretValidUntil` (24h); com `--immediate` ele é revogado na hora e o
|
|
126
|
+
* login do produto fica fora até o próximo deploy. Step-up MFA obrigatório.
|
|
127
|
+
*/
|
|
128
|
+
export async function runOidcLoginRotate(clientId, opts) {
|
|
129
|
+
const token = await requireToken(opts.json);
|
|
130
|
+
function fail(message) {
|
|
131
|
+
if (opts.json) {
|
|
132
|
+
console.log(JSON.stringify({ ok: false, error: 'missing_param', message }));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
log.error(message);
|
|
136
|
+
}
|
|
137
|
+
return safeExit(1);
|
|
138
|
+
}
|
|
139
|
+
if (!clientId || !clientId.trim())
|
|
140
|
+
fail('<clientId> é obrigatório.');
|
|
141
|
+
if (!opts.productId)
|
|
142
|
+
fail('--product-id é obrigatório.');
|
|
143
|
+
const { headers } = await resolveStepUp({ mfaToken: opts.mfaToken, json: opts.json });
|
|
144
|
+
const spinner = opts.json
|
|
145
|
+
? null
|
|
146
|
+
: ora({ text: `Rotacionando credencial de ${clientId}…`, color: 'blue' }).start();
|
|
147
|
+
let res;
|
|
148
|
+
try {
|
|
149
|
+
res = await apiRequest(`/api/cli/v1/products/${encodeURIComponent(opts.productId)}/oidc-login/rotate`, {
|
|
150
|
+
method: 'POST',
|
|
151
|
+
token,
|
|
152
|
+
headers,
|
|
153
|
+
body: { clientId: clientId.trim(), ...(opts.immediate ? { immediate: true } : {}) },
|
|
154
|
+
});
|
|
155
|
+
spinner?.stop();
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
spinner?.fail('Falha ao rotacionar a credencial.');
|
|
159
|
+
handleApiError(error, opts.json);
|
|
160
|
+
}
|
|
161
|
+
if (opts.json) {
|
|
162
|
+
console.log(JSON.stringify(res));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
console.log();
|
|
166
|
+
log.success(`Credencial do login-client ${chalk.cyan(res.clientId)} rotacionada.`);
|
|
167
|
+
console.log(chalk.yellow(' NEETRU_CLIENT_SECRET novo → Secret Manager; NÃO é exibido. O próximo deploy o injeta server-side.'));
|
|
168
|
+
if (res.immediate || opts.immediate) {
|
|
169
|
+
console.log(chalk.red(' --immediate: o secret anterior JÁ NÃO VALE — o login do produto fica fora até o próximo deploy. Rode o deploy agora.'));
|
|
170
|
+
}
|
|
171
|
+
else if (res.previousSecretValidUntil) {
|
|
172
|
+
console.log(` ${chalk.dim('secret anterior aceito até')} ${res.previousSecretValidUntil} — faça o deploy antes disso.`);
|
|
173
|
+
}
|
|
174
|
+
console.log();
|
|
175
|
+
}
|
|
114
176
|
export async function runOidcLoginList(opts) {
|
|
115
177
|
const token = await requireToken(opts.json);
|
|
116
178
|
if (!opts.productId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc-login.js","sourceRoot":"","sources":["../../../src/commands/admin/oidc-login.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oidc-login.js","sourceRoot":"","sources":["../../../src/commands/admin/oidc-login.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,5 +9,7 @@ export interface AgentReleaseOptions {
|
|
|
9
9
|
artifact?: string[];
|
|
10
10
|
/** se setado, só monta o payload e imprime, não chama API */
|
|
11
11
|
dryRun?: boolean;
|
|
12
|
+
/** `--mfa-token <código>` — TOTP do step-up MFA (pula o prompt interativo). */
|
|
13
|
+
mfaToken?: string;
|
|
12
14
|
}
|
|
13
15
|
export declare function runAgentRelease(opts: AgentReleaseOptions): Promise<void>;
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* Backend: `POST api.neetru.com/cli/v1/agent/release` (Bearer token nrt_*),
|
|
12
12
|
* exige role `admin` em `cli_api_keys/{keyId}`.
|
|
13
13
|
*
|
|
14
|
+
* Auditoria cli/v1 2026-09-29 (H1): o Core exige step-up MFA em TODO canal
|
|
15
|
+
* (sessão de 1h via `neetru auth mfa-session` → `--mfa-token` → prompt TOTP) e
|
|
16
|
+
* só aceita `artifacts.<arch>.url` em `https://core.neetru.com/releases/...` ou
|
|
17
|
+
* no bucket GCS de releases — validado aqui ANTES de chamar a API.
|
|
18
|
+
*
|
|
14
19
|
* Roadmap:
|
|
15
20
|
* - Sprint futura: comando `--upload` que faz GCS upload + sha256 + register
|
|
16
21
|
* numa só chamada (precisa de credenciais GCP locais ou signed URL via Core).
|
|
@@ -23,12 +28,16 @@ import chalk from 'chalk';
|
|
|
23
28
|
import { log } from '../utils/logger.js';
|
|
24
29
|
import { apiRequest } from '../lib/api-client.js';
|
|
25
30
|
import { handleApiError } from '../lib/api-error.js';
|
|
31
|
+
import { resolveStepUp } from '../lib/cli-write.js';
|
|
32
|
+
import { AGENT_ARTIFACT_URL_HINT, agentReleasesBucket, isAllowedAgentArtifactUrl, } from '../lib/agent-artifact-url.js';
|
|
26
33
|
import { safeExit } from '../utils/safe-exit.js';
|
|
27
34
|
const VALID_CHANNELS = ['stable', 'beta', 'canary'];
|
|
28
35
|
const VALID_ARCHS = ['linux-x64', 'linux-arm64', 'darwin-x64', 'darwin-arm64'];
|
|
29
36
|
const SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
|
|
30
37
|
const SHA256_RE = /^[a-f0-9]{64}$/;
|
|
31
|
-
|
|
38
|
+
function gcsBase() {
|
|
39
|
+
return `https://storage.googleapis.com/${agentReleasesBucket()}/releases`;
|
|
40
|
+
}
|
|
32
41
|
function isArch(s) {
|
|
33
42
|
return VALID_ARCHS.includes(s);
|
|
34
43
|
}
|
|
@@ -125,7 +134,7 @@ export async function runAgentRelease(opts) {
|
|
|
125
134
|
const { arch, filePath } = parseBinaryArg(a);
|
|
126
135
|
log.info(`Computando sha256 de ${chalk.dim(filePath)}...`);
|
|
127
136
|
const { sha256, sizeBytes } = await sha256File(filePath);
|
|
128
|
-
const url = `${
|
|
137
|
+
const url = `${gcsBase()}/${encodeURIComponent(opts.version)}/neetru-agent-${arch}`;
|
|
129
138
|
artifacts[arch] = { url, sha256, sizeBytes };
|
|
130
139
|
log.success(` ${arch}: sha256=${sha256.slice(0, 12)}... (${(sizeBytes / 1_000_000).toFixed(1)} MB)`);
|
|
131
140
|
log.dim(` URL: ${url}`);
|
|
@@ -154,6 +163,18 @@ export async function runAgentRelease(opts) {
|
|
|
154
163
|
safeExit(1);
|
|
155
164
|
return;
|
|
156
165
|
}
|
|
166
|
+
// H1 (auditoria cli/v1 2026-09-29): mesma allowlist de origem do Core —
|
|
167
|
+
// falha aqui, com mensagem clara, em vez de um 400 genérico da API.
|
|
168
|
+
const badUrls = Object.entries(artifacts).filter(([, a]) => !isAllowedAgentArtifactUrl(a.url));
|
|
169
|
+
if (badUrls.length > 0) {
|
|
170
|
+
for (const [arch, a] of badUrls) {
|
|
171
|
+
log.error(`--artifact ${arch}: URL fora da origem permitida de releases: ${a.url}`);
|
|
172
|
+
}
|
|
173
|
+
log.dim(` Origens aceitas: ${AGENT_ARTIFACT_URL_HINT}`);
|
|
174
|
+
log.dim(' Suba o binário pro bucket de releases (ou use --binary, que deriva a URL canônica).');
|
|
175
|
+
safeExit(1);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
157
178
|
// ── payload ─────────────────────────────────────────────────────────
|
|
158
179
|
const payload = {
|
|
159
180
|
version: opts.version,
|
|
@@ -169,9 +190,13 @@ export async function runAgentRelease(opts) {
|
|
|
169
190
|
return;
|
|
170
191
|
}
|
|
171
192
|
log.info(`Registrando release ${chalk.bold(opts.version)} (channel=${chalk.bold(channel)}, ${Object.keys(artifacts).length} arch(s))...`);
|
|
193
|
+
// H1: publicar release atinge a frota inteira via auto-update — step-up MFA
|
|
194
|
+
// obrigatório em todos os canais (mesmo fluxo de `agent yank`).
|
|
195
|
+
const { headers } = await resolveStepUp({ mfaToken: opts.mfaToken });
|
|
172
196
|
try {
|
|
173
197
|
const r = await apiRequest('/api/cli/v1/agent/release', {
|
|
174
198
|
method: 'POST',
|
|
199
|
+
headers,
|
|
175
200
|
body: payload,
|
|
176
201
|
});
|
|
177
202
|
if (r.alreadyExists) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-release.js","sourceRoot":"","sources":["../../src/commands/agent-release.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agent-release.js","sourceRoot":"","sources":["../../src/commands/agent-release.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ export interface AgentYankOptions extends StepUpOptions {
|
|
|
5
5
|
export declare function runAgentYank(version: string, opts: AgentYankOptions): Promise<void>;
|
|
6
6
|
export declare function runAgentCanaryStart(version: string, opts: {
|
|
7
7
|
json?: boolean;
|
|
8
|
+
mfaToken?: string;
|
|
8
9
|
}): Promise<void>;
|
|
9
10
|
export interface AgentCanaryRollbackOptions extends StepUpOptions {
|
|
10
11
|
reason: string;
|
|
@@ -47,6 +47,9 @@ export async function runAgentCanaryStart(version, opts) {
|
|
|
47
47
|
safeExit(1);
|
|
48
48
|
}
|
|
49
49
|
const token = await requireToken(opts.json);
|
|
50
|
+
// Auditoria cli/v1 2026-09-29 (revisão): `start` empurra a versão pra parte da
|
|
51
|
+
// frota (5→25→100%) — o Core exige step-up MFA como no rollback.
|
|
52
|
+
const { headers } = await resolveStepUp({ mfaToken: opts.mfaToken, json: opts.json });
|
|
50
53
|
const spinner = opts.json
|
|
51
54
|
? null
|
|
52
55
|
: ora({ text: `Iniciando canary de ${version}…`, color: 'blue' }).start();
|
|
@@ -55,6 +58,7 @@ export async function runAgentCanaryStart(version, opts) {
|
|
|
55
58
|
res = await apiRequest('/api/cli/v1/agent/canary?action=start', {
|
|
56
59
|
method: 'POST',
|
|
57
60
|
token,
|
|
61
|
+
headers,
|
|
58
62
|
body: { version },
|
|
59
63
|
});
|
|
60
64
|
spinner?.stop();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-write.js","sourceRoot":"","sources":["../../src/commands/agent-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EACL,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GAEd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAMjD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAe,EACf,IAAsB;IAEtB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;QAC3E,QAAQ,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,kBAAkB,CACtB,oBAAoB,OAAO,oDAAoD,EAC/E,IAAI,CACL,CAAC;IACF,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI;QACvB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,oBAAoB,OAAO,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IACzE,IAAI,GAAgG,CAAC;IACrG,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,UAAU,CAAC,yBAAyB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE;YACnF,MAAM,EAAE,MAAM;YACd,KAAK;YACL,OAAO;YACP,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;SACvC,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC1C,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IACD,gBAAgB,CACd,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAC/D,WAAW,GAAG,CAAC,OAAO,WAAW,EACjC,IAAI,CAAC,IAAI,CACV,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,
|
|
1
|
+
{"version":3,"file":"agent-write.js","sourceRoot":"","sources":["../../src/commands/agent-write.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/code.js
CHANGED
|
@@ -17,7 +17,9 @@ import { CliApiError } from '../lib/api-client.js';
|
|
|
17
17
|
import { buildSystemPrompt } from '../lib/code-agent-tools.js';
|
|
18
18
|
import { CODE_SKILLS_ROOT, installAllBuiltinSkills, loadCodeSkills, normalizeSkillName } from '../lib/code-agent-skills.js';
|
|
19
19
|
import { printBox, printEvent, printAssistantText, printPatchPreview, patchSummaryRows, renderHeader, renderInteractiveHelp, renderSessionStatus, renderPromptLabel, printFileSample, printFilePicker, printSessionList, startTurnSpinner, summarizeToolResult, } from '../lib/code-agent-ui.js';
|
|
20
|
-
|
|
20
|
+
// `../lib/code-agent-tui.js` (ink + react + ink-text-input) NAO e importado
|
|
21
|
+
// aqui de proposito: e carregado sob demanda em `runInteractive` — ver o
|
|
22
|
+
// comentario no ponto de uso (bug_b1e9af59).
|
|
21
23
|
import { configureSubagentRunner, startSubagent, stopSubagent, stopAllSubagents, listSubagents, getSubagentResult, getApplicablePatch, onSubagentSettled, } from '../lib/code-agent-subagents.js';
|
|
22
24
|
/** Spinner inerte pro modo silencioso (subagentes) — nunca escreve no terminal. */
|
|
23
25
|
const NOOP_TURN_SPINNER = { update: () => { }, stop: () => { } };
|
|
@@ -904,6 +906,13 @@ async function runInteractive(settings) {
|
|
|
904
906
|
}
|
|
905
907
|
});
|
|
906
908
|
try {
|
|
909
|
+
// Import sob demanda (bug_b1e9af59): a TUI arrasta ink + react +
|
|
910
|
+
// ink-text-input, que so a sessao interativa usa. Import estatico fazia o
|
|
911
|
+
// one-shot (`neetru code "tarefa"`) e todo teste que importa este modulo
|
|
912
|
+
// pagarem esse custo de carga — na suite inteira o 1o teste de
|
|
913
|
+
// code-session.test.ts estourava o testTimeout so no import. Dentro do
|
|
914
|
+
// `try` para o `finally` limpar subagentes mesmo se o import falhar.
|
|
915
|
+
const { runInkSession } = await import('../lib/code-agent-tui.js');
|
|
907
916
|
await runInkSession({
|
|
908
917
|
initialPromptLabel: renderPromptLabel(settings),
|
|
909
918
|
statusLine: formatCodeStatusLine(settings),
|