For the VP of store systems at a grocery retailer — the person Sunrise 2027 turns into the reader of a richer mark, with nowhere to put what it reads.
Here is the category error at the center of the 2D transition, stated once and then proven field by field: the transaction your lane writes and the event a traceability record needs are different documents about the same scan. The industry keeps conflating them — "our POS captures everything" — and the conflation survives because both records begin at the identical beep. They diverge at the first field.
The same scan, two records
A Sunrise-capable lane reads a 2D mark on that vanilla yogurt: GTIN, lot 4271, expiry June 30. Two records could describe what just happened. Your POS writes the first. The second is a conformant EPCIS 2.0 ObjectEvent — the GS1 event standard's answer to the same moment (illustrative figure, drawn from the tested event model behind this platform):
| The question | POS transaction line | EPCIS 2.0 ObjectEvent |
|---|---|---|
| What is this record about? | A sale: tender, tax, basket | An occurrence: something happened to identified items |
| What was scanned? | GTIN → price lookup; lot and expiry discarded at parse | epcList / quantity element carrying GTIN + lot — the instance, kept |
| When? | Transaction timestamp, store-local | eventTime + eventTimeZoneOffset — unambiguous instant |
| Where? | Store number, lane number | readPoint and bizLocation — GS1-identified places that join across parties |
| Why? | Implied: it sold | bizStep: retail_selling, disposition: retail_sold — CBV 2.0's controlled vocabulary, machine-comparable across every system that speaks it |
| Who? | Cashier ID, meaningful only inside your HR system | The standard has no performer field — EPCIS 2.0 §7.2.2 defines what, when, where, why, how, and party fields are organisation-grain. This platform's envelope adds the missing grain: an attested who (the observer) distinct from capturedBy (the warrantor account) — never collapsed |
| Joins upstream? | No — a transaction log references nothing outside the store | Yes — the same GTIN+lot appears in receiving events, DC events, supplier events; the trace is the join |
The left column is not deficient — it is excellent, at its job. Transaction logs were built to close tills, reconcile tender, and feed sales analytics, and forty years of retail run on them doing exactly that. The error is only ever the conflation: expecting the sale record to answer item questions it was never designed to hold. It discards the instance data at parse time, its locations and reasons are house conventions rather than shared vocabulary, and it joins to nothing outside your four walls.
The questions that arrive with 2D — and which record answers each
Sunrise makes your lanes read marks that can carry lot and expiry (whether a supplier encodes them is the brand's choice, never Sunrise's). The moment those marks exist in your stores, questions follow — and each one lands on exactly one of the two records:
- "Which lots of this SKU are on shelf right now?" — event record. The transaction log knows lots only by what already left.
- "Did any unit of the recalled lot sell, and when?" — event record, and this is the recall-scope question that turns "pull everything" into "pull lot 4271." A transaction log that discarded the lot at parse cannot answer it at any price.
- "Did we sell an expired unit?" — event record; the lane is the one moment the store provably touches every unit it sells.
- "What did lane 6 ring between 5 and 6 pm?" — transaction log, forever. Keep it. Nobody is proposing to replace it.
One record per purpose. The category error is funding a refresh that upgrades what the lane can read while keeping only the record that cannot hold what it read.
Both clocks land on you
You are the only seat in this industry that both clocks touch. Sunrise 2027 makes your lane the reader of the richer mark by end of December 2027. FSMA 204 makes your dock a receiving party — DSD and DC simultaneously — on the same event-shaped evidence. Same standard answers both: the receiving event at your back door and the selling event at your lane are the same EPCIS vocabulary at two read points, and a chain that stands up the record once serves both clocks with it. That is the deepest reason the record layer belongs in the refresh conversation rather than adjacent to it — the capital math is its own brief.
What to stand up next to the refresh
The record layer this platform provides is the destination the upgraded lane deserves: every capture validated against GS1's official EPCIS 2.0 schema before acceptance, each event carrying the attested-observer envelope — who and capturedBy, two grains, never collapsed — and every event's identity computed per CBV 2.0 §8.9, so two parties can agree an event is the same event without trusting each other's databases. It conforms to EPCIS 2.0 and CBV 2.0 — and, said plainly because we say it everywhere conformance comes up: no conformance attestation has ever been issued, and none is claimed. The stateless doors of the same engine are live today at epcis.dev — POST /translate, /validate and /hash, checkable by curl against sha256-pinned official GS1 artifacts — and capture workspaces are provisioned from the seat list, in order; every open gap between those two sentences is a named entry in the open P0 ledger, where we tell you the truth about it.
The read for your chain — both clocks, one refresh, and what the record layer costs next to the scanner line — starts at get started: your address first under the one-message promise, then questions that branch on your answers, ending in a written read that locks when it ends.