Pular para conteúdo

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 e switch do 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'