@nio-cli/cli 0.10.1 → 0.11.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 (60) hide show
  1. package/.env.example +118 -114
  2. package/Dockerfile.gateway +20 -20
  3. package/README.md +539 -539
  4. package/dist/adapters/pg/auth-event-repository.js +4 -4
  5. package/dist/adapters/pg/auth-session-repository.js +2 -2
  6. package/dist/adapters/pg/client.js +28 -4
  7. package/dist/adapters/pg/client.js.map +1 -1
  8. package/dist/adapters/pg/dependency-event-repository.js +4 -4
  9. package/dist/adapters/pg/login-challenge-repository.js +2 -2
  10. package/dist/adapters/pg/login-ip-repository.js +3 -3
  11. package/dist/adapters/pg/session-repository.js +3 -3
  12. package/dist/cli/commands/auth.js +38 -16
  13. package/dist/cli/commands/auth.js.map +1 -1
  14. package/dist/cli/commands/completion.js +28 -28
  15. package/dist/cli/commands/docs/html.js +78 -78
  16. package/dist/cli/copy/auth.json +13 -13
  17. package/dist/cli/copy/flows.json +5 -5
  18. package/dist/cli/copy/init.json +15 -15
  19. package/dist/cli/copy/sync.json +3 -3
  20. package/dist/cli.js +3 -7
  21. package/dist/cli.js.map +1 -1
  22. package/dist/gateway/index.js +11 -1
  23. package/dist/gateway/index.js.map +1 -1
  24. package/dist/lib/auth/gateway-process.js +59 -2
  25. package/dist/lib/auth/gateway-process.js.map +1 -1
  26. package/dist/lib/auth/nio-config.js +25 -5
  27. package/dist/lib/auth/nio-config.js.map +1 -1
  28. package/dist/lib/clients/client-configs.js +1 -1
  29. package/dist/lib/clients/client-configs.js.map +1 -1
  30. package/dist/lib/clients/nio-oc-config.js +84 -0
  31. package/dist/lib/clients/nio-oc-config.js.map +1 -0
  32. package/dist/lib/exec/plan-delegate.js.map +1 -1
  33. package/dist/lib/shutdown.js +25 -0
  34. package/dist/lib/shutdown.js.map +1 -0
  35. package/dist/mcp-server-lang.js +0 -0
  36. package/dist/mcp-server.js +0 -0
  37. package/dist/profiles/analyst.js +1 -0
  38. package/dist/profiles/analyst.js.map +1 -1
  39. package/dist/profiles/bi.js +1 -0
  40. package/dist/profiles/bi.js.map +1 -1
  41. package/dist/profiles/dba.js +3 -2
  42. package/dist/profiles/dba.js.map +1 -1
  43. package/dist/profiles/mcps.js.map +1 -1
  44. package/dist/profiles/scientist.js +3 -1
  45. package/dist/profiles/scientist.js.map +1 -1
  46. package/dist/tui/app.js +41 -12
  47. package/dist/tui/app.js.map +1 -1
  48. package/dist/tui/components.js +9 -8
  49. package/dist/tui/components.js.map +1 -1
  50. package/dist/tui/launch.js +13 -1
  51. package/dist/tui/launch.js.map +1 -1
  52. package/dist/tui/opencode.js +17 -0
  53. package/dist/tui/opencode.js.map +1 -1
  54. package/dist/tui/palette.js +29 -0
  55. package/dist/tui/palette.js.map +1 -1
  56. package/dist/tui/state.js +146 -92
  57. package/dist/tui/state.js.map +1 -1
  58. package/docker/docker-compose.yml +114 -114
  59. package/docker/kong.yml +59 -55
  60. package/package.json +97 -97
package/.env.example CHANGED
@@ -1,114 +1,118 @@
1
- # Database connection string
2
- # CLI/MCP: role `nio_cli` (migration 0008) — SELECT em user_cli/auth_sessions,
3
- # escreve só em sessions/dependency_events/log_session/session_activity.
4
- NIO_DATABASE_URL=postgres://nio_cli_user:senha@localhost:5432/nio_cli
5
-
6
- # Gateway: role `nio_gateway` — escreve em user_cli/auth_sessions/login_challenges/
7
- # auth_events/login_ip_events. Só o processo nio-gateway lê esta var; se ausente,
8
- # ele cai em NIO_DATABASE_URL (dev com um único role).
9
- # NIO_GATEWAY_DATABASE_URL=postgres://nio_gw_user:senha@localhost:5432/nio_cli
10
-
11
- # TLS — LIGADO POR PADRÃO em banco remoto (não-loopback), com verificação de
12
- # cert. Exceções: banco em loopback (dev local, sem TLS) ou opt-out explícito:
13
- # NIO_DATABASE_SSL=false
14
- # Com TLS ligado, o certificado do servidor É VERIFICADO. CA privada:
15
- # NIO_DATABASE_CA=/etc/ssl/nio/db-ca.pem
16
- # Último recurso — desliga a verificação de cert (expõe a MITM). Prefira NIO_DATABASE_CA:
17
- # NIO_DATABASE_SSL_INSECURE=1
18
-
19
- # Gateway — JWT (login v2). Sem prefixo NIO_ de propósito: segredo da equipe,
20
- # mesmo valor em toda máquina que roda o nio-gateway.
21
- # Mínimo 32 caracteres aleatórios. Gere com: `nio config setup` ou
22
- # node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
23
- JWT_SECRET=
24
- # JWT_EXPIRES_IN=12h
25
-
26
- # ── Endurecimento de cripto (ADR 0011) — tudo opcional, defaults = comportamento atual ──
27
- #
28
- # Pepper de senha: segredo de servidor combinado à senha antes do argon2. Um dump
29
- # do banco SEM ele não dá pra brute-forçar offline. MESMO valor em todo nó do
30
- # gateway. PERDER = reset de senha forçado dos usuários peppered FAÇA BACKUP.
31
- # Formato: id:segredo[,id:segredo] — o de maior id é o atual (rotação: adiciona o
32
- # novo, o re-hash on login migra, depois remove o velho). Gere: openssl rand -base64 32
33
- # NIO_PEPPERS=1:troque-por-um-segredo-forte-de-32-ou-mais-chars
34
- #
35
- # Chave do HMAC do OTP separa do JWT_SECRET. Default = JWT_SECRET.
36
- # OTP_HMAC_SECRET=
37
- #
38
- # Rotação de JWT sem derrubar sessão: JWT_SECRETS = kid:segredo[,kid:segredo].
39
- # A ÚLTIMA entrada assina os tokens novos; QUALQUER uma verifica. Token antigo
40
- # (sem kid) verifica contra JWT_SECRET. Fluxo: adiciona o kid novo no fim →
41
- # deploy → espera 12h (TTL do JWT) → remove o kid velho. Ausente = usa JWT_SECRET.
42
- # JWT_SECRETS=2026a:segredo-antigo-de-32+-chars,2026b:segredo-novo-de-32+-chars
43
- #
44
- # Params do argon2id defaults = piso OWASP. Calibre na máquina do gateway com
45
- # node scripts/argon2-calibrate.mjs (ou `bun run argon2:calibrate`)
46
- # mire ~250-500 ms no hash. Subir só re-hasheia no próximo login (não é breaking).
47
- # NIO_ARGON2_MEMORY_MIB=19
48
- # NIO_ARGON2_TIME=2
49
- # NIO_ARGON2_PARALLELISM=1
50
- #
51
- # Auditoria de IP de login (ADR 0011 §F) — o gateway registra de quais IPs cada
52
- # usuário loga (visível em `nio security status`; retenção 90 d). SÓ registro,
53
- # não bloqueia. Ligue NIO_TRUST_PROXY=1 pra usar o X-Forwarded-For **apenas** se
54
- # o Kong for a ÚNICA entrada do gateway (senão o IP é forjável).
55
- # NIO_TRUST_PROXY=1
56
-
57
- # Trilha de auth persistente (ADR 0012) `auth_events` guarda todo evento de auth
58
- # (login OK/falho, 2FA, mudanças de 2FA, logout). Retenção default 180 d.
59
- # NIO_AUTH_EVENTS_RETENTION_DAYS=180
60
- # No modo HOST (sem container), o stdout/stderr do gateway — incl. a trilha —
61
- # vai pra ~/.nio/gateway.log (chmod 600).
62
- #
63
- # Teto de sessões (dispositivos) ativas por usuário (SP-5). Login além disso
64
- # revoga as mais antigas. `nio logout --all` encerra todas de uma vez.
65
- # NIO_MAX_SESSIONS_PER_USER=5
66
- #
67
- # Checagem de senha vazada (SP-7): lista local (sempre) + Have I Been Pwned
68
- # (k-anonymity o prefixo do SHA-1 sai; falha de rede = ignora).
69
- # NIO_HIBP_DISABLE=1 # desliga o HIBP (ambiente sem saída pra internet)
70
- # NIO_HIBP_TIMEOUT_MS=1500
71
-
72
- # Bind do nio-gateway. Default 127.0.0.1 (loopback). Ponha 0.0.0.0 quando o Kong
73
- # roda em container e alcança o gateway via host.docker.internal.
74
- # NIO_GATEWAY_HOST=0.0.0.0
75
- # Onde a CLI acha o gateway. Default http://127.0.0.1:3000 (o nio-gateway direto).
76
- # Com Kong na frente: http://127.0.0.1:8000.
77
- # NIO_GATEWAY_URL=http://127.0.0.1:8000
78
- # Porta do proxy Kong publicada no host pelo `dev:kong` (default 8000).
79
- # NIO_KONG_PROXY_PORT=8010
80
-
81
- # 2º fator (WhatsApp OTP via Meta Graph) — spec 0004 / ADR 0006. Sem endpoint
82
- # + token, o login com auth_2 responde 503 "2FA não configurado" (o login de
83
- # 1 fator segue normal).
84
- # WHATSAPP_ENDPOINT_URL=https://graph.facebook.com/v25.0/1076830002188066/messages
85
- # WHATSAPP_TOKEN=<bearer da Meta Graph> # app secret; rotaciona ~24h
86
- # WHATSAPP_TEMPLATE_NAME=autenticao # template de autenticação aprovado
87
- # WHATSAPP_TEMPLATE_LANGUAGE=pt_BR # variação do template
88
- #
89
- # DEV: se WHATSAPP_ENDPOINT_URL for loopback (127.0.0.1/localhost o mock
90
- # `bun run dev:whatsapp-echo`), o gateway entra em "modo echo": NENHUM WhatsApp real sai.
91
- # A CLI avisa e mostra o código direto; `nio security status` mostra o backend.
92
-
93
- # Client de IA (nio ai) backend OpenAI-compatível que o provider `opencode`
94
- # consome (o SDK anexa /chat/completions). Estes são os knobs da "troca" do client.
95
- # Motor = provider DEDICADO (openai-compatible) direto no backend; o provider `opencode`
96
- # fica no default (big-pickle), fora do motor da CLI.
97
- # NIO_AI_PROVIDER=nio-local # id do provider dedicado no opencode.json
98
- # NIO_AI_BASE_URL=http://192.168.0.140:8001/v1 # backend de IA (default); raiz /v1
99
- # NIO_AI_MODEL=RedHatAI/Qwen3.8-27B-INT4 # id do model EXATO que o backend serve (sem prefixo de provider)
100
- # NIO_AI_CONTEXT=65536 # janela de contexto (tokens) declarada p/ o model; 0 = usa catálogo
101
- # NIO_AI_OUTPUT=2048 # teto de tokens de saída reservados dentro da janela
102
- # NIO_AI_MAX_INPUT=32000 # hard cap de input por prompt (0 = desativa a trava)
103
- # NIO_SKILLS_DESC_CHARS=200 # teto das descrições em prompts/list e resources/list (0 = sem corte)
104
- # NIO_SKILLS_PROMPT_CHARS=12000 # orçamento do texto montado por get_prompt (apoio excedente vira resource sob demanda; 0 = sem teto)
105
- # ^ NIO_AI_* NÃO valem no .env do projeto (cwd é allowlist) — ponha em ~/.nio/config.env ou no shell.
106
- #
107
- # Headroom proxy de compressão em container (ADR 0007), DORMENTE (ADR 0010).
108
- # NIO_HEADROOM_PORT=8787 # porta do proxy no host
109
- # NIO_HEADROOM_URL=http://127.0.0.1:8787/v1 # override total (o provider do OpenCode aponta pra cá)
110
- # NIO_HEADROOM_OPENAI_TARGET=https://opencode.ai/zen/v1 # upstream OpenAI-compatível (default: OpenCode Zen)
111
-
112
- # Debug
113
- # NIO_DEBUG=1 # log verboso [nio:debug] + stack trace completo nos erros
114
- # NIO_NO_ANIM=1 # logo Matrix sempre estático (sem a animação de chuva)
1
+ # Database connection string
2
+ # CLI/MCP: role `nio_cli` (migration 0008) — SELECT em user_cli/auth_sessions,
3
+ # escreve só em sessions/dependency_events/log_session/session_activity.
4
+ NIO_DATABASE_URL=postgres://nio_cli_user:senha@localhost:5432/nio_cli
5
+
6
+ # Gateway: role `nio_gateway` — escreve em user_cli/auth_sessions/login_challenges/
7
+ # auth_events/login_ip_events. Só o processo nio-gateway lê esta var; se ausente,
8
+ # ele cai em NIO_DATABASE_URL (dev com um único role).
9
+ # NIO_GATEWAY_DATABASE_URL=postgres://nio_gw_user:senha@localhost:5432/nio_cli
10
+
11
+ # TLS — LIGADO POR PADRÃO em banco remoto (não-loopback), com verificação de
12
+ # cert. Exceções: banco em loopback (dev local, sem TLS) ou opt-out explícito:
13
+ # NIO_DATABASE_SSL=false
14
+ # Com TLS ligado, o certificado do servidor É VERIFICADO. CA privada (ou o próprio
15
+ # cert self-signed, pra pinning):
16
+ # NIO_DATABASE_CA=/etc/ssl/nio/db-ca.pem
17
+ # Cert cujo SAN é um NOME mas você conecta por IP: verifica o hostname contra este
18
+ # nome (o do SAN) sem afrouxar a verificação — evita ERR_TLS_CERT_ALTNAME_INVALID:
19
+ # NIO_DATABASE_SSL_SERVERNAME=nome-no-san-do-cert
20
+ # Último recurso desliga a verificação de cert (expõe a MITM). Prefira NIO_DATABASE_CA:
21
+ # NIO_DATABASE_SSL_INSECURE=1
22
+
23
+ # Gateway — JWT (login v2). Sem prefixo NIO_ de propósito: segredo da equipe,
24
+ # mesmo valor em toda máquina que roda o nio-gateway.
25
+ # Mínimo 32 caracteres aleatórios. Gere com: `nio config setup` ou
26
+ # node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
27
+ JWT_SECRET=
28
+ # JWT_EXPIRES_IN=12h
29
+
30
+ # ── Endurecimento de cripto (ADR 0011) tudo opcional, defaults = comportamento atual ──
31
+ #
32
+ # Pepper de senha: segredo de servidor combinado à senha antes do argon2. Um dump
33
+ # do banco SEM ele não dá pra brute-forçar offline. MESMO valor em todo nó do
34
+ # gateway. PERDER = reset de senha forçado dos usuários peppered — FAÇA BACKUP.
35
+ # Formato: id:segredo[,id:segredo] o de maior id é o atual (rotação: adiciona o
36
+ # novo, o re-hash on login migra, depois remove o velho). Gere: openssl rand -base64 32
37
+ # NIO_PEPPERS=1:troque-por-um-segredo-forte-de-32-ou-mais-chars
38
+ #
39
+ # Chave do HMAC do OTP separa do JWT_SECRET. Default = JWT_SECRET.
40
+ # OTP_HMAC_SECRET=
41
+ #
42
+ # Rotação de JWT sem derrubar sessão: JWT_SECRETS = kid:segredo[,kid:segredo].
43
+ # A ÚLTIMA entrada assina os tokens novos; QUALQUER uma verifica. Token antigo
44
+ # (sem kid) verifica contra JWT_SECRET. Fluxo: adiciona o kid novo no fim
45
+ # deploy → espera 12h (TTL do JWT) → remove o kid velho. Ausente = usa JWT_SECRET.
46
+ # JWT_SECRETS=2026a:segredo-antigo-de-32+-chars,2026b:segredo-novo-de-32+-chars
47
+ #
48
+ # Params do argon2id — defaults = piso OWASP. Calibre na máquina do gateway com
49
+ # node scripts/argon2-calibrate.mjs (ou `bun run argon2:calibrate`)
50
+ # mire ~250-500 ms no hash. Subir só re-hasheia no próximo login (não é breaking).
51
+ # NIO_ARGON2_MEMORY_MIB=19
52
+ # NIO_ARGON2_TIME=2
53
+ # NIO_ARGON2_PARALLELISM=1
54
+ #
55
+ # Auditoria de IP de login (ADR 0011 §F) — o gateway registra de quais IPs cada
56
+ # usuário loga (visível em `nio security status`; retenção 90 d). SÓ registro,
57
+ # não bloqueia. Ligue NIO_TRUST_PROXY=1 pra usar o X-Forwarded-For **apenas** se
58
+ # o Kong for a ÚNICA entrada do gateway (senão o IP é forjável).
59
+ # NIO_TRUST_PROXY=1
60
+
61
+ # Trilha de auth persistente (ADR 0012) — `auth_events` guarda todo evento de auth
62
+ # (login OK/falho, 2FA, mudanças de 2FA, logout). Retenção default 180 d.
63
+ # NIO_AUTH_EVENTS_RETENTION_DAYS=180
64
+ # No modo HOST (sem container), o stdout/stderr do gateway incl. a trilha —
65
+ # vai pra ~/.nio/gateway.log (chmod 600).
66
+ #
67
+ # Teto de sessões (dispositivos) ativas por usuário (SP-5). Login além disso
68
+ # revoga as mais antigas. `nio logout --all` encerra todas de uma vez.
69
+ # NIO_MAX_SESSIONS_PER_USER=5
70
+ #
71
+ # Checagem de senha vazada (SP-7): lista local (sempre) + Have I Been Pwned
72
+ # (k-anonymity — só o prefixo do SHA-1 sai; falha de rede = ignora).
73
+ # NIO_HIBP_DISABLE=1 # desliga o HIBP (ambiente sem saída pra internet)
74
+ # NIO_HIBP_TIMEOUT_MS=1500
75
+
76
+ # Bind do nio-gateway. Default 127.0.0.1 (loopback). Ponha 0.0.0.0 quando o Kong
77
+ # roda em container e alcança o gateway via host.docker.internal.
78
+ # NIO_GATEWAY_HOST=0.0.0.0
79
+ # Onde a CLI acha o gateway. Default http://127.0.0.1:3000 (o nio-gateway direto).
80
+ # Com Kong na frente: http://127.0.0.1:8000.
81
+ # NIO_GATEWAY_URL=http://127.0.0.1:8000
82
+ # Porta do proxy Kong publicada no host pelo `dev:kong` (default 8000).
83
+ # NIO_KONG_PROXY_PORT=8010
84
+
85
+ # fator (WhatsApp OTP via Meta Graph) spec 0004 / ADR 0006. Sem endpoint
86
+ # + token, o login com auth_2 responde 503 "2FA não configurado" (o login de
87
+ # 1 fator segue normal).
88
+ # WHATSAPP_ENDPOINT_URL=https://graph.facebook.com/v25.0/1076830002188066/messages
89
+ # WHATSAPP_TOKEN=<bearer da Meta Graph> # app secret; rotaciona ~24h
90
+ # WHATSAPP_TEMPLATE_NAME=autenticao # template de autenticação aprovado
91
+ # WHATSAPP_TEMPLATE_LANGUAGE=pt_BR # variação do template
92
+ #
93
+ # DEV: se WHATSAPP_ENDPOINT_URL for loopback (127.0.0.1/localhost — o mock
94
+ # `bun run dev:whatsapp-echo`), o gateway entra em "modo echo": NENHUM WhatsApp real sai.
95
+ # A CLI avisa e mostra o código direto; `nio security status` mostra o backend.
96
+
97
+ # Client de IA (nio ai) — backend OpenAI-compatível que o provider `opencode`
98
+ # consome (o SDK anexa /chat/completions). Estes são os knobs da "troca" do client.
99
+ # Motor = provider DEDICADO (openai-compatible) direto no backend; o provider `opencode`
100
+ # fica no default (big-pickle), fora do motor da CLI.
101
+ # NIO_AI_PROVIDER=nio-local # id do provider dedicado no opencode.json
102
+ # NIO_AI_BASE_URL=http://192.168.0.140:8001/v1 # backend de IA (default); raiz /v1
103
+ # NIO_AI_MODEL=RedHatAI/Qwen3.8-27B-INT4 # id do model EXATO que o backend serve (sem prefixo de provider)
104
+ # NIO_AI_CONTEXT=65536 # janela de contexto (tokens) declarada p/ o model; 0 = usa catálogo
105
+ # NIO_AI_OUTPUT=2048 # teto de tokens de saída reservados dentro da janela
106
+ # NIO_AI_MAX_INPUT=32000 # hard cap de input por prompt (0 = desativa a trava)
107
+ # NIO_SKILLS_DESC_CHARS=200 # teto das descrições em prompts/list e resources/list (0 = sem corte)
108
+ # NIO_SKILLS_PROMPT_CHARS=12000 # orçamento do texto montado por get_prompt (apoio excedente vira resource sob demanda; 0 = sem teto)
109
+ # ^ NIO_AI_* NÃO valem no .env do projeto (cwd é allowlist) ponha em ~/.nio/config.env ou no shell.
110
+ #
111
+ # Headroom — proxy de compressão em container (ADR 0007), DORMENTE (ADR 0010).
112
+ # NIO_HEADROOM_PORT=8787 # porta do proxy no host
113
+ # NIO_HEADROOM_URL=http://127.0.0.1:8787/v1 # override total (o provider do OpenCode aponta pra cá)
114
+ # NIO_HEADROOM_OPENAI_TARGET=https://opencode.ai/zen/v1 # upstream OpenAI-compatível (default: OpenCode Zen)
115
+
116
+ # Debug
117
+ # NIO_DEBUG=1 # log verboso [nio:debug] + stack trace completo nos erros
118
+ # NIO_NO_ANIM=1 # logo Matrix sempre estático (sem a animação de chuva)
@@ -1,20 +1,20 @@
1
- # Build reprodutível (auditoria M-2 + I-3a): um lockfile só (`bun.lock`), imagens
2
- # pinadas por digest. Multi-stage — o Bun resolve as deps com o lockfile
3
- # congelado; o runtime continua sendo Node (o alvo do projeto).
4
-
5
- # --- deps: instala node_modules de runtime a partir do bun.lock ---
6
- FROM oven/bun:1-slim@sha256:cb3bbbb08e13a4a2ff400f24c7a2a1d5efa83f6ef8544d52d95a519631e2fc61 AS deps
7
- WORKDIR /app
8
- COPY package.json bun.lock ./
9
- RUN bun install --frozen-lockfile --production
10
-
11
- # --- runtime: Node + curl (healthcheck do compose) ---
12
- FROM node:20-slim@sha256:2cf067cfed83d5ea958367df9f966191a942351a2df77d6f0193e162b5febfc0
13
- RUN apt-get update && apt-get install -y --no-install-recommends curl \
14
- && rm -rf /var/lib/apt/lists/*
15
- WORKDIR /app
16
- COPY --from=deps /app/node_modules ./node_modules
17
- COPY package.json ./
18
- COPY dist ./dist
19
- EXPOSE 3000
20
- CMD ["node", "dist/gateway/index.js"]
1
+ # Build reprodutível (auditoria M-2 + I-3a): um lockfile só (`bun.lock`), imagens
2
+ # pinadas por digest. Multi-stage — o Bun resolve as deps com o lockfile
3
+ # congelado; o runtime continua sendo Node (o alvo do projeto).
4
+
5
+ # --- deps: instala node_modules de runtime a partir do bun.lock ---
6
+ FROM oven/bun:1-slim@sha256:cb3bbbb08e13a4a2ff400f24c7a2a1d5efa83f6ef8544d52d95a519631e2fc61 AS deps
7
+ WORKDIR /app
8
+ COPY package.json bun.lock ./
9
+ RUN bun install --frozen-lockfile --production
10
+
11
+ # --- runtime: Node + curl (healthcheck do compose) ---
12
+ FROM node:20-slim@sha256:2cf067cfed83d5ea958367df9f966191a942351a2df77d6f0193e162b5febfc0
13
+ RUN apt-get update && apt-get install -y --no-install-recommends curl \
14
+ && rm -rf /var/lib/apt/lists/*
15
+ WORKDIR /app
16
+ COPY --from=deps /app/node_modules ./node_modules
17
+ COPY package.json ./
18
+ COPY dist ./dist
19
+ EXPOSE 3000
20
+ CMD ["node", "dist/gateway/index.js"]