auroq-os 2.3.7 → 2.4.1

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,553 @@
1
+ #!/bin/bash
2
+ # Auroq OS — instalador do Mac.
3
+ #
4
+ # curl -fsSL https://arka.education/install.sh | bash
5
+ #
6
+ # Este script roda na maquina de alguem que ainda nao tem NADA: sem Git, sem o
7
+ # motor do sistema, as vezes sem as ferramentas da Apple. Por isso ele e escrito
8
+ # pro bash 3.2 (o que vem no macOS), nao pede senha nenhuma e nao usa sudo.
9
+ #
10
+ # Ordem obrigatoria (PRD "Embarque em 2 passos" §4.2):
11
+ # diagnostico -> Git -> motor -> login da mentoria -> pasta do negocio -> init
12
+ #
13
+ # O `init` e quem escreve o registro do conteudo ao vivo. O instalador nao mexe
14
+ # nisso (ADR-7) — a maquina do aluno tem um dono so pra esse arquivo.
15
+ #
16
+ # Modo biblioteca (usado pelos testes): AUROQ_INSTALL_LIB=1 . install.sh
17
+ # Modo ensaio (nao toca em nada): AUROQ_INSTALL_DRY_RUN=1 bash install.sh
18
+
19
+ set -u
20
+
21
+ SUPORTE="11 93621-4486"
22
+ NODE_MIN=20
23
+ MACOS_MIN=13
24
+ DISCO_MIN_MB=2048
25
+ AUROQ_DIR="${HOME}/.auroq"
26
+ NODE_DIR="${AUROQ_DIR}/node"
27
+
28
+ # Cores — desligadas quando a saida nao e um terminal (log de suporte fica limpo).
29
+ if [ -t 1 ]; then
30
+ ROXO=$'\033[38;2;120;80;200m'; CIANO=$'\033[38;2;34;211;238m'; VERDE=$'\033[38;2;52;211;153m'
31
+ AMBAR=$'\033[38;2;251;191;36m'; VERMELHO=$'\033[38;2;248;113;113m'; FRACO=$'\033[2m'; FIM=$'\033[0m'
32
+ else
33
+ ROXO=''; CIANO=''; VERDE=''; AMBAR=''; VERMELHO=''; FRACO=''; FIM=''
34
+ fi
35
+
36
+ # ─── Fala com o aluno ─────────────────────────────────────────────────────────
37
+
38
+ diz() { printf ' %s\n' "$*"; }
39
+ titulo() { printf '\n%s %s%s\n\n' "$ROXO" "$*" "$FIM"; }
40
+ passo() { printf '\n %s>%s %s\n' "$CIANO" "$FIM" "$*"; }
41
+ ok_feito() { printf ' %s+%s %s\n' "$VERDE" "$FIM" "$*"; }
42
+ aviso() { printf ' %s!%s %s\n' "$AMBAR" "$FIM" "$*"; }
43
+
44
+ # Toda falha diz tres coisas: o que aconteceu, o que fazer agora e o suporte.
45
+ # Um instalador que trava calado e pior que o passo a passo manual.
46
+ auroq_erro() {
47
+ printf '\n %sParou aqui:%s %s\n' "$VERMELHO" "$FIM" "${1:-Algo deu errado.}"
48
+ printf '\n %sO que fazer agora:%s %s\n' "$CIANO" "$FIM" "${2:-Rode o mesmo comando de novo.}"
49
+ printf '\n %sSe continuar travado, chame o suporte: %s%s\n\n' "$FRACO" "$SUPORTE" "$FIM"
50
+ auroq_registrar_log "erro" "${1:-}"
51
+ exit 1
52
+ }
53
+
54
+ # ─── Registro pro suporte (§5.7) ──────────────────────────────────────────────
55
+ # Uma linha por evento. Nunca entra senha, token ou e-mail — o suporte precisa
56
+ # saber o que aconteceu na maquina, nao quem e a pessoa.
57
+
58
+ auroq_registrar_log() {
59
+ [ -n "${AUROQ_INSTALL_DRY_RUN:-}" ] && return 0
60
+ mkdir -p "${HOME}/.auroq" 2>/dev/null || return 0
61
+ printf '%s\t%s\t%s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "${1:-}" "${2:-}" \
62
+ >> "${HOME}/.auroq/install.log" 2>/dev/null || true
63
+ }
64
+
65
+ # ─── Decisoes puras (testadas uma a uma) ──────────────────────────────────────
66
+
67
+ # So letras minusculas, numeros e hifen. Recusar e melhor que "consertar" sozinho:
68
+ # o nome da pasta e o nome do negocio dele, e ele precisa reconhecer.
69
+ auroq_validar_pasta() {
70
+ local nome="${1:-}"
71
+ local ok=1
72
+ # Enter vazio nao e erro do aluno: ele ainda nao escreveu nada. So repete a
73
+ # pergunta — acusar "nome errado" aqui assusta a toa.
74
+ if [ -z "$nome" ]; then
75
+ return 1
76
+ fi
77
+ case "$nome" in
78
+ '' ) ok=0 ;;
79
+ * ) LC_ALL=C; case "$nome" in
80
+ *[!a-z0-9-]* ) ok=0 ;;
81
+ -* | *-- ) ok=0 ;;
82
+ * ) ok=1 ;;
83
+ esac ;;
84
+ esac
85
+ if [ "$ok" -eq 1 ]; then
86
+ return 0
87
+ fi
88
+ diz "Esse nome nao serve: use so letras minusculas, numeros e hifen."
89
+ diz "${FRACO}Exemplo bom: minha-empresa${FIM}"
90
+ return 1
91
+ }
92
+
93
+ auroq_macos_serve() {
94
+ local versao="${1:-0}"
95
+ local maior="${versao%%.*}"
96
+ case "$maior" in
97
+ ''|*[!0-9]* ) return 1 ;;
98
+ esac
99
+ [ "$maior" -ge "$MACOS_MIN" ]
100
+ }
101
+
102
+ auroq_node_serve() {
103
+ local versao="${1:-}"
104
+ versao="${versao#v}"
105
+ local maior="${versao%%.*}"
106
+ case "$maior" in
107
+ ''|*[!0-9]* ) return 1 ;;
108
+ esac
109
+ [ "$maior" -ge "$NODE_MIN" ]
110
+ }
111
+
112
+ auroq_node_tarball() {
113
+ local versao="${1:-}"
114
+ local arq="${2:-}"
115
+ local alvo="x64"
116
+ [ "$arq" = "arm64" ] && alvo="arm64"
117
+ printf 'node-v%s-darwin-%s.tar.gz\n' "$versao" "$alvo"
118
+ }
119
+
120
+ # ─── Falar com o aluno de dentro de um `curl | bash` ──────────────────────────
121
+ # Quando o script chega por `curl ... | bash`, a entrada padrao dele — e de TUDO
122
+ # que ele chamar — e o proprio texto do script. Um programa filho que pergunta
123
+ # "qual o seu e-mail?" leria a proxima linha do install.sh como resposta.
124
+ # Por isso todo comando que conversa com o aluno e ligado no terminal de verdade.
125
+
126
+ auroq_tem_terminal() {
127
+ [ -t 0 ] && return 0
128
+ [ -e /dev/tty ] && (exec 3< /dev/tty) 2>/dev/null && return 0
129
+ return 1
130
+ }
131
+
132
+ # npx que o aluno consegue responder. Sem isso, login e as perguntas do `init`
133
+ # recebem pedaco do script no lugar da resposta dele.
134
+ auroq_npx_aluno() {
135
+ if [ -t 0 ]; then
136
+ npx -y auroq-os@latest "$@"
137
+ else
138
+ npx -y auroq-os@latest "$@" < /dev/tty
139
+ fi
140
+ }
141
+
142
+ # nova | vazia | auroq | ocupada — decidido ANTES de escrever qualquer coisa.
143
+ auroq_estado_pasta() {
144
+ local dir="${1:-}"
145
+ if [ ! -d "$dir" ]; then printf 'nova\n'; return 0; fi
146
+ if [ -d "${dir}/.auroq-core" ]; then printf 'auroq\n'; return 0; fi
147
+ local resto
148
+ resto="$(ls -A "$dir" 2>/dev/null | grep -v -x -e '.DS_Store' -e '.localized' | head -1)"
149
+ if [ -z "$resto" ]; then printf 'vazia\n'; else printf 'ocupada\n'; fi
150
+ }
151
+
152
+ # ─── O motor visivel pra quem abre pelo icone (§5.4) ──────────────────────────
153
+ # A falha mais perigosa do projeto: o app aberto pelo Dock monta o ambiente lendo
154
+ # os arquivos de perfil. Se o motor nao estiver la, o app sobe SEM ERRO NENHUM e
155
+ # o Companion parece burro. Por isso escrevemos nos dois arquivos, sempre.
156
+
157
+ auroq_aplicar_path() {
158
+ local arquivo="${1:-}"
159
+ local bin="${2:-}"
160
+ local tmp="${arquivo}.auroq-tmp.$$"
161
+ [ -f "$arquivo" ] || : > "$arquivo"
162
+ # tira o bloco antigo (se houver) e escreve o novo — nunca empilha
163
+ awk '
164
+ /^# >>> auroq >>>$/ { pulando=1; next }
165
+ /^# <<< auroq <<<$/ { pulando=0; next }
166
+ pulando != 1 { print }
167
+ ' "$arquivo" > "$tmp" 2>/dev/null || cp "$arquivo" "$tmp"
168
+ {
169
+ printf '# >>> auroq >>>\n'
170
+ printf '# Motor do Auroq OS. Bloco gerado pelo instalador — pode apagar se desinstalar.\n'
171
+ printf 'export PATH="%s:$PATH"\n' "$bin"
172
+ printf '# <<< auroq <<<\n'
173
+ } >> "$tmp"
174
+ mv "$tmp" "$arquivo"
175
+ }
176
+
177
+ # O motor precisa aparecer em DOIS lugares diferentes, por motivos diferentes.
178
+ #
179
+ # Os arquivos do zsh sao obrigatorios sempre: e por eles que o Claude Code e o
180
+ # Codex abertos pelo ICONE montam o ambiente. Sem isso o app sobe sem erro
181
+ # nenhum e o Companion "nao sabe de nada" (§5.4 do PRD).
182
+ #
183
+ # Os do shell do aluno sao pra janela que ele digita. O macOS 13+ usa zsh e os
184
+ # dois coincidem — mas quem trocou pra bash instalava com sucesso, nao via erro,
185
+ # e depois nenhum comando era reconhecido. Falha silenciosa e a pior de todas:
186
+ # nao tem o que pesquisar, entao a conclusao vira "esse sistema e ruim".
187
+ auroq_publicar_node_no_path() {
188
+ local bin="${1:-}"
189
+ local arquivo
190
+
191
+ # Sempre: o app aberto pelo icone le daqui.
192
+ for arquivo in "${HOME}/.zshrc" "${HOME}/.zprofile"; do
193
+ auroq_aplicar_path "$arquivo" "$bin"
194
+ done
195
+
196
+ case "${SHELL:-}" in
197
+ *zsh )
198
+ : # ja coberto acima
199
+ ;;
200
+ *bash )
201
+ for arquivo in "${HOME}/.bash_profile" "${HOME}/.bashrc"; do
202
+ auroq_aplicar_path "$arquivo" "$bin"
203
+ done
204
+ ;;
205
+ '' )
206
+ : # sem SHELL definido (roda dentro de outro programa): o zsh cobre
207
+ ;;
208
+ * )
209
+ # Nao invento a sintaxe de um shell que nao sei testar. Melhor o aluno
210
+ # saber agora, com nome e saida, do que descobrir que "nada funciona".
211
+ aviso "O seu terminal (${SHELL##*/}) nao e o padrao do Mac, entao eu nao consigo"
212
+ diz " deixar o sistema pronto nele. Use o app Terminal (que vem no Mac) pra"
213
+ diz " trabalhar com o Auroq, ou chame o suporte ${SUPORTE} pra ajustar o seu."
214
+ auroq_registrar_log "path" "shell-nao-suportado=${SHELL##*/}"
215
+ ;;
216
+ esac
217
+ }
218
+
219
+ # ─── Passo 1: diagnostico (§5.1) ──────────────────────────────────────────────
220
+
221
+ auroq_diagnostico() {
222
+ passo "Vendo o seu computador..."
223
+
224
+ local sistema
225
+ sistema="$(uname -s 2>/dev/null || echo desconhecido)"
226
+ if [ "$sistema" != "Darwin" ]; then
227
+ auroq_erro "Este instalador e do Mac, e aqui nao parece ser um Mac." "No Windows, use o outro endereco: arka.education/install.ps1"
228
+ fi
229
+
230
+ local versao
231
+ versao="${AUROQ_INSTALL_FAKE_MACOS:-$(sw_vers -productVersion 2>/dev/null || echo 0)}"
232
+ if ! auroq_macos_serve "$versao"; then
233
+ auroq_erro "Seu Mac esta no macOS ${versao} e o sistema precisa do 13 ou mais novo." "Atualize o Mac em Ajustes > Geral > Atualizacao de Software, ou fale com o suporte antes de continuar."
234
+ fi
235
+
236
+ local chip
237
+ chip="$(uname -m 2>/dev/null || echo desconhecido)"
238
+ local nome_chip="Intel"
239
+ [ "$chip" = "arm64" ] && nome_chip="chip Apple"
240
+ ok_feito "Mac com ${nome_chip}, macOS ${versao} — serve"
241
+
242
+ local livre_mb
243
+ livre_mb="${AUROQ_INSTALL_FAKE_DISCO_MB:-$(df -m "$HOME" 2>/dev/null | awk 'NR==2 {print $4}')}"
244
+ case "${livre_mb:-0}" in
245
+ ''|*[!0-9]* ) livre_mb=999999 ;;
246
+ esac
247
+ if [ "$livre_mb" -lt "$DISCO_MIN_MB" ]; then
248
+ auroq_erro "Falta espaco no disco: sobram ${livre_mb} MB e sao necessarios pelo menos 2 GB." "Libere espaco (Ajustes > Geral > Armazenamento) e rode o mesmo comando de novo."
249
+ fi
250
+
251
+ if [ -n "${AUROQ_INSTALL_FAKE_SEM_INTERNET:-}" ]; then
252
+ auroq_erro "Nao consegui falar com a internet." "Conecte na internet e rode o mesmo comando de novo. Nada foi instalado pela metade."
253
+ fi
254
+ if [ -z "${AUROQ_INSTALL_DRY_RUN:-}" ]; then
255
+ if ! curl -sfI --max-time 15 https://registry.npmjs.org/ >/dev/null 2>&1; then
256
+ auroq_erro "Nao consegui falar com a internet." "Conecte na internet e rode o mesmo comando de novo. Nada foi instalado pela metade."
257
+ fi
258
+ fi
259
+ auroq_registrar_log "diagnostico" "macos=${versao} chip=${chip} disco_mb=${livre_mb}"
260
+ }
261
+
262
+ # ─── Passo 2: Git (§5.2) ──────────────────────────────────────────────────────
263
+ # No Mac o Git vem junto das ferramentas da Apple. O script abre a janela; quem
264
+ # clica em "Instalar" e o aluno. Isso nao da pra automatizar — e janela do sistema.
265
+
266
+ auroq_git_responde() {
267
+ git --version >/dev/null 2>&1 && return 0
268
+ [ -x /usr/bin/git ] && /usr/bin/git --version >/dev/null 2>&1 && return 0
269
+ return 1
270
+ }
271
+
272
+ auroq_garantir_git() {
273
+ passo "Verificando o Git (o programa que guarda as versoes do seu trabalho)..."
274
+
275
+ if [ -n "${AUROQ_INSTALL_DRY_RUN:-}" ]; then
276
+ ok_feito "Git — seria verificado aqui"
277
+ return 0
278
+ fi
279
+
280
+ if auroq_git_responde; then
281
+ ok_feito "Git ja estava instalado"
282
+ auroq_registrar_log "git" "ja-existia"
283
+ return 0
284
+ fi
285
+
286
+ aviso "Falta instalar. Vai abrir uma janela da Apple agora."
287
+ diz " Clique em \"Instalar\" e volte pra ca — pode levar de 5 a 10 minutos."
288
+ diz " Pode deixar baixando e ir tomar um cafe; eu espero."
289
+ xcode-select --install >/dev/null 2>&1 || true
290
+
291
+ local esperou=0
292
+ while [ "$esperou" -lt 1200 ]; do
293
+ if auroq_git_responde; then
294
+ ok_feito "Git instalado"
295
+ auroq_registrar_log "git" "instalado-pelas-ferramentas-da-apple"
296
+ return 0
297
+ fi
298
+ sleep 10
299
+ esperou=$((esperou + 10))
300
+ if [ $((esperou % 120)) -eq 0 ]; then
301
+ diz "${FRACO} ainda baixando... (${esperou}s)${FIM}"
302
+ fi
303
+ done
304
+
305
+ auroq_erro "A instalacao das ferramentas da Apple nao terminou." "Termine a janela da Apple e rode o mesmo comando de novo — nada do que ja foi feito se perde."
306
+ }
307
+
308
+ # ─── Passo 3: o motor (§5.3) ──────────────────────────────────────────────────
309
+ # Fica numa pasta do proprio aluno. Sem senha, sem sudo, sem tocar no que ele ja
310
+ # tinha instalado: se ja existe um motor bom, usamos o dele.
311
+
312
+ # Abre o pacote do motor direto na pasta final.
313
+ #
314
+ # A versao anterior descompactava ao lado e movia com `mv .../node-v*-darwin-* destino`.
315
+ # O curinga pegava DOIS caminhos — a pasta aberta e o proprio .tar.gz, que mora no
316
+ # mesmo lugar — e `mv` com duas origens exige que o destino ja seja uma pasta. Como
317
+ # o destino tinha acabado de ser renomeado pra `.antigo`, ele nao existia: todo aluno
318
+ # sem motor na maquina batia em "Nao consegui guardar o motor na sua pasta".
319
+ #
320
+ # Aqui nao existe curinga: `--strip-components=1` joga o conteudo direto no destino.
321
+ auroq_desempacotar_node() {
322
+ local pacote="$1" destino="$2"
323
+
324
+ rm -rf "${destino}.antigo" 2>/dev/null || true
325
+ if [ -d "$destino" ]; then
326
+ mv "$destino" "${destino}.antigo" 2>/dev/null || return 1
327
+ fi
328
+
329
+ mkdir -p "$destino" 2>/dev/null || return 1
330
+ tar -xzf "$pacote" -C "$destino" --strip-components=1 2>/dev/null || return 1
331
+
332
+ # So e sucesso se o motor de fato ficou de pe.
333
+ [ -x "${destino}/bin/node" ] || return 1
334
+ }
335
+
336
+ auroq_garantir_node() {
337
+ passo "Verificando o motor do sistema..."
338
+
339
+ if [ -n "${AUROQ_INSTALL_DRY_RUN:-}" ]; then
340
+ ok_feito "Motor — seria instalado em uma pasta sua, sem senha"
341
+ return 0
342
+ fi
343
+
344
+ local atual
345
+ atual="$(node --version 2>/dev/null || true)"
346
+ if auroq_node_serve "$atual"; then
347
+ ok_feito "O motor ja estava instalado (${atual})"
348
+ auroq_registrar_log "motor" "ja-existia versao=${atual} origem=$(command -v node 2>/dev/null || echo desconhecida)"
349
+ return 0
350
+ fi
351
+
352
+ if [ -n "$atual" ]; then
353
+ aviso "Voce ja tinha um motor antigo (${atual}); vou instalar um novo do lado, sem mexer no seu."
354
+ fi
355
+ diz " (e um programa que fica numa pasta sua, nao pede senha e nao mexe em nada do seu Mac)"
356
+
357
+ local chip alvo indice versao tarball url tmpdir
358
+ chip="$(uname -m)"
359
+ alvo="$(auroq_node_tarball "0" "$chip")"
360
+
361
+ indice="$(curl -fsSL --max-time 30 https://nodejs.org/dist/index.json 2>/dev/null || true)"
362
+ [ -z "$indice" ] && auroq_erro "Nao consegui baixar o motor do sistema." "Confira a internet (ou o antivirus, se houver) e rode o mesmo comando de novo."
363
+
364
+ versao="$(printf '%s' "$indice" | tr ',' '\n' | grep -o '"version":"v24\.[0-9.]*"' | head -1 | sed 's/.*"v//; s/"//')"
365
+ [ -z "$versao" ] && versao="$(printf '%s' "$indice" | tr ',' '\n' | grep -o '"version":"v2[0-9]\.[0-9.]*"' | head -1 | sed 's/.*"v//; s/"//')"
366
+ [ -z "$versao" ] && auroq_erro "Nao consegui descobrir qual motor baixar." "Rode o mesmo comando de novo em alguns minutos. Se insistir, chame o suporte."
367
+
368
+ tarball="$(auroq_node_tarball "$versao" "$chip")"
369
+ url="https://nodejs.org/dist/v${versao}/${tarball}"
370
+ tmpdir="$(mktemp -d)"
371
+
372
+ curl -fsSL --max-time 600 -o "${tmpdir}/${tarball}" "$url" 2>/dev/null \
373
+ || auroq_erro "O download do motor nao completou." "Pode ser antivirus ou rede instavel. Rode o mesmo comando de novo; se repetir, chame o suporte."
374
+
375
+ # Sem conferir a soma oficial, nao instala. Binario nao verificado nao entra.
376
+ local somas esperado obtido
377
+ somas="$(curl -fsSL --max-time 60 "https://nodejs.org/dist/v${versao}/SHASUMS256.txt" 2>/dev/null || true)"
378
+ esperado="$(printf '%s' "$somas" | grep " ${tarball}\$" | awk '{print $1}')"
379
+ obtido="$(shasum -a 256 "${tmpdir}/${tarball}" 2>/dev/null | awk '{print $1}')"
380
+ if [ -z "$esperado" ] || [ "$esperado" != "$obtido" ]; then
381
+ rm -rf "$tmpdir"
382
+ auroq_erro "O arquivo do motor baixou com defeito." "Rode o mesmo comando de novo — o arquivo estragado ja foi apagado."
383
+ fi
384
+
385
+ auroq_desempacotar_node "${tmpdir}/${tarball}" "$NODE_DIR" \
386
+ || { rm -rf "$tmpdir"; auroq_erro "Nao consegui guardar o motor na sua pasta." "Rode o mesmo comando de novo."; }
387
+ rm -rf "$tmpdir" "${NODE_DIR}.antigo"
388
+
389
+ auroq_publicar_node_no_path "${NODE_DIR}/bin"
390
+ export PATH="${NODE_DIR}/bin:${PATH}"
391
+ # npm global dentro da pasta do aluno: instalar ferramenta depois nao pede senha
392
+ export npm_config_prefix="${NODE_DIR}"
393
+
394
+ ok_feito "Motor instalado (${versao})"
395
+ auroq_registrar_log "motor" "instalado versao=${versao} chip=${chip}"
396
+ }
397
+
398
+ # ─── Passo 4: login da mentoria (§5.5) ────────────────────────────────────────
399
+ # Mesma checagem que o resto do sistema usa. So contrato ativo instala.
400
+
401
+ auroq_login_mentoria() {
402
+ passo "Agora entre com o seu acesso da Mentoria Arcane."
403
+
404
+ if [ -n "${AUROQ_INSTALL_DRY_RUN:-}" ]; then
405
+ ok_feito "Login — seria pedido aqui (e-mail e senha da plataforma)"
406
+ return 0
407
+ fi
408
+
409
+ if ! auroq_tem_terminal; then
410
+ auroq_erro "Preciso do seu e-mail e senha da Mentoria Arcane, e esta janela nao aceita resposta." "Abra o Terminal (ou o terminal de dentro do Claude Code) e cole o mesmo comando la."
411
+ fi
412
+
413
+ # `check-access` e a mesma regua do resto do sistema: exit 0 so com contrato
414
+ # ativo conferido agora. Sem sessao salva, ele mesmo pede e-mail e senha; com
415
+ # sessao boa, passa direto e nao pergunta de novo.
416
+ #
417
+ # NAO usar `whoami` aqui: ele imprime "Nao autenticado" e mesmo assim sai com
418
+ # sucesso. Usado como pergunta de sim/nao, ele dizia "voce ja estava logado"
419
+ # pra quem nunca logou, pulava o portao e deixava a conta sem acesso chegar ate
420
+ # a criacao da pasta.
421
+ if ! auroq_npx_aluno check-access; then
422
+ auroq_registrar_log "login" "recusado"
423
+ printf '\n %sSem acesso ativo, a instalacao para aqui — e nada foi criado no seu computador.%s\n' "$FRACO" "$FIM"
424
+ printf ' %sO que fazer agora: fale com o suporte %s%s\n\n' "$FRACO" "$SUPORTE" "$FIM"
425
+ exit 1
426
+ fi
427
+ auroq_registrar_log "login" "ok"
428
+ }
429
+
430
+ # ─── Passo 5: pasta do negocio (§5.6) ─────────────────────────────────────────
431
+
432
+ auroq_escolher_pasta() {
433
+ passo "Qual o nome da pasta do seu negocio?"
434
+ diz "${FRACO}(so letras minusculas e hifen — ex: minha-empresa)${FIM}"
435
+
436
+ local nome="${AUROQ_INSTALL_PASTA:-}"
437
+ local tentativas=0
438
+
439
+ while : ; do
440
+ if [ -z "$nome" ]; then
441
+ # Rodando por `curl ... | bash`, a entrada padrao e o proprio script:
442
+ # a pergunta tem que ir pro terminal de verdade.
443
+ if [ ! -t 0 ]; then
444
+ if [ -e /dev/tty ] && (exec 3< /dev/tty) 2>/dev/null; then
445
+ printf ' Nome: '
446
+ read -r nome < /dev/tty 2>/dev/null || nome=''
447
+ else
448
+ auroq_erro "Nao consegui te perguntar o nome da pasta: esta janela nao aceita resposta." "Abra o Terminal (ou o terminal de dentro do Claude Code) e cole o mesmo comando la."
449
+ fi
450
+ else
451
+ printf ' Nome: '
452
+ read -r nome || nome=''
453
+ fi
454
+ fi
455
+
456
+ if auroq_validar_pasta "$nome"; then
457
+ PASTA_ALVO="${HOME}/${nome}"
458
+ case "$(auroq_estado_pasta "$PASTA_ALVO")" in
459
+ auroq )
460
+ printf '\n'
461
+ aviso "Ja existe um Auroq em ${PASTA_ALVO} — nao vou mexer nele."
462
+ diz "Pra conferir se esta tudo certo la, abra essa pasta e rode:"
463
+ diz "${CIANO} auroq-os doctor${FIM}"
464
+ auroq_registrar_log "pasta" "ja-tinha-auroq"
465
+ exit 0
466
+ ;;
467
+ ocupada )
468
+ aviso "A pasta ${nome} ja existe e tem coisa sua dentro. Escolha outro nome."
469
+ nome=''
470
+ ;;
471
+ * )
472
+ break
473
+ ;;
474
+ esac
475
+ else
476
+ nome=''
477
+ fi
478
+
479
+ tentativas=$((tentativas + 1))
480
+ if [ "$tentativas" -ge 5 ]; then
481
+ auroq_erro "Nao consegui um nome valido pra pasta." "Rode o mesmo comando de novo e escreva algo como: minha-empresa"
482
+ fi
483
+ done
484
+
485
+ if [ -n "${AUROQ_INSTALL_DRY_RUN:-}" ]; then
486
+ ok_feito "Pasta ${PASTA_ALVO} — seria criada aqui"
487
+ return 0
488
+ fi
489
+
490
+ mkdir -p "$PASTA_ALVO" 2>/dev/null \
491
+ || auroq_erro "Nao consegui criar a pasta ${PASTA_ALVO}." "Confira se voce tem permissao de escrita na sua pasta pessoal e rode de novo."
492
+ auroq_registrar_log "pasta" "criada"
493
+ }
494
+
495
+ # ─── Passo 6: montar o Auroq ──────────────────────────────────────────────────
496
+
497
+ auroq_rodar_init() {
498
+ passo "Montando o Auroq dentro de ${PASTA_ALVO}..."
499
+
500
+ if [ -n "${AUROQ_INSTALL_DRY_RUN:-}" ]; then
501
+ ok_feito "Sistema — seria montado aqui"
502
+ return 0
503
+ fi
504
+
505
+ cd "$PASTA_ALVO" || auroq_erro "Nao consegui entrar na pasta ${PASTA_ALVO}." "Rode o mesmo comando de novo."
506
+ # ligado no terminal de verdade: o `init` ainda pergunta se ele ja usa o Auroq
507
+ # em outra maquina (3a pergunta do §4.4), e essa resposta e do aluno.
508
+ if ! auroq_npx_aluno init; then
509
+ auroq_registrar_log "init" "falhou"
510
+ auroq_erro "A montagem do sistema parou no meio." "Rode o mesmo comando de novo. Se repetir, mande pro suporte o arquivo ~/.auroq/install.log"
511
+ fi
512
+ auroq_registrar_log "init" "ok"
513
+ }
514
+
515
+ # ─── Passo 7: fecho ───────────────────────────────────────────────────────────
516
+
517
+ auroq_fecho() {
518
+ printf '\n %s%s%s\n\n' "$ROXO" "─────────────────────────────────────────────" "$FIM"
519
+ diz "Pronto. O Auroq esta em ${PASTA_ALVO}"
520
+ printf '\n'
521
+ diz "Falta um detalhe importante:"
522
+ printf '\n'
523
+ diz " 1. FECHE o Claude Code (ou o Codex) por completo e abra de novo"
524
+ diz " ${FRACO}— sem isso ele nao enxerga o que acabou de ser instalado${FIM}"
525
+ diz " 2. Abra a pasta ${PASTA_ALVO##*/}"
526
+ diz " 3. Chame o Ops: ${CIANO}/AuroqOS:agents:ops${FIM} ${FRACO}(no Codex: \$ops)${FIM}"
527
+ diz " 4. Digite: ${CIANO}*bootstrap${FIM}"
528
+ printf '\n'
529
+ diz "O Ops instala o resto e te guia daqui pra frente."
530
+ printf '\n'
531
+ auroq_registrar_log "fim" "ok pasta=${PASTA_ALVO##*/}"
532
+ }
533
+
534
+ # ─── Fluxo ────────────────────────────────────────────────────────────────────
535
+
536
+ auroq_main() {
537
+ titulo "Auroq OS — instalacao"
538
+ auroq_diagnostico
539
+ auroq_garantir_git
540
+ auroq_garantir_node
541
+ auroq_login_mentoria
542
+ auroq_escolher_pasta
543
+ auroq_rodar_init
544
+ auroq_fecho
545
+ }
546
+
547
+ # Carregado pelos testes: so define as funcoes e sai.
548
+ if [ -n "${AUROQ_INSTALL_LIB:-}" ]; then
549
+ return 0 2>/dev/null || true
550
+ else
551
+ PASTA_ALVO=""
552
+ auroq_main
553
+ fi
package/lib/auth.js CHANGED
@@ -5,7 +5,7 @@ const { createAuthClient } = require('./supabase');
5
5
  const credentials = require('./credentials');
6
6
 
7
7
  const PLATFORM_URL = 'https://arcane.arka.education';
8
- const SUPPORT_CONTACT = '11 97312-2273';
8
+ const SUPPORT_CONTACT = '11 93621-4486';
9
9
  const MAX_LOGIN_ATTEMPTS = 3;
10
10
 
11
11
  const PURPLE = '\x1b[38;2;120;80;200m';
@@ -296,13 +296,24 @@ async function logout() {
296
296
  ok('Sessao encerrada. Credenciais locais removidas.');
297
297
  }
298
298
 
299
+ /**
300
+ * Mostra quem esta autenticado NESTA maquina, pelo que esta salvo no disco.
301
+ *
302
+ * Retorna `true` so quando ha sessao salva com o ultimo status conhecido
303
+ * 'ativo' — e o CLI transforma isso em codigo de saida. Antes ele saia com
304
+ * sucesso ate sem credencial nenhuma, e quem usasse `whoami` como pergunta de
305
+ * sim/nao (era o caso do instalador) concluia que o aluno ja estava logado.
306
+ *
307
+ * Continua sendo uma leitura LOCAL: pra decidir acesso de verdade, o portao e
308
+ * `check-access` / `requireActiveAccess()`, que confere online.
309
+ */
299
310
  function whoami() {
300
311
  const cred = credentials.load();
301
312
  if (!cred) {
302
313
  log(`${DIM}Nao autenticado.${RESET}`);
303
314
  log('');
304
315
  log(`${DIM}Para entrar: ${CYAN}auroq-os login${RESET}`);
305
- return;
316
+ return false;
306
317
  }
307
318
  const now = Math.floor(Date.now() / 1000);
308
319
  const validatedAgo = cred.last_validated_at ? Math.floor((now - cred.last_validated_at) / 60) : null;
@@ -320,6 +331,7 @@ function whoami() {
320
331
  }
321
332
  log(`${DIM}Access token:${RESET} ${expired ? `${GOLD}expirado${RESET}` : `${GREEN}valido${RESET}`}`);
322
333
  log('');
334
+ return cred.last_status === 'ativo';
323
335
  }
324
336
 
325
337
  /**