Documentação do spaceAI v1.0

Board de tarefas

Veja as 30 tarefas que saíram da auditoria e da verificação em código, em três colunas: fazer, decidir e feito. Filtre por app ou esforço e abra o card para ver a evidência no disco.

Nota

O estado de cada card vem da lista TASKS do build.py do guia. Para mover um card, edite lá e regenere: veja Como alterar esta documentação.

O progresso#

Concluídas — 5 de 30
17%
A fazer — 21 de 30
70%
A decidir — 4 de 30
13%
47%BARATO
40%MÉDIO
13%ALTO

A rosca mostra o esforço: das 30 tarefas, 14 custam pouco e 18 têm impacto alto. O board começa pelo barato que alivia rápido.

Filtros#

Filtre os cards por app ou por esforço. Sem JavaScript, todos os cards aparecem.

App:

Esforço:

mostrando 30 de 30

As colunas#

🔨 Fazer (21)

TB-02 — Fechar o cliente OpenAPI gerado no render
Esforço barato · impacto médio · render
TB-03 — Corrigir a documentação quebrada e criar os READMEs que faltam
Esforço barato · impacto alto · conta-central load-balance render motor agent-package
TB-04 — Instalar a varredura de segredo e o Renovate na raiz do monorepo
Esforço barato · impacto alto · spaceAI agent-package render
TB-05 — Pôr as três fechaduras nos containers do load-balance, do mypanel e do motor
Esforço barato · impacto alto · load-balance mypanel motor
TB-06 — Unificar o pin do @nomad/ui e padronizar os paths de health
Esforço barato · impacto médio · conta-central load-balance motor mypanel
TB-07 — Isolar o process.env em src/config e gerar o .env.example do schema
Esforço médio · impacto alto · load-balance motor mypanel conta-central
TB-08 — Adotar a RFC 9457 como envelope de erro único dos 6 backends
Esforço médio · impacto alto · conta-central mypanel load-balance motor
TB-09 — Adotar piso de cobertura e knip nos 4 projetos sem
Esforço médio · impacto médio · conta-central load-balance motor mypanel
TB-10 — Decidir a topologia do repositório por escrito e reduzir os lockfiles
Esforço médio · impacto médio · motor mypanel
TB-11 — Gerar o contrato REST nos projetos com catálogo manual
Esforço alto · impacto alto · motor conta-central load-balance mypanel
TB-12 — Padronizar features por domínio e a fonte de verdade do design system
Esforço médio · impacto médio · conta-central render mypanel motor
TB-16 — Rodar npm run gates no motor com instalação limpa
Esforço médio · impacto alto · motor
TB-17 — Corrigir o WorkingDirectory do systemd de /be para /backend
Esforço barato · impacto alto · motor
TB-22 — Dar versão e envelope único às tools MCP do agent-package
Esforço médio · impacto alto · agent-package render
TB-23 — Medir o N+1 por tool e padronizar a paginação
Esforço médio · impacto alto · agent-package render mypanel motor load-balance conta-central
TB-24 — Desacoplar o núcleo dos services do mcp/ no agent-package
Esforço médio · impacto médio · agent-package
TB-25 — Escrever o system prompt e a doc de tools de cada agente coordenador
Esforço médio · impacto alto · agent-package motor render mypanel load-balance conta-central
TB-26 — Levar o Swagger aos 4 backends que ainda não têm
Esforço médio · impacto alto · conta-central load-balance motor mypanel
TB-27 — Fechar as 134 operações sem contrato no agent-package
Esforço alto · impacto alto · agent-package
TB-28 — Levar o padrão de serviço com dois adaptadores aos outros 4 apps
Esforço alto · impacto alto · motor load-balance render conta-central
TB-29 — Rotacionar os dois tokens que ficaram no histórico do .mcp.json
Esforço barato · impacto alto · spaceAI agent-package mypanel

🤔 Decidir (4)

TB-18 — Decidir o destino do Dockerfile.worker órfão
Esforço barato · impacto médio · motor
TB-19 — Decidir o rename do pacote motor-fe
Esforço barato · impacto baixo · motor
TB-20 — Decidir se o nomad-ui vira workspace ou segue remoto
Esforço médio · impacto médio · spaceAI
TB-21 — Alinhar o Node 22 do motor com o Node 24 da casa
Esforço alto · impacto médio · motor

✅ Feito (5)

TB-01 — Instalar ESLint com regra de fronteira nos 3 backends sem lint
Esforço barato · impacto alto · load-balance motor mypanel
TB-13 — Rename de be/fe para backend/frontend aplicado no motor
Esforço barato · impacto médio · motor
TB-14 — AGENTS.md e CLAUDE.md da raiz escritos com a regra da casa
Esforço barato · impacto alto · spaceAI
TB-15 — Guard do Dockerfile trava o COPY do frontend
Esforço barato · impacto médio · motor
TB-30 — Tirar o eval do logger do load-balance
Esforço barato · impacto alto · load-balance

Detalhe das tarefas#

Cada card acima ancora aqui. Cada tarefa traz a descrição e a ficha: estado, apps, esforço e impacto, fase do roadmap, origem e a evidência no disco.

TB-01 — Instalar ESLint com regra de fronteira nos 3 backends sem lint

Entregue em 2026-10-25 e já na main. O load-balance, o motor e o servidor do mypanel ganharam ESLint flat (eslint.config.js) e Prettier, com os scripts lint, lint:fix, format e format:check. A regra de fronteira proíbe a rota de importar o ORM, tanto no import estático quanto no import() dinâmico. Ela entrou como aviso, porque a dívida existe: em vez de ninguém perceber, o lint agora lista cada rota que fala direto com o banco. Zerar essa lista e promover a regra a erro, como o render fez, é o passo seguinte. Na mesma entrega vieram o projectService: false explícito, sem o qual os erros de parsing voltam por variável de ambiente, e a saída do eval do logger do load-balance (TB-30).

TB-02 — Fechar o cliente OpenAPI gerado no render

O backend do render já emite a spec (scripts/openapi-spec.ts) e o frontend já declara o @hey-api/openapi-ts, mas ninguém consome a spec. Faltam o openapi-ts.config.ts, a pasta src/api/generated/ e os scripts api:spec, api:gen e api:check. Copie o par do agent-package: o cliente do frontend passa a nascer da API real, e o api:check reprova quando os dois divergem. É trocar a planilha copiada à mão pela consulta ligada na fonte.

TB-03 — Corrigir a documentação quebrada e criar os READMEs que faltam

O conta-central, o load-balance e o motor não têm README na raiz. Pior que faltar é descrever o que não existe: o README do frontend do load-balance cita pastas e um stack (Sonner) ausentes, o do frontend do motor descreve Astryx, StyleX e FSD, já removidos, e o components/ui/README.md do conta-central documenta componentes que o barrel não expõe. O backend/README.md do agent-package aponta para um ../AGENTS.md que não entrou no monorepo, e o gate docs:check do render estoura ENOENT dentro do próprio gerador. Crie os pontos de entrada, regenere os READMEs a partir da árvore real e ponha o docs:check de volta no verde.

TB-04 — Instalar a varredura de segredo e o Renovate na raiz do monorepo

A auditoria contava o kit no agent-package: pre-commit com gitleaks, .gitleaks.toml e renovate.json. No monorepo, só o renovate.json chegou; o .pre-commit-config.yaml e o .gitleaks.toml nunca entraram no git da casa. Hoje nenhum app tem varredura de segredo, e o gitleaks que o CLAUDE.md pede não tem config para rodar. Como o monorepo é um repositório só, hook de git e config do Renovate valem por repositório: instale o kit uma vez, na raiz, cobrindo os 6 apps. Foi esse buraco que deixou dois tokens entrarem no .mcp.json (TB-29). No render, resolva também a referência morta ao pre-commit no backend/knip.json.

TB-05 — Pôr as três fechaduras nos containers do load-balance, do mypanel e do motor

O load-balance (backend e frontend) e o mypanel (server e web) não têm nenhuma das três fechaduras: rodam como root, sem HEALTHCHECK e com base flutuante, e o web do mypanel sobe o nginx:alpine como root. O motor está no meio do caminho: o backend já tem USER e HEALTHCHECK, mas a base não tem digest, e o frontend roda o nginx como root, com a justificativa num comentário. Aplique USER não-root e HEALTHCHECK onde faltam (GET /health/live, como no agent-package), troque o nginx do mypanel pelo nginx-unprivileged e fixe o digest das bases, que é mecânico e sai em lote. Sem healthcheck, o orquestrador nunca sabe quando o container está pronto.

TB-06 — Unificar o pin do @nomad/ui e padronizar os paths de health

Os 5 frontends que usam o kit apontam para três refs: a tag v1.13.5 (agent-package, render e motor) e dois SHAs (conta-central e load-balance), que resolvem para duas versões em circulação, 1.13.5 e 1.13.7. Fixe um pin só. A auditoria recomenda a tag v1.13.5, já majoritária; como o conta-central e o load-balance estão na 1.13.7, confira antes o diff de API do createHttpClient e do createQueryClient. Na mesma tarefa, registre /health, /health/live e /health/ready nos 6 backends, com os paths atuais como alias, e escreva no mypanel que ele é a exceção do design system.

TB-07 — Isolar o process.env em src/config e gerar o .env.example do schema

No agent-package e no render, só src/config/ lê process.env, e uma regra de ESLint garante isso. Nos outros 4 backends a leitura está espalhada: cerca de 30 pontos no load-balance e quase 20 diretórios no motor. Concentre as leituras num módulo com schema zod (o motor ainda valida à mão) e ligue a regra de ESLint com lista de pendências, para não quebrar o build de uma vez. Só então gere o .env.example a partir do schema. Trocar uma variável hoje vira caça ao tesouro, e o .env.example do motor tem 92 chaves, tamanho em que é fácil documentar uma que o código nem lê.

TB-08 — Adotar a RFC 9457 como envelope de erro único dos 6 backends

Só o agent-package e o render respondem erro em application/problem+json. Os outros 4 têm cada um o seu formato, e todo cliente HTTP precisa saber com qual backend está falando. Migre os 4 em ordem de esforço: primeiro o conta-central e o mypanel, cujo envelope de erro e mensagem é trivial de converter, depois o load-balance e o motor. Mantenha error e message como apelidos durante a transição, como o agent-package já faz, e faça rota nova nascer no envelope padrão.

TB-09 — Adotar piso de cobertura e knip nos 4 projetos sem

Só o agent-package e o render medem cobertura (coverage-floor.json) e procuram código morto (knip). Nos outros 4 nenhum config de teste tem threshold, então uma queda de 30 pontos de cobertura passa em silêncio. O mínimo útil não é copiar o piso por diretório: é um test:coverage com threshold global, começando em 40% e subindo, ligado ao gate de cada projeto. Some o knip onde o alvo já é conhecido: o pacote compartilhado morto do mypanel e os scripts .mjs do motor que ficam fora do typecheck.

TB-10 — Decidir a topologia do repositório por escrito e reduzir os lockfiles

Três topologias convivem: pacotes irmãos sem workspaces (4 apps), npm workspaces no motor, com três lockfiles, e pnpm workspaces no mypanel, que ainda guarda um package-lock.json ao lado do pnpm-lock.yaml. Com dois locks de gerenciadores diferentes na mesma raiz, nenhum install reproduz a árvore testada. A TB-01 atualizou só o pnpm-lock.yaml, então o package-lock.json do mypanel ficou mais velho. Escreva a decisão num ADR e apague o lockfile que sobra; se a casa não for de workspaces, registre o motor e o mypanel como exceções explícitas.

TB-11 — Gerar o contrato REST nos projetos com catálogo manual

No motor, no conta-central, no load-balance e no mypanel, o frontend espelha as rotas do backend à mão, e o drift já aconteceu: o README do frontend do load-balance descreve pastas que não existem. Depois do render (TB-02), aplique a mesma geração ao REST do motor, que já tem gate de deriva no catálogo WS, e então aos outros 3. Onde gerar ainda for caro, o piso é um teste de paridade entre o catálogo do frontend e as rotas do backend; o load-balance já tem o precedente, topbarModelParity.test.ts.

TB-12 — Padronizar features por domínio e a fonte de verdade do design system

No conta-central, 13 componentes locais em src/components/ui/ fazem sombra ao @nomad/ui oficial: 108 arquivos importam o kit local, contra 37 que importam o pacote. Migre-os para o kit, com no máximo um barrel fino, como o motor faz. Adote features/<domínio>/ nas features novas do render e do mypanel, sem reverter o que existe, e junte as pastas duplicadas do motor: workflow com workflows e webhook com webhooks. É como ter duas pastas, Conta e Contas, no mesmo armário: o defeito é de nome, mas todo mundo abre a errada.

TB-13 — Rename de be/fe para backend/frontend aplicado no motor

As pastas do motor se chamavam be e fe e agora se chamam backend e frontend nos scripts e nos workspaces da raiz, nos 3 contexts do compose, no import de teste que tinha quebrado, nos testes que liam paths e no gerador do catálogo. Os nomes de serviço be e fe continuam só dentro do compose. Ficou de fora o WorkingDirectory dos units do systemd, que ainda aponta para .../motor/be: isso é a TB-17.

TB-14 — AGENTS.md e CLAUDE.md da raiz escritos com a regra da casa

A casa tem um documento canônico na raiz, o AGENTS.md, que declara o deploy por app em caixa alta: banco, container e ciclo de vida próprios. O CLAUDE.md da raiz é o resumo curto que aponta para ele.

TB-15 — Guard do Dockerfile trava o COPY do frontend

O teste de Dockerfiles do motor reprova se o backend copiar o frontend para dentro da imagem da API: a regex pega os dois nomes, fe e frontend. É o cadeado que impede misturar a cozinha com a sala.

TB-16 — Rodar npm run gates no motor com instalação limpa

O gate autoritativo do motor é o npm run gates da raiz: check-lock da raiz e do frontend, typecheck, lint, test, build e cycles, nessa ordem. Depois do rename, ninguém provou que ele voltou ao verde. No disco não há node_modules, e a validação da TB-01 rodou lint, typecheck e build dos backends, não o gates inteiro. Instale do zero (npm ci), rode o gates de ponta a ponta e cole o output na mensagem de merge.

TB-17 — Corrigir o WorkingDirectory do systemd de /be para /backend

Os dois units versionados no repo, motor-api.service e motor-worker.service, ainda têm WorkingDirectory=/home/myke/projetos/vps/motor/be. Quando a VPS puxar o código novo, a pasta vira backend e os dois serviços não sobem. Corrija os dois arquivos e reinstale os units na VPS. É como mudar de rua e esquecer de avisar o GPS.

TB-18 — Decidir o destino do Dockerfile.worker órfão

O backend tem um Dockerfile.worker que ninguém usa: nenhum arquivo do repo o cita, e o worker do compose sobe pelo Dockerfile normal, com o comando npm run worker. Decida entre apagar o arquivo ou passar a usá-lo. Arquivo órfão é o que alguém edita achando que vale para produção.

TB-19 — Decidir o rename do pacote motor-fe

A pasta virou frontend, mas o pacote ainda se chama motor-fe (o do backend se chama motor-agent). Decida se o nome do pacote acompanha a pasta ou fica como está.

TB-20 — Decidir se o nomad-ui vira workspace ou segue remoto

O código do kit está em nomad-ui/, na versão 1.13.7, mas ninguém o consome: os 5 frontends que usam o @nomad/ui baixam do GitHub remoto. Decida se ele vira workspace ou segue como espelho do remoto, com regra de sincronia escrita. Enquanto nada for decidido, o pin é a única fonte de verdade, e mexer em nomad-ui/ é mudança não versionada.

TB-21 — Alinhar o Node 22 do motor com o Node 24 da casa

A casa pede Node 24 para app novo, e o motor declara >=22.13.0 <23 no engines e constrói em node:22.23-alpine. Decida se migra agora, se agenda a migração ou se congela a exceção por escrito. É como a casa toda no 220 V e um cômodo ainda no 110 V. O conta-central tem a mesma dívida na imagem (node:22-alpine) e cabe na mesma decisão.

TB-22 — Dar versão e envelope único às tools MCP do agent-package

As tools declaram de dois jeitos e respondem de dois jeitos: o defineTool devolve texto JSON puro, e o renderTool devolve ok: true com structuredContent. Um agente que aprende um idioma troca de idioma no meio da conversa e erra a leitura do resultado. E a tool não tem versão própria: só o APP_VERSION global diz o que mudou. Feche um envelope único (ok, data e error) e dê versão a cada tool, para a descrição virar dado versionado em vez de comentário perdido no código.

TB-23 — Medir o N+1 por tool e padronizar a paginação

O gateway mede a latência de cada tool, mas ninguém conta quantas queries ela gasta, e N+1 é o bug que não aparece no teste e derruba o servidor quando o dado cresce. Some-se a isso a paginação que discorda de si mesma: o docs/api-guidelines.md manda padrão 50 e máximo 200, e o schemas/pagination.ts usa 500 e 1000. Exponha um contador de queries por chamada de tool, em métrica, e faça a paginação da casa valer em todo lugar.

TB-24 — Desacoplar o núcleo dos services do mcp/ no agent-package

Sete services importam o mcp/, e nomes de tool estão escritos à mão dentro deles: 44 menções a agentpack_*, 22 nomes distintos, em 14 arquivos de services/. A dependência está ao contrário: quem manda é o service, e o mcp/ é o adaptador. A regra de lint barra o service de importar tool, mas não barra o caminho de volta. Inverta a dependência (o service expõe dado, o adaptador descobre) e trave isso na regra.

TB-25 — Escrever o system prompt e a doc de tools de cada agente coordenador

Nenhum app tem um agente coordenador com prompt próprio. O agent-package tem as instructions do initialize e dois prompts MCP (executar task e handover): é o começo, não o produto. A casa já tem a entidade AgentPrompt e a decisão do dono: cada app tem um coordenador, com o seu system prompt e a documentação das suas tools. Falta a peça escrita, app por app.

TB-26 — Levar o Swagger aos 4 backends que ainda não têm

A casa pede Swagger em todo backend, gerado a partir das rotas. Dos 6 backends, só o do agent-package e o do render têm. Dos outros 4, três não têm nada (conta-central, load-balance e motor), e o servidor do mypanel tem um /api/docs escrito à mão em src/index.ts, que descreve 17 dos 23 endpoints. Doc escrita à mão envelhece a cada rota nova. Ligue o @fastify/swagger nos 4, com o plugin do agent-package como molde, e aposente o /api/docs manual.

TB-27 — Fechar as 134 operações sem contrato no agent-package

O Swagger existe, mas 134 operações estão congeladas na lista FROZEN_PENDING_OPERATIONS desde 2026-09-26: a rota funciona, o contrato não. Além disso, 93 validações (Schema.parse(request.*)) acontecem dentro do handler em vez de na declaração da rota, e o cliente gerado não sabe o que a rota aceita. A lista só pode encurtar, nunca crescer: o openapi-contract.test.ts reprova operação pendente fora dela.

TB-28 — Levar o padrão de serviço com dois adaptadores aos outros 4 apps

O padrão da casa é uma regra de negócio escrita uma vez, com dois adaptadores finos em cima: a rota REST e a tool MCP. O agent-package e o mypanel já são assim. Faltam 4: o motor consome MCP mas não expõe nenhum, o load-balance e o conta-central não têm MCP, e o render expõe tools pelo gateway do agent-package, sem servidor MCP próprio. Comece por um domínio piloto em cada app, depois o resto, medindo o N+1 a cada passo (TB-23).

TB-29 — Rotacionar os dois tokens que ficaram no histórico do .mcp.json

O .mcp.json foi limpo em 2026-10-25 (commit 31f898d): os tokens agora vêm do ambiente, por MYPANEL_MCP_TOKEN e AGENTPACK_MCP_TOKEN, e o arquivo segue versionado como configuração do time. Falta a metade que limpar o arquivo não resolve: os dois tokens em texto puro, o do mypanel e o do agentpack, continuam no histórico desde o primeiro commit (084ec6f), legíveis para quem clona o repositório. O runbook de rotação do agent-package registra a decisão do dono para segredo que entrou no git: não reescrever o histórico, só rotacionar. Revogue os dois tokens, emita novos e registre o incidente numa task do AgentPack.

TB-30 — Tirar o eval do logger do load-balance

Feito no mesmo commit da TB-01 (f87345f). O src/utils/logger.ts sondava o pino-pretty com eval('require'): em ESM o require não existe nesse escopo, o eval lançava ReferenceError, o catch devolvia false e o pino-pretty nunca era detectado, nem em dev. Trocado por createRequire(import.meta.url), como o config/logger.ts já fazia. O no-eval do lint novo é erro, e está certo: eval executa código.

Próximos passos#

Você viu cada tarefa com a evidência no disco. A seguir, a ordem de execução em 5 fases.

Explore além:

Documentação gerada por build.py.