Přeskočit obsah

Orbiplex Arca

Orbiplex Arca is a Node-attached, demand-side solution component that provides a buyer-side workflow orchestrator and an embedded buyer-local offer-catalog cache for discovery. It is the counterpart of Dator (the supply-side component); together the two form the Orbiplex marketplace runtime split: Dator owns publication and the responder side, the shared offer-catalog module owns the public/federated projection role, and Arca owns buyer-side workflow orchestration plus local cache consumption.

Arca does not author signed protocol artifacts. Service-orders, procurement contracts, settlement holds, and peer transport all belong to host-owned capabilities exposed by the daemon; Arca proposes workflow intent and consumes those host capabilities. This boundary keeps Arca a hosted module rather than a protocol authority (see story-006-buyer-node-components and the service-order-to-procurement-bridge memo).

The v1 deployment runs as a supervised channel_json middleware service. Its host lifecycle, readiness, middleware dispatch, and host-capability calls use the shared channel. Arca separately retains a bounded loopback product/workflow API (default 127.0.0.1:47981) and a narrowly scoped, host-authenticated adapter for daemon API routes that are not host-capability operations.

Purpose

The component is responsible for the solution-level execution path of:

  • normalising a configured workflow plan into a sequential, dependency-ordered step graph and creating a host-owned workflow run,
  • building per-step service-order.v1 requests, submitting them through the classified buyer ingress, polling execution through AwaitingManualRelease, and resolving each step to completed, failed, deadline_exceeded, or step_timeout,
  • applying per-step retry policy with retry_delay_ms backoff and a max_retries cap, and per-step fail_policy (currently abort_workflow) when the retry budget is exhausted,
  • emitting operator notifications and persisting final artifacts through host-owned module APIs,
  • embedding the shared Python offer-catalog runtime as a local SQLite-backed observed-offer cache populated through Agora replay, periodic background sync against discovered shared catalog peers, inbound offer-catalog.fetch.response and offer-catalog.push peer messages, and on-demand remote queries correlated through a threading.Event handle,
  • serving a combined participant-facing catalog view at GET /v1/enact/service-catalog merging local snapshots with observed remote offers,
  • consuming host capabilities (offers.local.query, seed.directory.query, peer.session.establish, peer.message.dispatch, artifact.delivery.send) for all peer transport and discovery, rather than opening its own peer sockets.

Scope

This document defines solution-level responsibilities of the Arca component.

It does not define:

  • the supply-side responsibilities owned by Dator (local standing-offer publication, provider-side offer-catalog.fetch.response answers, outbound offer-catalog.push emission for local offers),
  • daemon-owned protocol authority (signing service-orders, opening procurement, performing settlement holds, peer transport, capability passport issuance) — Arca consumes these through host capabilities,
  • per-kind semantic interpretation of service outputs — that lives in the per-service schema and the consumer module,
  • hidden middleware mutation of workflow step outputs as an authority to complete domain tasks — task fulfillment must be derived from workflow-declared policy, explicit decision sources, or requester confirmation,
  • the editorial, content, or research semantics of any specific workflow template (e.g. story-009 bielik-biweekly-publish.v1) — Arca only provides the orchestration substrate.

Must Implement

Workflow Run Orchestration

Based on:

  • doc/project/30-stories/story-006-voluntary-swarm-exchange.md
  • doc/project/30-stories/story-006-buyer-node-components.md
  • doc/project/20-memos/service-order-to-procurement-bridge.md
  • doc/project/40-proposals/021-service-offers-orders-and-procurement-bridge.md

Related schemas:

  • service-order.v1
  • procurement-contract.v1
  • procurement-receipt.v1

Responsibilities:

  • normalize a configured workflow plan into a sequential, dependency-ordered step graph (depends_on, input_from),
  • create a host-owned workflow run and update step status snapshots through the daemon module API,
  • build per-step service-order.v1 requests from configured request_input plus upstream step output references,
  • submit one service-order per step through the classified buyer ingress at POST /v1/service-orders,
  • poll execution state through AwaitingManualRelease and resolve to completed, failed, deadline_exceeded, or step_timeout,
  • apply per-step retry policy with retry_delay_ms backoff and max_retries cap; honor fail_policy (currently abort_workflow) on retry-budget exhaustion,
  • emit operator notifications via POST /v1/module/notify and persist final artifacts via POST /v1/module/artifact/write under host-owned module output roots,
  • resume a previously persisted workflow run on module restart.

Execution Completion vs. Task Fulfillment

Arca distinguishes transport-level execution completion from domain-level task fulfillment:

  • execution.completed means that the selected provider, role module, or connector returned a response that Arca can persist as step output.
  • task.fulfilled means that the workflow's declared fulfillment policy has accepted the domain task as done.

The fulfillment decision MUST be explicit in the workflow definition. It may be derived from the current step output, from a separate capability invocation, from requester/operator confirmation, or from an automatic policy. It MUST NOT be introduced by an unannounced middleware that mutates a JSON payload in the processing stream.

Supported policy vocabulary should start small:

Policy Meaning
output_match Derive fulfillment from the current step output using a JSON-path-like matcher.
external_decision Invoke a declared capability or middleware decision source and match its JSON response.
requester_confirmation Pause until the requesting participant or operator confirms completion through UI.
auto Treat successful execution as fulfillment.
never Never auto-fulfill; require a later explicit action or workflow transition.

external_decision is intentionally capability-shaped, not Sensorium-specific. The decision source may be a Sensorium OS action, another Sensorium connector, or an unrelated middleware capability. Arca does not need to understand the domain semantics of that component. It only needs the declared source, input mapping, result matcher, and transition policy (on_not_fulfilled, on_error).

This allows two integration styles:

  • an Arca-aware decision component may return an arca-task-fulfillment-decision.v1 envelope with fulfillment/status, evidence, and optional Memarium pointers;
  • an Arca-agnostic component may return a dull JSON shape such as { "ok": true } or { "status": "done" }, with the workflow template supplying the matcher that maps it to task.fulfilled.

Status:

  • partial in the bundled middleware module. Sequential single-target workflow with retry, dependency-ordered input_from chaining, persisted run state, notifications, and artifact writes are live. Task-type-targeted ordinary steps now flow through the same service-order path: target.resolve = task_type without fan_in is treated as provider selection, not host-managed fan-out; target.task_type maps to offer-catalog service/type when no explicit service_type is provided. Proposal-033 temporal shape is preserved (deadline, timing.timeout, timing.on_timeout); legacy deadline_seconds is rejected on template instantiation. Full non-fan-out timing.timeout enforcement is still pending.

Domain-Owned Strategy Registries

Arca resolves its closed selection, host-fan-out, and fulfillment strategies through Arca-owned semantic registries rather than through a global extension switch. Distribution entries are code-backed and carry their request/response contract, constraints, and implementation identity. Operator configuration may only remove exact entries from the effective sets; it cannot add a workflow action, bypass DAG admission, or widen dispatch authority.

The shared Python registry substrate supplies monotone intersection, exact generation fencing, prompt-free inspection, and durable deactivation recovery. The actual preferred-provider, fan-out, and fulfillment branches consult their registries before executing, so an empty or disabled effective set refuses without falling back to the earlier hard-coded branch.

Package-backed strategies use the same signed P085 semantic-entry lifecycle as the other owning domains. The manifest binds the exact strategy identity; activation projects one operator- and generation-bound binding, while current grant loss, rollback, restart, and revocation are handled by the shared lifecycle. Arca still owns workflow validation and effect admission, and a registry entry cannot create a DAG step or dispatch authority.

The authenticated local control surface exposes read-only strategy status and exact entry deactivation. Deactivation is immediately visible to concurrent selectors, persists one generation-bound terminal fact, replays idempotently, and survives process restart. Enabling a new strategy or advancing the registry generation remains restart-bound configuration; generation numbers are local to this Arca instance and are never interpreted as a federation-wide counter.

Remote Service-Order Transport over Artifact Delivery

Based on:

  • doc/project/40-proposals/021-service-offers-orders-and-procurement-bridge.md
  • doc/project/40-proposals/027-middleware-peer-message-dispatch.md
  • doc/project/60-solutions/023-artifact-delivery/023-artifact-delivery.md

Related schemas:

  • service-order.v1
  • service-order.dispatch.request.v1
  • service-order.result.v1
  • artifact-delivery-envelope.v1
  • deferred-operation.v1

Responsibilities:

  • submit the selected service-order.v1 to the buyer host before AD dispatch so the host can create the hold and durable dispatch correlation,
  • build service-order.dispatch.request.v1 artifacts for remote provider execution, carrying the P021 service-order.v1, dispatch payload, workflow lineage, correlation id, delivery deadline, and a privacy-aware reply/target plus optional reply/delivery_plan,
  • send those artifacts through the host-owned artifact.delivery.send?mode=deferred capability rather than a domain-owned peer waiter loop,
  • persist the returned deferred operation/status/audit references in workflow step details and keep the step in the existing awaiting_execution state until a terminal result artifact arrives,
  • own the single supervised inbound acceptor for service-order.result.v1,
  • relay the host-issued one-shot invocation token with the exact admitted artifact to the buyer host; Arca-provided source fields never authorize closeout,
  • consume typed host admission outcomes with stable reason codes and explicit retryable data rather than matching HTTP status or error text,
  • keep Arca's local result row as a workflow projection only, then poll the host execution snapshot to close the step exactly once,
  • ignore legacy peer-message service-order.dispatch.response frames; remote service-order completion is closed only by the AD result acceptor.

Status:

  • done for buyer-host remote closeout — bundled Arca opens the host execution and hold before dispatch, sends private request artifacts through AD deferred mode, stores operation/status/audit trace, and relays the exact terminal artifact plus its one-shot host invocation token to the buyer host. The host derives the authenticated source peer from AD provenance, admits identical replays idempotently, rejects conflicting digests, and owns release/refund/receipt effects; Arca only updates its workflow projection. A manual-review-only release settles the host execution but does not implicitly resume a paused Arca run; resume remains an explicit orchestration transition. The paid three-node Story-009 acceptance proves this with buyer node A and provider nodes B/C. The current slice defaults to direct node delivery, supports configured private-safe fallback plans, and has no legacy peer-message waiter. Activating object-store-indirect fallback still requires host AD routes and explicit INAC authorization material.

Observed Offer Catalog and Discovery

Based on:

  • doc/project/30-stories/story-006-voluntary-swarm-exchange.md
  • doc/project/30-stories/story-007-settlement-capable-node.md
  • doc/project/40-proposals/023-federated-offer-distribution-and-catalog-listener.md
  • doc/project/40-proposals/067-shared-offer-catalog-over-agora.md

Related schemas:

  • service-offer-relay.v1
  • service-offer.v1
  • agora-record.v1
  • trusted-provider.v1

Responsibilities:

  • embed the shared Python offer-catalog runtime as a buyer-local SQLite-backed cache with per-source trust metadata,
  • discover shared-offer-catalog peers through the daemon host capability surface (offers.local.query, seed.directory.query, peer.session.establish, peer.message.dispatch),
  • run a periodic background sync against discovered shared catalog peers (peer_sync_interval_sec) and Agora replay when configured,
  • accept inbound offer-catalog.fetch.response and offer-catalog.push peer messages during migration,
  • issue on-demand remote catalog queries (POST catalog/remote-query) and correlate the asynchronous responses through a threading.Event handle,
  • serve the combined participant-facing catalog view at GET /v1/enact/service-catalog merging local snapshots with observed remote offers,
  • delegate shared projection, replay diagnostics, and signature verification mechanics to the shared offer_catalog runtime.

Status:

  • done in the bundled middleware module as a buyer-local cache over the shared Python offer_catalog runtime. Peer discovery and background sync, legacy fetch.response / push compatibility, on-demand remote query, and the combined catalog view are live. Agora replay now uses the shared offer-catalog projection code rather than Arca-local signature/projection mechanics.

Host Capability Bridge Consumer

Based on:

  • doc/project/20-memos/node-middleware-init-and-capability-reporting.md
  • doc/project/40-proposals/019-supervised-local-http-json-middleware-executor.md
  • doc/project/40-proposals/027-middleware-peer-message-dispatch.md
  • doc/project/60-solutions/023-artifact-delivery/023-artifact-delivery.md

Related schemas:

  • middleware-init.schema.json
  • middleware-module-report.schema.json
  • peer-message-invoke.v1.schema.json
  • local-input-invoke.v1.schema.json
  • artifact-delivery-envelope.v1

Responsibilities:

  • run as a supervised channel_json middleware module under the daemon, with module config layered from ORBIPLEX_MIDDLEWARE_CONFIG_DIR and ORBIPLEX_NODE_CONFIG_DIR,
  • declare input_chains for inbound-local routes (GET service-catalog, POST catalog/remote-query) and for inbound-peer message types (offer-catalog.fetch.response, offer-catalog.push),
  • consume per-launch channel credentials and the host-owned middleware_home contract without persisting or logging credentials,
  • use host capability endpoints for all peer transport, never opening its own outbound peer sockets.

Status:

  • done in the bundled middleware module.

May Implement

Workflow Template Instantiation

Based on:

  • doc/project/40-proposals/029-workflow-template-catalog.md
  • doc/project/40-proposals/044-host-owned-generic-module-store.md
  • doc/project/30-stories/story-009-bielik-blog-arca.md

Related schemas:

  • workflow-template.v1 (proposed)

Responsibilities:

  • accept template_id plus operator-supplied parameters and produce a concrete WorkflowDefinition ready to dispatch,
  • resolve templates from a local template store. The current host-owned substrate is the Node module store, using record_kind = workflow-template; Arca owns the payload schema and instantiation semantics,
  • optionally browse and import templates from a public template catalog peer.

Status:

  • partial — the local path is implemented. Arca stores workflow templates in the host-owned module store (record_kind = workflow-template), accepts template_id plus parameters, renders a concrete normalized WorkflowDefinition, and can either return that materialized definition or start a host-owned workflow run from it. Public/federated template catalog publication, browsing, fetch, and import remain deferred.

Workflow Fan-Out and Aggregation

Based on:

  • doc/project/40-proposals/033-workflow-fan-out-and-temporal-orchestration.md
  • doc/project/30-stories/story-006-voluntary-swarm-exchange.md

Related schemas:

  • workflow-dispatch.v1
  • peer-message-invoke.v1

Responsibilities:

  • preserve target, fan_in, and timing fields in normalized plans passed to the host workflow run,
  • let the daemon dispatch host-managed workflow fan-out requests to static or protocol-capability-resolved targets,
  • wait for responses according to fan_in policy (any_one, all, or implemented-but-deferred best_of),
  • collect and surface the selected fan-out output as step details for downstream input_from consumption,
  • expose dispatch inspection records on WorkflowRunSnapshot.steps[].dispatches without leaking raw response payloads.

Status:

  • partial — the thin host-managed fan-out slice exists for explicit target + fan_in steps. The daemon resolves static and protocol-capability targets, persists WorkflowStepDispatch records, reconciles any_one, all, and implemented-but-deferred best_of, and surfaces inspection data in WorkflowRunSnapshot.steps[].dispatches. Arca only enters this path when fan_in is present; target.resolve = task_type without fan_in stays on the ordinary service-order path. Quorum and retry/backoff policies remain deferred.

Workflow Temporal Orchestration

Based on:

  • doc/project/40-proposals/033-workflow-fan-out-and-temporal-orchestration.md

Responsibilities:

  • honor per-step timing.timeout / timing.on_timeout and emit step_timeout when exceeded,
  • honor a workflow-run-level deadline and emit deadline_exceeded when exceeded,
  • express retry with explicit backoff and a max_attempts cap at the WorkflowDefinition layer.

Status:

  • partial — workflow-level deadline and fan-out step-level timing.timeout / timing.on_timeout are implemented in daemon fan-out reconciliation. Ordinary non-fan-out service-order steps still use Arca polling/retry and do not yet enforce timing.timeout.

Workflow Target Resolution by Task Type

Based on:

  • doc/project/30-stories/story-009-bielik-blog-arca.md
  • doc/project/30-stories/story-000-two-nodes-see-each-other.md

Responsibilities:

  • express ordinary service-order step targets as resolve: task_type with a task_type rather than a hard-coded participant,
  • at dispatch time, use the host/catalog lookup surface to resolve the current offer/provider for the mapped service/type, then continue through the ordinary service-order path.

Status:

  • partial — ordinary Arca execution accepts target.resolve = task_type; when service_type is omitted, target.task_type becomes the service lookup key. A task-type target with no fan_in does not trigger host-managed fan-out. Dedicated richer task-type lookup/filter semantics remain open beyond the phase-0 slice.

Peer Workflow Fan-Out Bridge

Based on:

  • doc/project/40-proposals/033-workflow-fan-out-and-temporal-orchestration.md

Responsibilities:

  • accept inbound peer workflow fan-out requests and process them as ordinary local catalog queries.

Status:

  • doneworkflow.fanout.request is implemented in the bundled Arca module as a local catalog-query responder. It returns a local active offer for the requested service_type or no_offer_available; it does not execute arbitrary services.

Out of Scope

  • local standing-offer publication and provider-side offer-catalog.fetch.response answers — those belong to Dator,
  • authoring or signing service-orders, procurement contracts, or receipts — those go through host-owned capabilities,
  • settlement, balance precheck, and hold management — host-owned through the deployment-local settlement write gate,
  • per-kind semantic interpretation of service outputs,
  • offer relay transport and peer session establishment — those are daemon host capabilities consumed by Arca, not owned by it,
  • editorial, research, or content semantics of any specific workflow template (e.g. story-009).

Consumes

  • service-offer-relay.v1
  • trusted-provider.v1
  • peer-message-invoke.v1
  • local-input-invoke.v1
  • middleware-init.schema.json
  • artifact-delivery-envelope.v1
  • service-order.result.v1

Produces

  • service-order.v1
  • service-order.dispatch.request.v1
  • catalog-local-query-request.schema.json
  • catalog-local-query-response.schema.json
  • arca-caps.edn

Notes

Arca is bundled as a supervised Python channel_json middleware module; the bundled implementation lives at node/middleware-modules/arca/ (see the module's README.md, service.py, and config/00-arca.json). The Arca/Dator split is the deployment model — the legacy offer_catalog.enabled flag has been removed, and Dator is the supply-side counterpart for local offer publication and responder-side offer-catalog.fetch.request answers.

Arca's MUST boundary is intentionally narrow: it orchestrates and it discovers, but it does not author signed acts. Every signed protocol artifact (service-order ingress, procurement open, settlement hold, peer dispatch) is reached through a host capability surface owned by the daemon. This is what makes Arca a hosted workflow module rather than a parallel protocol authority — see the service-order-to-procurement-bridge memo for the canonical statement of what Arca may and may not do.

Story-009 (bielik-biweekly-publish.v1) is the first story that exercises Arca beyond the story-006 single-vertical-slice profile. It now has the local phase-0 substrate: workflow templates can be stored in the host-owned module store, materialized from template_id plus parameters, and dispatched as ordinary service-order DAGs using target.resolve = task_type. The remaining Arca gaps are narrower: richer task-type lookup/filter policy, public/federated template catalog import, and full timing.timeout enforcement for ordinary non-fan-out service-order steps. Host-managed fan-out remains a separate path and requires an explicit fan_in block.