Pular para o conteúdo

Fronteira de capacidade

Rodar uma ação com os poderes que ela pode alcançar — e a lista honesta do que isto não é.

O `comptime` já recusava out, adopt, thread e parallel: é uma fronteira de capacidade escrita à mão, para um caso só. E o `--plugin=` roda um .df arbitrário do projeto com todos os poderes — uma regra de lint que pode abrir soquete.

dataforge
adopt Arcane.Capacidade as Cap

// a formula do usuario calcula, e so
action formula():
    adopt Arcane.Math as M
    yield M.sqrt(16) + len("abc")

assert Cap.executar(formula, []) is 7.0
dataforge
adopt Arcane.Capacidade as Cap

action ler_disco():
    adopt Arcane.IO as IO
    yield IO.exists(".")

// sem permissao, o adopt e recusado pelo NOME da capacidade
monitor:
    Cap.executar(ler_disco, [])
    assert no
handle Error as e:
    assert "arquivos" in e.message
    assert "Arcane.IO" in e.message

// com ela, o mesmo codigo passa
assert Cap.executar(ler_disco, ["arquivos"])

As capacidades#

CapacidadeO que libera
arquivosArcane.IO, Archive, Excel, ArquivoSeguro, Lago
redeHttp, Rede, Web, Email, Malha, Kiln, Vitrine
processoOS e Process — o sistema e outros processos
bancoDatabase, Forge, e o que persiste
threadsConcurrent, Async, Laco, Stm
nativoArcane.C — memória sem rede de proteção, a fronteira mais insegura que existe aqui
pythona ponte, que alcança tudo o que o Python alcança
ambientevariáveis de ambiente e argumentos

Um nome inventado é recusado com a lista: um erro de digitação concederia silenciosamente nada, e a fronteira pareceria mais aberta do que é.

dataforge
adopt Arcane.Capacidade as Cap

// descobrir de que uma acao precisa: rode sem nada e leia os negados
action tenta():
    monitor:
        adopt Arcane.OS as OS
        yield OS.name()
    handle Error:
        yield "negado"

r := Cap.observar(tenta, [])
assert r["negados"][0]["capacidade"] is "processo"
assert Cap.exige("Arcane.OS") is "processo"
assert Cap.exige("Arcane.Math") is void      // inofensivo

O que isto NÃO é#

LimitePor quê
não tira o que foi ENTREGUEpassar o módulo é passar o poder junto. Isso é o modelo, não um defeito: numa linguagem de capacidade, poder é o que se passa, não o que está no ar — e é por isso que bloquear o adopt é a fronteira certa
a ponte para o Python é capacidade própriaela alcança tudo o que o Python alcança; deixá-la junto de outra faria o resto da lista virar enfeite
a lista de módulos é escrita à mãoum erro nela é um furo. Contra código que você escreveu e revisou — plugin, fórmula de usuário, comptime — isto vale
contra código malicioso, não use istouse processo separado, contêiner, ou o sistema operacional
dataforge
adopt Arcane.Capacidade as Cap
adopt Arcane.IO as IO

// IO foi ENTREGUE por quem chamou: o cofre nao o retira
action com_o_que_recebeu(ferramenta):
    yield ferramenta.exists(".")

assert Cap.executar(com_o_que_recebeu, [], [IO])

E a fronteira se desfaz sempre — inclusive quando o corpo falha. Uma fronteira que não se desfizesse travaria o programa inteiro, e é o finally que garante isso.