Expand description
§tapes-capture
The Tapes capture protocol: the primitives that are true of every harness.
This is the half of capture that no harness changes. Nothing here may learn
a harness’s name — the moment it does, it has stopped being the thing every
harness shares. Where capture needs something from a harness, it declares a
trait and tapes-harnesses implements it; the
dependency edge runs one way and Cargo enforces it rather than review.
§Public seams
envelope— theX-Tapes-*envelope producer and the harness-id vocabulary it stamps. This is a cross-language contract: produced here in Rust, parsed by the Go implementations in tapes’ ingest and gateway capture.gateway— the capture-gateway environment contract and two sub-protocols over it. The launch-nonce protocol covers what a launched process is told about where to send capture, and what proves the process is the one that was launched. The provider-route protocol covers how one gateway address serves several upstream providers, by labelling the request path with the provider it belongs to. A summary that mentions only the nonce leaves out five of the module’s nine public items — all nine are re-exported at the crate root.peer_pid— resolving the process on the other end of a local connection.peer_trust— the ancestry walk that decides whether that peer is trusted.session—HarnessSession, the trait by which a harness supplies the envelope the session fields it needs.
§Features
| feature | default | what it does |
|---|---|---|
envelope-fixtures | off | Exposes envelope::fixtures, the reader for the shared fixture corpus vendored under vendor/tapes-envelope-fixtures/, so a consumer can table-test its own envelope composition against the same cases this crate does. |
envelope-fixtures is off by default and must stay that way: the reader panics
by design on a malformed corpus, which does not belong in a production build.
Enable it under [dev-dependencies].
The corpus itself resolves by a path relative to the crate manifest, and it
ships inside the packaged crate — so the reader works from a crates.io
dependency and from a git checkout alike. This crate’s own documentation is
built with every feature enabled, so envelope::fixtures is on the API docs
even though a default build does not compile it.
§The fixture corpus
Do not change producer behaviour without updating the shared corpus in the tapes
repository first, then re-vendoring with scripts/sync-envelope-fixtures.sh. The
oracle in src/envelope_fixtures.rs must stay green against the vendored copy —
if a change makes it fail, the contract conversation happens in tapes, not by
editing the fixtures here.
That last rule is enforced, not merely stated: the corpus carries a DIGEST
over its case set, and tests/envelope_corpus_seal.rs recomputes it on every
cargo test. Editing a vendored case turns a contract disagreement that would
have been caught in review into a red seal naming the file.
§Stability
This crate is supported public API, meant to be depended on directly. So
are its two siblings — tapes-harnesses (the
harness knowledge) and tapes-client (the read
client) — and all three version independently on crates.io.
Pre-1.0, 0.x versions carry the usual Cargo meaning: a breaking change bumps
the minor (0.2.0), anything compatible bumps the patch (0.1.1). What counts
as breaking is the boundary in the repository README,
not just the signatures: a capture primitive that starts knowing a harness’s
name has broken this crate’s promise whether or not anything stops compiling.
The X-Tapes-* envelope is the exception worth stating outright, because it is
not only Rust. It is a cross-language contract that Go parsers read on the other
side, so an envelope change is a change to something this crate’s version number
cannot describe on its own — it goes through the shared fixture corpus first.
Changes are recorded in CHANGELOG.md.
§License
Dual-licensed under MIT OR Apache-2.0; see the repository root.
§Module map
The README’s seam list above says what each module is for. This is the same set with the arguments that decided their boundaries, and with links.
envelope— theX-Tapes-*request-header contract: the producer that turns a resolved session identity into the on-wire header set, the header names and caps that set obeys, and the vocabulary of harness ids it stamps. It is a wire format, and a wire format that changed when a harness was added would not be one. Every id it can carry is declared here, and the harness registry takes its ids from this list rather than restating them — that direction is the point, not an accident: the envelope is the contract a harness declaration must be consistent with.gateway— two protocols, not one. The launch-nonce protocol names the proxy, mints a per-launch secret, and checks the header that echoes it back; the provider-route protocol lets one gateway address serve several upstream providers by labelling the path. Both are protocol; the plugin files written against them are artifacts and live with the harness they are installed into. Conflating the two is what let a protocol change ride along with an artifact change.peer_pid— maps an accepted loopback connection to one of a candidate PID set via per-OS kernel APIs.peer_trust— the ancestry walk that answers whether the process on the other end of a connection is the harness this client launched, or one of its descendants.session—HarnessSession, the trait a harness crate implements to describe one of its sessions to the envelope producer. It is the shape of the boundary rather than a primitive: stating what is needed, so nothing here has to import a supplier of it.
peer_pid and peer_trust together are the question every capture
client asks before it believes anything a connection tells it about itself,
and neither has ever needed a harness id to answer it.
§Where the envelope contract is written down
envelope documents the producer. The contract it implements is
documented beside the fixture corpus that seals it, in
vendor/tapes-envelope-fixtures/SOURCE.md, and the parts a parser author
needs are summarised in envelope::fixtures (present with the
envelope-fixtures feature; docs.rs builds it) — including the rule that
makes several vendored copies one corpus:
- The corpus is vendored into every implementation of the contract, in every language, and all copies must move together from one upstream revision. A copy that moves alone is a suite that goes green against bytes no other implementation has.
DIGESTis what makes that checkable: sort the case files by base name, feed"<basename> <sha256>\n"for each into SHA-256, and compare. The recipe is deliberately trivial so each language restates it in a few lines rather than sharing an implementation that would itself need vendoring.- Cases carry a direction —
roundtrip,encode, ordecode— that says which half of the contract asserts them. A producer runs the first two and skips the third by design; a parser runs the first and third.
§Names
The repository is tapes-crates; this crate is one of its four members.
tapes is a different repository entirely — the server whose ingest reads
these headers back, and the authoring home of the fixture corpus vendored
here.
Re-exports§
pub use gateway::GATEWAY_NONCE_ENV;pub use gateway::GATEWAY_NONCE_HEADER;pub use gateway::GATEWAY_PROVIDER_ROUTE_PREFIX;pub use gateway::GATEWAY_PROVIDER_ROUTES_ENV;pub use gateway::GATEWAY_PROVIDER_ROUTES_ON;pub use gateway::GATEWAY_SCHEMA_ENV;pub use gateway::GATEWAY_URL_ENV;pub use gateway::nonce_matches;pub use gateway::provider_route;pub use gateway::split_provider_route;pub use peer_pid::PeerPidLookup;pub use peer_pid::lookup as peer_pid_lookup;pub use peer_trust::is_launched_or_descendant;pub use peer_trust::peer_is_launched_harness;pub use peer_trust::peer_is_launched_harness_async;pub use session::HarnessSession;
Modules§
- envelope
- The capture envelope.
- gateway
- The capture-gateway environment contract, and the two protocols carried over it.
- peer_
pid - Per-OS “which PID owns this TCP loopback connection” lookup.
- peer_
trust - Whether the process on the other end of a connection is the harness the capture client launched.
- session
- What the envelope needs to know about a harness’s session.