Um dos 27 packages do monorepo descreve a própria infraestrutura como DADO tipado: config validada na borda sem dependência nenhuma, logger que por default não faz nada, topologia host | droplet | ci com invariante executável — e um provisionamento que NASCE dry-run e recusa aplicar. É a doutrina fail-closed do motor, aplicada ao chão onde o motor roda.
O cabeçalho de packages/infra/src/index.ts:1–15 declara a identidade: "DevOps as code for the Alembic engine" — o pacote embarca artefatos REAIS de infraestrutura em diretórios irmãos (terraform/, docker/, caddy/, github/, host/, secrets/, backup/, observability/ — prove com ls packages/infra/) e, por cima, uma superfície de config TIPADA em src/ com seis módulos: result, logger, config, topology, resource, provision.
O detalhe que define o design: o pacote declara ZERO dependências de runtime. Por isso ele NÃO importa o Result de @alembic/contracts — ele carrega um espelho local, byte-compatível na forma (result.ts:1–6: "a tiny, dependency-free Result<T, E> mirroring the narrow waist"), com ok/err/isOk/isErr/toError/tryCatchAsync. E a validação de borda usa um checker próprio minúsculo (reqString, oneOf, regexes) em vez de Zod — mesma doutrina, custo de dependência zero.
@alembic/infra (prova: grep -rln '@alembic/infra' packages/*/src apps/*/src → vazio). Os consumidores reais são os artefatos irmãos e o wiring futuro marcado no código como TODO(P4, #116) (resource.ts:32, provision.ts:39). O pacote é a PLANTA da casa — a fiação que a lê ainda está na fila.Pense como… a planta elétrica de uma casa: ela nomeia cada disjuntor, cada tomada e cada fase — mas a planta em si não liga NADA. Onde a analogia quebra: aqui até o botão "ligar" (apply: true) existe e responde — recusando educadamente com um err, até que a fiação real seja instalada.
topology.ts modela ONDE cada workload roda como dado: PLANES = ['host', 'droplet', 'ci'] (topology.ts:14). O host é o Mac — hot path: modelos locais, agent-browser, cron launchd (02:00 wiki, 04:00 cortex), backups — e NUNCA exposto à internet. O droplet (DigitalOcean) é a ÚNICA superfície TLS pública, com Caddy terminando :80/:443 na frente de council-api e gateway. O ci (GitHub Actions) constrói, testa e faz deploy — sem estado de longa duração.
O DEFAULT_WORKLOADS (topology.ts:30–66) fixa os seis workloads canônicos nos seus planos — e a doutrina vira FUNÇÃO: findExposureViolations (topology.ts:73–79) devolve os ids de qualquer workload public fora do droplet. Lista vazia = topologia sadia. A regra de segurança não é um comentário: é um filtro que um teste pode rodar.
config.ts define interfaces explícitas por provedor — DigitalOceanConfig, GithubConfig, AgentBrowserConfig, LocalModelsConfig — e enums FECHADOS: 3 tamanhos de droplet (DO_DROPLET_SIZES), 5 regiões (DO_REGIONS), 2 backends locais (ollama | mlx). parseInfraConfig (config.ts:216–228) estreita unknown → InfraConfig e nunca lança: cada campo inválido vira err(new Error('infra config: caminho.motivo')) com o caminho exato do problema.
E a regra de segredo é estrutural: config carrega o NOME da env var (apiTokenEnv, tokenEnv…), validado pelo regex ENV_VAR = /^[A-Z][A-Z0-9_]*$/ (config.ts:117) — a credencial em si nunca entra no JSON. Blocos opcionais ausentes caem em defaults tipados (browser alembic/headless/120s; modelos locais em http://127.0.0.1:11434 com keep-alive de 900s — config.ts:98–110).
export const parseInfraConfig = (raw: unknown): Result<InfraConfig, Error> => { if (!isRecord(raw)) return fail('<root>', 'must be an object'); const digitalOcean = parseDigitalOcean(raw.digitalOcean); if (!digitalOcean.ok) return digitalOcean; const github = parseGithub(raw.github); if (!github.ok) return github; return ok({ digitalOcean: digitalOcean.value, github: github.value, agentBrowser: DEFAULT_AGENT_BROWSER, // defaults tipados localModels: DEFAULT_LOCAL_MODELS, // p/ blocos opcionais }); };
logger.ts segue a regra da casa "library code never calls console.log": createLogger emite LogRecords estruturados para um LogSink injetado — e o sink default é NOOP_SINK (logger.ts:36), então IMPORTAR o módulo tem efeito colateral zero. Quem quiser observabilidade real injeta um sink de verdade.
O mesmo espírito, mais radical, em provision.ts: as três entradas de apply — terraformPlan, composeUp, launchdLoad — montam o argv real da ferramenta, mas o helper dryRun (provision.ts:28–45) tem DOIS caminhos: sem apply, loga e devolve ok({ applied: false, argv }); COM apply: true, devolve err('apply path not implemented …'). Ou seja: hoje é IMPOSSÍVEL este pacote mutar infraestrutura — o caminho de mutação está fechado por construção, não por disciplina do operador.
composeUp({ apply: true }) hoje. O que acontece?dryRun (provision.ts:28–45) só tem dois destinos — sem apply, ok({applied:false, argv}); com apply, err(...) marcado TODO(P4, #116). O pacote descreve e planeja; mutar infraestrutura é um passo futuro explícito, não um efeito escondido.@alembic/infra tem um Result próprio em vez de importar o de @alembic/contracts?result.ts:1–6 explica — o pacote não declara dependência de runtime nenhuma (nem Zod, nem contracts), então carrega um espelho minúsculo do mesmo Result. Call sites leem igual em qualquer pacote; a cintura estreita é a FORMA, não o import.Tudo $0 e read-only — verifique cada afirmação desta lição você mesmo:
# a identidade e os seis módulos sed -n '1,22p' packages/infra/src/index.ts ls packages/infra/ # terraform/ docker/ caddy/ github/ host/ secrets/ backup/ observability/ # os 3 planos, os 6 workloads e a invariante executável sed -n '14,80p' packages/infra/src/topology.ts # a borda de config: regex de env var, enums fechados, parse nunca-lança grep -n 'ENV_VAR\|DO_DROPLET_SIZES\|DO_REGIONS\|parseInfraConfig' packages/infra/src/config.ts # o fail-closed do provisionamento (apply → err) sed -n '28,46p' packages/infra/src/provision.ts # prova de que ninguém importa o pacote (ainda) grep -rln '@alembic/infra' packages/*/src apps/*/src
src/ descrevendo oito diretórios de verdade.Result espelhado local e checker próprio no lugar de Zod — a mesma doutrina, sem custo.findExposureViolations — "public só no droplet" é função, não comentário.apply devolve err — fail-closed por construção (TODO(P4, #116) explícito).apply: false é o mesmo padrão dupla-trava do marketing. Próxima lição: a disciplina que construiu este curso inteiro — internalizada como pacote: @alembic/loop-engineering.