Declarando dependências
dependencies: source: type: git-repository description: Repositório a analisar. mutable: false gcpCredential: form: file sensitive: true privilege: high description: >- Chave de service account. O escopo real depende dos papéis da conta e raramente é mínimo.Duas formas de declarar, e exatamente uma por dependência.
Inline, que é o caso comum
Seção intitulada “Inline, que é o caso comum”form diz o que o motor materializa — diretório, arquivo, string, socket,
capability — e é isso que ele consegue enforçar. Some sensitive: true quando
for credencial, e description para dizer o que é.
Não exige registrar nada, funciona offline, e é o que você vai escrever na maior parte das vezes.
Nomeado, quando o nome compra algo
Seção intitulada “Nomeado, quando o nome compra algo”type referencia o vocabulário do núcleo. Ele é fechado — tipo desconhecido
é erro de validação — e pequeno de propósito: só entra ali o que enforça algo
além da forma.
| Tipo | Forma | Privilégio | O que ele enforça além da forma |
|---|---|---|---|
directory |
diretório | baixo | — |
git-repository |
diretório | baixo | exige .git no caminho, antes de subir container |
file |
arquivo | baixo | — |
string |
string | baixo | — |
secret |
string | médio | marca sensível: redigido em log, fora do lockfile |
secret-file |
arquivo | médio | conteúdo sensível montado como arquivo — nunca escrito no host |
socket |
socket | crítico | um canal para o daemon que estiver escutando |
engine/docker |
socket | crítico | conhece o caminho convencional do socket |
network |
capability | médio | — (declarável, ainda não enforçado) |
endpoint/tcp |
endpoint | médio | um endereço vivo que o worker alcança — veja Providers e endpoints |
endpoint/postgres, endpoint/redis |
endpoint | médio | estendem endpoint/tcp: uma alegação de protocolo, casada mas nunca verificada — veja abaixo |
Um nome também compra identidade: dois documentos que citam o mesmo tipo são sabidamente a mesma coisa. É disso que dependem busca no catálogo e o auto-wiring de credenciais, que ainda não existe.
O que o nome não compra é garantia. O que o motor enforça é a forma, e a forma está nos dois caminhos.
O que cada coluna decide
Seção intitulada “O que cada coluna decide”Três coisas, e elas são ortogonais.
Forma é como o valor atravessa a fronteira do container, e o runtime faz
trabalho diferente para cada uma:
| Forma | O que o worker recebe |
|---|---|
directory |
um diretório montado, no mountPath que a implementação declara |
file |
um arquivo só, montado como secret quando o valor é conteúdo em vez de caminho |
string |
uma variável de ambiente, marcada como secreta quando o tipo é sensitive |
socket |
um socket Unix ligado ao container |
capability |
nada no filesystem — a concessão é a ausência de restrição |
Privilégio é quanto custa conceder, e é o que o gate de consent lê. Abaixo
de medium a dependência é concedida sem perguntar, porque não há o que decidir
em ler um diretório. mutable: true sobe um degrau: escrever no diretório de
alguém custa mais que ler.
extends é herança. git-repository é um directory, e serve onde o
contrato pede um — o inverso não vale.
Por que o vocabulário é fechado
Seção intitulada “Por que o vocabulário é fechado”Tipo desconhecido é erro dos dois lados: a CLI recusa resolver, e o portal recusa publicar.
Isso é deliberado. Esta é a única parte do spec que a CLI e o portal precisam
interpretar de forma idêntica. Se viesse de banco ou de um arquivo do seu
projeto, dois portais teriam vocabulários diferentes e o mesmo oren.yaml
significaria coisas diferentes em cada um.
Admitir o desconhecido também obrigaria a assumir um privilégio para ele — e privilégio assumido para baixo é exatamente o que faz o gate de consent ficar calado sobre algo caro.
Pedindo um tipo novo
Seção intitulada “Pedindo um tipo novo”Tipo novo é mudança do spec, com release — não configuração. Antes de pedir, veja se você precisa mesmo:
Provavelmente não. Uma credencial de qualquer nuvem é
form: file, sensitive: true, privilege: high declarada inline, e isso descreve
tudo que o motor precisa saber. O que um nome compra é identidade — busca no
catálogo, auto-wiring — e não garantia.
Sete tipos de fornecedor já moraram no núcleo e saíram por isso: nenhum
enforçava nada além da forma. A semântica deles vive melhor na description do
contrato, onde é lida.
Provavelmente sim quando a forma é nova: algo que não é diretório, nem arquivo, nem variável, nem socket, nem capacidade pura. Isso ainda não aconteceu.
O que uma proposta precisa ter: o nome, a forma, o privilégio e — a parte que
importa — por que esse privilégio. O engine/docker é critical porque o
socket do Docker é root na máquina; se você não consegue escrever uma frase
dessas, o privilégio é chute, e privilégio chutado é pior que tipo nenhum.
Cardinalidade
Seção intitulada “Cardinalidade”A chave é a identidade; type é um atributo. Declarar várias do mesmo tipo é
normal:
dependencies: source: { type: git-repository, mutable: true } artifacts: { type: directory, mutable: true } gcpProd: { form: file, sensitive: true, privilege: high } gcpStaging: { form: file, sensitive: true, privilege: high }mutable
Seção intitulada “mutable”Sem ele, o que o worker escreve é descartado com o container. Com ele, a alteração volta para o host e os steps seguintes a enxergam.
Precisa ser explícito: é a diferença entre uma task que lê o repositório e uma que reescreve o working dir de quem executou. E sobe o privilégio um degrau.
Na implementação
Seção intitulada “Na implementação”O contrato nomeia; a implementação posiciona:
dependencies: source: mountPath: /source gcpCredential: mountPath: /secrets/gcp-key.json gitToken: env: GIT_TOKEN # forma string chega por variávelUma chave que não existe no contrato é dependência adicional da
implementação, e precisa declarar type. É o delta que o catálogo compara.