Repository navigation
feat(jobs): end-to-end encrypted jobs (DIP-0032); v0.3.3 - #215
Merged
Merged
Conversation
Job offers went to gossip topics with the whole job inline, so every peer and relay on c0mpute/jobs/<workload> read every prompt, transcript and URL, and inputs and results were plaintext chunks anyone could fetch by the hash the offer and receipt published. - Offers carry only a public spec (per-workload allowlist of small scalars plus size buckets), a fresh buyer X25519 key and a salted commitment as spec_hash; buyers require c0mpute:e2e:v1 so pre-e2e workers never bid. - Bids carry a fresh worker X25519 key signed by the worker's libp2p ed25519 identity; buyers verify it against the bidder's peer id. - X25519 -> HKDF-SHA256 -> AES-256-GCM, keys and associated data bound to job id, workload, both peers and both keys. The accept carries no spec; the winner fetches the sealed spec over request-response (c0mpute.job.payload.v1), served only to the authenticated winner. The winner checks the commitment and the public spec, re-runs the workload's filter on the whole spec, then runs it. - Results are sealed to the buyer before they are stored (results, render frames, text adapters and answers); buyers open them in fetch_result. - Inputs (STT audio, img2vid images, OCR documents, .blend files, training corpora, chat adapters) are stored sealed under per-input keys carried in the sealed spec; spec_ref (large specs as plaintext chunks) is no longer used by buyers. - Every offer filter judges the public spec at bid time. - confidential requirement: c0mpute:confidential tag, attest nonce, report data binding the TEE to the sealed-to key, AttestationVerifier and AttestationProvider hooks, failing closed. SNP/TDX evidence is deferred. - Workers still serve plaintext offers for one release (C0MPUTE_REJECT_PLAINTEXT_OFFERS=1 refuses them now). Tests: crypto unit tests (wrong worker, tamper, truncation, moved job, commitment, public views per workload), dispatch downgrade test, and e2e_jobs_e2e: buyer, two workers and a passive gossip subscriber across 15 workloads; the passive node sees no plaintext, the loser is refused the sealed spec, result and input chunks are ciphertext, the buyer opens them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ThreatCrush Security Scan13 finding(s) HIGH/CRITICAL: 1 | MEDIUM: 8 | LOW: 4
Snippets are redacted; ThreatCrush never prints matched credential material. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.3.1 went to #216 meanwhile. Drops jobs_gateway::internal, unused since specs no longer go through the bridge's store. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Job offers went to the gossip topic
c0mpute/jobs/<workload>with the whole job inline. Every peer and relay on the topic could read every prompt, transcript and URL. Inputs and results were plaintext chunks, and anyone could fetch them by the hash that the offer and the receipt published. This PR makes every job end-to-end encrypted between the buyer and the one worker that wins. The design is indips/0032-e2e-encrypted-jobs.md.What changes on the wire
base_model, plus power-of-two size buckets), a fresh buyer X25519 key, and a salted commitment asspec_hash.required_capabilitiesgainsc0mpute:e2e:v1, so pre-e2e workers never bid.c0mpute.job.payload.v1). The buyer serves it only to the noise-authenticated winner, and only while the auction is open.gateway_util::fetch_result/fetch_result_to_fileopen them with the auction's result key. Receipts name the ciphertext hash..blendfiles, training corpora and chat adapters are stored sealed, each under its own key, and the key rides inside the sealed spec. The winner decrypts inputs only in memory or in the job dir. A sealed.blendstays sealed in the cache. A sealed adapter is never put in the adapter cache.spec_ref(large specs stored as plaintext chunks) is no longer used, because sealed specs travel point to point.with_confidential(true)auction requiresc0mpute:confidential. The offer carries an attest nonce. The report data binds the TEE to the sealed-to key.AttestationVerifier/AttestationProviderhooks fail closed. A concrete SEV-SNP/TDX producer and verifier are deferred.C0MPUTE_REJECT_PLAINTEXT_OFFERS=1refuses them now.What the winning worker still sees
The plaintext of the job it computes on. For sensitive work, use private mode or the confidential requirement. Observers still see metadata: the public spec, price, timing, bidders, sizes, and text-train progress events.
Tests
SECRETfor any workload.tests/e2e_jobs_e2e.rs: a buyer, two workers and a passive gossip subscriber, across 15 workloads. The passive node sees no plaintext in any offer, bid, accept or receipt. The loser is refused the sealed spec. Result and input chunks fetched by the passive node are ciphertext. The buyer opens the results.ads_e2efails on dev2 only because the hosting disk floor refuses replicas at 46 GiB free; that is environmental and unrelated. Gossip tests needC0MPUTE_DISABLE_MDNS=1on dev2's busy LAN, the same as before.🤖 Generated with Claude Code