Introduction
This documentation specifies the normative contract between the Chef Courier Runner and interpreter binaries. An interpreter is an external program invoked by the Courier Runner to perform a single job step action. The specification defines the interpreter’s life‑cycle, command format, input and output transport, artifact handling, error signalling, security boundaries, idempotency guidance, and extension mechanisms. It aims to enable interoperable interpreters written in any language while preserving backwards compatibility and future extensibility. Implementation details are expressly out of scope; examples and JSON snippets are non‑normative and provided solely for illustration.
Chef Courier orchestrates jobs comprised of one or more steps. Each step delegates its work to an interpreter. An interpreter receives a structured JSON command through standard input, performs the requested action, emits results or artifacts, and terminates. By standardizing the interaction between the Runner and interpreters, users can implement bespoke interpreters or adopt official ones (for example, Shell, InSpec, or Chef Infra Client) without coupling to a particular language or runtime. This specification is intended for internal engineers and external developers and uses the requirement keywords defined in RFC 2119 and RFC 8174.
Terminology
| Term | Definition |
|---|---|
| Courier Runner | The host process that executes jobs. It locates interpreters, spawns them as child processes, supplies input, collects output, and enforces policies. |
| Interpreter | An executable program invoked by the Runner to perform a single job step. It functions as a plug‑in running in its own operating‑system context. |
| Job step | A discrete unit of work defined in a Courier job. Each step uses exactly one interpreter invocation. |
| Interpreter command | A structured JSON document (UTF‑8 encoded) describing the action requested of an interpreter. It contains interpreter metadata, context, timeout, and a command payload. |
| Artifact | Any output produced by an interpreter and attached to the job context. Standard types include logs, metrics, reports, and state; interpreters may define additional types. |
| Job context | A mutable key/value map, maintained by the Runner, that carries named step variables forward across steps (inputs, expected inputs, and extracted outputs) along with associated artifacts. Step inputs provide initial values, expectedInputs declare which variable names exist (and defaults, sensitivity, and requirement level), and outputFieldRules extract values from a step’s results (stdout, stderr, exit code, files, or artifacts) into those variables for subsequent steps. |
Architectural overview
Chef Courier employs a client–server architecture in which a central dispatcher schedules jobs across nodes. Each node runs a Courier Runner that executes job steps and manages interpreters. For each step the Runner:
- Locates the interpreter binary through configuration or naming conventions.
- Spawns the interpreter as an external process in its own OS context.
- Writes exactly one JSON document to the interpreter’s
stdin. - Waits for the interpreter to consume the input, execute the requested action, emit output and artifacts to
stdout/stderr, and exit. - Captures the process exit code, standard output, standard error, and any files or artifacts produced.
- Applies job rules (for example, output extraction, conditions, retries) to update the job context and determine step success or failure.
An interpreter only operates within the boundaries defined in this RFC. It doesn’t interact with the dispatcher or other system components directly.