Artifact Delivery FAQ¶
What is Artifact Delivery?¶
Artifact Delivery is the host-owned delivery and inbound admission plane for
schema-bound artifacts. A component submits one artifact-delivery-envelope.v1
request to the host capability artifact.delivery.send; the host validates the
envelope, checks outbound permissions, expands the delivery plan, resolves
recipients, selects concrete transport adapters, executes the transport, records
the result, and exposes status to the operator.
The important boundary is that components express delivery intent, not transport mechanics. A middleware component does not need to know whether a public artifact should be published through Agora, whether a private artifact should travel through INAC over an authenticated WSS peer session, or whether a future mailbox adapter is available. The daemon owns that routing and records the resulting delivery in the Artifact Delivery ledger.
Artifact Delivery also owns inbound admission. Artifacts arriving from transport adapters enter one shared admission path, where the host checks byte identity, source-adapter policy, idempotency, and the single-owner acceptor registry. A given artifact schema/content-type class is accepted by at most one authoritative acceptor. If a domain needs fan-out, that domain acceptor must own the fan-out behind its own contract.
Data is transformed in a deliberately staged way. On egress, component-local JSON
is first normalized into a delivery envelope, then into an expanded dispatch plan,
then into adapter-specific transport requests. On ingress, transport frames such
as inac-control.v1 are converted into an inbound admission request, then into
one domain acceptor invocation. The artifact bytes are expected to remain
byte-identical across those transformations.
flowchart TD
Middleware["Middleware or node-attached component"]
HostCapability["artifact.delivery.send host capability"]
AD["Artifact Delivery runtime"]
Ledger["SQLite delivery ledger"]
Routes["Routes, defaults, groups, outbound allows"]
Resolver["Recipient resolver"]
Selector["Transport selector"]
Agora["Agora publish adapter"]
INAC["INAC direct adapter"]
Peer["Authenticated WSS peer session"]
Admission["Artifact Delivery inbound admission"]
Acceptors["Single-owner acceptor registry"]
Domain["Domain acceptor"]
Operator["Operator APIs and UI"]
Middleware --> HostCapability --> AD
AD --> Ledger
AD --> Routes
AD --> Resolver --> Selector
Selector --> Agora
Selector --> INAC --> Peer
Peer --> Admission
INAC --> Admission
Admission --> Acceptors --> Domain
AD --> Operator
Admission --> Operator
What is the rationale behind Artifact Delivery?¶
Artifact Delivery exists to avoid making every component a transport owner. INAC, Agora, peer sessions, retry loops, route tables, and inbound admission are host concerns; a component should not duplicate that machinery just to move one artifact.
The layer also keeps authority visible. A valid artifact schema is not enough to send an artifact. The sending component must have an explicit outbound allow for the artifact schema, route references, selector classes, target node ids, size limits, fan-out limits, and fallback limits that apply to the resolved plan.
The inbound side has a similar discipline. Inbound artifacts are admitted through a single shared path and dispatched to exactly one authoritative acceptor. This prevents middleware-chain ambiguity: the same artifact should not be silently accepted by several unrelated modules that each interpret it differently.
Artifact Delivery is also a stratification boundary. INAC remains the private/direct node-to-node transport adapter under AD, Agora remains the public/federated record substrate, and Memarium remains local custody. AD does not replace those components; it coordinates the host-owned movement and admission of artifacts between them.
What components use Artifact Delivery?¶
node/artifact-delivery-coreprovides the pure contract layer: envelope DTOs, plan validation, route expansion, recipient resolution, target deduplication, outbound authorization, deterministic delivery ids, and failure classes.node/artifact-deliveryprovides the runtime layer: adapter registry, referenced payload resolution, synchronous submit, deferred submit, delivery ledger, recovery, inbound admission registry, and admission ledger.- The daemon exposes
POST /v1/host/capabilities/artifact.delivery.send,GET /v1/artifact-delivery/routes,GET /v1/artifact-delivery/deliveries, per-delivery status lookup,POST /v1/artifact-delivery/recover,POST /v1/artifact-delivery/admissions, and admission status lookup. - The daemon registers the
agora-defaultpublish adapter for signedagora-record.v1artifacts. - The daemon registers the
inac-directadapter for local INAC short-circuit delivery and remote INAC delivery over authenticated WSS peer-message sessions. - Remote WSS INAC
pushframes feed Artifact Delivery inbound admission on the receiver. - Supervised HTTP middleware, in-process daemon acceptors, and explicitly configured pure JSON-e Flow acceptors can receive inbound artifacts through the acceptor registry.
- Node UI exposes
/admin/artifact-deliveryfor route, adapter, recovery, delivery, and admission visibility.
How can middleware use Artifact Delivery?¶
Middleware can use Artifact Delivery in two directions: outbound send and inbound
acceptance. Outbound send means the middleware calls the host capability
artifact.delivery.send with an artifact-delivery-envelope.v1. Inbound
acceptance means the host calls a registered acceptor after an artifact arrives
from a transport adapter and passes admission checks.
Outbound use always requires the caller to be an authenticated middleware module:
the daemon checks that component/id in the envelope matches the authenticated
module id. The runtime then checks the host-level outbound allow table. Inbound
use is configured by the operator through artifact_delivery_acceptors; the
current implementation does not infer Artifact Delivery acceptors directly from a
module report.
Built-in Rust middleware¶
Built-in Rust components can be wired directly by the daemon when the behavior is
host-owned and deserves to live in the trusted process. For outbound delivery,
daemon-composed Rust code can build a DeliveryEnvelope and call the runtime or
the same host-capability path used by middleware. For inbound delivery, the MVP
supports daemon-composed in-process acceptors through
artifact_delivery_acceptors.in_process.
The currently supported in-process acceptor invoke target is inac.push. It is
used to feed admitted artifacts into the local INAC runtime without going through
loopback HTTP.
{
"artifact_delivery_acceptors": {
"in_process": [
{
"acceptor_id": "acceptor.inac.push",
"artifact_schema": "agora-record.v1",
"content_type": "application/json",
"invoke": "inac.push"
}
]
}
}
Supervised HTTP middleware¶
Supervised HTTP middleware can send artifacts by calling the daemon host
capability endpoint with its normal module capability authentication. It submits
one envelope and receives either artifact-delivery-result.v1 or, when using
?mode=deferred, deferred-operation.v1.
POST /v1/host/capabilities/artifact.delivery.send HTTP/1.1
Content-Type: application/json
{
"schema": "artifact-delivery-envelope.v1",
"component/id": "story005-whisper",
"artifact": {
"schema": "agora-record.v1",
"content/type": "application/json",
"digest": "sha256:EXAMPLE_DIGEST",
"size/bytes": 512,
"bytes/base64": "eyJzY2hlbWEiOiJhZ29yYS1yZWNvcmQudjEifQ=="
},
"delivery/plan": {
"route/ref": "public-agora"
},
"idempotency/key": "whisper:candidate:example"
}
Supervised HTTP middleware can also be an inbound acceptor. The operator registers
the acceptor in host config, and the daemon calls the component-local
invoke_path with an artifact-delivery-acceptor-invoke.v1 payload.
{
"artifact_delivery_acceptors": {
"supervised_http": [
{
"acceptor_id": "acceptor.whisper.private",
"component_id": "component/middleware/whisper",
"artifact_schema": "agora-record.v1",
"content_type": "application/json",
"invoke_path": "/v1/artifact-delivery/accept",
"request_timeout_ms": 5000,
"max_response_bytes": 65536
}
]
}
}
Sensorium OS Actions¶
Sensorium OS Actions are not Artifact Delivery acceptors by themselves. They are
actions behind the Sensorium OS connector, so the recommended current pattern is
to let a role flow or supervised middleware call Sensorium, receive the action
result, build an artifact envelope, and then call artifact.delivery.send.
This keeps the OS action focused on local sensing or execution while the host keeps delivery, authorization, route selection, and retry semantics. If an action needs to produce deliverable content, return bounded JSON or bytes to its caller; the caller should wrap that output in a schema-bound artifact and use AD.
JSON-e Flow or supervised role middleware
-> sensorium.directive.invoke
-> normalize action result
-> artifact.delivery.send
JSON-e Flows¶
JSON-e Flow middleware can use Artifact Delivery outbound by listing
artifact.delivery.send in allowed_calls and using a host-capability call step
that renders an artifact-delivery-envelope.v1. This is useful for bounded
low-code adapters that need to publish or transfer an artifact after rendering a
small JSON value.
{
"id": "example.artifact.sender",
"module_id": "example-artifact-sender",
"component_id": "example-artifact-sender",
"profile_version": "orbiplex.json_e_flow.v1",
"allowed_calls": ["artifact.delivery.send"],
"steps": [
{
"id": "send",
"kind": "call",
"capability": "artifact.delivery.send",
"input": {
"schema": "artifact-delivery-envelope.v1",
"component/id": "example-artifact-sender",
"artifact": "${artifact}",
"delivery/plan": { "route/ref": "public-agora" }
}
}
]
}
JSON-e Flow can also serve as an inbound acceptor, but this acceptor mode is
intentionally pure. The configured flow must have a respond step that yields an
InboundAdmissionResult, and it must not declare host capability calls. The host
compiles this flow once at daemon startup and invokes it inside the admission
boundary.
{
"artifact_delivery_acceptors": {
"json_e_flow": [
{
"acceptor_id": "acceptor.json-e-flow.whisper",
"artifact_schema": "agora-record.v1",
"content_type": "application/json",
"flow_id": "whisper.private.acceptor"
}
]
}
}
How is Artifact Delivery configured?¶
Artifact Delivery configuration is host-owned. A package may ship suggested configuration fragments, but the effective authority comes from daemon config that the operator accepts.
Host-level configuration¶
artifact_delivery is the core delivery policy and route table.
defaultsdefine named recipient selectors that can be referenced from plans.groupsdefine named sets of recipient selectors.routesdefine named delivery plans withroute/id, optionalroute/version, and an inlineplan.outbound/allowsdefine which component may send which artifact schema and through which selector classes, route refs, target node ids, fan-out size, fallback count, and maximum bytes.
artifact_delivery_adapters configures concrete adapter behavior.
agora_publish.endpointoptionally overrides the local Agora service endpoint.agora_publish.auth_headeroptionally overrides the auth header name.agora_publish.auth_token_fileoptionally points to the token used by the Agora publish adapter.inac_peer_transport.enabledcontrols whether remote WSS INAC transport can be used byinac-directtargets.inac_peer_transport.inbound_allowed_peersis the receiver-side allowlist for remote WSS INAC Artifact Delivery frames. Empty means deny-all.inac_peer_transport.response_timeout_msbounds the wait for a peer response.
artifact_delivery_recovery configures deferred delivery recovery.
enableddefaults totrue.interval_msis the idle interval between background recovery passes.batch_limitcaps the number of recoverable deliveries processed in one pass.pass_deadline_mscaps one recovery pass.
artifact_delivery_acceptors configures inbound admission.
http_admission_allowed_source_adaptersallows selected source adapters to usePOST /v1/artifact-delivery/admissions; empty means deny-all for that HTTP control-plane path.supervised_httpregisters loopback HTTP middleware acceptors.json_e_flowregisters pure JSON-e Flow acceptors.in_processregisters daemon-composed acceptors such asinac.push.
The runtime also creates host-owned storage under the node data directory:
storage/artifact-delivery.sqlite for the delivery ledger and
storage/artifact-store for the initial artifact-store: referenced payload
resolver.
Package-level configuration¶
There is no separate Artifact Delivery package-level authority contract in the current implementation. A middleware package can ship config fragments, templates, examples, or operator instructions, but outbound allows, routes, adapters, recovery policy, and acceptor registrations become effective only when they are present in the daemon's effective host configuration.
This is intentional: package installation should not silently grant artifact send authority or inbound acceptance authority.
Envelope-level configuration¶
The envelope controls only the delivery request, not the host's authority model.
component/idnames the caller and must match the authenticated middleware module id on the host-capability path.artifactdeclaresschema,content/type,digest,size/bytes, and exactly one payload location: inlinebytes/base64orartifact/ref.delivery/plancontains eitherroute/refor inlinestages, but not both.- A stage contains
stage/id, targets, optionalsuccess/policy, optionalquorum/min-success, and optionalon/failure. - Recipient selectors currently include
node,configured-default,group,agora-default,capability-first, andcapability-many. policycan carryprivacy,delivery, andtimeout/ms. The runtime records and validates the shape, but full generic enforcement is still route-, adapter-, or acceptor-specific.idempotency/keylets the runtime treat repeated submissions as the same delivery intent.
Deferred mode is not an envelope field. It is selected by calling
POST /v1/host/capabilities/artifact.delivery.send?mode=deferred.
What data shapes are used by Artifact Delivery?¶
artifact-delivery-envelope.v1is the component-facing host capability request. It carries one artifact, one delivery plan, optional policy, and optional idempotency key.artifact-delivery-result.v1is the synchronous response returned after the runtime accepts and attempts a delivery.artifact-delivery-status.v1is the operator/export shape for one recorded delivery run.artifact-delivery-recovery.v1is the operator response after a manual recovery pass.deferred-operation.v1is returned when the caller uses?mode=deferred.deferred-operation-status.v1is exposed at the canonical per-delivery operation-status URL.inac-control.v1is the transport control frame used by INAC foroffer,request,push, and response/refusal operations.agora-record.v1is the signed record format accepted by the Agora publish adapter.memarium-blob.v1is a signed content-addressed artifact envelope that can be moved through AD and INAC paths.
The daemon also uses daemon-local admission shapes:
artifact-delivery-admission-request.v1,
artifact-delivery-admission-response.v1, and
artifact-delivery-acceptor-invoke.v1. They are implementation contracts of the
current daemon admission surface; they are not yet the primary public
component-facing schema family.
How does Artifact Delivery decide routing?¶
Routing starts from delivery/plan. If the plan contains route/ref, the host
loads the named route from artifact_delivery.routes. If the plan contains
inline stages, the host validates and expands those stages directly.
Each stage contains recipient selectors. The resolver turns those selectors into concrete targets:
agora-defaultresolves to the Agora publish adapter.noderesolves to aninac-directtarget for that node id.configured-defaultresolves throughartifact_delivery.defaults.groupexpands throughartifact_delivery.groups.capability-firstandcapability-manyare part of the envelope vocabulary; complete capability-based resolution remains a later resolver layer.
After resolution, the runtime deduplicates concrete targets and checks outbound authorization for the calling component. It verifies the artifact schema, optional route ref allowlist, selector class allowlist, target node id allowlist, maximum byte size, maximum target count, and maximum fallback stage count.
Transport selection is then exact: a resolved target carries an adapter scheme,
and the runtime invokes the registered adapter for that scheme. The current
production adapter schemes are Agora publish and INAC direct. The stage success
policy (all, any, or quorum) decides whether a stage succeeded. If it
fails and on/failure points to another stage, the runtime follows that
fallback stage.
On the receiving side, incoming transport frames do not bypass AD. Remote WSS INAC frames must pass the receiver-side INAC peer allowlist first, then feed the shared Artifact Delivery admission path. Admission chooses exactly one acceptor by artifact schema and optional content type; exact content-type registrations win over wildcard registrations.
Sequential examples¶
Public Whisper publication through Agora¶
- A middleware component builds a signed
agora-record.v1artifact. Artifact Delivery does not sign it. - The component calls
artifact.delivery.sendwith anartifact-delivery-envelope.v1. - The envelope uses
delivery/plan.route/ref, for examplepublic-agora. - The daemon validates the envelope through schema-gate.
- The daemon checks that
component/idmatches the authenticated middleware module id. - Artifact Delivery expands the route and resolves it to the Agora publish adapter.
- Artifact Delivery checks the component's outbound allow for
agora-record.v1, the route ref, selector class, limits, and artifact size. - The Agora publish adapter verifies that the inline bytes are JSON with
schema = "agora-record.v1"and atopic/key. - The adapter posts the record to the configured local Agora service.
- Artifact Delivery records the delivery id, stage outcomes, status, and any diagnostic data in the delivery ledger.
Private direct delivery through INAC¶
- Node A middleware builds a signed byte-identical artifact, for example a
private
agora-record.v1. - The middleware calls
artifact.delivery.sendwith a plan that resolves to a target node. - Artifact Delivery resolves the target to the
inac-directadapter. - If the target is the local node, the adapter short-circuits into the local INAC runtime.
- If the target is remote, the adapter requires inline artifact bytes and an authenticated WSS peer session to that node.
- The adapter wraps the artifact in an
inac-control.v1pushframe and sends it as peer messagemsg = "inac.v1". - Node B receives the peer message and checks
artifact_delivery_adapters.inac_peer_transport.inbound_allowed_peers. - If the peer is allowed, Node B converts the frame into an Artifact Delivery inbound admission request.
- Admission checks byte identity, idempotency, and acceptor availability.
- The selected acceptor receives the artifact; AD records the admission result on the receiver.
Inbound supervised HTTP acceptor¶
- The operator configures a supervised HTTP acceptor for one artifact schema and optional content type.
- A transport adapter feeds an inbound artifact into Artifact Delivery admission.
- Admission finds the exact acceptor or a wildcard fallback for the schema.
- The daemon builds an
artifact-delivery-acceptor-invoke.v1payload containing source adapter, optional source peer, idempotency key, and artifact descriptor. - The daemon POSTs that payload to the component-local
invoke_path. - The acceptor returns an
InboundAdmissionResult. - Artifact Delivery records the receiver-local admission id and status.
Deferred delivery and recovery¶
- A middleware component calls
POST /v1/host/capabilities/artifact.delivery.send?mode=deferred. - The daemon validates and persists the delivery intent.
- The daemon returns
deferred-operation.v1with a stable operation id and status URL. - The background recovery worker periodically retries recoverable deliveries
according to
artifact_delivery_recovery. - An operator can also call
POST /v1/artifact-delivery/recover?limit={n}to run one manual recovery pass. - The delivery can be inspected through
/v1/artifact-delivery/deliveries/{delivery-id}and/v1/artifact-delivery/deliveries/{delivery-id}/operation-status.