Date: 2026-07-17 · Diagram-backed summary of 2026-07-17-datahub-driver-consensus-design.md for the sync. Draft to converge on — the Open decisions at the bottom are what we still need to agree.
The driver writes pipeline outputs directly to CoreWeave object storage — no bytes through DataHub, no DataHub-minted presigned URLs. It gets temporary S3 credentials from its own projected OIDC token (CoreWeave mints them), and uploads with nf-amazon (a light fork). DataHub keeps everything DataHub-specific by exposing two small control-plane calls the driver makes around each file: Allocate (DataHub returns the object key + a per-file SSE-C key it mints and KMS-wraps) and Commit (DataHub finalizes the drive_file + sidecar). Completion and progress ride nf-foxfire's signed telemetry, fanned to a DataHub inbox. The nf-side glue is a path factory + s3-driver fork, not a full datahub:// filesystem. Net: bytes go direct (scales to GB outputs), DataHub still owns layout, keys, records, and download.

sequenceDiagram
autonumber
participant U as User / DataHub UI
participant DH as DataHub
participant W as wisp
participant DRV as nf driver Job
participant CW as CoreWeave Object Storage
participant FOX as foxfire
U->>DH: run pipeline on this file
Note over DH: ensureFolder(dest), mint run correlation
DH->>W: POST /submit {job_type, immediacy, params, callback_url=DH inbox}
W-->>DH: {run_id}
W->>DRV: launch driver Job — mount 2 OIDC tokens (aud coreweave.com/iam, aud datahub), FOXFIRE_*, callback
rect rgb(232,238,248)
Note over DRV,CW: CREDS — driver mints temp S3 creds from its own OIDC token
DRV->>CW: exchange OIDC token (aud coreweave.com/iam) for temporary S3 creds
CW-->>DRV: temp access key + secret + session token
end
rect rgb(198,219,247)
Note over DRV,CW: INPUT — allocate at DataHub, read direct from CoreWeave
DRV->>DH: POST input:allocate (aud datahub, run-bound) name+ref
DH-->>DRV: object_key + per-file SSE-C key
DRV->>CW: GET object (SSE-C) via nf-amazon + temp creds
end
DRV->>DRV: nextflow run (k8s executor to task pods)
rect rgb(200,236,206)
Note over DRV,CW: OUTPUT per file — allocate, write direct, commit
DRV->>DH: POST files:allocate (aud datahub) name
DH-->>DRV: object_key opaque + per-file SSE-C key (DataHub keeps the KMS-wrapped form)
DRV->>CW: PUT object (SSE-C) via nf-amazon + temp creds — direct, no DataHub bytes
DRV->>DH: POST files/{id}:commit size + sha256
Note over DH: finalize drive_file + sidecar in the run folder
end
par Telemetry — signed lifecycle events
DRV->>FOX: submit / start / complete (EC-P256 signed)
and Progress + completion to DataHub via callback fan-out
DRV->>DH: FOXFIRE_CALLBACK_URLS same signed events
end
Note over DH: run completed event → mark job SUCCEEDED
DH-->>U: outputs in the run folder, live progress from the event stream

flowchart LR
subgraph DHside[DataHub owns]
SUB[submit client to wisp]
ALLOC[Allocate and Commit endpoints]
KMS[per-file SSE-C key mint plus KMS wrap]
REG[drive_file plus sidecar plus download-decrypt]
INBOX[telemetry inbox for completion and progress]
OFFER[offer engine and generic form]
end
subgraph PLAT[Platform owns]
WISP[wisp classify launch Kueue]
PLUGIN[nf plugin path factory plus nf-amazon SSE-C fork]
DRIVER[driver image plus workflows plus 2 OIDC tokens]
FOXP[nf-foxfire signed telemetry]
end
CW[(CoreWeave Object Storage SSE-C at rest)]
FOXR[(foxfire receiver)]
SUB -->|POST /submit| WISP
WISP -->|launch Job| DRIVER
DRIVER --> PLUGIN
PLUGIN -->|allocate and commit aud datahub| ALLOC
PLUGIN -->|temp creds via OIDC aud coreweave| CW
PLUGIN -->|PUT and GET SSE-C direct| CW
ALLOC --> KMS
ALLOC --> REG
FOXP -->|signed events| FOXR
FOXP -->|callback fan-out| INBOX
| # | Endpoint (DataHub) | Auth | Request → Response |
|---|---|---|---|
| 1 | POST /api/pipeline/{run_id}/files:allocate |
datahub-aud token, run-bound | {name, contentType} → {file_id, object_key, sse_algorithm, sse_c_key_b64} |
| 2 | (write → CoreWeave directly) | CW temp creds (OIDC) | nf-amazon PUT + SSE-C |
| 3 | POST /api/pipeline/{run_id}/files/{file_id}:commit |
datahub-aud token, run-bound | {size, sha256} → {ok} |
| 4 | POST /api/pipeline/{run_id}/input:allocate |
datahub-aud token, run-bound | {input_ref} → {object_key, sse_c_key_b64} |
| 5 | POST /submit (exists) · foxfire telemetry inbox |
— · signed events | as already specified |
Auth: the driver mounts two projected OIDC tokens — aud: coreweave.com/iam (→ CW temp creds, bytes) and aud: datahub (→ Allocate/Commit, run-bound via the T4-SECURITY pod-name binding). Neither token crosses to the other system.
Every driver→DataHub call carries the driver pod's projected Kubernetes ServiceAccount token (aud: datahub), which DataHub validates in-cluster via TokenReview. That gives four guarantees:
TokenReview; it can't be forged.datahub audience is enforced, so a coreweave.com/iam or default-audience token can't be replayed here./api/pipeline/** requires ROLE_DRIVER.TokenReview) must startsWith(run_id); since wisp names the Job = run_id, a run-A driver can't act on run B. (A run-scoped audience datahub:<run_id> is the stronger future bind.)No shared secret, nothing DataHub-minted, short-lived + auto-rotated; the cluster is the trust anchor. Two caveats: it proves "a pod named <run_id>-* running as the driver SA is calling," not which image that pod runs (supply-chain — mitigated by only wisp being able to create driver Jobs); and pod-name binding must be confirmed to appear in the cluster's TokenReview or drivers fail closed. CoreWeave byte access is a separate plane — the driver's coreweave.com/iam token → CW temp S3 creds, never touching DataHub.
nf-amazon SSE-C — confirm the fork can set the per-object customer key (AWS SDK supports it)./submit, and the foxfire telemetry inbox (completion + progress).UploadService's key-mint + row/sidecar commit; drops the presign step). T4-SECURITY's run-bound datahub-audience token still gates it.Open decision #2 is resolved in mechanism, verified against CoreWeave docs. AI Object Storage supports OIDC Workload Identity Federation (CKS clusters are OIDC IdPs, Nov 2025); the exchange endpoint GET /v1/cwobject/temporary-credentials/oidc/{orgId} matches the AWS container-credentials provider shape, so a projected SA token (aud https://coreweave.com/iam) plus the AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE / AWS_CONTAINER_CREDENTIALS_FULL_URI env pair gives the driver SDK-managed, auto-refreshing S3 credentials — no exchange or refresh code anywhere. The principal is structural (system:serviceaccount:<ns>:<sa> via the cluster issuer), so nothing DataHub-minted rides the workflow layer. Scoping: organization access policies evaluate first, bucket policies (S3 API) second; s3:* actions scope to buckets and key prefixes with Condition + explicit Deny. Recommended posture: per-org runner SA as the IAM boundary; run-level write isolation via plan-vs-observed reconciliation through foxfire, not per-run IAM. In-cluster transfers should use the LOTA endpoint (http://cwlota.com, virtual addressing). Remaining spikes: org WIF enablement, nf-amazon → SDK default-chain smoke test, TokenReview pod-name. Full contracts: advaita-datahub-storage-data-model §S2.
The design was approved at review. Remaining open: #1 key/path granularity (steer: per-run acceptable) and #4 confirm the nf-amazon SSE-C fork. Resolved: #2 temp-cred scope (per-org runner SA + bucket policy; ambient SDK-managed creds per the research resolution above), #5 input (allocate-read, symmetric with output); #3 is drafted per-file in the interface contract. The submit input model was extended after review: a top-level data map (named keys → URIs) beside params, carried via -params-file in the per-run ConfigMap, with template-declared schemas (params + data_inputs) validated at submit — contracts in advaita-datahub-storage-data-model §S0/§S3.
#1 closed — per-file (2026-07-17, post-review read-through). One SSE-C key per file, minted at Allocate; a key may be shared across the parts of that file's multipart upload but never across files. This is DataHub's existing data model, kept intact. With #4 confirmed on both sides (CW SSE-C support; stock nf-amazon has no customer-key path, so the fork threads the headers), no numbered decisions remain open — everything left is build work, tracked in advaita-datahub-storage-data-model's ledger.