Arquitetura
O Firstlume é um server com Postgres, mais agents que criam um Job Kubernetes efêmero para cada fase de um run.
┌──────────────────────────────┐ ┌──────────┐
usuário ──▶│ server (API + UI) │◀────▶│ Postgres │
(UI/API) │ /api/v1 usuários (admin) │ └──────────┘
│ /agent/v1 agents │
│ /exec/v1 executores │
│ /state/v1 state (Terraform) │
└──────▲───────────────▲───────┘
│ claim (pull) │ spec, logs, plano, resultado
┌──────┴───────┐ │ (token válido só para 1 fase)
│ agent │──cria──▶ Job "flr-<run>-plan" ─┘
└──────────────┘ └─ firstlume exec
Um binário, uma imagem
Os subcomandos são firstlume server | agent | exec | migrate | keygen. A UI em React é embutida no binário e servida pelo server no mesmo endereço da API.
O agent busca o trabalho
O agent só faz requisições de saída, então pode rodar em outro cluster ou na rede do cliente sem que a API precise alcançá-lo. Um agent pertence a uma organização e só recebe runs dela. Veja Um agent adicional em outro cluster.
Cada fase roda num Job efêmero
O plan e o apply têm cada um o seu Job. O pod é endurecido:
- não roda como root
- tem rootfs somente leitura
- não pode escalar privilégios
- o Job nunca é retentado
As credenciais de nuvem vêm da identidade do pod (IRSA, Workload Identity), via anotações no ServiceAccount do executor. Você pode escolher os nodes onde os Jobs rodam.
O token do Job vale para uma única fase. Cada fase também recebe uma credencial de state, válida só enquanto a fase está ativa e só para aquele stack.
Um run por vez, por stack
Só um run por vez executa ou aguarda aprovação em cada stack. Os demais esperam na fila, em ordem de chegada. Dois stacks do mesmo repositório têm locks e filas independentes.
O apply roda exatamente o que foi planejado
O plan grava o commit SHA e o arquivo de plano, criptografado no banco. O apply faz checkout desse commit e aplica esse arquivo, com as variáveis que o plan usou. Veja Runs e aprovação.
Segredos criptografados
Variáveis sensíveis, tokens git e planos são cifrados com AES-256-GCM, usando uma chave derivada de FIRSTLUME_SECRET_KEY. As versões de state também são cifradas, com uma chave própria. Valores sensíveis são mascarados nos logs e nunca são devolvidos pela API.
Com os segredos do Vault é diferente: eles nunca chegam ao server nem ao banco, porque o executor os lê dentro do pod do run. Veja Segredos do Vault.
State
O Firstlume serve o backend http do Terraform em /state/v1. Os metadados e os locks ficam sempre no Postgres. As versões de state ficam no Postgres ou num bucket S3. Veja Backend de state e Onde o state fica.