Skip to main content

Input contract

Transport

  • Standard input only - The Runner MUST supply input as a single JSON document over the interpreter’s stdin. No other channels (for example, command‑line arguments, files, environment variables) MAY be used for step‑specific data.
  • Single document - Exactly one document MUST be provided. Streaming multiple JSON documents or concatenated commands is forbidden.
  • UTF‑8 encoding - The JSON document MUST be encoded as UTF‑8.
  • No framing layer - The Runner MUST NOT send any framing bytes (length prefixes, newline delimiters, and more) outside of the JSON document itself.

Structure of the interpreter command/invocation contract

This section defines the Runner to Interpreter invocation contract, which is transmitted as a single JSON document through standard input. The contract is intentionally split into two parts:

  • Runner-defined envelope fields that are stable across all interpreters and provide consistent execution semantics.
  • An interpreter-defined command object whose structure, validation rules, and semantics are defined by the selected interpreter.

An interpreter MUST treat all fields outside command as belonging to the Runner-defined envelope. An interpreter MUST treat the command field as interpreter-specific and MUST validate it according to the interpreter’s published contract discovery specification (refer to the Interpreter discovery section for further details).

Top-level object

The input document MUST be a JSON object with the following fields.

Required fields

  • name The fully qualified interpreter name (for example, chef-platform/inspec-interpreter).

  • inputs A key value map used to indicate the values from the job context being presented to the interpreter. They MAY use variable substitution, environment variables, and/or templating of step-scoped values. Values MAY be any JSON type, but interpreters SHOULD treat them as data inputs rather than executable content.

  • command The interpreter-specific command payload. The schema of this object is defined by the interpreter.

Optional fields

  • skill Skill version constraints used by the Runner to select an installed skill package. This field is part of the Runner envelope and isn’t interpreter-defined.

  • minVersion, maxVersion Interpreter compatibility constraints. These values define a compatibility window for the interpreter implementation the Runner selects. They’re part of the Runner envelope.

  • runContext Execution context metadata supplied by the Runner (job identifiers, node identifiers, correlation identifiers, timestamps, and environment descriptors). Interpreters MAY use this for logging and correlation, but MUST NOT treat it as authoritative policy.

  • outputFieldRules Optional output extraction and transformation rules supplied by the Runner. This field describes how the Runner will extract values from step results and store them in the job context for subsequent steps. It’s part of the Runner envelope.

  • expectedInputs Optional input schema and validation metadata supplied by the Runner. This field declares which job context variables are expected to exist for the step and how they should be interpreted by the Runner. It’s part of the Runner envelope.

  • limits Optional resource constraints, including timeout and other execution caps. The Runner enforces limits. Interpreters MAY use this information for internal guardrails but MUST NOT assume that the Runner will permit execution beyond defined limits.

  • accessMode Optional execution access mode (for example, agent or agentless) used by the Runner and interpreter to determine execution and command restrictions when supported.

Interpreter-defined command

The command field is the only portion of the input contract whose internal structure is defined by the interpreter.

  • The interpreter MUST define the schema for command and publish it through the interpreter contract discovery mechanism in the Interpreter discovery section.
  • The interpreter MUST validate command according to its published schema.
  • The interpreter SHOULD return a clear diagnostic error when validation fails.

The command value MAY be a JSON object, array, or string if the interpreter’s contract permits it. The interpreter’s contract discovery output is authoritative for the allowed structure.

Example interpreter invocation contract

The following example illustrates the complete invocation contract for an interpreter. The command section is interpreter-specific; all other fields are part of the Runner envelope.

# Complete interpreter invocation contract (example)
name: "chef-platform/example-interpreter"

skill:
  minVersion: "1.0.0"
  maxVersion: "2.0.0"

minVersion: "1.0.0"
maxVersion: "2.0.0"

inputs:
  profile_path: "/tmp/compliance-profiles/cis-linux"
  report_dir: "/tmp/inspec-reports"
  control_id: "CIS-1.2.3"
  waiver_id: "waiver-2024-001"
  port: 22
  enable_cache: true

command:
  command: "exec"
  profile: "{{profile_path}}"
  target: "{{target_host}}"
  backend_cache: "{{enable_cache}}"
  controls:
    - "{{control_id}}"
  reporter:
    - "cli"
    - "json:{{report_dir}}/report-{{control_id}}.json"
  input_file:
    - "/tmp/inputs/production.yml"
  waiver_file:
    - "/tmp/waivers/{{waiver_id}}.yaml"
  attributes:
    environment: "production"
    compliance_level: "high"

runContext:
  jobId: "job-12345-abcdef"
  environment: "production"
  correlationId: "corr-67890"
  nodeId: "node-linux-web-01"
  timestamp: "2024-12-16T10:30:00Z"

outputFieldRules:
  requiredFields:
    - "status"
    - "output"
  fieldTypes:
    status: "integer"
    output: "object"
  transformations:
    reportPath: "output.report_file"

expectedInputs:
  requiredInputs:
    - "profile_path"
    - "target_host"
  optionalInputs:
    - "controls"
    - "reporter"
    - "waiver_file"
  inputSchema:
    profile_path:
      type: "string"
      required: true
      description: "Path to InSpec compliance profile"
      pattern: "^/.*"
    target_host:
      type: "string"
      required: true
      description: "Target host in URI format"
      pattern: "^(ssh|winrm|docker)://.*"
    enable_cache:
      type: "bool"
      required: false
      default: true
      description: "Enable backend caching"

limits:
  timeout: 300
  maxMemory: "512MB"
  maxCPU: "1.0"
  maxDiskIO: "100MB/s"

accessMode: "agent"

Command payload examples

Shell interpreter command

The Shell interpreter executes commands on Linux and Windows nodes. The Courier documentation specifies that a job step using the Shell interpreter includes a command object with OS‑specific arrays of commands: linux and windows. An Interpreter Command payload for the Shell interpreter therefore has the form:

{
  "Interpreter": {"Name": "shell-interpreter"},
  "Context": {},
  "Timeout": 120,
  "Command": {
    "linux": ["sleep 10"],
    "windows": ["echo 'hello'"],
    "dir": "/tmp",               // Optional working directory (overrides default)
    "expectedInputs": {},
    "outputFieldRules": {}
  }
}

The arrays of strings under linux and windows correspond to the syntax defined in the Shell interpreter documentation. The optional dir field allows overriding of the default working directory.

InSpec interpreter command

The Chef InSpec interpreter integrates with Chef InSpec for audit scans. The example below would invoke an InSpec audit with a scan command and arguments such as path to the profile. An Interpreter command payload might look like:

{
  "Interpreter": {"Name": "inspec-interpreter"},
  "Context": {},
  "Timeout": 600,
  "Command": {
    "exec": "scan",
    "args": {
      "path": "https://github.com/dev-sec/ssh-baseline",
      "waiver": null,
      "input": null,
      "username": null,
      "token": null,
      "source": null,
      "sourceURL": null,
      "reporterType": "json",
      "reporterFileName": "scan-report.json",
      "licenseKey": null,
      "licenseServer": null,
      "minSuccess": 90
    }
  }
}

Arguments correspond to the fields documented in the Chef InSpec interpreter description. The interpreter must validate required fields (for example, path) and ignore unknown fields unless strict mode is enabled.

Generic ping interpreter

The skeleton repository provides an example of a networking interpreter that performs a ping test. Its command payload might resemble:

{
  "Interpreter": {"Name": "ping-interpreter"},
  "Context": {},
  "Timeout": 30,
  "Command": {
    "host": "example.com",
    "count": 5,
    "timeout": 10,
    "packet_size": 64,
    "interval": 1,
    "ttl": 64
  }
}

This command instructs the interpreter to ping example.com five times with a 10‑second timeout for each ping, 64‑byte packets, 1‑second intervals, and a Time To Live (TTL) of 64. Interpreters must document their schema and validate numeric ranges accordingly.

Unknown fields and versioning

Interpreters SHOULD ignore unknown fields in Command, Interpreter, or Context. They MAY fail on unknown fields if strict validation is desirable. Explicit protocol versioning isn’t included in this specification; compatibility is implicitly bound to the job definition version. Future revisions may introduce a Version field if necessary.

Thank you for your feedback!

×