AUR-411 — Perfil polyglot toolchain offline (polyglot-toolchain-v1)
Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.
Este documento descreve a entrada polyglot-toolchain-v1 publicada no registry
canônico de profiles. O card publica somente documentos: nenhum toolchain é
instalado, nenhum pacote é baixado, nenhum runtime é invocado, nenhum engine é
chamado e o runner permanece fail-closed para esta chave até um card de
implementação dependente habilitá-la explicitamente.
Artefatos
| Artefato | Caminho |
|---|---|
| Schema | .board/schemas/polyglot-toolchain-profile.schema.json |
| Profile | .board/oci/profiles/polyglot-toolchain-v1.json |
| Lock | .board/locks/oci/polyglot-toolchain-v1.lock.json |
| Registry | .board/oci/profiles/registry.v1.json |
O registry passa a publicar exatamente onze chaves, em ordem canônica crescente
(LC_ALL=C sort, não estimada): bootstrap-readonly-v1,
docs-tool-offline-v1, fake-provider-v1, fake-scm-offline-v1,
go-git-offline-v1, go-unit-offline-v1, oci-conformance-v1,
parser-worker-v1, polyglot-toolchain-v1, registry-v1,
sqlite-offline-v1.
Em ordem C, polyglot- vem depois de parser- — a (0x61) precede o (0x6F)
no primeiro byte que difere — e antes de registry-, porque p precede r.
A chave ocupa portanto o índice 8 (base 0), e exatamente duas chaves deslocam
uma posição à direita: registry-v1 (8→9) e sqlite-offline-v1 (9→10).
Nenhuma chave existente muda de digest, schema ou lock.
Imagem pinada e o que ela realmente contém
O lock fixa Go e Bash na imagem de bootstrap já presente localmente, por digest imutável:
aurum-bootstrap-go-bash@sha256:503ac356fa6bca4bad56fade87b5479ff371bd446ffb9c7db91f211323c7c73e
A imagem foi escolhida por prova, não por conveniência. Sob
--pull=never --network=none --read-only --user=65534:65534 --cap-drop=ALL
(mais --security-opt=no-new-privileges e tmpfs limitado) o probe devolve
bash 5.2.26, go1.21.13 e uma única interface de rede, lo.
Este é o resultado literal do probe, e é o limite honesto deste card. Das oito
linguagens declaradas, a imagem de bootstrap carrega apenas bash:
| Partição | Runtime declarado | bootstrap 503ac356… |
golang 4746d264… |
|---|---|---|---|
bash |
bash |
presente (5.2.26) | presente (5.2.15) |
c-cpp |
cc |
ausente | presente (cc, gcc, g++, ld, make) |
python |
python3 |
ausente | presente (sem pip/pip3) |
javascript |
node |
ausente | ausente |
typescript |
tsc |
ausente | ausente |
dotnet |
dotnet |
ausente | ausente |
rust |
cargo |
ausente | ausente |
powershell |
pwsh |
ausente | ausente |
Nenhuma imagem local carrega as oito. Cinco runtimes — node, tsc,
dotnet, cargo e pwsh — não existem em nenhuma das duas imagens pinadas do
board. Este documento não afirma o contrário e o profile não finge que
existem. Nenhuma imagem foi fabricada para este card e nenhum profile foi
afrouxado para acomodar a ausência.
O probe registra também o que está presente e é honesto declarar: a imagem de
bootstrap carrega os applets BusyBox wget e nc e o gerenciador de pacotes
apk; a imagem golang carrega apt/apt-get, curl, wget, ssh, git e
perl. Este plano não afirma que esses binários estão ausentes — afirma que não
alcançam nada, porque network é none, egress é denied, HTTP_PROXY e
HTTPS_PROXY são vazios, NO_PROXY é *, e porque instalar é negado em três
campos independentes (toolchain_install, toolchain_bootstrap,
package_install) mais o índice/registry de cada gerenciador fechado por
variável de ambiente.
Por que a ausência é o contrato, e não uma lacuna tolerada
toolchain_materialization é pre-materialized e toolchain_install é
denied. O profile pina cada partição já materializada e nunca cria uma.
Um runtime que a imagem não carrega jamais pode passar a existir sob este plano,
porque a única forma de obtê-lo seria uma instalação ou a rede, e as duas são
negadas. A resposta correta a node ausente não é instalar node: é falhar
fechado.
É exatamente isso que o loader faz. ResolveLanguageAUR411 recebe a
disponibilidade medida e devolve:
| Situação | Código |
|---|---|
| runtime medido presente, partição pinada e isolada | valid (plano offline isolado) |
| runtime medido ausente | toolchain-unavailable |
| runtime nunca medido | toolchain-unmeasured |
| linguagem fora do conjunto registrado | language-unregistered |
| toolchain sem digest (plano ou partição) | unpinned-toolchain / digest-invalid |
| plano rejeitado pelo loader | o código da rejeição, nunca valid |
toolchain-unmeasured existe porque ausência de evidência não é evidência de
ausência nem de presença. Um runtime que ninguém mediu não é "indisponível"
por padrão silencioso: é uma medição que não aconteceu, e tem código próprio.
Um card de implementação dependente que queira executar node, tsc,
dotnet, cargo ou pwsh precisa primeiro fornecer uma imagem pinada por
digest que já os carregue. Até lá o runner permanece fail-closed para esta
chave, e as cinco partições resolvem toolchain-unavailable sob a imagem atual.
O que é medido, e o que a medição significa
Duas medições são executadas pela acceptance, e o texto abaixo não afirma nada além do que o mecanismo observa.
1. Disponibilidade de runtime. A acceptance mede, para cada um dos oito
runtimes declarados, se o comando resolve através do PATH dentro da imagem
de execução. A medição é feita no PATH intacto, antes de qualquer shim
existir — do contrário um shim chamado cargo ou dotnet responderia ao probe
e a medição relataria um toolchain inexistente. O que ela mede é resolução por
PATH; um runtime alcançável apenas por caminho absoluto não apareceria nela, e
nada aqui afirma o contrário.
O probe é falsificável nos dois sentidos por dois controles:
aurum-control-present-411 é criado no PATH imediatamente antes da medição e
precisa voltar present; aurum-control-absent-411 não pode existir e precisa
voltar absent. Um probe fixado em qualquer das duas respostas falha em um dos
controles com availability-probe-inert.
O ledger é lido em Go com falha dura em todos os modos de erro: variável não definida, arquivo ilegível, linha malformada, nome duplicado, nome faltando ou nome a mais param o teste. Um ledger ausente não é "nada estava disponível" e não é "tudo estava disponível" — é uma medição que não aconteceu.
Antes de qualquer medição real ser consultada, o argumento de disponibilidade é
provado carregador com três medições sintéticas (todas presentes, todas
ausentes, nada medido), que devem produzir valid, toolchain-unavailable e
toolchain-unmeasured respectivamente. Se o argumento fosse ignorado as três
concordariam e a medição real seria decorativa. Essas três não observam máquina
nenhuma e este documento não as apresenta como observação.
2. Instalações de pacote. package_installs: 0 é uma afirmação de um
documento JSON; o ledger é a medição que precisa concordar com ela. Vinte e
cinco entrypoints de instalação e de gerenciamento de pacote — apk, apt,
apt-get, pip, pip3, pipx, poetry, npm, npx, yarn, pnpm,
corepack, bun, deno, tsc, dotnet, nuget, cargo, rustup, gem,
bundler, conda, brew, curl, wget — são sombreados por shims à frente
do PATH; cada shim registra o próprio nome e sai 70. O ledger é provado
carregador antes de virar evidência de ausência: um shim é invocado de propósito
e precisa aparecer, ou a execução falha com install-ledger-inert. Só então o
ledger é zerado e exigido zero, e a camada Go recusa o plano se a contagem
declarada e a medida divergirem. O que o mecanismo mede é uma invocação
resolvida por PATH; um chamador que alcançasse um gerenciador de pacotes por
caminho absoluto não apareceria nele.
Plano declarado
Limites e isolamento:
| Chave | Valor |
|---|---|
network |
none |
user |
65534:65534 |
cap_drop / cap_add |
ALL / none |
mounts / devices / sockets |
none / none / none |
pull |
never |
tmpfs |
rw,nosuid,nodev |
checkout_readonly |
true |
read_only_rootfs |
true |
no_new_privileges |
true |
privileged |
false |
timeout_seconds |
60 |
memory_mb |
256 |
cpu_millis |
1000 |
pids_limit |
128 |
tmpfs_mb |
128 |
stdout_limit_bytes / stderr_limit_bytes |
65536 / 65536 |
max_input_files / max_input_bytes |
10000 / 67108864 |
module_cache |
/go/pkg/mod (module_cache_read_only: true) |
Capacidades polyglot, todas verificadas pelo loader:
| Chave | Valor | Efeito |
|---|---|---|
polyglot_root |
/tmp/aurum-polyglot |
todas as partições vivem no tmpfs limitado, nunca no checkout |
toolchain_source |
digest-pinned |
um toolchain só é admitido content-addressed |
toolchain_materialization |
pre-materialized |
o plano pina o que já existe e nunca cria |
toolchain_install |
denied |
nenhum toolchain é instalado |
toolchain_bootstrap |
denied |
nenhum runtime é provisionado |
package_install |
denied |
nenhum pacote é instalado |
package_registry |
denied |
nenhum índice/registry de pacote é alcançado |
package_installs |
0 |
declarado zero e medido zero por ledger |
cache_mode |
read-only |
os package caches são somente leitura |
telemetry |
denied |
nenhuma telemetria de runtime ou de gerenciador |
egress |
denied |
nenhuma saída de rede |
host_toolchain |
denied |
nenhum toolchain do host é usado |
host_cache |
denied |
nenhum cache de pacote do host é montado |
host_filesystem |
denied |
nenhum caminho do host é lido |
subprocess |
denied |
nenhum subprocesso |
unregistered_language |
denied |
uma linguagem fora do conjunto falha fechado |
max_languages |
8 |
teto exato de partições |
max_packages |
4096 |
teto exato de pacotes materializados |
max_package_bytes |
16384 |
teto exato por pacote |
max_cache_bytes |
8388608 |
teto exato por partição (8 MiB) |
resolve_timeout_seconds |
5 |
wall-clock por resolução de linguagem |
As oito partições
Cada linguagem declara uma partição fechada de cinco campos, e o languages
publicado e o objeto toolchains precisam descrever exatamente o mesmo
conjunto — uma linguagem listada sem partição é uma partição que ninguém valida,
e uma partição não listada é um plano alcançável por um nome que a lista não
admite.
| Linguagem | Runtime | Cache root |
|---|---|---|
bash |
bash |
/tmp/aurum-polyglot/bash |
c-cpp |
cc |
/tmp/aurum-polyglot/c-cpp |
dotnet |
dotnet |
/tmp/aurum-polyglot/dotnet |
javascript |
node |
/tmp/aurum-polyglot/javascript |
powershell |
pwsh |
/tmp/aurum-polyglot/powershell |
python |
python3 |
/tmp/aurum-polyglot/python |
rust |
cargo |
/tmp/aurum-polyglot/rust |
typescript |
tsc |
/tmp/aurum-polyglot/typescript |
Cada partição carrega toolchain: "digest-pinned", cache_mode: "read-only" e
telemetry: "denied", e a cópia por partição precisa concordar com a política
global: uma política com uma partição isenta não é uma política.
O isolamento é imposto pelas constantes pinadas: cada partição precisa declarar
exatamente o runtime que expectedRuntimes411 dá à sua linguagem e exatamente
o cache_root polyglot_root + "/" + linguagem. Os mutantes shared-runtime e
shared-cache-root são recusados por essas igualdades, que rodam primeiro.
O loader também exige que duas partições nunca compartilhem um cache_root nem
um runtime, e que nenhum cache_root seja, contenha ou esteja fora de
polyglot_root. Essas regras são defesa em profundidade, não a defesa: como
expectedRuntimes411 é injetiva (oito runtimes distintos) e cada cache_root é
derivado da própria linguagem (oito diretórios distintos), nenhum documento que
passe pelas igualdades acima pode colidir. Foi verificado por deleção: removendo
o bloco de distinção do loader, shared-runtime e shared-cache-root continuam
negados e a acceptance continua saindo 0. Nenhum mutante atual isola essas
regras, e este documento não as credita por rejeições que as constantes já
fazem. Elas permanecem para o caso de um card dependente derivar runtime ou
cache_root de outra fonte que não a tabela pinada.
Limites são constantes exatas, nunca mínimos
Todo limite é uma constante exata. max_cache_bytes: 0,
max_cache_bytes: 34359738368 e max_cache_bytes: 33554432 são todos
rejeitados, e o que os rejeita é a igualdade pinada max_cache_bytes == 8388608
— o mesmo vale para max_packages: 8192 contra max_packages == 4096. É por
isso que aggregate-cache-overflow e oversized-package-set falham, e este
documento não credita outra regra por essas rejeições.
O loader mantém, além das igualdades, um conjunto de relações de defesa em profundidade. Elas são de fato executadas em toda validação; o que hoje é inalcançável é a rejeição por elas, porque as igualdades pinadas rodam antes e já recusam todo documento que as violaria:
max_cache_bytes <= tmpfs_mb * 1024 * 1024;len(languages) * max_cache_bytes <= tmpfs_mb * 1024 * 1024— as oito partições coexistem no mesmo tmpfs limitado, então o teto somado precisa caber. Com os valores publicados,8 * 8388608é exatamente67108864, metade dos 128 MiB;max_packages <= max_input_filesemax_packages * max_package_bytes <= max_input_bytes— com os valores publicados,4096 * 16384é exatamentemax_input_bytes;0 < resolve_timeout_seconds <= timeout_seconds;len(languages) <= max_languages.
Raízes ancoradas
polyglot_root e cada cache_root são validados por expressões ancoradas com
\A e \z — início e fim do texto, nunca de uma linha. Por isso
/workspace, uma travessia que começa dentro da raiz limitada e sai dela, uma
barra final, um irmão parecido (…-host), um newline embutido, um newline
final, um espaço à esquerda, uma grafia em maiúsculas, um homóglifo cirílico
(U+043E no lugar do o) e a string vazia são todos negados igualmente.
Ambiente
O ambiente é fechado sobre exatamente vinte chaves. Cada uma fecha um canal real por onde um gerenciador de pacotes alcançaria um índice, um registry ou um endpoint de telemetria:
| Chave | Valor |
|---|---|
GOPROXY / GOSUMDB / GONOSUMDB / GOTOOLCHAIN |
off / off / * / local |
CGO_ENABLED |
0 |
AURUM_POLYGLOT_ROOT |
/tmp/aurum-polyglot |
PIP_NO_INDEX / PIP_DISABLE_PIP_VERSION_CHECK |
1 / 1 |
NPM_CONFIG_OFFLINE / NPM_CONFIG_REGISTRY |
true / `` (vazio) |
NUGET_PACKAGES |
/tmp/aurum-polyglot/dotnet |
DOTNET_CLI_TELEMETRY_OPTOUT / DOTNET_NOLOGO |
1 / 1 |
CARGO_HOME / CARGO_NET_OFFLINE |
/tmp/aurum-polyglot/rust / true |
POWERSHELL_TELEMETRY_OPTOUT / POWERSHELL_UPDATECHECK |
1 / Off |
HTTP_PROXY / HTTPS_PROXY / NO_PROXY |
/ / * |
Essas variáveis são defesa em profundidade, não a defesa: a imagem pinada não
carrega pip, npm, dotnet, cargo nem pwsh para configurar. Cada uma é
pinada por constante, então reabrir qualquer uma delas é um mutante provado.
AURUM_POLYGLOT_ROOT, NUGET_PACKAGES e CARGO_HOME são a segunda grafia de
diretórios que o plano também declara. O loader e a camada de integração exigem
que as duas grafias concordem: se divergirem, um gerenciador de pacotes lê ou
escreve um caminho que o plano nunca limitou.
Comandos permitidos
["go", "test", "-mod=readonly", "./..."]
Qualquer outro comando, ou o mesmo comando com aridade diferente, invalida o plano.
Constantes pinadas três vezes
As constantes de segurança do schema estão pinadas nos bytes do schema e, em Go,
em profileSchemaConstants411, environmentSchemaConstants411 e
toolchainSchemaConstants411, todas verificadas por
validateSchemaInvariant411. Um revisor que afrouxe o documento de schema e
recompute o schema_digest no registry move os dois arquivos de forma
consistente e ainda assim falha, porque os mapas Go não se movem com eles.
Compatibilidade com as chaves vizinhas
Os dez loaders de registry já entregues fecham o allowlist de chaves sobre o conjunto registrado, e o loader de AUR-403 ainda afirma o comprimento do registry e a ordem posicional das chaves; a camada de contratos de AUR-404 afirma a aridade. Registrar uma décima primeira chave quebra essas regressões de fora deste card a menos que elas aprendam a chave no mesmo commit. Nenhuma delas lê os documentos polyglot: cada uma verifica apenas os caminhos declarados e o formato do digest, de modo que registrar o profile polyglot não pode re-apontar silenciosamente o plano Go unit, o Git, o fake provider, o parser worker, o SQLite, a documentação, o fake SCM ou o conformance.
A aridade de AUR-403 vai de dez para onze e a de tests/contracts/AUR-404.go
também, ambas exatas e não relaxadas para mínimo: toda rejeição que faziam
antes continua falhando, e cada chave continua afirmada no único índice que a
ordem canônica ascendente lhe dá.
A aridade total do registry é afirmada em tests/unit/AUR-411.go, que este card
possui, e deliberadamente não em tests/contracts/AUR-411.go: este card
possui a chave polyglot-toolchain-v1, não o tamanho do registry.
Códigos de rejeição
| Código | Quando |
|---|---|
profile-unregistered |
a chave não está no registry, ou o conjunto de chaves não é exatamente o registrado |
duplicate-profile |
a chave aparece duas vezes |
order-invalid |
as chaves não estão em ordem canônica ascendente |
schema-invalid |
schema afrouxado, chave obrigatória ausente, campo desconhecido, JSON duplicado ou lixo no fim |
schema-missing / profile-missing / lock-missing |
documento ausente ou não regular |
schema-digest-mismatch / lock-digest-mismatch |
digest do registry não confere com os bytes |
digest-invalid |
toolchain_source ou o toolchain de uma partição sem digest, ou digest malformado |
mutable-input |
lock com tag mutável, nome sem digest ou outro repositório |
unsafe-plan |
qualquer limite, negação, raiz, partição ou variável de ambiente fora do plano |
credential-present |
forma de credencial em qualquer valor de ambiente |
language-unregistered |
linguagem fora do conjunto registrado, ou impersonação de uma declarada |
unpinned-toolchain |
resolução de partição cujo toolchain não é content-addressed |
toolchain-unavailable |
runtime declarado, medido ausente na imagem de execução |
toolchain-unmeasured |
runtime declarado, nunca medido — falha fechado, nunca assume |
Diagnóstico offline
bash tests/acceptance/AUR-411.sh AC-001 executa a validação completa sem rede,
sem engine, sem subprocesso de runtime e sem instalação. Seletores individuais
(TestAUR411, ContractAUR411, IntegrationAUR411, E2EAUR411,
AC-001-MUT-001, AC-001-MUT-002, AC-001-MUT-003) executam uma camada ou uma
mutação isolada; um seletor desconhecido sai 64. Falha de ambiente sai 69 e
nunca é confundida com RED comportamental.
Compatibilidade, migração, rollback
Profiles existentes conservam chave e digest; uma mudança incompatível cria uma nova chave versionada. A migração altera consumidores por card dependente e nunca redireciona uma chave existente. O rollback remove somente esta entrada e seus arquivos quando nenhum consumidor depender dela.