Skip to main content

Crate ikigai_script

Crate ikigai_script 

Source
Expand description

Scripts as resources in any ikigai host. A script is not a feature beside the resources; it IS one, named urn:script:{name}, and every way of reaching it (a REST door, the REPL, an MCP agent, a timer, a panel) is a door onto the same names.

urn:script:{name}                    Source Exists Sink Delete  the script: fetch WITHOUT running, publish, retire
urn:script:{name}:version:{digest}   Source Exists              one immutable, content-addressed version
urn:script:{name}:compiled           Source                     the head prepared for its evaluator (cached)
urn:script:{name}:result             Source                     run it as a READ: its answer
urn:script:{name}:runs               Sink                       run it for EFFECTS: answers the run's IRI
urn:script:{name}:run:{id}           Source Exists              one recorded run
urn:script:eval                      Sink                       run supplied code under the caller's own authority
urn:script:catalog                   Source                     every script the caller may read

§A host library

This crate binds no binary and mounts nowhere by itself. A host (ikigai-embedded, gonk, the CMS) mounts space beside the evaluator it offers and decides the three things only a host can — see SpaceConfig:

  • where scripts live: a Backend (MemoryBackend, or DirBackend for plain files under a directory the host chooses);
  • the ceiling each script may run under (authority::CeilingPolicy, from the host’s <config home>/script-authority/{name});
  • who a request comes from: the principal its door mints into the request’s capability (Capability::with_principal, urn:cap:principal:<iri>), read back with authority::principal_of, recorded on every publish and run and never taken from the caller.
use ikigai_core::{Capability, Fallback, Kernel, Space};
use ikigai_script::{authority, space, MemoryBackend, SpaceConfig};
use std::sync::Arc;

let scripts = space(SpaceConfig::new(
    Arc::new(MemoryBackend::new()),
    // Fail closed: a script the host has not given a ceiling may touch nothing.
    authority::same_for_all(authority::Ceiling::nothing()),
));
// Beside the evaluator the scripts are written for (`ikigai_lisp::space()`):
let root = Fallback::new(vec![Arc::new(scripts) as Arc<dyn Space> /*, lisp, … */]);
let kernel = Kernel::new(Arc::new(root));

§The authority rule

Three authorities, never merged: publish (urn:cap:script:write:{name}, and …:delete:{name} to retire), run (urn:cap:script:run:{name}, or authority::CAP_RUN_PUBLIC for a public script), and runs as. Each grant names one script or a namespace of them (urn:cap:script:{act}:{namespace}-*, authority::cap_namespace), and authority::holds decides. A run runs as:

runner's capability, attenuated to
  { declared } ∩ { what the publisher held at publish } ∩ { the host's ceiling }
  + every exclusion the publisher or the ceiling carries

No elevation: a publish declaring a scope its publisher does not hold is refused, a run never holds anything its runner does not, and the only way a run’s authority is made is Invocation::issue_attenuated — there is no form that widens. See authority.

§Languages are resources

A run is a sub-request to the language’s evaluator, so this crate links no interpreter:

  • Lisp reaches urn:lisp:eval, and the evaluator’s own capability (urn:cap:lisp) is part of what every Lisp script declares: evaluating code is itself authority.
  • SPARQL reaches the host’s store through its graph-scoped doors (sparql::SparqlDoor). A query’s form, its declared and typed parameters, and the authority it needs (the store’s per-graph grants) are all read from the parsed text, and parameter values are bound into the parsed algebra, never spliced. Each published query is its own catalog entry with its parameters as arguments. See sparql.
  • Plans (ik:Process graphs) reach the host’s urn:plan:eval. A plan is validated by urn:plan:validate before it is stored, its authority is DERIVED from its steps’ contracts by urn:plan:requires, and it is a read or a write by its steps’ verbs. Each published plan is its own catalog entry with its parameters as arguments. See plan.

Preference order when assembling anything: a query, then a plan, then Lisp. The first two derive their authority and are checked before they run; use Lisp for control flow a plan cannot express, and preferably as one step inside a plan.

Re-exports§

pub use backend::Backend;
pub use backend::DirBackend;
pub use backend::MemoryBackend;
pub use endpoints::space;
pub use endpoints::Catalog;
pub use endpoints::CatalogEntry;
pub use endpoints::ChangeHook;
pub use endpoints::LastRun;
pub use endpoints::Prepared;
pub use endpoints::ScriptSpace;
pub use endpoints::SpaceConfig;
pub use endpoints::TRANSPORT_ARGUMENTS;
pub use model::Head;
pub use model::Language;
pub use model::Outcome;
pub use model::Run;
pub use model::State;
pub use model::Version;

Modules§

authority
The three authorities, never merged — and the one computation that decides what a run may touch.
backend
Where the atoms’ state lives: a Backend the host chooses.
endpoints
The resources, as endpoints.
graph
The graph face (as=text/turtle) of the catalog and the run records.
limits
Bounds on caller-supplied SPARQL, checked before the parser sees a byte (ledger #915).
model
What the atoms hold: a script’s head, its immutable versions, and its runs.
name
Script names and the IRIs built from them.
plan
Plans as a script language: a stored ik:Process graph is a script whose language is plan.
sparql
SPARQL as a script language: a stored query is a script whose language is SPARQL.