Observability and traceability are one.
31 July 2026 · the launch journal
Open a trace. A request enters at the edge, fans out through nine services, and returns in 240 milliseconds. The waterfall reads top to bottom like a story: every span knows its trace, every span knows its parent, and the whole story hangs on three fields — traceId, spanId, parentSpanId. OpenTelemetry carries that structure in every span, and W3C trace-context makes it portable across any vendor boundary.
Now ask the waterfall who did it. It does not know. service.name names the deployment that emitted the telemetry — which software ran, not who acted. Observability built a causation structure no record tradition had ever had, and left the performer blank.
Now open a chain of custody. A lot of product is commissioned at a plant, packed onto a pallet, received at a distribution center, received at a store. EPCIS 2.0 — GS1's standard for supply-chain events, the one trace-back programs are converging on — gives each of those events five dimensions: what, when, where, why, how (EPCIS 2.0 §7.2.2). Dimension for dimension it is a better-provenanced record than a span will ever be. It knows the lot number, the location as a GLN, the business step, the disposition of the goods.
Ask it two questions and it goes quiet. Who observed this event? The standard has no performer dimension. Its party fields are organisation-grain (EPCIS §7.3.6.4; CBV §7.4.3), so a company doing a process is answered and a worker doing a task is structurally absent — there is no Who field to leave blank. Which event caused this one? EPCIS has containment — a pallet physically holds its cases, parentID over childEPCs — but no causation. In the entire standard, the only cross-event reference is an error declaration's correctiveEventIDs. No event parents another event. There is no trace.
So the trace knows its causation and forgot the physical world and the performer. The custody event knows the physical world and forgot the causation and the performer. Two record traditions, raised by different industries over two decades, each shipped the same observation with different fields blank — and one blank in common.
The same sentence, different words missing.
These are not similar records. They are the same record, and the rhyme runs clause for clause.
OTel Logs carries Timestamp and ObservedTimestamp — the moment a thing happened and the moment the system learned of it. EPCIS spells the identical split eventTime and recordTime. OTel exports one record per span, at span end, because an observation is only assertable once the fact is complete. Event sourcing has carried correlationId and causationId for years: exactly the event-grain pair EPCIS never defined. Nobody copied anybody. The traditions keep deriving the same clauses because they are describing the same thing: an observation of the world, carrying what, who, when, where, why, and how.
Each tradition even names the word it left blank. In EPCIS, the Who is a company — the GLN of the legal entity involved. In OTel, the who is a deployment.
epcis.dev writes the whole sentence, and writes it as conformant EPCIS. The five dimensions stay where GS1 put them. The performer rides as a namespaced extension, the standard's own mechanism for exactly this (EPCIS §6.3). The causation fields the trace tradition proved out ride the same way: a trace_id shaped to W3C trace-context, a parent_event_id for event-grain causation, links for the fan-in a single parent cannot express. Every such document still validates against GS1's own pinned schema.
A superset that stops being conformant is not a superset; it is a fork.
One detail carries unusual weight. parent_event_id points at a content hash — the standardized EPCIS event hash of CBV 2.0 §8.9, checked against the OpenEPCIS reference vectors. An event's identity is computed from what it says, never assigned by whoever stored it. The same event captured twice is the same event, so the causal chain survives replication, migration, and any particular database's death. Traceability's own standard supplies the one property distributed tracing always wanted: causation you can carry between stores.
Who, exactly.
The shared blank gets the most careful law in the model, and it is two fields, not one.
who is the attested observer — the human, agent, or embodied agent that performed the act — asserted by the caller and graded at the door. capturedBy is the warrantor — the account that stands behind the record. Never the same thing, never merged. A who is an address that dereferences — an id.org.ai identity, not a string in a log line.
Watch what happens when an OTLP span arrives. traceId maps identically; the timestamps carry over losslessly. The workload named by service.name enters as the who, in the third identity class beside Human and Agent — Code, deployed software that executes without deciding — at the attestation grade the record can honestly claim. capturedBy is the account standing behind the ingest — the warrantor of the key that presented the span, never the workload itself. What never happens is inference: no human is ever conjured out of a span. The schema says what it knows instead of guessing what it doesn't.
Every field on the span has a home — a dimension, a causation field, or a namespaced rider; nothing is dropped. And the one field OTel never had is the one EPCIS never had either.
Read the fixture.
This is not an analogy, so it should survive contact with a real file. In the public golden corpus there is a four-hop document — golden-corpus/valid-superset/sequence-worked-trace-four-hop.json, committed in the repository: valid EPCIS 2.0, the spine namespace declared alongside GS1's own context. Lot 7A-4412 is commissioned at 05:41, spine:who = id.org.ai/humans/line-lead-3. At 05:58 the goods are packed onto pallet urn:epc:id:sscc:0614141.0000005501 by pack-out-crew-1. At 06:04 the pallet is received at the DC dock by dc-west-dock-crew-4. At 06:12 the item is received at the store by store-crew-handheld-9. Four events, four attested performers. The dimension neither tradition could write is sitting in a public file, in the standard's own extension grammar, and the document still validates.
What the file demonstrates is the Who. The causation fields are the model's design, riding the same grammar — and the story they formalize is already legible in the file's own EPCs. Read it top to bottom and you are reading a waterfall: item into pallet, pallet to dock, item to shelf, spans named commissioning, packing, receiving, receiving. Project events like these as OTLP and any stock trace viewer can render them; the fields line up by construction, so nothing in the record has nowhere to go.
And the document is not dressed up to pass. What is categorically refused is the cheat: a span costumed as an ObjectEvent with an empty epcList, schema-valid and semantically a lie. An event either serializes as honest EPCIS or is never serialized as EPCIS at all. The engine enforcing that law answers on epcis.dev today — POST /translate, /validate, /hash, no key — and its conformance tests pass against GS1's normative artefacts, verified by the build that ships the site, digests on the pins page.
The objection.
"These are different things. Traces are sampled, torrential, disposable telemetry. Custody events are legal evidence. One table either drags evidence ceremony into the hot path or quietly degrades evidence to the standards of telemetry."
Every distinction in that objection is real, and each is a column with a law on it. The unification is of the grammar, never the policy. Split events into two classes — call them telemetry and record — and the laws write themselves. Telemetry may be sampled; events of record are never sampled. A dangling parent — head-sampled upstream, never arrived — is tolerated in telemetry and forbidden in record class. Retention and privacy split along the same line. An authentication event is always record-class: auth is evidence by nature. And a span's status never becomes a CBV disposition by resemblance — it crosses into CBV vocabulary only through an explicit registry.
The table both traditions already drew.
When either tradition gets serious about storage, it converges on the same physical shape: the wide event table. The ClickHouse OTel exporter is one wide table for traces, one for logs. GS1's pinned EPCIS schema models one event supertype with a type discriminator. Storage engineers and standards authors, solving different workloads, drew the same table without consulting each other.
Yet run a GitHub-wide code search for EPCIS alongside OpenTelemetry (searched 2026-07-31) and every hit is incidental: EPCIS vendors using OTel to watch their own services, plus our own repositories. Repository searches for the pairing return zero. Even the people who implement EPCIS for a living point OTel only at themselves; nobody in public bridges the two semantically. A bounded claim, not proof of absence: if the bridge exists, show us and we will link it. Two disciplines drew the same table and have not noticed each other.
epcis.dev is built on noticing. It and its sister properties run on the very spine they offer: their own API calls, scans, and captures are events in the same append-only record, through one ingestion path, and everything above that record — every trace view, dashboard, and EPCIS document — is a derived, disposable, conformant projection. That is the thesis in operational form: observability is a query on your traceability record, not a stack beside it. None of it asks for faith. The doors answer without a key, and the four-hop document sits in the public corpus for you to validate yourself.
Your pallets have been distributed traces all along. Your traces are custody chains missing a name. One table. Six dimensions. The projection is exact.
We answer in writing. We take at most five conversations a month, only when you ask for one, and only after you already have the written read.