Skip to main content

Files and media

ECP (Execution Control Protocol) does not shove file bytes through the workflow graph. Steps pass a ticket (FileRef) that says where the bytes live. When a capability needs the file, it turns that ticket into bytes with resolveFile. Think coat check: the workflow carries the stub; the coat stays in a locker until someone needs it.

FileRef kinds

A browser upload usually becomes:
ecp://browser/... is not Azure and not a filesystem path. It is a private locker id in the run-scoped blob map (ctx.blobs).

Resolve and write

Extensions should not invent their own fs / fetch / artifact maps. Use core:
file.path may be a Node path or an ecp://browser/<id> locator. artifact.uri may point at run artifacts, ecp://storage/…, or the same browser locator shape when bytes live in ctx.blobs.

Host disk storage (~/.ecp)

When a step writes media through writeMediaArtifact (Sharp, Azure download, and similar), bytes go through @executioncontrolprotocol/storage on the host: URI shapes for media:
  • Temp: ecp://storage/temp/<key>
  • Durable: ecp://storage/artifacts/<key>
Workflow files on the host are Fluent TypeScript (.workflow.ts). Download can export Fluent or a plain workflow manifest JSON. In the browser demo:
  • Save (paired with ecp up) writes Fluent to ~/.ecp/workflows/<id>.workflow.ts
  • Download asks TypeScript (default) or JSON — one representation only
  • Open lists host-saved workflows and compiles Fluent back into the editor; drag a .workflow.ts or .workflow.json onto the canvas to reload
ecp up creates the home layout and wipes only ~/.ecp/temp. It binds storage so the browser demo can hop write/read, save workflows, and preview via GET /v1/artifacts. For large cloud-to-cloud flows, prefer Azure SAS URLs so bytes never enter the host. Override the home directory with ECP_HOME when needed.

Browser upload to Azure

@executioncontrolprotocol/azure-blob-storage uploads with a mixed capability: some work stays in the tab, and signing hops to a trusted host.

1. Pick a file

The UI (or your app) creates ecp://browser/<id>, stashes the real File in a blob map, and puts only the ticket into workflow input — not base64 in the form.

2. Run mixed upload

On the browser graph, upload reads the stashed file, then calls create-sas-url with write permissions (c + w).

3. Keys stay on the host

create-sas-url is host execution. From the browser that call goes to ecp up, which holds the Azure connection string or account key and mints a temporary SAS URL. The tab never sees the account key.

4. Browser talks to Azure

With the write SAS, the browser PUTs bytes straight to Azure Blob Storage. Bytes go browser → Azure, not browser → ECP host → Azure. Container CORS must allow your origin for PUT, expose ETag, and allow x-ms-blob-type and Content-Type. If createReadSas is set, the host mints a read SAS. Downstream steps (for example Firefly or Photoshop) get an HTTPS URL they can fetch — still without Azure keys in the browser.

Why this design

  • Workflows stay portable — JSON and Fluent carry tickets, not giant payloads.
  • The browser stays safer — account keys never leave the host.
  • Large files stay efficient — upload goes client → cloud; the host only signs.
  • One media language — Sharp, model providers, Azure, and other extensions all use resolveFile / writeMediaArtifact.

One-sentence model

You upload a file → ECP gives the workflow a coat-check stub (ecp://browser/…) → Azure upload asks the trusted host for a temporary door key (SAS) → the browser opens Azure’s door and hangs the coat itself.