bankai/rules/registry

Pillar 2 — mobile rules: content-addressed, executable, sync-able.

A “rule” is a gleamunison S-expression source string. Its identity is the SHA-256 of its source (gleamunison/identity.hash_bytes). Rules are stored in a registry, gated by an allow-list, executed via gleamunison/repl, and synced across registries by hash (identical sources dedupe cleanly).

SECURITY (per ADR-0003, layered defense in depth):

Types

pub opaque type Registry
pub type Rule {
  Rule(name: String, source: String, hash: identity.Hash)
}

Constructors

Values

pub fn approve(reg: Registry, hash: identity.Hash) -> Registry
pub fn count(reg: Registry) -> Int
pub const default_eval_max_heap_words: Int

Hard worker heap cap in BEAM words (~2 MiB on a 64-bit VM).

pub const default_eval_reduction_limit: Int

Maximum reductions consumed by one rule evaluation.

pub const default_eval_timeout_ms: Int

Default wall-clock budget for a single rule eval (ms).

pub fn eval(
  reg: Registry,
  hash: identity.Hash,
) -> Result(String, String)

Execute an approved rule, isolated + timeout-bounded at the default budget.

pub fn eval_source_with_input(
  source: String,
  input_json: String,
  timeout_ms: Int,
) -> Result(String, String)

Evaluate a source artifact as a pure unary lambda over an immutable JSON text view. The quoted argument prevents task-view data escaping into syntax; this worker has no task, file, network, or process authority.

pub fn eval_with_timeout(
  reg: Registry,
  hash: identity.Hash,
  timeout_ms: Int,
) -> Result(String, String)

Execute an approved rule with an explicit wall-clock budget (ms).

pub fn is_approved(reg: Registry, hash: identity.Hash) -> Bool
pub fn lookup(
  reg: Registry,
  hash: identity.Hash,
) -> Result(Rule, Nil)
pub fn merge(a: Registry, b: Registry) -> Registry

Content-addressed sync: union two registries by rule hash (identical sources dedupe — same hash). BUT approvals stay LOCAL — BUG-06 fix: the old code set.union-ed approvals, letting a rule approved on ANY rig become executable everywhere after merge, bypassing ADR-0003’s trust layer (“registration is arrival, approval is trust”). Sync propagates RULES (data), never TRUST — each rig approves locally.

pub fn new() -> Registry
pub fn register(
  reg: Registry,
  name: String,
  source: String,
) -> #(Registry, identity.Hash)

Register a rule. NOT auto-approved — call approve to make it executable. (ADR-0003 trust layer: registration is arrival, approval is trust.)

pub fn revoke(reg: Registry, hash: identity.Hash) -> Registry
pub fn run_bounded(
  work: fn() -> Result(String, String),
  timeout_ms: Int,
  max_heap_words: Int,
  reduction_limit: Int,
) -> Result(String, String)
pub fn run_isolated(
  work: fn() -> Result(String, String),
  timeout_ms: Int,
) -> Result(String, String)

Execute pure work in an unlinked worker bounded independently by wall-clock, heap words, and BEAM reductions. The Erlang boundary owns process monitoring so a heap kill cannot be mistaken for a normal evaluator result.

pub fn source_hash(source: String) -> identity.Hash

Content address of a rule source = SHA-256 of the source bytes.

pub fn source_hash_text(source: String) -> String
Search Document