@statedelta/engine-registry
v0.1.1
Published
Engine acquisition registry for StateDelta - resolves engineKey to a runnable EngineFactory from a versioned bundle manifest
Maintainers
Readme
@statedelta/engine-registry
O registry de aquisição de engines do StateDelta — resolve uma chave de engine para um
EngineFactoryexecutável a partir de um manifest de bundles versionados.
É a implementação do contrato EngineRegistry declarado em
@statedelta/protocol — o eixo paralelo ao Gateway: o
Gateway resolve uri → Artifact (documentos); este resolve
engineKey → EngineFactory (engines).
O que faz
registry.resolve("[email protected]")
│ 1. lê o manifest (objeto in-memory · arquivo local · URL opt-in)
│ 2. resolve o channel "0.4" → versão exata "0.4.0"
│ 3. acha a entry de "0.4.0" → { url, sha256 }
│ 4. obtém o bundle .cjs (download remoto + cache · ou leitura local)
│ 5. valida o sha256
│ 6. carrega o módulo → o `create` exportado
│ 7. checa o handshake de protocolo
▼
ResolvedEngine { factory, version, integrity, protocol? }Instalação
pnpm add @statedelta/engine-registryModos
A fonte do manifest é sempre explícita — não há endpoint default. As engines que um launcher serve são decisão do operador, não um recurso que muda pelas costas dele.
| Modo | Como | Quando |
|---|---|---|
| In-memory | { manifest } — objeto já carregado | testes, embedding |
| Arquivo local | { manifestPath } — JSON no disco | o padrão — versionado com o deploy |
| URL (opt-in) | { manifestUrl } — endpoint que o operador controla | quando explicitamente desejado |
E o bundle (a url de cada entry do manifest) pode ser remoto
(http(s), baixado + cacheado por hash) ou local (path / file:,
lido do disco). Manifest local + bundles locais = air-gapped, zero
rede — e o sha256 é verificado nos dois casos.
Manter um manifest remoto atualizado (refresh periódico, download em massa de bundles) é um processo fora do registry — ele só consome.
Uso
import { createEngineRegistry } from "@statedelta/engine-registry";
import { createEnvironment } from "@statedelta/protocol";
import { createLauncher } from "@statedelta/launcher";
// Manifest local — o operador declara quais engines este launcher serve.
const registry = createEngineRegistry({ manifestPath: "./engines.json" });
const environment = createEnvironment({
engines: {}, // mapa in-memory (mocks/dev) — opcional
registry, // aquisição de engines reais
}).freeze();
const launcher = createLauncher({ environment });
const engine = await launcher.launch("./save.json");createEngine do environment usa o mapa engines quando a chave está
nele (source in-memory); senão cai no registry.
API
createEngineRegistry(options): EngineRegistry
Declare uma fonte de manifest — sem nenhuma, lança.
| Opção | Descrição |
|---|---|
| manifest | Manifest in-memory (objeto) |
| manifestPath | Caminho de um arquivo JSON local — a fonte idiomática |
| manifestUrl | URL do manifest — opt-in explícito, nunca default |
| cacheDir | Cache dos bundles remotos verificados (default ~/.statedelta/engines) |
| fetchImpl | fetch injetável (manifest + bundle remotos) |
| loadBundleImpl | Loader de bundle injetável — para testes sem download/require |
Precedência quando mais de uma é dada: manifest › manifestPath ›
manifestUrl. Paths de bundle relativos no manifest resolvem contra o
diretório do manifestPath.
Chave de engine
- Channel —
[email protected](ex.:[email protected]). Ponteiro móvel; resolvido para a última patch viamanifest.channels. - Pin —
[email protected](ex.:[email protected]). Exato.
Erros
Falhas são ResolutionError (de @statedelta/protocol):
ENGINE_NOT_AVAILABLE— manifest/channel/versão ausente, manifest ilegível, download/leitura do bundle falho, ou sha256 não bate (details.reasondiscrimina).ENGINE_PROTOCOL_INCOMPATIBLE— o range de protocolo declarado pelo bundle não cobre oPROTOCOL_VERSIONdo launcher.
Testes
pnpm test # unit — manifest, loader, registry (sem rede)
pnpm test:e2e # integração — baixa o [email protected] real e rodaOs testes unitários cobrem parse de chave, resolução de channel/pin,
carga de bundle remoto (download + cache) e local (air-gapped), a
verificação sha256, e o handshake de protocolo — sem rede.
O test:e2e é a prova ponta-a-ponta: resolve [email protected], baixa o
bundle real engine-0.4.0.cjs, verifica o sha256, carrega, e via
launcher.launch() boota um mundo tic-tac-toe — depois simula uma
jogada (X em (0,0)) e confirma que o runtime avançou o estado.
Segurança
Carregar um bundle é executar código. As defesas: a fonte do manifest é
sempre explícita (sem endpoint default), o sha256 é verificado contra
o manifest antes de carregar — remoto ou local, defesa em
profundidade — e o caminho air-gapped (manifest + bundles locais)
elimina a rede por completo.
Node-only nesta fase — bundles são .cjs, carregados via createRequire.
Licença
MIT
