AUR-405 — Perfil fake provider offline (fake-provider-v1)
Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.
Este documento descreve a entrada fake-provider-v1 publicada no registry
canônico de profiles. O card publica somente documentos: nenhum engine é
invocado, nenhum fake OpenAI-format é implementado, nenhum script de resposta é
escrito 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/fake-provider-profile.schema.json |
| Profile | .board/oci/profiles/fake-provider-v1.json |
| Lock | .board/locks/oci/fake-provider-v1.lock.json |
| Registry | .board/oci/profiles/registry.v1.json |
O registry passa a publicar exatamente cinco chaves, em ordem canônica
crescente: bootstrap-readonly-v1, fake-provider-v1, go-git-offline-v1,
go-unit-offline-v1, registry-v1. Nenhuma chave existente muda de digest,
schema ou lock.
Imagem pinada
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. O fake local
vive nesse loopback; não há rota, DNS ou egress a partir do namespace. O adapter
OpenAI-format é Go e não precisa de git, então a imagem de bootstrap basta e a
imagem golang usada por go-git-offline-v1 não é necessária aqui.
Somente aurum-bootstrap-go-bash@sha256:<64 hex> é aceito. Uma tag mutável
(aurum-bootstrap-go-bash:1.21), um nome sem digest ou outro repositório é
rejeitado com mutable-input antes de qualquer resolução de imagem.
Plano declarado
Limites e isolamento:
| Chave | Valor |
|---|---|
network |
none |
user |
65534:65534 |
cap_drop / cap_add |
ALL / none |
mounts / devices |
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 do provider fake, todas verificadas pelo loader:
| Chave | Valor | Efeito |
|---|---|---|
provider_endpoint |
http://127.0.0.1:8080/v1 |
único endereço admitido; qualquer outro host, esquema ou porta é egress |
dns |
denied |
nenhuma resolução de nome é permitida |
egress |
denied |
nenhuma saída do namespace é permitida |
api_key |
absent |
nenhuma API key real integra o plano |
credential_sources |
denied |
nenhuma origem de credential (env, arquivo, helper) é consultada |
response_scripts |
digest-pinned |
scripts de resposta só são admitidos content-addressed |
response_scripts_root |
/tmp/aurum-fake-provider |
scripts vivem no tmpfs limitado, nunca no checkout |
request_timeout_seconds |
5 |
wall-clock por requisição ao fake |
max_response_bytes |
65536 |
resposta limitada; 0 é ilimitado e é recusado |
max_responses |
64 |
número de respostas do script limitado |
response_scripts: "digest-pinned" pina a exigência, não os bytes: os
scripts de resposta são um não-objetivo deste card e pertencem ao card de
implementação dependente. O que este card garante é que um conjunto de scripts
sem digest nunca é resolvido.
Comandos permitidos
["go", "test", "-mod=readonly", "./..."]
Qualquer outro comando, ou o mesmo comando com aridade diferente, invalida o plano. O ambiente é fechado sobre exatamente estas chaves:
| Variável | Valor |
|---|---|
GOPROXY |
off |
GOSUMDB |
off |
GONOSUMDB |
* |
GOTOOLCHAIN |
local |
OPENAI_API_KEY |
(vazio) |
OPENAI_BASE_URL |
http://127.0.0.1:8080/v1 |
HTTP_PROXY |
(vazio) |
HTTPS_PROXY |
(vazio) |
NO_PROXY |
* |
OPENAI_BASE_URL e provider_endpoint são duas grafias do mesmo endereço; o
teste de integração recusa qualquer divergência entre elas, porque uma
divergência é exatamente um egress. Nenhuma credencial, valor de ambiente do
host ou segredo entra no documento, e o loader recusa qualquer valor com forma
de credencial mesmo em campo cujo valor não seja pinado por constante.
Códigos de rejeição
O loader (ValidateRegistryAUR405 / ValidateProfileAUR405) é
side-effect-free, não abre socket e devolve exatamente um código:
| Código | Causa |
|---|---|
registry-missing |
registry ausente ou não regular |
schema-invalid |
registry, schema ou profile fora da forma canônica (inclui chave duplicada dentro de um objeto JSON e limite obrigatório ausente, como timeout_seconds) |
schema-missing |
documento de schema ausente |
schema-digest-mismatch |
schema_digest não reproduz os bytes do schema |
profile-missing |
documento do profile ausente |
profile-unregistered |
chave desconhecida, ou fake-provider-v1 ausente do registry |
duplicate-profile |
a mesma chave publicada duas vezes |
order-invalid |
chaves fora da ordem canônica crescente |
credential-present |
api_key ou valor de ambiente com forma de credential real |
digest-invalid |
digest vizinho fora do formato sha256:<64 hex>, ou script de resposta sem digest |
unsafe-plan |
limite obrigatório relaxado, endpoint externo, resposta ilimitada, DNS/egress/credential source habilitados, rede, mount, device, root ou capability |
lock-missing |
lock ausente |
mutable-input |
imagem por tag mutável, repositório inesperado ou lock fora do schema |
lock-digest-mismatch |
lock_digest não reproduz os bytes do lock |
Mutantes provados
O acceptance executa cada mutante contra bytes reais em disco e exige o código declarado; o restore volta byte-idêntico.
| Mutante | Mudança | Código |
|---|---|---|
| MUT-001 | chave fake-provider-v1 duplicada com bytes diferentes |
duplicate-profile |
| MUT-002 | imagem do lock por tag mutável | mutable-input |
| MUT-003 | network de none para host |
unsafe-plan |
| endpoint externo | provider_endpoint para https://api.openai.com/v1 |
unsafe-plan |
| base URL externa | OPENAI_BASE_URL para https://api.openai.com/v1 |
unsafe-plan |
| credential real | api_key para uma chave com forma real (montada em runtime) |
credential-present |
| credential source | credential_sources para environment |
unsafe-plan |
| resposta ilimitada | max_response_bytes para 0 |
unsafe-plan |
| script sem digest | response_scripts para unpinned |
digest-invalid |
| timeout ausente | timeout_seconds removido do documento |
schema-invalid |
| egress habilitado | egress para allowed |
unsafe-plan |
O vetor de credential nunca aparece como literal em arquivo versionado: ele é
montado em runtime, dentro da cópia descartável do acceptance, para que o portão
de credenciais de oci-run não veja forma de segredo em nenhuma entrada
materializada nem em nenhuma saída.
Loaders vizinhos
Registrar uma quinta chave fecha a allowlist dos loaders já entregues, então este card os estende no mesmo commit:
tests/unit/AUR-402.go— allowlist de chaves do registry canônico.tests/unit/AUR-403.go— allowlist, aridade (5) e ordem posicional.tests/unit/AUR-404.go— conjunto de chaves registradas eswitchdo loader.
Nenhum deles lê os documentos do fake provider: cada um checa apenas os caminhos declarados e a forma do digest, de modo que registrar o fake provider não pode re-apontar silenciosamente o plano Go unit nem o plano Git.
A aridade total do registry é asserida em tests/unit/AUR-405.go, que este card
possui. tests/contracts/AUR-405.go não assere aridade: este card é dono da
chave fake-provider-v1, não do tamanho do registry.
Diagnóstico offline
# a chave está publicada e em ordem?
grep -n '"key"' .board/oci/profiles/registry.v1.json
# os digests do registry reproduzem os bytes?
sha256sum .board/schemas/fake-provider-profile.schema.json \
.board/locks/oci/fake-provider-v1.lock.json
printf '%s' "$(sed -n 's/.*"image": "\(.*\)".*/\1/p' \
.board/locks/oci/fake-provider-v1.lock.json)" | sha256sum
# o runtime da imagem pinada ainda satisfaz o plano?
docker run --rm --pull=never --network=none --read-only \
--user=65534:65534 --cap-drop=ALL --entrypoint= \
aurum-bootstrap-go-bash@sha256:503ac356fa6bca4bad56fade87b5479ff371bd446ffb9c7db91f211323c7c73e \
bash -c 'command -v go; ls /sys/class/net'