Skip to content

Repository files navigation

CipherJob

Run approved Docker tasks on your own computer from another device without exposing the computer to the Internet or trusting the relay with your data.

CipherJob lets a phone, laptop, or other client ask your workstation to perform a small set of tasks that you chose ahead of time. Your workstation can stay behind NAT with no inbound service open. A public relay moves encrypted messages between the client and worker, but it cannot read the task input or result and it cannot decide what the worker is allowed to execute.

A client does not get a shell. It cannot choose a Docker image, command, mount, secret, environment variable, or resource limit. It can only request capabilities that the worker has installed and authorized locally.

That makes CipherJob useful for things such as running a build from your phone, invoking a private local model, processing a file on a powerful workstation, triggering a trusted automation, or eventually running a coding agent without turning the machine into a general remote execution server.

CipherJob 0.3.0 is the Phase 3 release.

The idea

Most remote execution systems solve reachability by giving the remote side broad access to a machine or by putting a trusted service in the middle.

CipherJob uses a narrower model.

phone / laptop
      |
      | signed + encrypted request
      v
+-----------------------+
| public blind relay    |
|                       |
| routes ciphertext     |
| cannot read the job   |
| cannot authorize it   |
+-----------------------+
      |
      | opaque ciphertext
      v
+-----------------------+
| your worker           |
|                       |
| verifies device       |
| checks local policy   |
| maps capability ID    |
| to local Docker task  |
+-----------------------+
      |
      v
restricted container
      |
      | signed + encrypted result
      v
client

The central rule is simple:

The relay controls delivery. The worker controls execution.

The relay can make a message late, unavailable, or duplicated. It cannot turn a request into a different capability, authorize a new device, select a different image, or read the encrypted payload.

Why this is different

CipherJob separates network reachability from execution authority.

Property CipherJob
Public worker port required No
Remote shell No
Client chooses Docker image No
Client chooses command No
Relay sees task input No
Relay sees task output No
Relay can authorize execution No
Worker owns network policy Yes
Worker owns workspace policy Yes
Worker owns resource limits Yes
Tasks run in containers Yes
Structured JSON jobs Yes
Encrypted progress events Yes
Resumable encrypted artifacts Yes

The worker exposes a signed capability menu instead of a shell or arbitrary Docker API. Each capability maps to trusted local configuration.

This keeps the wire protocol small while still allowing very different applications to run on top of it.

What Phase 3 includes

CipherJob 0.3.0 provides a complete path from device enrollment to reliable container execution.

Area Phase 3 behavior
Enrollment Approval-based device enrollment with a verification code
Authentication Passkey-protected public client and worker-side device authorization
Scheduling Leases, retries, cancellation, backpressure, and bounded concurrency
Requests String and structured JSON inputs
Results String and structured JSON outputs
Progress Ordered end-to-end encrypted job events
Artifacts Resumable encrypted file transfer
Tasks Container-native multi-action task images
Isolation Worker-controlled Docker sandbox policy
Users Stable local users independent of individual device keys
Devices Multiple authorized devices with revocation
Workspaces Persistent per-user worker workspaces
Operations Local operator dashboard, doctor checks, pause, drain, and resume
Relay Cloudflare Worker and Durable Object control plane

The cryptographic wire protocol is v2, the leased relay API is v3, and container task images use task protocol v1. Those are independent version numbers for separate layers of the system.

Quick start

Requirements:

  • Python 3.11 or newer
  • Docker
  • Node.js and npm
  • a Cloudflare account for the public relay

Clone the repository:

git clone https://github.com/Aryadeepta/cipherjob.git
cd cipherjob

Set up the local environment:

./scripts/quickstart.sh

Check the worker:

cipherjob doctor --config .cipherjob/worker.yaml

Open the local operator dashboard:

cipherjob operator

Deploy the public relay:

cipherjob deploy cloudflare

Create a join link and terminal QR code:

cipherjob share --qr

Open the link on another device, create or unlock the passkey, request access, compare the verification code, and approve the device from the operator dashboard.

The browser can then load the authenticated capability menu and run installed tasks.

See docs/GETTING_STARTED.md for the full setup flow.

Container execution model

CipherJob does not expose Docker itself to the network.

A remote job contains a capability ID and input. The worker resolves that capability ID to local configuration. The local configuration determines the image and all execution policy.

A typical container starts with restrictions equivalent to:

docker run
  --rm
  --interactive
  --pull=never
  --read-only
  --cap-drop=ALL
  --security-opt=no-new-privileges=true
  --network=none
  --memory=<worker policy>
  --cpus=<worker policy>
  --pids-limit=<worker policy>
  --tmpfs=/tmp:...
  <immutable image id>

Capabilities may opt into a worker-controlled read-only or read-write workspace. Network access is denied by default. Host environment variables are available only when explicitly configured by the operator.

The remote client cannot weaken these settings.

Task images are installed by immutable Docker image ID so a mutable local tag cannot silently change the image referenced by worker configuration.

cipherjob doctor checks that configured task images still exist locally before the worker accepts jobs.

Container-native tasks

A task image can expose several related actions from one OCI image.

For example:

{
  "version": 1,
  "id": "task-toolbox",
  "label": "Task Toolbox",
  "description": "Small example task image.",
  "actions": [
    {
      "id": "echo",
      "label": "Echo",
      "description": "Return the input unchanged.",
      "risk": "green"
    },
    {
      "id": "sha256",
      "label": "SHA-256",
      "description": "Hash the input.",
      "risk": "green"
    }
  ]
}

Install it with:

cipherjob task install examples/task-toolbox \
  --config .cipherjob/worker.yaml

The image describes its actions. It does not grant itself authority.

The worker still decides:

network access
workspace access
resource limits
timeouts
host environment
authorization
concurrency

This boundary is important. A future coding agent can be packaged as a task image without adding special agent privileges to the relay or core protocol.

See docs/TASK_IMAGES.md.

Structured jobs and progress

Capabilities can accept either strings or JSON values.

A future coding task could receive an input such as:

{
  "prompt": "Add a streaming parser",
  "workspace_artifact": "art_123",
  "mode": "edit",
  "options": {
    "run_tests": true
  }
}

String capabilities remain supported.

Long-running jobs can emit ordered progress and log events while they execute. Those events use the same end-to-end encrypted reply path as other private job data. The relay routes ciphertext and does not receive plaintext logs.

The final result remains a separately authenticated result message.

Encrypted artifacts

Large inputs and outputs do not need to fit inside one job message.

CipherJob provides resumable encrypted artifacts with chunk hashing and worker-local storage.

Example:

cipherjob artifact put ./input.tar --client-config .demo/client.yaml
cipherjob artifact list --client-config .demo/client.yaml
cipherjob artifact get art_... --output ./result.tar --client-config .demo/client.yaml
cipherjob artifact delete art_... --client-config .demo/client.yaml

Artifacts are scoped to a stable local user. Multiple authorized devices for that user can access the same workspace without sharing a device private key.

The relay sees routing metadata, timing, and ciphertext sizes. It does not receive the artifact contents in plaintext.

Reliability

Remote execution needs stronger semantics than a simple queue.

Phase 3 adds leased delivery so a worker crash or lost response does not silently discard queued work. The worker renews active leases, applies bounded concurrency, handles cancellation, backs off when work cannot be accepted, and suppresses automatic replay of an execution that may already have caused side effects.

Jobs have persistent local state so worker recovery can distinguish a completed request from an interrupted one.

This matters for real workloads. A build, deployment, file mutation, or agent action cannot be treated like an idempotent text lookup by default.

Security model

CipherJob uses two independent authorization layers.

The public service authenticates access to relay resources. The worker separately authenticates the device that signed the encrypted request.

Compromising relay authentication is therefore different from compromising execution authorization.

Protocol v2 uses:

Ed25519 signatures
RFC 9180 HPKE Base mode
DHKEM(X25519, HKDF-SHA256)
HKDF-SHA256
ChaCha20-Poly1305

Signed payloads use domain separation. Broker-visible routing metadata is authenticated as associated data. Executable request IDs are checked against worker-local replay state.

The worker does not trust capability metadata from the client. The client cannot request an arbitrary image, command, mount, network mode, or secret.

The relay still observes traffic metadata such as route identifiers, request timing, expiration, ciphertext sizes, and network addresses. End-to-end encryption does not hide that metadata.

For the detailed threat model, see SECURITY.md, docs/THREAT_MODEL.md, and docs/PROTOCOL_V2.md.

Operator experience

The worker has a local management interface:

cipherjob operator

It binds to localhost and provides the operational controls needed for one worker:

worker status
doctor results
public relay status
installed tasks
task image health
join link and QR code
pending enrollment approval
authorized device management
pause
drain
resume

State-changing requests use a per-launch management token.

The operator UI is deliberately local. CipherJob does not add a second remote administration service beside the encrypted job protocol.

Why this is a strong software engineering project

I built CipherJob to exercise the parts of software engineering that are easy to hide in a small demo.

The system crosses Python, TypeScript, React, Cloudflare Workers, Durable Objects, WebAuthn, public-key cryptography, SQLite, Docker, Linux resource controls, HTTP, WebSockets, and local operator tooling. Those pieces have to agree on protocol semantics and failure behavior.

The engineering work is visible in the boundaries:

Engineering area What this project demonstrates
System design Clear separation between routing, authorization, execution, and application tasks
Security Explicit trust boundaries instead of relying on network location
Distributed systems Leases, retry behavior, cancellation, backpressure, deduplication, and recovery
Containers Read-only execution, dropped capabilities, resource ceilings, network policy, workspaces, and immutable image references
Protocol design Signed canonical payloads, encrypted envelopes, versioned schemas, structured jobs, and ordered events
Product engineering Passkey login, QR enrollment, operator approval, device management, and useful diagnostics
Debugging End-to-end failures were traced through Cloudflare storage semantics, relay behavior, Docker image identity, and worker state
Compatibility Existing string tasks continue to work while the data plane gained JSON, artifacts, and progress
Testing Python, relay TypeScript, browser TypeScript, production web builds, and live phone-to-Docker execution are all part of release validation
Scope control Agent behavior stays outside the core protocol so future applications can be added as capabilities instead of privileged platform features

The part I value most is that the project has been tested as a real system rather than only as isolated modules. Bugs found in live use changed the design. Duplicate task installation exposed a mutable-tag failure mode. Cloudflare SQL write accounting exposed an incorrect lease assumption. Operator testing exposed UX and diagnostics problems. Those were fixed at the layer that owned the problem and covered with regression tests.

That is the kind of engineering I want this repository to represent: understanding a system across layers, finding the actual failure boundary, and leaving the architecture cleaner after the fix.

Phase 4 boundary

CipherJob core does not need to know what a coding agent is.

A coding agent can be another installed capability that receives structured input, accesses an authorized workspace, emits progress, transfers artifacts, and returns a structured result.

That is the Phase 4 direction.

The transport, authorization, scheduling, container isolation, artifact channel, and operator controls remain general infrastructure.

Project status

CipherJob 0.3.0 is an educational and portfolio security project. It has not received an independent security audit and should not be treated as a hardened hostile multi-tenant execution service.

The intended deployment is a self-hosted worker controlled by its operator with a narrow set of explicitly trusted task images.

Repository guide

Path Purpose
src/cipherjob/ Python client, worker, protocol, scheduler, task runtime, artifacts, and operator tooling
relay/ Cloudflare Worker and Durable Object relay
web/ Passkey-protected browser client
examples/task-toolbox/ Multi-action task image example
docs/GETTING_STARTED.md Current setup guide
docs/TASK_IMAGES.md Task image contract
docs/PROTOCOL_V2.md Cryptographic wire protocol
docs/THREAT_MODEL.md Security boundaries and assumptions
SECURITY.md Security status and reporting

Development checks

python3 -m pytest -q
python3 -m ruff check .

cd relay
npm run check
cd ..

cd web
npm run check
npm run build
cd ..

Version

cipherjob version

Expected output:

CipherJob 0.3.0 | platform phase 3 | crypto protocol v2 | relay API v3 | task protocol v1

License

CipherJob is licensed under the Apache License, Version 2.0.

See LICENSE, NOTICE, THIRD_PARTY_NOTICES.md, and docs/OPEN_SOURCE.md.

About

No description, website, or topics provided.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages