Skip to content

The v1 protocol

A worker is an image that reads one file and writes another. There is no mandatory SDK, no preferred language and no API to implement.

/oren/
├── input.json # read only — validated inputs
├── context.json # read only — run metadata
└── output.json # the worker writes here

The paths also arrive as environment variables:

Variable Value
OREN_INPUT_PATH /oren/input.json
OREN_OUTPUT_PATH /oren/output.json
OREN_CONTEXT_PATH /oren/context.json
#!/bin/sh
INPUT=$(cat "$OREN_INPUT_PATH")
echo "processing" # free logging
echo '{"change":"minor"}' > "$OREN_OUTPUT_PATH"

The previous version passed JSON in argv and read the output from stdout, delimited by markers. That brought three problems:

  • Escaping. JSON in argv crosses the entrypoint’s shell; $, quotes and newlines require escaping that neither side got right.
  • Collision with logging. stdout was a channel for logs and for data at the same time.
  • Leaking. Tokens in argv show up in ps and in any echo of the command.

An unplanned gain: the protocol became platform-agnostic. The same worker runs through the CLI or through a CI job without knowing the difference.

Exit code Meaning
0 success — output.json is read and validated
1125 task failure
126+ infrastructure failure

Output outside the contract fails the step even with exit code zero. A contract that is not checked is not a contract.

Each is delivered according to the form of its type. The worker never knows which semantic type was declared — only where the resource is, which it finds out from context.json:

{
"dependencies": {
"source": { "type": "git-repository", "path": "/source" }
}
}

The CLI grants exactly what was declared. An implementation that uses the Docker socket without declaring engine/docker fails at run time — that is what stops under-declaring from becoming an advantage in the catalogue.