The event
One job: read one event and know what every field is for. An EPCIS 2.0 event records one observed moment. The standard defines five dimensions on it — what, when, where, why, how. The event here has six: who — the attested observer — carried as spine:who under a declared JSON-LD context, so the document stays valid against the pinned official schema.
One fixture, annotated by dimension
This event ships in the package at golden-corpus/valid-superset/object-event-attested-observer.json:
{
"type": "ObjectEvent",
"eventID": "urn:uuid:8a1b2c3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d",
"eventTime": "2026-07-19T11:45:00.000Z",
"eventTimeZoneOffset": "+02:00",
"epcList": ["urn:epc:id:sgtin:0614141.107346.2021"],
"action": "OBSERVE",
"bizStep": "receiving",
"disposition": "in_progress",
"readPoint": { "id": "urn:epc:id:sgln:0614141.00999.0" },
"spine:who": "https://id.org.ai/agents/dock-scanner-7",
"spine:activity": "https://event-spine.internal/activities/inbound-receiving/run/42"
}
| dimension | fields | in this event |
|---|---|---|
| What | epcList, action | one serialized item, observed (OBSERVE: seen, not created or removed) |
| When | eventTime, eventTimeZoneOffset | when it happened, in local wall-clock terms; recordTime — when the door heard — is stamped at capture, never caller-supplied |
| Where | readPoint, bizLocation | the point that saw it; the business location it speaks for |
| Why | bizStep, disposition, bizTransactionList, sourceList, destinationList | receiving, in progress — the CBV's vocabulary, not free text |
| How | sensorElementList | absent here; present when an instrument observed |
| Who | spine:who | the attested observer — a human, an agent, or an embodied agent; the sixth dimension this spine adds |
The standard's own party fields are organisation-grain — GLNs and PGLNs name legal entities, and no standard field names the performer. spine:who carries the performer without forking the schema; the next page, who vs capturedBy, states the two grains exactly.
The event supertype, and the five types
Every field above except epcList and action belongs to the event supertype — the shape all five event types share. The types differ only in their What:
| type | its What |
|---|---|
| ObjectEvent | objects observed, added or removed |
| AggregationEvent | a parent (the pallet) and its children (the cases) — physical nesting, action ADD/OBSERVE/DELETE |
| TransactionEvent | objects declared against business transactions |
| TransformationEvent | inputs consumed, outputs produced — genealogy |
| AssociationEvent | an assembly relation (a sensor bolted to a reusable asset) |
The diff, by dimension
The sixth dimension is exactly what the conformant projection removes — executed 2026-07-31 against the published package:
$ node --input-type=module -e '
import { readFileSync, writeFileSync } from "node:fs";
import { project } from "epcis.dev";
const doc = JSON.parse(readFileSync(
"node_modules/epcis.dev/golden-corpus/valid-superset/object-event-attested-observer.json",
"utf8"));
const ev = doc.epcisBody.eventList[0];
writeFileSync("event.json", JSON.stringify(ev, null, 2) + "\n");
writeFileSync("event.projected.json", JSON.stringify(project(ev), null, 2) + "\n");'
$ diff event.json event.projected.json
14,16c14
< },
< "spine:who": "https://id.org.ai/agents/dock-scanner-7",
< "spine:activity": "https://event-spine.internal/activities/inbound-receiving/run/42"
---
> }
Five dimensions survive projection untouched; the sixth lifts off cleanly. That round-trip discipline is the whole envelope contract — the projection states it, and proves the projected event validates against the pinned official schema.
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.