A named attestation REQUIREMENT — the policy for one kind of sign-off,
declared once on the node that owns the raw data (attestation :name do … end
in the reactive block) and consumed by name from an attested combinator or
a gate: on an edge.
Fields:
name— the requirement's name; whatrequirement:/gate:reference.on— the cell id the assertions are about (filled at graph assembly from the declaring node; records store this as theircell_id).scope— the GRAIN of one assertion::key— per row ofon(one admission per raw row);{:filter, key_scope}— ONE set-level instance: an assertion about the whole set the filter selects (estate completeness is the filter that selects everything, e.g.{:prefix, "%"}). The view writes a single row, keyed byinstance_key(default"all");{:filter_by, fun}— one set-level instance PER ELIGIBILITY ROW:fun.(eligibility_key)returns{instance_key, key_scope}(nil — or a clause that doesn't match the key — skips it), deduped by instance key. The per-person completeness shape: "these are ALL my machines" derives one filter per person from the same cell that licenses them to sign it.
signers— the ELIGIBILITY CELL's id (an atom, like anyref). Who may sign is data: this cell's keys, filtered per-scope throughjoin. It is a real input edge of every attested cell, so authority changes propagate and appear in lineage.join—(scope, eligibility_key) -> who | nil: does this eligibility row license signing this scope, and as whom? The eligibility cell's key grammar is the host's; this is where it is interpreted.quorum—:any | :all | {:n_of, k}over the eligible set.tolerance— how long an assertion holds:nil(no time bound — the host applies its strength-derived default elsewhere), an integer of seconds, or a keyword ofweeks:/days:/hours:/minutes:/seconds:(units combine; unknown units are rejected, not zeroed).statuses— optional override of the admission-state → spine-status vocabulary (default%{affirmed: "covered", pending: "pending", unsigned: "unsigned", refused: "refused"}); status vocabulary is the host's.pendingis what a blocking (:require) gate writes for a not-yet-signed row;unsignedis what a non-blocking (:annotate) view writes for the same row — flowing, but distinguished from signed.
Summary
Functions
The admission-state → spine-status map for this requirement.
Tolerance normalized to seconds, or nil for no time bound.
Validate a tolerance value (the DSL schema's custom type): nil, seconds
as a non-negative integer, or a non-empty keyword of [:weeks, :days, :hours, :minutes, :seconds]
with non-negative integer values. Returns {:ok, value} or {:error, message}.
Types
@type quorum() :: :any | :all | {:n_of, pos_integer()}
@type scope() :: :key | {:filter, ReactiveDag.Tuple.key_scope()} | {:filter_by, (String.t() -> {String.t(), ReactiveDag.Tuple.key_scope()} | nil)}
@type t() :: %ReactiveDag.Attestation.Requirement{ __identifier__: term(), __spark_metadata__: term(), instance_key: String.t(), join: (ReactiveDag.Attestation.Scope.t(), String.t() -> String.t() | nil), name: atom(), on: String.t() | nil, quorum: quorum(), scope: scope(), signers: atom(), statuses: %{required(atom()) => String.t()} | nil, tolerance: nil | non_neg_integer() | keyword() }
Functions
The admission-state → spine-status map for this requirement.
@spec tolerance_seconds(t()) :: non_neg_integer() | nil
Tolerance normalized to seconds, or nil for no time bound.
Validate a tolerance value (the DSL schema's custom type): nil, seconds
as a non-negative integer, or a non-empty keyword of [:weeks, :days, :hours, :minutes, :seconds]
with non-negative integer values. Returns {:ok, value} or {:error, message}.