# One run went bad. You withdrew all of them.

> The size of a withdrawal is set by what your record can tell apart — not by what actually went wrong. — Food CPG and QSR — whoever owns the recall desk.

You have run the drill. It is scoped at twenty-four hours, and somewhere around hour ten the first DC confirms receipt and the received-by field says DOCK-04. Hour eleven, the second DC confirms, and its received-by field is empty. Neither one is wrong. A dock door is not a person, and an empty box is what a system has when there was never a place to put the answer. Past that the co-manufacturer’s case ranges arrive as a PDF of a spreadsheet, the franchise stores are contractually somebody else’s data, and the rest of the exercise is phone calls looking for a person who can vouch for a handoff the record could not. The clock does not stop for any of that. The worked timeline is on this site, marked illustrative, hour by hour.

None of that is a program failure. The drill is on the calendar, the traceability lot code is assigned, the key data elements are mapped, and the people running it know which hop will break before it breaks. That is not a team that needs to try harder. It is what a correct program produces: a boundary, drawn precisely where the record stops resolving, by people who did everything right.

## What it costs you

Your record knows the lot, or the production day, or the shipment that left the dock. It does not know the case. So the boundary of the withdrawal gets drawn where the record stops resolving, and everything inside that boundary comes back — including all of it that was fine. The difference between the two boundaries is the whole bill: the product, the freight both ways, the disposal, the weeks of supply, and the conversation with the retailer afterward.

It is not a data-quality problem and it is not an integration problem. Both of those assume the information existed and something went wrong on the way to using it. More data does not fix it. Better data does not fix it. Fourteen more connectors do not fix it, and neither will the fifteenth. Every one of those systems is downstream of a barcode that names a kind, and a system cannot report a distinction its inputs never carried.

And the trace-back is worst exactly where you do not own the building. A co-manufacturer’s record says a legal entity received a pallet; a franchisee’s says the same. Both are true, both are useless the moment they are contested, and a company has no hands.

## Both records are conformant. Only one can answer.

The same receiving event, written twice. Once it names two hundred and forty units of one lot; once it names one case. Post both to the validator that checks against GS1’s own published EPCIS 2.0.1 schema — no key, no account, and nothing of ours in the answer.

The lot-grain event — a quantity of 7A-4412:

```
$ curl -sX POST https://epcis.dev/validate \
    -H 'content-type: application/json' -d @lot.json

  "valid": true,  "errors": []
  "schema": { "artefact": "epcis-json-schema.json",
              "version": "2.0.1",
              "sha256": "0f46ff69…210af" }
```

The unit-grain event — one case, and not the case behind it:

```
$ curl -sX POST https://epcis.dev/validate \
    -H 'content-type: application/json' -d @unit.json

  "valid": true,  "errors": []
```

The standard does not prefer one over the other, and no amount of software makes the first one into the second. The lot document is not a coarser record of the same subject — it is a record about a different subject, and there is no query that recovers the case from it. That choice was made at the print head, before any of this ran. — https://epcis.dev/

## What changes

visibility.cloud will record the handoff at the grain you withdraw at — the case, the pallet, the unit — and will put an attested observer on every event, kept distinct from capturedBy, the account that stands behind the capture. That two-grain record is not a sketch: the capture spine already writes both, taking the observer from the capture and stamping capturedBy server-side, and the tests that hold that line pass today. What remains is the door: the hosted capture spine answers at api.epcis.dev to a capture key, and issuing those keys is not open yet. When it is, the trace-back that ran for days across a co-manufacturer or a franchise boundary is a query, and the boundary of the withdrawal is drawn where the goods actually went.

FSMA 204 is the return, never the urgency. The enforcement floor moved to July 2028 and FDA is actively soliciting further flexibilities, so the rule’s own record is softening rather than hardening. Anyone selling you that date as a gun to your head is one search away from being caught. Use FSMA 204 for operational return and GS1’s Sunrise 2027 for timing, never the reverse.

What this is not. It is not a compliance product, and it will not move the FDA’s clock by a day. It cannot make a co-manufacturer capture something they do not capture — nothing can, short of your contract. What it can do is make the hop where their record stops visible before a drill finds it, and give them something to send instead of a letter to write.

## Before you take this to a meeting

1. The date you were quoted has probably moved. The enforcement floor is July 2028, and FDA is actively soliciting further flexibilities. If a vendor is still selling you January 2026, that is worth knowing about the vendor.
2. Nothing in the rule asks for unit-level identifiers. A traceability lot code is assigned at a lot, and going finer than that is a decision with a real cost at the print head. It is an operational choice, not a compliance one, and this page is arguing the operational case.
3. Validating a document is not filing anything. epcis.dev/validate checks a document against a published schema and returns a verdict. It submits nothing, to anyone, ever.
4. The withdrawal boundary is not ours to draw. It is set by your counsel and a regulator, to the last verified-good control point. A finer record changes where that point can be, and it does not change who decides.

## Fork the scan.

The retail lane will read the whole symbol and keep a twelfth of it. The other eleven twelfths are yours for the asking, and asking costs nobody a behavior change.

From the end of December 2027, under GS1’s Sunrise program, retail point of sale is expected to scan and process 2D barcodes as well as the linear ones. A 2D symbol on a consumer pack can carry the GTIN, the serial, the batch or lot, and the expiry date, in one scan, at the same counter, on the same hardware. The register needs the GTIN. It has no field for the rest and no reason to keep it.

So the fork is the whole idea, and it is deliberately unambitious: the GTIN goes where it already goes, and the serial, the lot and the expiry go to your record instead of to the floor. Nobody scans differently. Nothing new is bought for the lane. The date is already on somebody’s plan in your company, because the artwork has to change anyway.

## The other three bills

There is no single company message on this surface, by design — one defect, four costs.

- **Authenticity** (https://visibility.cloud/for/authenticity/) — A convincing copy carries the same digits as the original. Jewelry, watches and luxury — brand protection, and whoever answers the client.
- **Shrink** (https://visibility.cloud/for/shrink/) — Every unit was scanned, and the investigation still ends at “seen here, then not.” Apparel and general merchandise — loss prevention, and the fulfillment side that owns the dock it happens on.
- **The discarded scan** (https://visibility.cloud/for/the-discarded-scan/) — The lane reads the serial, the lot and the expiry, and keeps none of them. Retailers and brands on the Sunrise 2027 timeline.

The typed index of all four, with each read's evidence class: https://visibility.cloud/variants.json
