Contextfulv0.23.0

Docs / Specification

contract surface · 70-control-plane.md · 71-console.md · guide · card

Cadence, dispatch and the operator plane

The control plane decides when work runs and where. It holds the schedule grammar and its trigger, the reconciler that turns an applied snapshot into an armed set, the fire stage, the bounded dispatch pool and its worker adapter, the operator’s edit and apply path over the control document, and the region a data plane resides in. The published hostname and the read path’s two hops belong to the topology contract.

The path from an operator’s edit to a dispatched unit, and where it meets topology and the run path:

Flowchart diagram Flowchart, top to bottom. 12 nodes, 11 edges. operator → control document [CRDT edits] operator plane: control document → snapshot store [apply: claim manifest@vN] operator plane: snapshot store → reconciler [poll] operator plane: reconciler → armed set [diff, armed cursor] operator plane: operator-local job blocks → armed set [local jobs] operator plane: trigger adapter → armed set [tick] operator plane: armed set → dispatch pool [fire due entries] operator plane: dispatch pool → durable orchestrator instance [orchestrated job]; → worker target [worker job] operator plane: region allow-set → reconciler [EnforceRegionMismatch at startup] topology contract: catalog lease rows → dispatch pool [cadence lease, exclusion keys] run contract: durable orchestrator instance workers: worker target operator plane apply: claim manifest@vN poll diff, armed cursor local jobs tick fire due entries EnforceRegionMismatch atstartup control document snapshot store reconciler operator-local job blocks trigger adapter armed set dispatch pool region allow-set topology contract catalog lease rows run contract durable orchestrator instance workers worker target CRDT edits orchestrated job worker job cadence lease, exclusionkeys operator

arm

The schedule grammar and cron dialect, the trigger adapter and its durability, the wake route, and how an entry computes its next fire.

reconcile

The control source, snapshot pointer, signed pulled-head validation against local declarations, schedule diff, and what a failed poll leaves running.

Scenarios

fire

Job declaration, the closed kind union, same-tick order, the fire watermark, and one-shot evaluation.

dispatch

The bounded fire pool and its exclusion keys, the reconciler’s hold on the cadence lease, step results, and the worker adapter with its attempt-fenced callback.

unsettled: Does an export on one node quiesce a serve on another, given the publication’s intent and inputs locks are files on the exporting node’s disk? owner: pipeline affects: surface.dispatch

delegate

A delegate is deploy-bound code outside the binary that runs a store-driven item’s body over one signed call request and answers with a closed outcome vocabulary.

Scenarios

edit

The configuration document, the records it presents read-only, the structured schedule specification, and connector configuration.

  • secret-in-documenttestA credential value typed into a configuration field raises SecretMaterialInDocument; the document holds references and the backend holds material.
    Whybecause a value in the document reaches every daemon and replica that reads a snapshot
  • connector-uploadtestAn artifact uploaded through the operator surface raises ConnectorUploadRefused; the surface references registered connectors by id and version.
    Whybecause publishing into the registry runs a separate signed path
  • store-drafttestAn Admin edit validates a complete control document and saves one store-scoped draft bound to its applied version, verified operator and random nonce, leaving the applied pointer unchanged.
    WhyA-surface#control-document-cas

apply

Validation, the immutable version claim, the pointer advance, the owner’s storage, and the authority an apply carries.

Scenarios

reside

Where the data plane runs, the region allow-set gating placement, and operation with no external reach.

connection

Runtime lifecycle of one tenant’s external source connection and its scheduled pipeline.

unsettled: Which manifest block supplies a connection pipeline’s OAuth client references and Drive origin? owner: surface affects: surface.connection

Scenarios

Shapes

A daemon’s own configuration, the control wiring and its operator-local jobs:

[control]
snapshot_dir = "./.contextful/control/research"   # or url = "http://127.0.0.1:8787/control"
poll         = "every 30s"
pool         = 4
trigger      = "in-process"                         # or "external", with `pipeline serve --http`

[control.delegates.stages]
url     = "http://127.0.0.1:9005/stage/screen"     # loopback, or http://contextful.delegate/stages
mode    = "call"                                   # or "submit", the worker protocol
timeout = "300s"
version = "stage-prompts-v3"                       # rotated when the delegate's semantics change

[residency]
regions = ["eu-west-1", "eu-central-1"]

[[job]]
name     = "nightly-fold"
schedule = "0 3 * * *"
kind     = "fold"
target   = "meta_ads_insights"

[[job]]
name     = "hourly-push"
schedule = "every 1h"
kind     = "sync-push"

[[job]]
name          = "score-documents"
schedule      = "every 1m"
kind          = "store-driven"
body          = "score"               # compiled code the embedding binary registers
statement     = "SELECT doc_id, body FROM documents ORDER BY doc_id"
as_of         = "2030-01-01T00:00:00Z" # absent, the instant the execution opens
max_in_flight = 4
tables        = ["scores"]

[[job]]
name           = "stage-screen"
schedule       = "every 15m"
kind           = "store-driven"
body           = { delegate = "stages" }   # deploy-bound code outside the binary
statement      = "SELECT entity_id, pass_id FROM due_items"
max_in_flight  = 5
tables         = ["screen_result"]
isolated_items = { logical_key = "pass_id", entity_key = "entity_id", entity_namespace = "entity", max_attempts = 3 }

The envelope one call request carries, signed over call, its timestamp and this body:

{"job": "stage-screen", "execution_id": "x-7f3a", "step": "row/p-7/delegate/1", "input_hash": "c1d9…",
 "idempotency_key": "9e2b…", "attempt": 1, "entity": {"namespace": "entity", "key": "e-1", "fence": 4},
 "as_of": "2030-01-01T00:00:10Z", "version": 3, "pins": {"input": "ab12…", "body_dependency_delegate": "stages"},
 "tables": ["screen_result"], "row": {"entity_id": "e-1", "pass_id": "p-7"}, "deadline": "2030-01-01T00:05:10Z"}

A delegate’s answers, one per line, each signed over answer, the request’s idempotency key, a timestamp and the body:

{"outcome": "ok", "rows": {"screen_result": [{"entity_id": "e-1", "pass_id": "p-7", "proceed": true}]}}
{"outcome": "defer", "retry_at": "2030-01-01T00:10:00Z"}
{"outcome": "permanent", "reason": "subject withdrawn"}

The wake route’s answer:

{
  "fired": ["field-notes", "nightly-fold"],
  "failed": [],
  "pending": ["hourly-push"],
  "armed": 14,
  "next_due": "<instant, RFC 3339 UTC>"
}