Skip to content
HARA
>_

Hara extensions

Hara extensions are loaded through ordinary namespace clauses. Runtime extensions are packaged as WASM modules; the program does not construct an engine or transport directly.

(ns app
  (:require [crypto.hash :as hash]))

(deref (hash/sha256 data))

An extension package contains a hara.extension.edn manifest beside its provider artifact:

{:namespace "crypto.hash"
 :version "0.1.0"
 :provider :wasm
 :module "math.wasm"
 :abi :core.v1
 :exports {"add" {:args [:i32 :i32] :returns :i32}}
 :capabilities []}

The runtime first checks the nearest project's fixed extensions/ directory and then configured extension roots. It validates the provider handshake and generates the requested namespace during :require. Extension namespaces are runtime generated and are not .hal source files.

WASM providers implement the extension lifecycle:

discover -> describe -> invoke -> result or error -> cancel -> shutdown

Arguments and results use Hara values and explicit opaque handles. Remote calls return promises. WASM providers use a host WASM engine. Compilation, instantiation, export calls, and memory access remain behind the provider boundary. :core.v1 invokes low-level scalar exports directly. :hta.v1 uses an import-free, host-driven mailbox and returns Hara promises. On the JVM one virtual thread owns each nested GraalWasm context; in a browser one Web Worker owns each context. Explicit host/call events are checked against the descriptor's optional host-calls allowlist before a result or structured rejection is delivered to the module.

Loading a manifest does not grant authority. The host applies capability policy and resource limits, preserving distinct errors for unsupported providers, denied capabilities, malformed manifests, crashes, timeouts, cancellation, and remote failures.

An official build can separate its source namespace from its registry coordinate: ledger.noir is required by Hara code while hara/ledger.noir identifies the maintained package.

External-toolchain extensions may instead declare host-selected HTA targets and a closed list of built assets. The Noir package uses a managed Node process with HTA over stdin/stdout on JVM/native-image hosts and a Web Worker with HTA over postMessage in browsers. Hara code sees the same exports, values, errors, promises, and artifacts on both targets. Compiled circuits use hara/ledger.noir/v1 as their format identity. Installed projects contain the built JavaScript, WASM, and worker assets, but not node_modules. See the multi-target HTA package contract for the descriptor and directory layout. Package authors can validate and install built artifacts with hara extension check, build, install, and test; build and process-backed tests require --allow-process.