@neetru/cli 2.4.0 → 2.6.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.
@@ -0,0 +1,359 @@
1
+ /**
2
+ * `neetru ops` — comandos de operação interna do Neetru Core.
3
+ *
4
+ * Substitui os scripts ad-hoc em scripts/ com interface consistente, autenticação
5
+ * via Bearer token e flags --dry-run onde há mutação.
6
+ *
7
+ * Namespace ops:
8
+ * neetru ops heartbeat — checar heartbeat do agente em um server
9
+ * neetru ops smoke notification — dispara notification de smoke end-to-end
10
+ * neetru ops smoke observability — smoke test do pipeline de observability
11
+ * neetru ops reg-token <serverId> — gerar registration token para um server
12
+ * neetru ops resolve-errors — resolver erros abertos em lote
13
+ * neetru ops openapi-diff — detectar breaking changes na spec OpenAPI
14
+ *
15
+ * TODO (próximo sprint): bootstrap-admin, backfill incidents-source, backfill workspaces,
16
+ * seed api-catalog, rehash-sdk-secrets, migrate cli-keys.
17
+ */
18
+ import chalk from 'chalk';
19
+ import ora from 'ora';
20
+ import { apiRequest } from '../lib/api-client.js';
21
+ import { requireToken, handleApiError } from '../lib/cli-read.js';
22
+ import { log } from '../utils/logger.js';
23
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
24
+ function deprecationBanner(scriptName, command) {
25
+ console.warn(chalk.yellow(`[aviso] scripts/${scriptName} está deprecado. Use: neetru ${command}`));
26
+ }
27
+ export async function runOpsHeartbeat(opts) {
28
+ const token = await requireToken(opts.json);
29
+ const serverId = opts.serverId ?? 'srv-test-01';
30
+ const spinner = opts.json ? null : ora({ text: `Verificando heartbeat de ${serverId}…`, color: 'blue' }).start();
31
+ let res;
32
+ try {
33
+ res = await apiRequest(`/api/cli/v1/ops/heartbeat?serverId=${encodeURIComponent(serverId)}`, { token });
34
+ spinner?.stop();
35
+ }
36
+ catch (error) {
37
+ spinner?.fail('Falha ao verificar heartbeat.');
38
+ handleApiError(error, opts.json);
39
+ }
40
+ if (opts.json) {
41
+ console.log(JSON.stringify(res));
42
+ return;
43
+ }
44
+ const data = res;
45
+ const exists = data.exists;
46
+ if (!exists) {
47
+ console.log(chalk.red(` server/${serverId} NÃO ENCONTRADO`));
48
+ return;
49
+ }
50
+ const fields = data.fields;
51
+ console.log(chalk.bold(`=== servers/${serverId} ===`));
52
+ if (fields) {
53
+ for (const [k, v] of Object.entries(fields).sort()) {
54
+ console.log(` ${chalk.cyan(k)}: ${JSON.stringify(v)}`);
55
+ }
56
+ }
57
+ }
58
+ export async function runOpsSmokeNotification(opts) {
59
+ const token = await requireToken(opts.json);
60
+ const body = {
61
+ recipientRole: opts.recipientRole ?? 'admin',
62
+ recipientUid: opts.recipientUid,
63
+ kind: opts.kind ?? 'smoke_test',
64
+ title: opts.title,
65
+ link: opts.link ?? '/dashboard',
66
+ };
67
+ const spinner = opts.json ? null : ora({ text: 'Disparando smoke notification…', color: 'blue' }).start();
68
+ let res;
69
+ try {
70
+ res = await apiRequest('/api/cli/v1/ops/smoke/notification', {
71
+ method: 'POST',
72
+ body,
73
+ token,
74
+ });
75
+ spinner?.stop();
76
+ }
77
+ catch (error) {
78
+ spinner?.fail('Falha ao disparar smoke notification.');
79
+ handleApiError(error, opts.json);
80
+ }
81
+ if (opts.json) {
82
+ console.log(JSON.stringify(res));
83
+ return;
84
+ }
85
+ const data = res;
86
+ const action = data.action;
87
+ if (action === 'dedup') {
88
+ log.warn(`DEDUP: notification existente ${String(data.docId ?? '')} — occurrences incrementado.`);
89
+ }
90
+ else {
91
+ log.success(`Notification criada: ${String(data.docId ?? '')}`);
92
+ }
93
+ console.log(' Valide em core.neetru.com: sino no header deve mostrar badge unread.');
94
+ }
95
+ export async function runOpsSmokeObservability(opts) {
96
+ const token = await requireToken(opts.json);
97
+ const body = {
98
+ baseUrl: opts.baseUrl ?? 'https://core.neetru.com',
99
+ bearer: opts.bearer,
100
+ waitSec: opts.waitSec ?? 30,
101
+ };
102
+ const spinner = opts.json
103
+ ? null
104
+ : ora({ text: 'Executando smoke observability (aguarda settle)…', color: 'blue' }).start();
105
+ let res;
106
+ try {
107
+ // timeout longo pois o endpoint aguarda settle do Firestore
108
+ res = await apiRequest('/api/cli/v1/ops/smoke/observability', {
109
+ method: 'POST',
110
+ body,
111
+ token,
112
+ });
113
+ spinner?.stop();
114
+ }
115
+ catch (error) {
116
+ spinner?.fail('Falha ao executar smoke observability.');
117
+ handleApiError(error, opts.json);
118
+ }
119
+ if (opts.json) {
120
+ console.log(JSON.stringify(res));
121
+ return;
122
+ }
123
+ const data = res;
124
+ const probes = data.probes;
125
+ console.log(chalk.bold('\nResultado do smoke observability:'));
126
+ if (probes && probes.length > 0) {
127
+ const header = ` ${'FONTE'.padEnd(22)} ${'STATUS HTTP'.padEnd(12)} ${'ÚLTIMA (s)'.padEnd(12)} MATCH`;
128
+ const sep = ` ${'─'.repeat(22)} ${'─'.repeat(12)} ${'─'.repeat(12)} ─────`;
129
+ console.log(chalk.dim(header));
130
+ console.log(chalk.dim(sep));
131
+ for (const p of probes) {
132
+ const matched = p.matched ? chalk.green('SIM') : chalk.red('NÃO');
133
+ console.log(` ${String(p.source ?? '').padEnd(22)} ${String(p.endpointStatus ?? '—').padEnd(12)} ${String(p.lastAgeSec ?? '—').padEnd(12)} ${matched}`);
134
+ }
135
+ }
136
+ const tag = data.runTag;
137
+ if (tag)
138
+ console.log(chalk.dim(`\n run tag: ${tag}`));
139
+ }
140
+ export async function runOpsRegToken(serverId, opts) {
141
+ const token = await requireToken(opts.json);
142
+ const spinner = opts.json ? null : ora({ text: `Gerando registration token para ${serverId}…`, color: 'blue' }).start();
143
+ let res;
144
+ try {
145
+ res = await apiRequest('/api/cli/v1/ops/reg-token', {
146
+ method: 'POST',
147
+ body: { serverId, expiresMin: opts.expiresMin ?? 30 },
148
+ token,
149
+ });
150
+ spinner?.stop();
151
+ }
152
+ catch (error) {
153
+ spinner?.fail('Falha ao gerar registration token.');
154
+ handleApiError(error, opts.json);
155
+ }
156
+ if (opts.json) {
157
+ console.log(JSON.stringify(res));
158
+ return;
159
+ }
160
+ const data = res;
161
+ console.log(chalk.bold('Registration token gerado:'));
162
+ console.log(` ${chalk.green(String(data.token ?? ''))}`);
163
+ console.log(` server: ${String(data.serverId ?? serverId)}`);
164
+ console.log(` expira em: ${String(data.expiresAt ?? '—')}`);
165
+ console.log(chalk.dim(' (use este token no agente durante o registro — uso único)'));
166
+ }
167
+ export async function runOpsResolveErrors(opts) {
168
+ const token = await requireToken(opts.json);
169
+ if (!opts.dryRun && !opts.json) {
170
+ const { default: readline } = await import('node:readline');
171
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
172
+ const answer = await new Promise((resolve) => {
173
+ rl.question(chalk.yellow('Isso irá marcar TODOS os erros abertos como resolvidos. Confirmar? (sim/não): '), (a) => {
174
+ rl.close();
175
+ resolve(a.trim().toLowerCase());
176
+ });
177
+ });
178
+ if (answer !== 'sim' && answer !== 's') {
179
+ log.warn('Operação cancelada.');
180
+ process.exit(0);
181
+ }
182
+ }
183
+ const spinner = opts.json ? null : ora({ text: `Resolvendo erros abertos${opts.dryRun ? ' (dry-run)' : ''}…`, color: 'blue' }).start();
184
+ let res;
185
+ try {
186
+ res = await apiRequest('/api/cli/v1/ops/resolve-errors', {
187
+ method: 'POST',
188
+ body: {
189
+ dryRun: opts.dryRun ?? false,
190
+ resolvedBy: opts.resolvedBy ?? `cli-ops-${new Date().toISOString().slice(0, 10)}`,
191
+ },
192
+ token,
193
+ });
194
+ spinner?.stop();
195
+ }
196
+ catch (error) {
197
+ spinner?.fail('Falha ao resolver erros.');
198
+ handleApiError(error, opts.json);
199
+ }
200
+ if (opts.json) {
201
+ console.log(JSON.stringify(res));
202
+ return;
203
+ }
204
+ const data = res;
205
+ const results = data.results;
206
+ console.log(chalk.bold(`\nResultado (modo: ${opts.dryRun ? 'DRY-RUN' : 'WRITE'}):`));
207
+ if (results) {
208
+ for (const r of results) {
209
+ const skipped = r.skipped ? ` (+${r.skipped} dry-run skipped)` : '';
210
+ console.log(` ${r.collection}: ${chalk.green(String(r.resolved))} resolvidos${skipped}`);
211
+ }
212
+ }
213
+ }
214
+ export async function runOpsOpenapiDiff(opts) {
215
+ const token = await requireToken(opts.json);
216
+ const spinner = opts.json ? null : ora({ text: 'Verificando diff da spec OpenAPI…', color: 'blue' }).start();
217
+ let res;
218
+ try {
219
+ res = await apiRequest('/api/cli/v1/ops/openapi-diff', {
220
+ method: 'POST',
221
+ body: { update: opts.update ?? false },
222
+ token,
223
+ });
224
+ spinner?.stop();
225
+ }
226
+ catch (error) {
227
+ spinner?.fail('Falha ao checar OpenAPI diff.');
228
+ handleApiError(error, opts.json);
229
+ }
230
+ if (opts.json) {
231
+ console.log(JSON.stringify(res));
232
+ return;
233
+ }
234
+ const data = res;
235
+ const breakingChanges = data.breakingChanges;
236
+ const snapshotUpdated = data.snapshotUpdated;
237
+ const status = data.status;
238
+ if (status === 'no_snapshot') {
239
+ log.success('Snapshot inicial criado. Adicione docs/openapi-snapshot.json ao commit.');
240
+ return;
241
+ }
242
+ if (status === 'updated') {
243
+ log.success('Snapshot atualizado com --update.');
244
+ return;
245
+ }
246
+ if (breakingChanges && breakingChanges.length > 0) {
247
+ console.log(chalk.red('\nBREAKING CHANGES DETECTADOS:'));
248
+ for (const b of breakingChanges) {
249
+ console.log(` ${chalk.red('–')} ${b}`);
250
+ }
251
+ console.log(chalk.yellow('\n Recomendação: bump de versão major na spec (info.version).'));
252
+ console.log(chalk.dim(' Para atualizar: neetru ops openapi-diff --update'));
253
+ }
254
+ else if (snapshotUpdated) {
255
+ log.success('Spec mudou sem breaking changes — snapshot atualizado.');
256
+ }
257
+ else {
258
+ log.success('Sem mudanças na spec. Snapshot inalterado.');
259
+ }
260
+ }
261
+ // ─── Registro do comando `ops` em program ─────────────────────────────────────
262
+ export function registerOpsCommand(program) {
263
+ const opsCmd = program
264
+ .command('ops')
265
+ .description('Operações internas do Core (migrado de scripts/)');
266
+ // ── ops heartbeat ──────────────────────────────────────────────────────────
267
+ opsCmd
268
+ .command('heartbeat')
269
+ .description('Verificar heartbeat e estado de um server')
270
+ .option('--server-id <id>', 'ID do server (default: srv-test-01)', 'srv-test-01')
271
+ .option('--json', 'saída em JSON')
272
+ .action(async (cmdOpts) => {
273
+ await runOpsHeartbeat({ serverId: cmdOpts.serverId, json: !!cmdOpts.json });
274
+ });
275
+ // ── ops smoke ──────────────────────────────────────────────────────────────
276
+ const smokeCmd = opsCmd
277
+ .command('smoke')
278
+ .description('Smoke tests end-to-end do Core');
279
+ smokeCmd
280
+ .command('notification')
281
+ .description('Disparar notification de smoke e validar fluxo de alertas')
282
+ .option('--recipient-role <role>', 'role destinatário (admin|operator|billing|viewer)', 'admin')
283
+ .option('--recipient-uid <uid>', 'uid específico (prevalece sobre --recipient-role)')
284
+ .option('--kind <kind>', 'kind da notification (default: smoke_test)', 'smoke_test')
285
+ .option('--title <title>', 'título da notification')
286
+ .option('--link <link>', 'link de destino (default: /dashboard)', '/dashboard')
287
+ .option('--json', 'saída em JSON')
288
+ .action(async (cmdOpts) => {
289
+ await runOpsSmokeNotification({
290
+ recipientRole: cmdOpts.recipientRole,
291
+ recipientUid: cmdOpts.recipientUid,
292
+ kind: cmdOpts.kind,
293
+ title: cmdOpts.title,
294
+ link: cmdOpts.link,
295
+ json: !!cmdOpts.json,
296
+ });
297
+ });
298
+ smokeCmd
299
+ .command('observability')
300
+ .description('Smoke test fim-a-fim do pipeline de observability')
301
+ .option('--base-url <url>', 'base URL do Core', 'https://core.neetru.com')
302
+ .option('--bearer <token>', 'Bearer token da CLI key (opcional — exercita telemetry log)')
303
+ .option('--wait-sec <n>', 'segundos de espera para Firestore propagar (default: 30)', '30')
304
+ .option('--json', 'saída em JSON')
305
+ .action(async (cmdOpts) => {
306
+ await runOpsSmokeObservability({
307
+ baseUrl: cmdOpts.baseUrl,
308
+ bearer: cmdOpts.bearer,
309
+ waitSec: cmdOpts.waitSec ? Number.parseInt(cmdOpts.waitSec, 10) : 30,
310
+ json: !!cmdOpts.json,
311
+ });
312
+ });
313
+ // ── ops reg-token ──────────────────────────────────────────────────────────
314
+ opsCmd
315
+ .command('reg-token <serverId>')
316
+ .description('Gerar registration token para um server (uso único, expira em 30min)')
317
+ .option('--expires-min <n>', 'minutos até expiração (default: 30)', '30')
318
+ .option('--json', 'saída em JSON')
319
+ .action(async (serverId, cmdOpts) => {
320
+ await runOpsRegToken(serverId, {
321
+ expiresMin: cmdOpts.expiresMin ? Number.parseInt(cmdOpts.expiresMin, 10) : 30,
322
+ json: !!cmdOpts.json,
323
+ });
324
+ });
325
+ // ── ops resolve-errors ─────────────────────────────────────────────────────
326
+ opsCmd
327
+ .command('resolve-errors')
328
+ .description('Marcar todos os erros abertos (client_errors + server_errors) como resolvidos')
329
+ .option('--dry-run', 'lista o que seria resolvido sem aplicar')
330
+ .option('--resolved-by <id>', 'identificador do ator (default: cli-ops-<data>')
331
+ .option('--yes', 'pula confirmação interativa')
332
+ .option('--json', 'saída em JSON')
333
+ .action(async (cmdOpts) => {
334
+ await runOpsResolveErrors({
335
+ dryRun: !!cmdOpts.dryRun,
336
+ resolvedBy: cmdOpts.resolvedBy,
337
+ json: !!cmdOpts.json,
338
+ });
339
+ });
340
+ // ── ops openapi-diff ───────────────────────────────────────────────────────
341
+ opsCmd
342
+ .command('openapi-diff')
343
+ .description('Detectar breaking changes na spec OpenAPI comparando com o snapshot')
344
+ .option('--update', 'atualizar o snapshot sem checar breaking changes')
345
+ .option('--json', 'saída em JSON')
346
+ .action(async (cmdOpts) => {
347
+ await runOpsOpenapiDiff({ update: !!cmdOpts.update, json: !!cmdOpts.json });
348
+ });
349
+ // ── TODO (próximo sprint) ──────────────────────────────────────────────────
350
+ // - neetru ops bootstrap-admin (→ scripts/bootstrap-admin.ts)
351
+ // - neetru ops backfill incidents-source (→ scripts/backfill-incidents-source.ts)
352
+ // - neetru ops backfill workspaces (→ scripts/backfill-workspaces.ts)
353
+ // - neetru ops seed api-catalog (→ scripts/seed-api-catalog.mjs)
354
+ // - neetru ops rehash-sdk-secrets (→ scripts/rehash-sdk-client-secrets.mjs)
355
+ // - neetru ops migrate cli-keys (→ scripts/migrate-cli-api-keys.mjs)
356
+ }
357
+ // ─── Re-export deprecation helper para uso em scripts/ ───────────────────────
358
+ export { deprecationBanner };
359
+ //# sourceMappingURL=ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ops.js","sourceRoot":"","sources":["../../src/commands/ops.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -822,13 +822,14 @@ program
822
822
  .command('logs')
823
823
  .description('Visualizar logs do workspace (suporta tail contínuo)')
824
824
  .option('--client-id <id>', 'oauthClientId do workspace')
825
- .option('-f, --follow', 'tail contínuo (poll a cada 5s)')
825
+ .option('-f, --follow', 'tail contínuo (poll a cada 5s, SSE se disponível)')
826
826
  .option('-n, --lines <count>', 'número de linhas a buscar', '50')
827
827
  .option('--since <duration>', 'logs desde N atrás (ex: 30m, 2h, 1d)', '15m')
828
828
  .option('--level <level>', 'filtrar por nível: info | warn | error | debug')
829
829
  .option('--product <product>', 'v1.3 — filtrar por productId')
830
830
  .option('--channel <channel>', 'v1.3 — filtrar por channel (stdout | stderr | app)')
831
831
  .option('--correlation-id <id>', 'v1.3 — filtrar por correlationId (UUID)')
832
+ .option('--json', 'saída em JSON (NDJSON linha a linha, útil para pipes)')
832
833
  .action(async (opts) => {
833
834
  const { runLogs } = await import('./commands/logs.js');
834
835
  await runLogs({
@@ -840,6 +841,7 @@ program
840
841
  product: opts.product,
841
842
  channel: opts.channel,
842
843
  correlationId: opts.correlationId,
844
+ json: !!opts.json,
843
845
  });
844
846
  });
845
847
  // ── neetru validate ───────────────────────────────────────────────────
@@ -913,14 +915,38 @@ mocksCmd
913
915
  // ── neetru env ────────────────────────────────────────────────────────
914
916
  const envCmd = program
915
917
  .command('env')
916
- .description('Gerenciar NEETRU_ENV no .env.local');
918
+ .description('Gerenciar NEETRU_ENV (.env.local) e env vars de serviços Cloud Run');
917
919
  envCmd
918
920
  .command('switch <target>')
919
- .description('Alternar NEETRU_ENV (dev/workspace/production)')
921
+ .description('Alternar NEETRU_ENV (dev/workspace/production) no .env.local')
920
922
  .action(async (target) => {
921
923
  const { runEnvSwitch } = await import('./commands/env.js');
922
924
  await runEnvSwitch({ target });
923
925
  });
926
+ envCmd
927
+ .command('set')
928
+ .description('Setar env vars de um serviço Cloud Run (merge, step-up MFA)')
929
+ .requiredOption('--service <service>', 'nome do serviço Cloud Run alvo')
930
+ .option('--set <KEY=VALUE>', 'env var literal (repetível)', (v, acc = []) => [...acc, v], [])
931
+ .option('--secret <KEY=secretName[:version]>', 'env var via Secret Manager (repetível)', (v, acc = []) => [...acc, v], [])
932
+ .option('--unset <KEY>', 'remover env var (repetível)', (v, acc = []) => [...acc, v], [])
933
+ .option('--mfa-token <code>', 'código TOTP (step-up MFA, pula prompt)')
934
+ .option('--dry-run', 'valida e mostra efeito sem aplicar')
935
+ .option('--yes', 'pula confirmações (modo script)')
936
+ .option('--json', 'saída em JSON')
937
+ .action(async (opts) => {
938
+ const { runEnvSet } = await import('./commands/env.js');
939
+ await runEnvSet({
940
+ service: opts.service,
941
+ set: opts.set,
942
+ secret: opts.secret,
943
+ unset: opts.unset,
944
+ mfaToken: opts.mfaToken,
945
+ dryRun: !!opts.dryRun,
946
+ yes: !!opts.yes,
947
+ json: !!opts.json,
948
+ });
949
+ });
924
950
  // ── neetru db ─────────────────────────────────────────────────────────
925
951
  const dbCmd = program
926
952
  .command('db')
@@ -994,6 +1020,24 @@ program
994
1020
  const { runDoctor } = await import('./commands/doctor.js');
995
1021
  await runDoctor({ json: !!opts.json });
996
1022
  });
1023
+ // ── neetru bootstrap ──────────────────────────────────────────────────
1024
+ // Setup zero-to-working da máquina dev: checa Node/gcloud/Docker/Firebase/git,
1025
+ // roda `npm ci` no cwd se necessário, faz `gcloud auth ADC login`,
1026
+ // e termina rodando `neetru doctor` pra confirmar.
1027
+ program
1028
+ .command('bootstrap')
1029
+ .description('Setup completo da máquina dev (binários + deps NPM + ADC)')
1030
+ .option('-y, --yes', 'aceita todos os auto-installs sem prompt')
1031
+ .option('--check', 'só lista o que falta, sem instalar nada')
1032
+ .option('--json', 'saída em JSON (machine-readable)')
1033
+ .action(async (opts) => {
1034
+ const { runBootstrap } = await import('./commands/bootstrap.js');
1035
+ await runBootstrap({
1036
+ yes: !!opts.yes,
1037
+ check: !!opts.check,
1038
+ json: !!opts.json,
1039
+ });
1040
+ });
997
1041
  // ── neetru upgrade ────────────────────────────────────────────────────
998
1042
  program
999
1043
  .command('upgrade')
@@ -1179,6 +1223,49 @@ hostingCmd
1179
1223
  const { runHostingList } = await import('./commands/infra-read.js');
1180
1224
  await runHostingList({ json: !!opts.json });
1181
1225
  });
1226
+ hostingCmd
1227
+ .command('create-mapping')
1228
+ .description('Criar domain mapping pra serviço Cloud Run (admin + step-up MFA)')
1229
+ .requiredOption('--service <service>', 'nome do serviço Cloud Run alvo')
1230
+ .requiredOption('--domain <domain>', 'domínio FQDN (ex: api.dev.neetru.com)')
1231
+ .option('--mfa-token <code>', 'código TOTP (step-up MFA, pula prompt)')
1232
+ .option('--dry-run', 'valida e mostra efeito sem aplicar')
1233
+ .option('--yes', 'pula confirmações (modo script)')
1234
+ .option('--json', 'saída em JSON')
1235
+ .action(async (opts) => {
1236
+ const { runHostingCreateMapping } = await import('./commands/hosting-write.js');
1237
+ await runHostingCreateMapping({
1238
+ service: opts.service,
1239
+ domain: opts.domain,
1240
+ mfaToken: opts.mfaToken,
1241
+ dryRun: !!opts.dryRun,
1242
+ yes: !!opts.yes,
1243
+ json: !!opts.json,
1244
+ });
1245
+ });
1246
+ // ── neetru artifact-registry ─────────────────────────────────────────
1247
+ const arCmd = program
1248
+ .command('artifact-registry')
1249
+ .alias('ar')
1250
+ .description('Gerenciar repositórios do Artifact Registry');
1251
+ arCmd
1252
+ .command('create <name>')
1253
+ .description('Criar repositório (one-shot por produto) — admin only')
1254
+ .option('--location <location>', 'região (default us-central1)', 'us-central1')
1255
+ .option('--format <format>', 'DOCKER (default) | NPM | MAVEN | PYTHON | APT | YUM | GO | KFP', 'DOCKER')
1256
+ .option('--description <text>', 'descrição opcional')
1257
+ .option('--dry-run', 'valida e mostra efeito sem aplicar')
1258
+ .option('--json', 'saída em JSON')
1259
+ .action(async (name, opts) => {
1260
+ const { runArtifactRegistryCreate } = await import('./commands/artifact-registry.js');
1261
+ await runArtifactRegistryCreate(name, {
1262
+ location: opts.location,
1263
+ format: opts.format,
1264
+ description: opts.description,
1265
+ dryRun: !!opts.dryRun,
1266
+ json: !!opts.json,
1267
+ });
1268
+ });
1182
1269
  // ── neetru builds ────────────────────────────────────────────────────
1183
1270
  program
1184
1271
  .command('builds')
@@ -1234,6 +1321,13 @@ drCmd
1234
1321
  const { registerSchemaCommand } = await import('./commands/schema.js');
1235
1322
  registerSchemaCommand(program);
1236
1323
  }
1324
+ // ── neetru ops ────────────────────────────────────────────────────────
1325
+ // Operações internas migradas de scripts/ (heartbeat, smoke, reg-token,
1326
+ // resolve-errors, openapi-diff). Substitui acesso ad-hoc via tsx/node.
1327
+ {
1328
+ const { registerOpsCommand } = await import('./commands/ops.js');
1329
+ registerOpsCommand(program);
1330
+ }
1237
1331
  // ── parse ─────────────────────────────────────────────────────────────
1238
1332
  if (!process.argv.slice(2).length) {
1239
1333
  if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {