@nio-cli/cli 0.3.7 → 0.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.
Files changed (163) hide show
  1. package/.env.example +88 -12
  2. package/Dockerfile.gateway +13 -5
  3. package/README.md +186 -78
  4. package/dist/adapters/lang/vendor.js +5 -10
  5. package/dist/adapters/lang/vendor.js.map +1 -1
  6. package/dist/adapters/pg/auth-event-repository.js +30 -0
  7. package/dist/adapters/pg/auth-event-repository.js.map +1 -0
  8. package/dist/adapters/pg/client.js +24 -4
  9. package/dist/adapters/pg/client.js.map +1 -1
  10. package/dist/adapters/pg/login-challenge-repository.js.map +1 -1
  11. package/dist/adapters/pg/login-ip-repository.js +26 -0
  12. package/dist/adapters/pg/login-ip-repository.js.map +1 -0
  13. package/dist/adapters/pg/user-repository.js +47 -18
  14. package/dist/adapters/pg/user-repository.js.map +1 -1
  15. package/dist/adapters/sms/whatsapp.js +83 -0
  16. package/dist/adapters/sms/whatsapp.js.map +1 -0
  17. package/dist/app/ai-client.js +2 -2
  18. package/dist/app/ai-client.js.map +1 -1
  19. package/dist/brand.js +1 -1
  20. package/dist/brand.js.map +1 -1
  21. package/dist/cli/commands/ai.js +2 -2
  22. package/dist/cli/commands/ai.js.map +1 -1
  23. package/dist/cli/commands/auth.js +27 -20
  24. package/dist/cli/commands/auth.js.map +1 -1
  25. package/dist/cli/commands/config.js +17 -7
  26. package/dist/cli/commands/config.js.map +1 -1
  27. package/dist/cli/commands/docker.js +4 -4
  28. package/dist/cli/commands/docker.js.map +1 -1
  29. package/dist/cli/commands/docs/content.js +80 -11
  30. package/dist/cli/commands/docs/content.js.map +1 -1
  31. package/dist/cli/commands/exec.js +1 -12
  32. package/dist/cli/commands/exec.js.map +1 -1
  33. package/dist/cli/commands/init/index.js +1 -2
  34. package/dist/cli/commands/init/index.js.map +1 -1
  35. package/dist/cli/commands/init/provision-step.js +2 -20
  36. package/dist/cli/commands/init/provision-step.js.map +1 -1
  37. package/dist/cli/commands/plan.js +1 -12
  38. package/dist/cli/commands/plan.js.map +1 -1
  39. package/dist/cli/commands/security.js +82 -11
  40. package/dist/cli/commands/security.js.map +1 -1
  41. package/dist/cli/commands/sync.js +9 -19
  42. package/dist/cli/commands/sync.js.map +1 -1
  43. package/dist/cli/commands/validate-plan.js +1 -10
  44. package/dist/cli/commands/validate-plan.js.map +1 -1
  45. package/dist/cli/copy/flows.json +1 -2
  46. package/dist/cli/copy.js.map +1 -1
  47. package/dist/cli/flows/dependencies.js +0 -4
  48. package/dist/cli/flows/dependencies.js.map +1 -1
  49. package/dist/cli/help-guide.js +69 -0
  50. package/dist/cli/help-guide.js.map +1 -0
  51. package/dist/cli/program.js +3 -3
  52. package/dist/cli/program.js.map +1 -1
  53. package/dist/cli/ui/render.js +0 -27
  54. package/dist/cli/ui/render.js.map +1 -1
  55. package/dist/cli.js +10 -2
  56. package/dist/cli.js.map +1 -1
  57. package/dist/gateway/config.js +23 -1
  58. package/dist/gateway/config.js.map +1 -1
  59. package/dist/gateway/edge-filter.js +20 -3
  60. package/dist/gateway/edge-filter.js.map +1 -1
  61. package/dist/gateway/index.js +145 -22
  62. package/dist/gateway/index.js.map +1 -1
  63. package/dist/gateway/middleware/auth.js +15 -3
  64. package/dist/gateway/middleware/auth.js.map +1 -1
  65. package/dist/gateway/services/login.js +52 -17
  66. package/dist/gateway/services/login.js.map +1 -1
  67. package/dist/gateway/services/register.js +20 -0
  68. package/dist/gateway/services/register.js.map +1 -0
  69. package/dist/gateway/services/security.js +69 -16
  70. package/dist/gateway/services/security.js.map +1 -1
  71. package/dist/gateway/throttle.js +57 -0
  72. package/dist/gateway/throttle.js.map +1 -0
  73. package/dist/lib/auth/backup-codes.js +4 -4
  74. package/dist/lib/auth/backup-codes.js.map +1 -1
  75. package/dist/lib/auth/breach-check.js +58 -0
  76. package/dist/lib/auth/breach-check.js.map +1 -0
  77. package/dist/lib/auth/gateway-client.js +17 -2
  78. package/dist/lib/auth/gateway-client.js.map +1 -1
  79. package/dist/lib/auth/gateway-process.js +17 -2
  80. package/dist/lib/auth/gateway-process.js.map +1 -1
  81. package/dist/lib/auth/gateway-token.js +5 -2
  82. package/dist/lib/auth/gateway-token.js.map +1 -1
  83. package/dist/lib/auth/nio-config.js +57 -7
  84. package/dist/lib/auth/nio-config.js.map +1 -1
  85. package/dist/lib/auth/otp.js +3 -3
  86. package/dist/lib/auth/otp.js.map +1 -1
  87. package/dist/lib/auth/password.js +33 -10
  88. package/dist/lib/auth/password.js.map +1 -1
  89. package/dist/lib/auth/secrets.js +96 -0
  90. package/dist/lib/auth/secrets.js.map +1 -0
  91. package/dist/lib/auth/session-store.js +2 -2
  92. package/dist/lib/auth/session-store.js.map +1 -1
  93. package/dist/lib/clients/client-configs.js +81 -86
  94. package/dist/lib/clients/client-configs.js.map +1 -1
  95. package/dist/lib/clients/client-install.js +22 -4
  96. package/dist/lib/clients/client-install.js.map +1 -1
  97. package/dist/lib/deps/dependencies.js +0 -25
  98. package/dist/lib/deps/dependencies.js.map +1 -1
  99. package/dist/lib/deps/dependency-install.js +3 -23
  100. package/dist/lib/deps/dependency-install.js.map +1 -1
  101. package/dist/lib/exec/exec-delegate.js +69 -48
  102. package/dist/lib/exec/exec-delegate.js.map +1 -1
  103. package/dist/lib/exec/plan-delegate.js +25 -34
  104. package/dist/lib/exec/plan-delegate.js.map +1 -1
  105. package/dist/lib/exec/qwen-client.js +74 -0
  106. package/dist/lib/exec/qwen-client.js.map +1 -0
  107. package/dist/lib/exec/validate-plan-delegate.js +13 -30
  108. package/dist/lib/exec/validate-plan-delegate.js.map +1 -1
  109. package/dist/lib/fetch-zipball.js +59 -0
  110. package/dist/lib/fetch-zipball.js.map +1 -0
  111. package/dist/lib/load-env.js +17 -5
  112. package/dist/lib/load-env.js.map +1 -1
  113. package/dist/lib/open-url.js +5 -2
  114. package/dist/lib/open-url.js.map +1 -1
  115. package/dist/lib/proc.js +27 -0
  116. package/dist/lib/proc.js.map +1 -1
  117. package/dist/lib/provision/provision.js +2 -2
  118. package/dist/lib/provision/provision.js.map +1 -1
  119. package/dist/lib/skills/patterns.js +15 -24
  120. package/dist/lib/skills/patterns.js.map +1 -1
  121. package/dist/lib/skills/skills-cache.js +25 -12
  122. package/dist/lib/skills/skills-cache.js.map +1 -1
  123. package/dist/lib/skills/skills.js +1 -1
  124. package/dist/lib/skills/skills.js.map +1 -1
  125. package/dist/lib/version-check.js +1 -11
  126. package/dist/lib/version-check.js.map +1 -1
  127. package/dist/mcp-server.js +5 -17
  128. package/dist/mcp-server.js.map +1 -1
  129. package/dist/tools/delegate-exec.js +3 -10
  130. package/dist/tools/delegate-exec.js.map +1 -1
  131. package/dist/tools/plan.js +6 -13
  132. package/dist/tools/plan.js.map +1 -1
  133. package/dist/tools/validate-plan.js +6 -14
  134. package/dist/tools/validate-plan.js.map +1 -1
  135. package/dist/tui/app.js +102 -18
  136. package/dist/tui/app.js.map +1 -1
  137. package/dist/tui/components.js +161 -88
  138. package/dist/tui/components.js.map +1 -1
  139. package/dist/tui/launch.js +6 -1
  140. package/dist/tui/launch.js.map +1 -1
  141. package/dist/tui/opencode.js +27 -0
  142. package/dist/tui/opencode.js.map +1 -1
  143. package/dist/tui/palette.js +12 -5
  144. package/dist/tui/palette.js.map +1 -1
  145. package/dist/tui/prompt-input.js +168 -0
  146. package/dist/tui/prompt-input.js.map +1 -0
  147. package/dist/tui/state.js +252 -20
  148. package/dist/tui/state.js.map +1 -1
  149. package/dist/tui/test-utils.js +24 -0
  150. package/dist/tui/test-utils.js.map +1 -0
  151. package/dist/version.js +17 -6
  152. package/dist/version.js.map +1 -1
  153. package/docker/docker-compose.yml +56 -26
  154. package/docker/kong.yml +10 -0
  155. package/package.json +21 -12
  156. package/dist/adapters/sms/http-generic.js +0 -50
  157. package/dist/adapters/sms/http-generic.js.map +0 -1
  158. package/dist/cli/commands/clean.js +0 -108
  159. package/dist/cli/commands/clean.js.map +0 -1
  160. package/dist/lib/clients/hooks.js +0 -191
  161. package/dist/lib/clients/hooks.js.map +0 -1
  162. package/dist/lib/exec/exec-engines.js +0 -63
  163. package/dist/lib/exec/exec-engines.js.map +0 -1
@@ -3,6 +3,7 @@ import { tmpdir } from 'node:os';
3
3
  import { join } from 'node:path';
4
4
  import AdmZip from 'adm-zip';
5
5
  import { homePath } from '../../brand.js';
6
+ import { codeloadZipUrl, fetchZipball, rejectSymlinks } from '../../lib/fetch-zipball.js';
6
7
  import { LANG_REPOS } from './repos.js';
7
8
  const DEFAULT_TIMEOUT_MS = 30_000;
8
9
  async function downloadRepo(spec, baseDir, opts) {
@@ -11,32 +12,26 @@ async function downloadRepo(spec, baseDir, opts) {
11
12
  if (!opts.force && existsSync(dest)) {
12
13
  return { ...base, status: 'cached' };
13
14
  }
14
- const url = `https://codeload.github.com/${spec.repo}/zip/refs/heads/${spec.ref}`;
15
+ const url = codeloadZipUrl(spec.repo, spec.ref);
15
16
  const staging = join(tmpdir(), `nio-lang-${spec.dir}-${process.pid}-${Date.now()}`);
16
17
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
17
- const ac = new AbortController();
18
- const timer = setTimeout(() => ac.abort(), timeoutMs);
19
18
  try {
20
- const res = await fetch(url, { signal: ac.signal });
21
- if (!res.ok)
22
- throw new Error(`HTTP ${res.status} ao baixar ${url}`);
23
- const buf = Buffer.from(await res.arrayBuffer());
19
+ const buf = await fetchZipball(url, { timeoutMs });
24
20
  rmSync(staging, { recursive: true, force: true });
25
21
  mkdirSync(staging, { recursive: true });
26
22
  new AdmZip(buf).extractAllTo(staging, true);
27
23
  const dirs = readdirSync(staging, { withFileTypes: true }).filter((e) => e.isDirectory());
28
24
  const root = dirs.length === 1 ? join(staging, dirs[0].name) : staging;
25
+ rejectSymlinks(root);
29
26
  rmSync(dest, { recursive: true, force: true });
30
27
  mkdirSync(dest, { recursive: true });
31
28
  cpSync(root, dest, { recursive: true });
32
29
  return { ...base, status: 'fetched' };
33
30
  }
34
31
  catch (err) {
35
- const msg = ac.signal.aborted ? `timeout após ${timeoutMs}ms` : err.message;
36
- return { ...base, status: existsSync(dest) ? 'cached' : 'failed', error: msg };
32
+ return { ...base, status: existsSync(dest) ? 'cached' : 'failed', error: err.message };
37
33
  }
38
34
  finally {
39
- clearTimeout(timer);
40
35
  rmSync(staging, { recursive: true, force: true });
41
36
  }
42
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vendor.js","sourceRoot":"","sources":["../../../src/adapters/lang/vendor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vendor.js","sourceRoot":"","sources":["../../../src/adapters/lang/vendor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { query } from './client.js';
2
+ const NAME_MAX = 128;
3
+ const FAILURE_EVENTS = ['password_fail', '2fa_fail', '2fa_expired'];
4
+ export function createAuthEventRepository() {
5
+ return {
6
+ async record(input) {
7
+ await query(`INSERT INTO auth_events (event, name, user_id, ip, trace_id, detail)
8
+ VALUES ($1, $2, $3, $4, $5, $6)`, [
9
+ input.event,
10
+ input.name ? input.name.slice(0, NAME_MAX) : null,
11
+ input.userId ?? null,
12
+ input.ip ?? null,
13
+ input.traceId ?? null,
14
+ input.detail ? JSON.stringify(input.detail) : null,
15
+ ]);
16
+ },
17
+ async recentFailures({ userId, name, limit = 5 }) {
18
+ const res = await query(`SELECT at, event, host(ip) AS ip FROM auth_events
19
+ WHERE event = ANY($1)
20
+ AND ( ($2::bigint IS NOT NULL AND user_id = $2) OR ($3::text IS NOT NULL AND name = $3) )
21
+ ORDER BY at DESC LIMIT $4`, [FAILURE_EVENTS, userId ?? null, name ?? null, limit]);
22
+ return res.rows.map((r) => ({ at: r.at, event: r.event, ip: r.ip }));
23
+ },
24
+ async pruneOlderThan(days) {
25
+ const res = await query(`DELETE FROM auth_events WHERE at < NOW() - ($1 || ' days')::interval`, [days]);
26
+ return res.rowCount ?? 0;
27
+ },
28
+ };
29
+ }
30
+ //# sourceMappingURL=auth-event-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-event-repository.js","sourceRoot":"","sources":["../../../src/adapters/pg/auth-event-repository.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,QAAQ,GAAG,GAAG,CAAC;AAGrB,MAAM,cAAc,GAAG,CAAC,eAAe,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;AAEpE,MAAM,UAAU,yBAAyB;IACvC,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,KAAqB;YAChC,MAAM,KAAK,CACT;yCACiC,EACjC;gBACE,KAAK,CAAC,KAAK;gBACX,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;gBACjD,KAAK,CAAC,MAAM,IAAI,IAAI;gBACpB,KAAK,CAAC,EAAE,IAAI,IAAI;gBAChB,KAAK,CAAC,OAAO,IAAI,IAAI;gBACrB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI;aACnD,CACF,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE;YAE9C,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB;;;mCAG2B,EAC3B,CAAC,cAAc,EAAE,MAAM,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,EAAE,KAAK,CAAC,CACtD,CAAC;YACF,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACpF,CAAC;QAED,KAAK,CAAC,cAAc,CAAC,IAAI;YACvB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,sEAAsE,EACtE,CAAC,IAAI,CAAC,CACP,CAAC;YACF,OAAO,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { readFileSync } from 'node:fs';
1
2
  import { Pool } from 'pg';
2
3
  function readDatabaseUrl() {
3
4
  const url = process.env.NIO_DATABASE_URL?.trim();
@@ -10,16 +11,34 @@ function readDatabaseUrl() {
10
11
  }
11
12
  return url;
12
13
  }
13
- function readSslOption() {
14
- const flag = process.env.NIO_DATABASE_SSL?.trim().toLowerCase();
15
- if (flag === 'true' || flag === '1')
14
+ function envFlag(name) {
15
+ const v = process.env[name]?.trim().toLowerCase();
16
+ return v === 'true' || v === '1';
17
+ }
18
+ export function readSslOption() {
19
+ if (!envFlag('NIO_DATABASE_SSL'))
20
+ return undefined;
21
+ if (envFlag('NIO_DATABASE_SSL_INSECURE')) {
22
+ console.error('[pg] AVISO: NIO_DATABASE_SSL_INSECURE=1 — TLS sem verificação de certificado. ' +
23
+ 'A conexão com o banco fica vulnerável a MITM. Use NIO_DATABASE_CA em vez disso.');
16
24
  return { rejectUnauthorized: false };
17
- return undefined;
25
+ }
26
+ const caPath = process.env.NIO_DATABASE_CA?.trim();
27
+ if (caPath) {
28
+ try {
29
+ return { rejectUnauthorized: true, ca: readFileSync(caPath, 'utf8') };
30
+ }
31
+ catch (err) {
32
+ throw new Error(`NIO_DATABASE_CA não pôde ser lido ("${caPath}"): ${err.message}`);
33
+ }
34
+ }
35
+ return { rejectUnauthorized: true };
18
36
  }
19
37
  let pool = null;
20
38
  export function getPool() {
21
39
  if (pool)
22
40
  return pool;
41
+ globalThis.__nioPgPoolOpen = true;
23
42
  pool = new Pool({
24
43
  connectionString: readDatabaseUrl(),
25
44
  ssl: readSslOption(),
@@ -69,6 +88,7 @@ export async function closePool() {
69
88
  return;
70
89
  const p = pool;
71
90
  pool = null;
91
+ globalThis.__nioPgPoolOpen = false;
72
92
  await p.end();
73
93
  }
74
94
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/adapters/pg/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/adapters/pg/client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"login-challenge-repository.js","sourceRoot":"","sources":["../../../src/adapters/pg/login-challenge-repository.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAe7D,MAAM,IAAI,GACR,yFAAyF,CAAC;AAG5F,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAsB;IACzD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC3B,OAAO,EAAE,GAAG,CAAC,OAA2B;QACxC,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,OAAO,EAAE,GAAG,CAAC,OAAgB;QAC7B,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC9B,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC5C,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,KAA6B;YACxC,OAAO,eAAe,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBAClC,MAAM,EAAE,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;gBACxE,MAAM,EAAE,CAAC,KAAK,CACZ,yEAAyE,EACzE,CAAC,KAAK,CAAC,MAAM,CAAC,CACf,CAAC;gBACF,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,KAAK,CACxB;;uBAEa,IAAI,EAAE,EACnB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAC9E,CAAC;gBACF,OAAO,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;YAC5C,CAAC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,EAAE;YACf,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpC,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,UAAU,IAAI,sCAAsC,EACpD,CAAC,EAAE,CAAC,CACL,CAAC;YACF,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxB,OAAO,GAAG,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChD,CAAC;QAED,KAAK,CAAC,iBAAiB,CAAC,EAAE;YACxB,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAAE,OAAO,CAAC,CAAC;YACjC,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,sFAAsF,EACtF,CAAC,EAAE,CAAC,CACL,CAAC;YACF,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC;QAC5C,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,EAAE;YACd,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAAE,OAAO;YAC/B,MAAM,KAAK,CACT,uFAAuF,EACvF,CAAC,EAAE,CAAC,CACL,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,aAAa;YACjB,MAAM,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACvE,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"login-challenge-repository.js","sourceRoot":"","sources":["../../../src/adapters/pg/login-challenge-repository.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAe7D,MAAM,IAAI,GACR,yFAAyF,CAAC;AAG5F,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAsB;IACzD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAC3B,OAAO,EAAE,GAAG,CAAC,OAA2B;QACxC,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,OAAO,EAAE,GAAG,CAAC,OAAqB;QAClC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC9B,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC5C,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,KAA6B;YACxC,OAAO,eAAe,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;gBAClC,MAAM,EAAE,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;gBACxE,MAAM,EAAE,CAAC,KAAK,CACZ,yEAAyE,EACzE,CAAC,KAAK,CAAC,MAAM,CAAC,CACf,CAAC;gBACF,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,KAAK,CACxB;;uBAEa,IAAI,EAAE,EACnB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAC9E,CAAC;gBACF,OAAO,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;YAC5C,CAAC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,EAAE;YACf,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpC,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,UAAU,IAAI,sCAAsC,EACpD,CAAC,EAAE,CAAC,CACL,CAAC;YACF,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxB,OAAO,GAAG,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChD,CAAC;QAED,KAAK,CAAC,iBAAiB,CAAC,EAAE;YACxB,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAAE,OAAO,CAAC,CAAC;YACjC,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,sFAAsF,EACtF,CAAC,EAAE,CAAC,CACL,CAAC;YACF,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC;QAC5C,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,EAAE;YACd,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAAE,OAAO;YAC/B,MAAM,KAAK,CACT,uFAAuF,EACvF,CAAC,EAAE,CAAC,CACL,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,aAAa;YACjB,MAAM,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACvE,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { query } from './client.js';
2
+ const map = (r) => ({
3
+ ip: r.ip,
4
+ firstSeen: r.first_seen,
5
+ lastSeen: r.last_seen,
6
+ count: Number(r.count),
7
+ });
8
+ export function createLoginIpRepository() {
9
+ return {
10
+ async record(userId, ip) {
11
+ await query(`INSERT INTO login_ip_events (user_id, ip) VALUES ($1, $2)
12
+ ON CONFLICT (user_id, ip)
13
+ DO UPDATE SET last_seen = NOW(), count = login_ip_events.count + 1`, [userId, ip]);
14
+ },
15
+ async recent(userId, limit = 10) {
16
+ const res = await query(`SELECT host(ip) AS ip, first_seen, last_seen, count FROM login_ip_events
17
+ WHERE user_id = $1 ORDER BY last_seen DESC LIMIT $2`, [userId, limit]);
18
+ return res.rows.map(map);
19
+ },
20
+ async pruneOlderThan(days) {
21
+ const res = await query(`DELETE FROM login_ip_events WHERE last_seen < NOW() - ($1 || ' days')::interval`, [days]);
22
+ return res.rowCount ?? 0;
23
+ },
24
+ };
25
+ }
26
+ //# sourceMappingURL=login-ip-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-ip-repository.js","sourceRoot":"","sources":["../../../src/adapters/pg/login-ip-repository.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AASpC,MAAM,GAAG,GAAG,CAAC,CAAM,EAAgB,EAAE,CAAC,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,EAAE;IACR,SAAS,EAAE,CAAC,CAAC,UAAU;IACvB,QAAQ,EAAE,CAAC,CAAC,SAAS;IACrB,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;CACvB,CAAC,CAAC;AAEH,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE;YACrB,MAAM,KAAK,CACT;;4EAEoE,EACpE,CAAC,MAAM,EAAE,EAAE,CAAC,CACb,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,EAAE;YAC7B,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB;6DACqD,EACrD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;YACF,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAED,KAAK,CAAC,cAAc,CAAC,IAAI;YACvB,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,iFAAiF,EACjF,CAAC,IAAI,CAAC,CACP,CAAC;YACF,OAAO,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,5 +1,10 @@
1
- import { hashPassword, verifyPassword } from '../../lib/auth/password.js';
1
+ import { randomBytes } from 'node:crypto';
2
+ import { hashPassword, needsRehash, verifyPassword, MIN_PASSWORD_LENGTH } from '../../lib/auth/password.js';
2
3
  import { query } from './client.js';
4
+ let decoyHashPromise = null;
5
+ function decoyHash() {
6
+ return (decoyHashPromise ??= hashPassword(`decoy-${randomBytes(16).toString('hex')}`).then((h) => h.phc));
7
+ }
3
8
  function parseIps(raw) {
4
9
  if (!raw)
5
10
  return [];
@@ -23,48 +28,72 @@ export function mapUserRow(row) {
23
28
  timestampLastSession: row.timestamp_last_session,
24
29
  };
25
30
  }
26
- const COLS = 'id, name, password, timestamp_creation, timestamp_password_change, ' +
27
- 'auth_2, phone, backup_codes, timestamp_last_session, ips_using';
31
+ const PUBLIC_COLS = 'id, name, password_pepper_id, timestamp_creation, timestamp_password_change, ' +
32
+ 'auth_2, phone, backup_pepper_id, timestamp_last_session, ips_using';
33
+ const FULL_COLS = `${PUBLIC_COLS}, password, backup_codes`;
28
34
  export function createUserRepository() {
29
35
  return {
30
36
  async findByName(name) {
31
- const res = await query(`SELECT ${COLS} FROM user_cli WHERE name = $1`, [name]);
37
+ const res = await query(`SELECT ${PUBLIC_COLS} FROM user_cli WHERE name = $1`, [name]);
32
38
  const row = res.rows[0];
33
39
  return row ? mapUserRow(row) : null;
34
40
  },
35
41
  async findById(id) {
36
- const res = await query(`SELECT ${COLS} FROM user_cli WHERE id = $1`, [id]);
42
+ const res = await query(`SELECT ${PUBLIC_COLS} FROM user_cli WHERE id = $1`, [id]);
37
43
  const row = res.rows[0];
38
44
  return row ? mapUserRow(row) : null;
39
45
  },
40
46
  async create(input) {
41
- const passwordHash = await hashPassword(input.password);
42
- const res = await query(`INSERT INTO user_cli (name, password) VALUES ($1, $2) RETURNING ${COLS}`, [input.name, passwordHash]);
47
+ if (input.password.length < MIN_PASSWORD_LENGTH) {
48
+ throw new Error(`Senha muito curta (mínimo ${MIN_PASSWORD_LENGTH} caracteres).`);
49
+ }
50
+ const { phc, pepperId } = await hashPassword(input.password);
51
+ const res = await query(`INSERT INTO user_cli (name, password, password_pepper_id) VALUES ($1, $2, $3) RETURNING ${PUBLIC_COLS}`, [input.name, phc, pepperId]);
43
52
  return mapUserRow(res.rows[0]);
44
53
  },
45
54
  async verifyCredentials(name, password) {
46
- const res = await query(`SELECT ${COLS} FROM user_cli WHERE name = $1`, [name]);
55
+ const res = await query(`SELECT ${FULL_COLS} FROM user_cli WHERE name = $1`, [name]);
47
56
  const row = res.rows[0];
48
- if (!row)
57
+ if (!row) {
58
+ await verifyPassword(await decoyHash(), password, 0);
59
+ return null;
60
+ }
61
+ const ok = await verifyPassword(row.password, password, row.password_pepper_id);
62
+ if (!ok)
49
63
  return null;
50
- const ok = await verifyPassword(row.password, password);
51
- return ok ? mapUserRow(row) : null;
64
+ if (needsRehash(row.password, row.password_pepper_id)) {
65
+ try {
66
+ const fresh = await hashPassword(password);
67
+ await query('UPDATE user_cli SET password = $2, password_pepper_id = $3, timestamp_password_change = NOW() WHERE id = $1', [Number(row.id), fresh.phc, fresh.pepperId]);
68
+ }
69
+ catch {
70
+ }
71
+ }
72
+ return mapUserRow(row);
52
73
  },
53
74
  async touchLastSession(userId) {
54
75
  await query('UPDATE user_cli SET timestamp_last_session = NOW() WHERE id = $1', [userId]);
55
76
  },
56
- async enable2fa(userId, phone, backupCodeHashes) {
57
- await query('UPDATE user_cli SET auth_2 = TRUE, phone = $2, backup_codes = $3 WHERE id = $1', [userId, phone, backupCodeHashes]);
77
+ async updatePasswordHash(userId, phc, pepperId) {
78
+ await query('UPDATE user_cli SET password = $2, password_pepper_id = $3, timestamp_password_change = NOW() WHERE id = $1', [userId, phc, pepperId]);
79
+ },
80
+ async enable2fa(userId, phone, backupCodeHashes, backupPepperId) {
81
+ await query('UPDATE user_cli SET auth_2 = TRUE, phone = $2, backup_codes = $3, backup_pepper_id = $4 WHERE id = $1', [userId, phone, backupCodeHashes, backupPepperId]);
58
82
  },
59
83
  async disable2fa(userId) {
60
- await query('UPDATE user_cli SET auth_2 = FALSE, phone = NULL, backup_codes = NULL WHERE id = $1', [userId]);
84
+ await query('UPDATE user_cli SET auth_2 = FALSE, phone = NULL, backup_codes = NULL, backup_pepper_id = 0 WHERE id = $1', [userId]);
61
85
  },
62
- async updateBackupCodes(userId, joined) {
63
- await query('UPDATE user_cli SET backup_codes = $2 WHERE id = $1', [userId, joined]);
86
+ async updateBackupCodes(userId, joined, pepperId) {
87
+ await query('UPDATE user_cli SET backup_codes = $2, backup_pepper_id = $3 WHERE id = $1', [
88
+ userId,
89
+ joined,
90
+ pepperId,
91
+ ]);
64
92
  },
65
93
  async getBackupCodes(userId) {
66
- const res = await query('SELECT backup_codes FROM user_cli WHERE id = $1', [userId]);
67
- return res.rows[0]?.backup_codes ?? null;
94
+ const res = await query('SELECT backup_codes, backup_pepper_id FROM user_cli WHERE id = $1', [userId]);
95
+ const row = res.rows[0];
96
+ return { codes: row?.backup_codes ?? null, pepperId: row?.backup_pepper_id ?? 0 };
68
97
  },
69
98
  };
70
99
  }
@@ -1 +1 @@
1
- {"version":3,"file":"user-repository.js","sourceRoot":"","sources":["../../../src/adapters/pg/user-repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"user-repository.js","sourceRoot":"","sources":["../../../src/adapters/pg/user-repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ export function formatWhatsAppNumber(phone) {
2
+ return phone.replace(/^\+/, '');
3
+ }
4
+ export function buildPayload(phone, code, env = {}) {
5
+ const payload = {
6
+ messaging_product: 'whatsapp',
7
+ to: formatWhatsAppNumber(phone),
8
+ type: 'template',
9
+ template: {
10
+ name: env.templateName ?? 'autenticao',
11
+ language: { code: env.templateLanguage ?? 'pt_BR' },
12
+ components: [
13
+ {
14
+ type: 'body',
15
+ parameters: [{ type: 'text', text: code }],
16
+ },
17
+ {
18
+ type: 'button',
19
+ sub_type: 'url',
20
+ index: '0',
21
+ parameters: [{ type: 'text', text: code }],
22
+ },
23
+ ],
24
+ },
25
+ };
26
+ return JSON.stringify(payload);
27
+ }
28
+ function readEnv() {
29
+ return {
30
+ url: process.env.WHATSAPP_ENDPOINT_URL?.trim(),
31
+ token: process.env.WHATSAPP_TOKEN?.trim(),
32
+ templateName: process.env.WHATSAPP_TEMPLATE_NAME?.trim(),
33
+ templateLanguage: process.env.WHATSAPP_TEMPLATE_LANGUAGE?.trim(),
34
+ };
35
+ }
36
+ const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1', '[::1]', '0.0.0.0']);
37
+ export function smsMode(env = readEnv()) {
38
+ if (!env.url || !env.token)
39
+ return 'unconfigured';
40
+ try {
41
+ return LOOPBACK_HOSTS.has(new URL(env.url).hostname) ? 'echo' : 'provider';
42
+ }
43
+ catch {
44
+ return 'provider';
45
+ }
46
+ }
47
+ export function smsProviderHost(env = readEnv()) {
48
+ if (!env.url)
49
+ return null;
50
+ try {
51
+ return new URL(env.url).hostname;
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ export function createWhatsAppSender(env = readEnv()) {
58
+ return {
59
+ async sendOtp(to, code) {
60
+ if (!env.url || !env.token) {
61
+ return { status: 'skipped', error: 'WHATSAPP_ENDPOINT_URL / WHATSAPP_TOKEN não configurados' };
62
+ }
63
+ const body = buildPayload(to, code, env);
64
+ try {
65
+ const res = await fetch(env.url, {
66
+ method: 'POST',
67
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${env.token}` },
68
+ body,
69
+ signal: AbortSignal.timeout(10_000),
70
+ });
71
+ if (!res.ok) {
72
+ const detail = (await res.text().catch(() => '')).slice(0, 300);
73
+ return { status: 'failed', error: `WhatsApp respondeu ${res.status} ${detail}`.trim() };
74
+ }
75
+ return { status: 'sent' };
76
+ }
77
+ catch (err) {
78
+ return { status: 'failed', error: err.message };
79
+ }
80
+ },
81
+ };
82
+ }
83
+ //# sourceMappingURL=whatsapp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../../src/adapters/sms/whatsapp.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { spawn } from 'node:child_process';
2
- import { installOpencodeGlobal, NIO_OPERATOR_MODEL } from '../lib/clients/client-configs.js';
2
+ import { installOpencodeGlobal, NIO_OPERATOR_MODEL, NIO_AI_BASE_URL } from '../lib/clients/client-configs.js';
3
3
  import { isBinaryInstalled } from '../lib/clients/client-install.js';
4
4
  import { c, sym } from '../lib/colors.js';
5
5
  import { dlog } from '../lib/debug.js';
@@ -12,7 +12,7 @@ export class HeadroomRequiredError extends Error {
12
12
  export async function ensureHeadroomAndWire() {
13
13
  try {
14
14
  installOpencodeGlobal([]);
15
- dlog('opencode.json: provider direto (Headroom desativado), model =', NIO_OPERATOR_MODEL);
15
+ dlog('opencode.json: motor →', NIO_AI_BASE_URL, ', model =', NIO_OPERATOR_MODEL);
16
16
  }
17
17
  catch (err) {
18
18
  console.warn(` ${c.yellow(sym.warn)} não gravei o opencode.json: ${err.message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"ai-client.js","sourceRoot":"","sources":["../../src/app/ai-client.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAOvC,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,MAAc;QACxB,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAcD,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,IAAI,CAAC;QACH,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,+DAA+D,EAAE,kBAAkB,CAAC,CAAC;IAC5F,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAiC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAChG,CAAC;AACH,CAAC;AAGD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAqC,EACrC,OAAqB,EAAE;IAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC;IACtC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,iBAAiB,CAAC;IAE1D,MAAM,qBAAqB,EAAE,CAAC;IAE9B,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,mEAAmE,CAC3F,CAAC;QACF,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,OAAO,CACnB,UAAU,EACV,CAAC,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,EACnD,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CACpC,CAAC;QACF,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/C,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC,KAAK,CAAC,uCAAuC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"ai-client.js","sourceRoot":"","sources":["../../src/app/ai-client.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAC9G,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAOvC,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,MAAc;QACxB,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAaD,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,IAAI,CAAC;QACH,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,wBAAwB,EAAE,eAAe,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACnF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAiC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAChG,CAAC;AACH,CAAC;AAGD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAqC,EACrC,OAAqB,EAAE;IAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC;IACtC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,iBAAiB,CAAC;IAE1D,MAAM,qBAAqB,EAAE,CAAC;IAE9B,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,mEAAmE,CAC3F,CAAC;QACF,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,OAAO,CACnB,UAAU,EACV,CAAC,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,EACnD,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CACpC,CAAC;QACF,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/C,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC,KAAK,CAAC,uCAAuC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/brand.js CHANGED
@@ -15,7 +15,7 @@ export const brand = {
15
15
  envPrefix: 'NIO',
16
16
  patPrefix: 'nio_',
17
17
  skillsRepo: 'hugoreiis12-png/NIO-SKILLS-',
18
- skillsRef: 'main',
18
+ skillsRef: '11980256cff5c261740e0abd0c549da9b1da3d95',
19
19
  skillsPackage: '@nio-cli/skills',
20
20
  toolPrefix: 'nos_',
21
21
  cliToolPrefix: 'nio_',
package/dist/brand.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"brand.js","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAYjC,MAAM,CAAC,MAAM,KAAK,GAAG;IAGnB,IAAI,EAAE,KAAK;IAEX,WAAW,EAAE,KAAK;IAElB,eAAe,EAAE,KAAK;IAGtB,SAAS,EAAE,iBAAiB;IAE5B,UAAU,EAAE,UAAU;IAEtB,WAAW,EAAE,cAAc;IAE3B,UAAU,EAAE,SAAS;IAErB,YAAY,EAAE,KAAK;IAOnB,MAAM,EAAE,EAAE;IAIV,WAAW,EAAE,MAAM;IAEnB,iBAAiB,EAAE,UAAU;IAI7B,SAAS,EAAE,KAAK;IAMhB,SAAS,EAAE,MAAM;IAIjB,UAAU,EAAE,6BAA6B;IACzC,SAAS,EAAE,MAAM;IAEjB,aAAa,EAAE,iBAAiB;IAIhC,UAAU,EAAE,MAAM;IAElB,aAAa,EAAE,MAAM;CACb,CAAC;AASX,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,eAAe,CAAC,CAAC;AAGvE,MAAM,UAAU,QAAQ,CAAC,GAAG,KAAe;IACzC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC;AACtD,CAAC;AAGD,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,GAAG,KAAK,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;AACtC,CAAC;AAGD,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACpC,CAAC"}
1
+ {"version":3,"file":"brand.js","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAYjC,MAAM,CAAC,MAAM,KAAK,GAAG;IAGnB,IAAI,EAAE,KAAK;IAEX,WAAW,EAAE,KAAK;IAElB,eAAe,EAAE,KAAK;IAGtB,SAAS,EAAE,iBAAiB;IAE5B,UAAU,EAAE,UAAU;IAEtB,WAAW,EAAE,cAAc;IAE3B,UAAU,EAAE,SAAS;IAErB,YAAY,EAAE,KAAK;IAOnB,MAAM,EAAE,EAAE;IAIV,WAAW,EAAE,MAAM;IAEnB,iBAAiB,EAAE,UAAU;IAI7B,SAAS,EAAE,KAAK;IAMhB,SAAS,EAAE,MAAM;IAIjB,UAAU,EAAE,6BAA6B;IAWzC,SAAS,EAAE,0CAA0C;IAErD,aAAa,EAAE,iBAAiB;IAIhC,UAAU,EAAE,MAAM;IAElB,aAAa,EAAE,MAAM;CACb,CAAC;AASX,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,eAAe,CAAC,CAAC;AAGvE,MAAM,UAAU,QAAQ,CAAC,GAAG,KAAe;IACzC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC;AACtD,CAAC;AAGD,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,GAAG,KAAK,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;AACtC,CAAC;AAGD,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACpC,CAAC"}
@@ -46,11 +46,11 @@ async function runAi() {
46
46
  export function registerAiCommand(program) {
47
47
  const ai = program
48
48
  .command("ai")
49
- .description("Abre a interface NIO da sessão ativa (Headroom + opencode serve + Ink)")
49
+ .description("Abre a interface NIO da sessão ativa (opencode serve headless + chat Ink)")
50
50
  .action(runAi);
51
51
  ai
52
52
  .command("status")
53
- .description("Estado do Headroom (proxy obrigatório do client de IA)")
53
+ .description("Estado do Headroom (proxy de compressão desativado por ADR 0010, dormente)")
54
54
  .action(async () => {
55
55
  const up = await headroomHealthy();
56
56
  console.log(`${up ? c.green(sym.ok) : c.red(sym.err)} Headroom ${c.dim(HEADROOM_URL)} — ${up ? "no ar" : "fora"}`);
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../../src/cli/commands/ai.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../../src/cli/commands/ai.ts"],"names":[],"mappings":"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"}
@@ -3,27 +3,33 @@ import { brand } from "../../brand.js";
3
3
  import { animateMatrixLogo } from "../../matrix-logo.js";
4
4
  import { startSpinner } from "../../lib/spinner.js";
5
5
  import { c, sym } from "../../lib/colors.js";
6
- import { createUserRepository } from "../../adapters/pg/user-repository.js";
7
- import { gatewayLogin, gatewayLogout, gatewayVerify2fa, } from "../../lib/auth/gateway-client.js";
6
+ import { MIN_PASSWORD_LENGTH } from "../../lib/auth/password.js";
7
+ import { gatewayLogin, gatewayLogout, gatewayLogoutAll, gatewayRegister, gatewayVerify2fa, } from "../../lib/auth/gateway-client.js";
8
8
  import { loadSession, saveSession, clearSession } from "../../lib/auth/session-store.js";
9
9
  import { ensureConfig } from "../../lib/auth/nio-config.js";
10
10
  import { ensureGatewayRunning } from "../../lib/auth/gateway-process.js";
11
11
  import { continueChain } from "../flows/onboarding.js";
12
12
  import { box, cmd } from "../../lib/colors.js";
13
13
  import { authCopy } from "../copy.js";
14
- async function resolveSecondFactor(challengeId, phoneHint) {
15
- console.log(` ${c.dim(`código enviado por SMS para ${phoneHint}`)}`);
14
+ async function resolveSecondFactor(challengeId, phoneHint, sms) {
15
+ if (sms?.smsMode === "echo") {
16
+ console.log(` ${c.yellow(sym.warn)} modo echo (dev) — nenhum WhatsApp real foi enviado` +
17
+ (sms.devCode ? `. Código: ${c.bold(sms.devCode)}` : " (veja ~/.nio/whatsapp-echo-last.json)"));
18
+ }
19
+ else {
20
+ console.log(` ${c.dim(`código enviado por WhatsApp para ${phoneHint}`)}`);
21
+ }
16
22
  let type = "otp";
17
23
  for (let attempt = 0; attempt < 4; attempt++) {
18
24
  const code = (await input({
19
- message: type === "otp" ? "Código de confirmação (SMS)" : "Código de backup",
25
+ message: type === "otp" ? "Código de confirmação (WhatsApp)" : "Código de backup",
20
26
  validate: (v) => v.trim().length > 0 || "obrigatório",
21
27
  })).trim();
22
28
  const res = await gatewayVerify2fa(challengeId, code, type);
23
29
  if (res.ok)
24
30
  return res;
25
31
  if (res.requiresBackupCode) {
26
- console.log(` ${c.yellow(sym.warn)} tentativas de SMS esgotadas — use um código de backup.`);
32
+ console.log(` ${c.yellow(sym.warn)} tentativas de código esgotadas — use um código de backup.`);
27
33
  type = "backup";
28
34
  continue;
29
35
  }
@@ -32,7 +38,6 @@ async function resolveSecondFactor(challengeId, phoneHint) {
32
38
  }
33
39
  return null;
34
40
  }
35
- const MIN_PASSWORD_LENGTH = 8;
36
41
  async function requireGateway() {
37
42
  const result = await ensureGatewayRunning();
38
43
  if (result.ok)
@@ -60,7 +65,10 @@ export async function runLogin() {
60
65
  session = result;
61
66
  }
62
67
  else {
63
- const s = await resolveSecondFactor(result.challengeId, result.phoneHint);
68
+ const s = await resolveSecondFactor(result.challengeId, result.phoneHint, {
69
+ smsMode: result.smsMode,
70
+ devCode: result.devCode,
71
+ });
64
72
  if (!s) {
65
73
  console.error(`${c.red(sym.err)} 2º fator não concluído.`);
66
74
  process.exit(1);
@@ -87,6 +95,7 @@ export async function runLogin() {
87
95
  }
88
96
  export async function runRegister() {
89
97
  await ensureConfig({ interactive: true });
98
+ await requireGateway();
90
99
  const name = await input({
91
100
  message: authCopy.register.namePrompt,
92
101
  validate: (v) => v.trim().length > 0 || authCopy.register.nameInvalid,
@@ -96,17 +105,11 @@ export async function runRegister() {
96
105
  mask: "*",
97
106
  validate: (v) => v.length >= MIN_PASSWORD_LENGTH || authCopy.register.passwordInvalid,
98
107
  });
99
- const repo = createUserRepository();
100
108
  const spinner = startSpinner("Criando usuário...");
101
109
  try {
102
- const existing = await repo.findByName(name.trim());
103
- if (existing) {
104
- spinner.fail(`Usuário "${name.trim()}" já existe.`);
105
- process.exit(1);
106
- }
107
- const user = await repo.create({ name: name.trim(), password: pass });
110
+ const user = await gatewayRegister(name.trim(), pass);
108
111
  spinner.stop();
109
- console.log(`${c.green(sym.ok)} Usuário criado: ${user.name} (id ${user.id})`);
112
+ console.log(`${c.green(sym.ok)} Usuário criado: ${user.name} (id ${user.userId})`);
110
113
  }
111
114
  catch (err) {
112
115
  spinner.fail(`Falha ao criar usuário: ${err.message}`);
@@ -118,7 +121,7 @@ export async function runRegister() {
118
121
  function registerRegisterCommand(program) {
119
122
  program
120
123
  .command("register")
121
- .description("Cria um novo usuário no banco (user_cli) e já entra (login)")
124
+ .description("Cria um novo usuário via nio-gateway e já entra (login)")
122
125
  .action(async () => {
123
126
  await runRegister();
124
127
  await continueChain({ from: "command" });
@@ -137,17 +140,21 @@ function registerLogoutCommand(program) {
137
140
  program
138
141
  .command("logout")
139
142
  .description("Encerra a sessão local e revoga a auth_session no banco")
140
- .action(async () => {
143
+ .option("--all", "Revoga TODAS as sessões do usuário (todos os dispositivos)")
144
+ .action(async (opts) => {
141
145
  const session = await loadSession();
142
146
  if (session) {
143
147
  try {
144
- await gatewayLogout(session.sessionId);
148
+ if (opts.all)
149
+ await gatewayLogoutAll(session.token);
150
+ else
151
+ await gatewayLogout(session.sessionId, session.token);
145
152
  }
146
153
  catch {
147
154
  }
148
155
  }
149
156
  await clearSession();
150
- console.log("Sessão removida.");
157
+ console.log(opts.all ? "Todas as sessões foram encerradas." : "Sessão removida.");
151
158
  });
152
159
  }
153
160
  function registerWhoamiCommand(program) {