Skip to content

Decide the file-aperture contract boundary and representation #719

Description

@flyingrobots

Rewritten after review. The first version of this issue asserted that echo-file-aperture "cannot be consumed because it lacks a wire format" and prescribed a dedicated echo-file-aperture-wire crate as the answer. Both were overclaims: the first is false, and the second chose a solution before the requirement was established. Rewritten as a design issue.

Observation

echo-file-aperture defines Echo's host-file contract — FileSiteId, FileBasisToken, FileContentProposal, FileContentIntentReceipt, FileApertureError::StaleBasis, materialization verification postures. It is pure: blake3 and thiserror, zero filesystem calls, 782 lines. Its purity is correct and should be preserved — it should not be "finished" by teaching it to open files.

It has zero consumers. Outside its own directory it appears only in the workspace members list and workspace.dependencies. It is also entirely unbound to the runtime: grep -rn 'FileContentProposal|FileAperture|file_aperture' across crates/warp-wasm/, crates/warp-core/src/, and crates/echo-wasm-abi/ returns nothing. Its own rustdoc anticipates this gap: "Later slices should bind these records to WAL/WSC retention and Echo scheduler receipts."

Correction to the original framing

A Rust library does not need a canonical encoding to have a consumer. Lack of serialization blocks transport-neutral, out-of-process, and cross-language consumers. It does not block a direct crate dependency, a git dependency, an adapter compiled into the same process, or a deliberately typed in-process boundary.

So "no wire format" is not why the crate has no users. The honest statement is that nobody has yet decided what kind of boundary this contract is supposed to be.

The actual question

What representation, if any, does the file-aperture contract need in order to serve its intended consumers?

Options worth comparing rather than assuming:

Option Serves Cost
Direct typed linkage In-process consumers only Cheapest; no new crate; couples consumers to Rust and to Echo's release cadence
Reuse existing Echo envelope framing Consumers already speaking Echo's framing No new format to maintain; may not fit a file-shaped domain
Generated Echo contract payloads Consumers on the existing contract-host path Consistent with other Echo domains; more machinery
Dedicated domain wire crate Out-of-process and cross-language consumers Most flexible; most new surface to version and maintain

The decision should follow from a decided consumer set, not precede it.

Requirements that hold regardless of representation

Whatever is chosen, these responsibilities have to land somewhere or an out-of-process implementation will quietly differ from an in-process one:

  • protocol version
  • operation id — so retry behaviour is explicit rather than inferred
  • session or capability reference — authority capability-rooted, never deduced from an ambient path
  • requested revision
  • basis token

And for a receipt: disposition, input digest, result digest, prior revision, settled revision, updated basis, evidence reference.

One constraint worth stating early: Echo currently implements a boundary crossing as three WAL records (ADR 0026). That is internal choreography, not a promise. Whatever surface is exposed should let Echo collapse it to two without breaking a consumer.

Open questions this issue should answer

  • Who are the intended consumers, and are any of them out-of-process or non-Rust?
  • Does WARP DRIVE need a serialized contract, or would a published crate dependency suffice? (See warp-drive#20 — its workspace excludes echo path deps and the crate is unpublished, which is a packaging blocker, tracked separately at Package Publish And Versioning #523.)
  • Is host file-site identity the same thing as a causal site identity, or does a translation law sit between them? See WARPDrive POSIX Materialization Optic #447 — a WARP DRIVE optic identity is specified to include coordinate and optic law, not just path bytes, while FileSiteId is explicitly not portable WSC causal identity. This is unresolved and may be the real blocker.
  • Does the contract need runtime admission binding (artifact type, registered handler, durable settlement) before representation matters at all?

That last question may well reorder this issue behind a larger one.

Origin

Found auditing the Echo/WARP DRIVE seam at echo c354d53 / warp-drive 63b1f9e. Successor in spirit to #533, which shipped the in-memory contract slice and closed without a follow-up.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfeatureFeature umbrella (epic)legend:platformMethod legend platform.needs-designMethod closeout state needs-design.runtimeRuntime corespecSpec/Design documenttoolingTooling/CI/CLItype:spikeMethod work type spike.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions