Files
kane-diagnostics/docs/orchestrator/README.md
2026-06-16 11:01:43 -04:00

6.4 KiB

Orchestrator

Purpose: Receives diagnostic record envelopes from Hubzilla addons, validates them, and persists them. Anchors Scenario submissions on-chain when Ğ1 payment is available.


What the Orchestrator Does

The orchestrator is the only thing on this node that writes diagnostic records to durable storage. Hubzilla addons collect input, validate it locally, assemble a complete envelope, and POST it once. The orchestrator never asks an addon for more information mid-transaction. The envelope arrives complete or it does not arrive.

The orchestrator does three things:

  1. Authenticates the request (single shared node_token)
  2. Validates the envelope against the receiver contract for its addon field
  3. Persists the record according to that record type's storage rule

It does not render HTML. It does not manage sessions. It does not know what a Privacy Group is. Those are Hubzilla's job.


Trust Boundary — One Shared Token

All addons on this node (vs01, dsc01, scn01, g1wallet) share a single node_token. This is a deliberate scope decision, not an oversight.

What this means: any addon holding the shared token is trusted to identify itself correctly via the addon field in its envelope. The orchestrator does not independently verify that a request claiming "addon": "scn01" actually originated from the scn01 module. The token proves the request came from this node. It does not prove which addon on this node sent it.

Why this is acceptable: every addon on this node is part of the same codebase, reviewed under the same coding guidelines, deployed through the same tarball-and-pull workflow, and authored by the same operator. There is no scenario in the current architecture where one addon needs to be protected from another addon on the same node.

What this rules out: a future addon that requires its own authorization boundary — for example, a third-party-operated addon, a addon with a different trust level, or an addon whose compromise should not grant write access to other addons' record types — does not fit this model. That addon needs its own token, its own scope, and likely its own orchestrator instance or a scoped-token upgrade to this one. Do not bolt that requirement onto the shared-token design. Build it separately, or revisit this document and upgrade the authentication model deliberately, with a version bump.

If you are adding a sixth addon to this node and asking "does it need its own token," the answer is governed by one question: does this addon's compromise need to be contained from the others? If yes, it does not belong in the shared-token model as currently built.


Record Types and Storage Rules

The orchestrator has exactly two storage behaviors. Every record type uses one of them.

Overwrite-by-Placekey (mutable institutional memory)

Used by: vs01, dsc01

The participant's participant_id (their Placekey) is the storage key. Each submission replaces the previous one in full. There is no version history, no audit trail of prior states, and no concept of "undo." The current file always represents the participant's current understanding.

This is intentional. A Vital Signs or DSC Category record is not a complaint or a claim — it is an ongoing assessment. The record belongs to the address, not the person occupying it at any given moment. When a unit changes hands, the new occupant inherits the existing record exactly as the prior occupant left it, in the same way an incoming Board inherits the obligations and liabilities of the outgoing one. Staleness is expected and acceptable. Silence from a non-participating occupant is itself informative — the absence of an update is a fact about that address, not a gap to be hidden or auto-filled.

Storage path:

/srv/civic-orchestrator/data/{addon}/{association_slug}/{participant_id}.json

Append-only (immutable attestation record)

Used by: scn01

Every submission is appended to an array. Nothing is ever overwritten, edited, or deleted by the orchestrator. Each entry carries its own submitted_at timestamp and a snapshot of the participant's VS and DSC records at the moment of submission, so the entry is self-contained and does not depend on the current state of the mutable records to be understood.

Storage path:

/srv/civic-orchestrator/data/scn01/{association_slug}/records.json

The Ğ1 Coin Is a Utility, Not a Currency

A Scenario submission carries an optional g1_tx_hash field. When present, it is the transaction hash of a one-Ğ1 transfer the participant made to submit. This serves two purposes: it is a deliberate, cost-bearing act that discourages frivolous or automated submission, and it is a timestamped, third-party-anchored fact that exists independently of this node.

The orchestrator does not require this field to accept or persist a record. A Scenario record is valid, stored, and complete whether or not g1_tx_hash is present. The coin strengthens the record's evidentiary weight; its absence does not invalidate the record. This must remain true in every future version of the receiver contract. If a future change makes record acceptance conditional on a successful Ğ1 transaction, that change requires a deliberate architectural decision and sign-off — it is not an incidental tightening to slip into a validation patch.


What the Orchestrator Does Not Decide

The orchestrator does not check whether a participant is allowed to submit a Scenario (the VS-Set-and-DSC-Set-must-exist-first prerequisite is enforced by the Hubzilla addon before the envelope is ever assembled). The orchestrator does not verify SASE standing. The orchestrator does not check Privacy Group membership. All of that happens upstream, in Hubzilla, before the POST is made. The orchestrator trusts the node that sends it a request with a valid token to have already done its job.

This mirrors the trust boundary above: the orchestrator trusts the node; within the node, the node trusts each addon to identify itself honestly. Two layers of trust, each scoped to what it can actually verify.


  • receiver-spec.md — the /receive endpoint contract, request/response shapes, validation rules per addon
  • ../CODING-GUIDELINES.md — rule 2 (named contracts) and rule 4 (Hubzilla/orchestrator boundary) govern this design
  • ../hubzilla/addon/vs01/contracts/spool-v1.json — the vs01 envelope contract (existing, predates this document)