Minimal server runtime for connecting execution backends to Coda.
Project description
coda-node
Production-ready runtime for connecting an execution backend to the Coda cloud platform.
It boots a FastAPI service, provisions or reconnects node credentials, manages VPN health, consumes Redis jobs, and posts signed execution results back to Coda.
What It Does
- Provisions a node from a one-time node token
- Reconnects on restart with persisted JWT credentials
- Verifies and continuously monitors VPN connectivity
- Sends periodic heartbeats to keep QPU status "online"
- Consumes jobs from Redis Streams with crash recovery
- Optionally batches Redis jobs when the executor implements
batch_run - Sends JWT-signed webhook results to Coda with retry
- Drains in-flight work on graceful shutdown
- Supports pluggable execution backends via factory convention
- Auto-discovers executor factories from installed packages
Install
uv sync --dev
Requires Python 3.11+. Two equivalent CLI entry points are installed:
codacoda-node
Quick Start
Provision with a node token:
uv run coda-node start --token <node-token>
Or set the token as an environment variable:
export CODA_NODE_TOKEN=<node-token>
uv run coda start
After a successful first run, credentials are persisted to disk and subsequent restarts reconnect automatically without a fresh token.
How It Works
On startup the runtime:
- Loads configuration from
CODA_-prefixed environment variables, then persisted state on disk, then hardcoded defaults. - Connects to Coda using either a node token or persisted JWT credentials (with exponential-backoff retry on transient failures).
- Brings up or validates VPN connectivity when required.
- Starts the FastAPI service, a background Redis Streams consumer, and a heartbeat loop that periodically POSTs node status to the cloud.
- Dispatches jobs to the configured executor, optionally in batches, and posts signed results back via webhook.
On shutdown the runtime drains the in-flight job (up to
CODA_SHUTDOWN_DRAIN_TIMEOUT_SEC), cancels background tasks, closes
connections, and stops the managed VPN daemon.
Endpoints
| Endpoint | Purpose |
|---|---|
GET /health |
Liveness probe. Returns 200 if the process is running. |
GET /ready |
Readiness probe. Returns 200 with component status when VPN and Redis are healthy; 503 when either is degraded or the check times out. |
The /ready response body always includes vpn_state, redis_healthy,
and current_job fields for observability.
Configuration
All settings are driven by CODA_-prefixed environment variables. When
no node token is provided, the runtime automatically loads
previously persisted config from disk.
Core
| Variable | Default | Description |
|---|---|---|
CODA_NODE_TOKEN |
"" |
One-time node token for first-run provisioning. |
CODA_JWT_PRIVATE_KEY |
"" |
PEM-encoded RSA private key for direct JWT startup. |
CODA_JWT_KEY_ID |
"" |
kid header value for signed JWTs. |
CODA_REDIS_URL |
"" |
Redis connection string (redis://…). |
CODA_WEBAPP_URL |
https://coda.conductorquantum.com |
Coda cloud base URL. Overridden by the node bundle on first connect. |
CODA_HOST |
0.0.0.0 |
Bind address for the FastAPI server. |
CODA_PORT |
8080 |
Bind port for the FastAPI server. |
CODA_EXECUTOR_FACTORY |
"" |
Import path for a custom executor (see below). Highest priority when set. |
CODA_DEVICE_CONFIG |
"" |
Path to a YAML device config read by the executor factory. Defaults to ./site/device.yaml if that file exists. The runtime also looks for an optional top-level executor_factory key in this file when CODA_EXECUTOR_FACTORY is unset. |
Provide either CODA_NODE_TOKEN for auto-provisioning, or both
CODA_JWT_PRIVATE_KEY and CODA_JWT_KEY_ID for direct JWT startup.
VPN
| Variable | Default | Description |
|---|---|---|
CODA_VPN_REQUIRED |
true |
Fail preflight if no VPN tunnel is detected. |
CODA_VPN_CHECK_INTERVAL_SEC |
10 |
Seconds between background VPN health checks. |
CODA_VPN_INTERFACE_HINT |
null |
Specific TUN/TAP interface name to look for. |
CODA_ALLOW_DEGRADED_STARTUP |
false |
Allow the server to start even if VPN preflight fails. |
Resilience
| Variable | Default | Description |
|---|---|---|
CODA_NODE_CONNECT_RETRIES |
3 |
Max attempts when connecting to the Coda cloud. |
CODA_SHUTDOWN_DRAIN_TIMEOUT_SEC |
30 |
Seconds to wait for an in-flight job before forced shutdown. |
CODA_NODE_TIMEOUT_SEC |
15 |
HTTP timeout for node connect requests. |
Persisted State
After successful node provisioning, the runtime writes:
| File | Contents |
|---|---|
/tmp/coda.config |
JSON with QPU identity, Redis URL, API paths, and VPN settings. |
/tmp/coda-private-key |
PEM-encoded RSA private key. |
Both files use 0600 permissions on POSIX systems and are validated on
read. They enable token-free reconnects across restarts, preserving JWT
credentials, machine fingerprint, VPN profile path, and connection
settings.
To wipe persisted state, run coda reset.
CLI
coda start [--token TOKEN] [--host HOST] [--port PORT] [--daemon]
Start the node server. Pass --token on first run for node
provisioning. Use --daemon (or -d) to run as a background process.
coda stop
Stop the background daemon process.
coda status
Show daemon status (running/stopped, PID, log file, VPN interface).
coda logs [-n LINES]
Show recent daemon log output (default: last 50 lines).
coda doctor
Print a diagnostic summary (endpoints, executor, VPN interface, OpenVPN status).
coda stop-vpn
Stop the managed OpenVPN daemon without clearing credentials.
coda reset
Stop the daemon and VPN, then remove all persisted runtime files.
Executor Resolution
load_executor() resolves the execution backend in priority order:
CODA_EXECUTOR_FACTORY(explicit) -- set to amodule:attributeimport path to force a specific executor factory.executor_factoryinCODA_DEVICE_CONFIG-- optional top-level YAML key used when the env var is unset.- Convention-based auto-discovery -- scan installed packages for
<pkg>.executor_factory:create_executor. If exactly one match is found, use it. If multiple match, log a warning and fall back. NoopExecutorfallback -- returns deterministic all-zeros results, allowing the service to boot without hardware integration.
Factory Convention
Backend packages should expose a factory at
<package>.executor_factory:create_executor. The factory must be
either:
- A callable that accepts a
Settingsobject and returns an object with an asyncrun(ir, shots)method. - A callable that accepts no parameters and returns the same.
- A pre-built object that already has a
runmethod.
Example: Custom Executor
from coda_node.server.executor import ExecutionResult
from coda_node.server.ir import NativeGateIR
class MyExecutor:
async def run(self, ir: NativeGateIR, shots: int) -> ExecutionResult:
counts = run_on_hardware(ir, shots)
return ExecutionResult(
counts=counts,
execution_time_ms=42.0,
shots_completed=shots,
)
def create_executor() -> MyExecutor:
return MyExecutor()
Place this in my_package/executor_factory.py and install the package.
The runtime will discover it automatically. Or set it explicitly:
export CODA_EXECUTOR_FACTORY="my_package.executor_factory:create_executor"
Error Handling
All domain exceptions inherit from CodaError, making it easy to
distinguish expected operational errors from unexpected bugs:
| Exception | When |
|---|---|
ConfigError |
Invalid or missing configuration. |
AuthError |
JWT signing or verification failure. |
VPNError |
VPN tunnel or health check failure. |
NodeError |
Node provisioning or reconnect failure. |
ExecutorError |
Executor loading or job execution failure. |
WebhookError |
Webhook delivery failure. |
Import from the top-level package:
from coda_node import CodaError
from coda_node.errors import ConfigError, VPNError
Development
Install dependencies (including dev tools):
uv sync --dev
Run the full quality check suite:
uv run ruff check .
uv run ruff format --check .
uv run mypy src/coda_node
uv build
uv run pytest --cov --cov-report=term-missing
Run the opt-in live smoke tests against
https://coda.conductorquantum.com:
export CODA_RUN_E2E=1
export CODA_E2E_NODE_TOKEN=<node-token>
uv run pytest -m e2e
To include the live VPN tunnel check as well:
export CODA_RUN_VPN_E2E=1
uv run pytest -m e2e
Install pre-commit hooks (runs ruff format and lint on every commit):
uv run pre-commit install
Run all hooks manually:
uv run pre-commit run --all-files
Architecture
- FastAPI -- HTTP service, lifespan management, health endpoints
- Pydantic Settings -- environment-driven configuration with layered defaults and persisted state
- Redis Streams -- job delivery with consumer groups and crash recovery
- httpx -- async HTTP for webhooks and node API calls
- RS256 JWT -- authentication between the node and the Coda cloud
- OpenVPN -- managed as a subprocess when VPN connectivity is required
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file coda_node-0.1.0.tar.gz.
File metadata
- Download URL: coda_node-0.1.0.tar.gz
- Upload date:
- Size: 157.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aaa5f8f32f6ed94b0bed5ec3564b91ea82ed2aa03d496afe185d495335f5be51
|
|
| MD5 |
88a13643d8b7bc86beacd9d3b469a7d0
|
|
| BLAKE2b-256 |
9420d2f70c16682d941e0ac00715bf2bf412e5a96ceb915c33c4f7be0fa6a0d3
|
Provenance
The following attestation bundles were made for coda_node-0.1.0.tar.gz:
Publisher:
publish.yml on conductorquantum/coda-node
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
coda_node-0.1.0.tar.gz -
Subject digest:
aaa5f8f32f6ed94b0bed5ec3564b91ea82ed2aa03d496afe185d495335f5be51 - Sigstore transparency entry: 1210081659
- Sigstore integration time:
-
Permalink:
conductorquantum/coda-node@b2c8f7f8d453cffeb7cb5416486665cebb11d751 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/conductorquantum
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b2c8f7f8d453cffeb7cb5416486665cebb11d751 -
Trigger Event:
release
-
Statement type:
File details
Details for the file coda_node-0.1.0-py3-none-any.whl.
File metadata
- Download URL: coda_node-0.1.0-py3-none-any.whl
- Upload date:
- Size: 51.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c67e27b9df2541cfd54f50e8bf524b8352bfce3db2e85f18bcd4d4a8473f98cb
|
|
| MD5 |
f956bc6bdfee65d63d932ad47c267224
|
|
| BLAKE2b-256 |
8ed869859bc1299b122e46753ec551c52bb13597b0894969e077c90711136d83
|
Provenance
The following attestation bundles were made for coda_node-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on conductorquantum/coda-node
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
coda_node-0.1.0-py3-none-any.whl -
Subject digest:
c67e27b9df2541cfd54f50e8bf524b8352bfce3db2e85f18bcd4d4a8473f98cb - Sigstore transparency entry: 1210081825
- Sigstore integration time:
-
Permalink:
conductorquantum/coda-node@b2c8f7f8d453cffeb7cb5416486665cebb11d751 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/conductorquantum
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b2c8f7f8d453cffeb7cb5416486665cebb11d751 -
Trigger Event:
release
-
Statement type: