Event
| Source file | schemas/event.schema.json |
$id | urn:synapsecommand:cdm:3.0.0:event |
| CDM schema version | 3.0.0 |
| SHA-256 of source | 527f30670e991bb67df508137e130bba8a7bbf4d035ee5e9a0a8142fd94d7149 |
Anything that happens. The audit-bearing object: two timestamps and a source, always.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
event_id | string (uuid) | yes | |
event_type | EventType | yes | |
geometry | Point | LineString | Polygon | MultiPoint | MultiLineString | MultiPolygon | null | no | GeoJSON, WGS84, [lon, lat] order — e.g. a jamming footprint. Default null. |
integrity | Integrity | null | no | PQC signature block — designed, not yet populated. A DATA CONTAINER and nothing more: this package makes no signature and verifies none, no conformance check, harness column or evidence field reads it, and its presence on an object proves nothing about the object. A record carrying one is unverified until something outside this package verifies it. Default null. |
object_kind | "event" | no | |
observed_at | string | yes | When the SOURCE saw it. Never receipt time. (pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$) |
oes | OesMetadata | null | no | The SC-OES wire-semantic block. None = the producer made no SC-OES assertion, which is NOT the producer asserting defaults. Optional so that every object written before SC-OES existed stays structurally valid and every producer that knows nothing about SC-OES keeps emitting objects these models accept. Default null. |
payload | object | no | Event-specific fields. Validated against PAYLOAD_MODELS[event_type] when one is registered; free-form otherwise. Also the never-drop bag for events. |
quality | Quality | null | no | How good the SOURCE says this object is. None = the source said nothing about quality, which is not the same as saying it is poor. Default null. |
received_at | string | yes | When WE took delivery. Never source time. (pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$) |
related_entities | array<string (uuid)> | no | entity_id values this event concerns. Empty when the event concerns no specific entity (a feed-level status change). |
residual | Residual | null | no | Source information the CDM does not model, under the name of the format it came from (§28). None = nothing was left over, or — for the fourteen adapters shipped before this container existed — the leftovers are parked in attributes / payload under source_extras, which ARCHITECTURE.md §5 rules they keep through Part 1. Default null. |
schema_version | string | no | Semver of the CDM this object was written against. Default "3.0.0". (pattern ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$) |
severity | Severity | yes | |
source | SourceRef | yes | Which adapter produced this object. Required on every kind. |
source_ids | array<SourceId> | yes | Every external identifier this object is known by. At least one, on EVERY kind — see the class docstring. (min items 1) |
status | OperationalStatus | null | no | The source's own operational state for this object, namespaced. None = the source stated none. Default null. |
additionalProperties: falseUnknown keys are rejected. That is safe only because the CDM pairs strictness
with a declared escape hatch — Entity.attributes and Event.payload accept
anything — so an adapter never has to choose between dropping a field and failing
validation.
Referenced definitions
Every $ref on this page resolves to one of these, inlined here so the page is a
complete reference and not a starting point for chasing pointers.
EntityRelation
What ROLE an entity already related to this event plays in it.
Event.related_entities remains the single answer to "which entities does this event
concern"; this adds the role. The membership rule that keeps the two lists agreeing lives on
Event (models.py), because it is the only place both lists are visible.
| Field | Type | Required | Description |
|---|---|---|---|
entity_id | string (uuid) | yes | Must also appear in the event's related_entities — see Event._oes_relations. |
predicate | string | yes | An absolute semantic identifier: a governed ontology term or a valid third-party one. A bare word or a local name is refused. (min length 1) |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
EventClass
What KIND of assertion an event is — the coarsest semantic distinction SC-OES makes.
Eight members, and a consumer that understands no event type at all can still act on this
one. It is asserted by the producer and never inferred: 02-event-classes.md forbids
deriving it from type_id, from the payload or from the producer's identity, because the
whole value of the field is that somebody took responsibility for the claim.
Closed vocabulary — a value outside this list is invalid, and UNKNOWN is a
member rather than a null wherever the enum has one.
| Value |
|---|
OBSERVATION |
STATE_CHANGE |
CONSTRAINT |
ASSESSMENT |
IMPACT |
RECOMMENDATION |
DECISION |
ACTION |
EventRelation
One typed reference from this event to another event.
Both halves are required: a predicate with no target says nothing, and a target with no
predicate is the association CORRELATES_WITH exists to spell honestly.
| Field | Type | Required | Description |
|---|---|---|---|
event_id | string (uuid) | yes | The event this relation points at. It need not be locally available — rejecting an event because its antecedent has not arrived would make delivery order part of the contract. |
predicate | EventRelationPredicate | yes | One of the seven governed predicates. An unrecognised predicate is refused rather than read as a nearby one. |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
EventRelationPredicate
The seven governed relationship predicates. Direction is part of the meaning.
Five are carried by the LATER event and point at the earlier one; CONTRADICTS and
CORRELATES_WITH are conceptually symmetric. An unrecognised predicate is a failure and
must not be interpreted as a nearby one — 08-event-relationships.md is explicit, because
the nearby predicate is always a stronger claim than the one the producer could support.
Closed vocabulary — a value outside this list is invalid, and UNKNOWN is a
member rather than a null wherever the enum has one.
| Value |
|---|
DERIVED_FROM |
UPDATES |
SUPERSEDES |
RESOLVES |
RETRACTS |
CONTRADICTS |
CORRELATES_WITH |
EventType
Closed vocabulary — a value outside this list is invalid, and UNKNOWN is a
member rather than a null wherever the enum has one.
| Value |
|---|
DETECTION |
GNSS_INTERFERENCE |
TRACK_UPDATE |
ALERT |
STATUS_CHANGE |
PLAN_INJECT |
SIM_RESULT |
EvidenceKind
What an evidence reference points at: another assertion, a source record, or the outside.
Closed vocabulary — a value outside this list is invalid, and UNKNOWN is a
member rather than a null wherever the enum has one.
| Value |
|---|
EVENT |
SOURCE_RECORD |
EXTERNAL_ARTIFACT |
EvidenceRef
What stands behind an assertion. Descriptive: nothing here is fetched or verified.
One model with a declared kind rather than three, because evidence[] is a heterogeneous
list and a discriminated union in the wire form would make a non-Python consumer negotiate a
discriminator to read a citation. The per-kind field rules are a validator instead, so the
published schema stays readable and the refusal names the kind and the field.
| Field | Type | Required | Description |
|---|---|---|---|
description | string | null | no | Default null. (min length 1) |
event_id | string (uuid) | null | no | EVENT only. The cited event need not resolve locally, and a consumer that cannot find it must not reject the citing event for that reason. Default null. |
hash | string | null | no | DESCRIPTIVE METADATA ONLY. Not an integrity guarantee, not a signature and not evidence of authenticity; no conformance dimension asserts anything about its value. SC-OES v0.1.0 implements no signing and no verification. Default null. (min length 1) |
kind | EvidenceKind | yes | Which of the three kinds of reference this is. |
media_type | string | null | no | Default null. (min length 1) |
source_id | SourceId | null | no | SOURCE_RECORD only. The CDM's own source-identifier representation, reused rather than re-invented — never the pair flattened into one opaque string. Default null. |
uri | string | null | no | EXTERNAL_ARTIFACT only. Never retrieved, at validation time or any other. Default null. (min length 1) |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
Integrity
DESIGNED, NOT IMPLEMENTED — the field the PQC signature will occupy.
No crypto happens in this package (tests/test_cdm_boundary.py asserts the package imports no crypto module). The field exists from day one so that turning signing on is a value change rather than a schema change: a schema change would be a MAJOR bump rippling through every store and every consumer, and would arrive exactly when the signing work is already late.
algorithm is a free string rather than an enum, naming what the platform's ledger
already uses — ML-DSA-87 for entry signatures, SLH-DSA for checkpoints. Free, because the
algorithm that replaces those is not knowable now, and an enum would make the migration a
MAJOR bump for a value nobody reasons over programmatically.
All three fields or none. A block holding a signature with no algorithm is unverifiable, and an unverifiable signature that LOOKS present is worse than an absent one: it reads as assurance to everything downstream that does not check.
| Field | Type | Required | Description |
|---|---|---|---|
algorithm | string | yes | e.g. ML-DSA-87, SLH-DSA-SHAKE-256s. (min length 1) |
chain_hash | string | yes | Hash binding this object to the chain. (min length 1) |
signature | string | yes | (min length 1) |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
LifecycleStatus
The lifecycle state of the represented CONDITION — not of the message, not of a workflow.
Optional, and absence is the ordinary case: most sensor sources report occurrences rather
than managed conditions. 05-lifecycle.md forbids defaulting it to ACTIVE or to anything
else, and forbids deriving it from the effective interval — an event whose effective_to
has passed is not thereby EXPIRED, because the interval is what the producer said about
the world and this is what the producer says about the assertion's own standing.
Closed vocabulary — a value outside this list is invalid, and UNKNOWN is a
member rather than a null wherever the enum has one.
| Value |
|---|
PLANNED |
ACTIVE |
RESOLVED |
EXPIRED |
CANCELLED |
RETRACTED |
SUPERSEDED |
LineString
| Field | Type | Required | Description |
|---|---|---|---|
coordinates | array<array<number>> | yes | (min items 2) |
type | "LineString" | no |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
MultiLineString
Several lines that are one thing — a route with a gap, a corridor in two legs.
| Field | Type | Required | Description |
|---|---|---|---|
coordinates | array<array<array<number>>> | yes | (min items 1) |
type | "MultiLineString" | no |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
MultiPoint
Several points that are ONE thing — a scatter of detections from one report.
Not a list of Point objects, because a list of geometries is a list of objects and this is
one object with a discontinuous location. The difference is visible the moment a consumer
counts contacts.
| Field | Type | Required | Description |
|---|---|---|---|
coordinates | array<array<number>> | yes | (min items 1) |
type | "MultiPoint" | no |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
MultiPolygon
Several polygons that are one thing — an airspace in disjoint lateral parts.
The ring rules are Polygon's and are enforced per part, for the reason they are enforced
there: a ring that arrives open is a source or adapter defect, and closing it invents an edge
the source never stated.
| Field | Type | Required | Description |
|---|---|---|---|
coordinates | array<array<array<array<number>>>> | yes | (min items 1) |
type | "MultiPolygon" | no |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
OesMetadata
The wire-semantic block. §52's thirteen fields, and maturity is not among them.
Maturity is a property of a governed semantic DEFINITION, not of an occurrence: it lives in
the event registry, in ontology-term metadata and in profile documents. Putting it on the
wire would duplicate registry governance metadata on every message and give it a second
authority, which would then go stale (12-versioning.md).
Three states are distinguished throughout and are not collapsed (01-core.md): a field
present with a value is ASSERTED, an absent field or a null confidence is UNKNOWN, and a
value whose meaning is "none" is ASSERTED-ABSENT. An unknown value is never represented as a
zero, an empty string or a default enumeration member — which is why every optional field
here defaults to None and none of the enumerations carries an UNKNOWN member the way the
CDM's own vocabularies do (enums.py:3). The CDM's rule is right for a closed structural
classification a map has to render; SC-OES's optional fields are assertions a producer either
made or did not, and "not asserted" is exactly what absence already says.
| Field | Type | Required | Description |
|---|---|---|---|
confidence | number | null | no | 0..1 on the producer's own scale. None = unknown, never 0.0, and this specification defines no universal confidence algorithm. Default null. (≥ 0; ≤ 1) |
effective_from | string | null | no | When the represented condition begins. NEVER defaulted to observed_at, received_at or the time of validation. Default null. (pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$) |
effective_to | string | null | no | When it ceases. None = the producer did not state an end; it does not mean the condition is permanent and it does not mean it is still in force. Default null. (pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$) |
entity_relations | array<EntityRelation> | no | Roles for entities already in related_entities. |
event_class | EventClass | yes | Asserted by the producer. Never inferred from type_id or from the payload. |
event_relations | array<EventRelation> | no | Empty or absent asserts nothing. No universal cap. |
evidence | array<EvidenceRef> | no | What stands behind the assertion. No universal cap. |
extensions | object | no | The one declared open bag. Keys are x.<namespace>.<name>; sc.* is reserved and rejected in v0.1; values are preserved and never interpreted. |
security | SecurityMarking | null | no | Transported markings. Absence is never a conformance failure and is never proof of unclassified status. Default null. |
spec_version | string | yes | The SC-OES version whose semantics the producer is claiming. Semver, on the same rule CDMBase applies to schema_version; NOT derived from SCHEMA_VERSION or PACKAGE_VERSION, and not required to equal this package's SC_OES_VERSION — a producer at a later spec version stays transportable. |
status | LifecycleStatus | null | no | None = the source says nothing about lifecycle. Default null. |
type_id | string | yes | The governed or third-party semantic type identifier, under one of the two frozen grammars. Syntax here; recognition is dimension C's. |
verification | Verification | null | no | None = nothing is asserted about corroboration. Default null. |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
OperationalStatus
What state the source says a thing is in, in the SOURCE's vocabulary, namespaced.
THERE IS NO ENUM HERE AND THERE WILL NOT BE ONE. "SERVICEABLE", "DEGRADED", "MISSION CAPABLE",
"RED" and "U/S" come from five different domains and mean five different things, and a closed
CDM vocabulary would have to map each of them onto a member — which is a judgement about
somebody else's operational language, made inside a translator, invisible in the output, and
exactly what Rule 6 forbids. namespace says whose vocabulary state belongs to, so a
consumer meeting an unfamiliar value can find out what it means instead of guessing; a
consumer MUST NOT compare state across namespaces.
since is when the state began, not when it was reported. Absent means the source did not
say — never the receipt time, which would make every restart look like a state change.
| Field | Type | Required | Description |
|---|---|---|---|
attributes | object | no | Status-specific source fields with no canonical home. |
namespace | string | yes | Whose vocabulary state is in — normally the source format's name. Required: an unnamespaced status is a word with no owner. (min length 1) |
since | string | null | no | When the state began. None = the source did not say. Default null. (pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$) |
state | string | yes | The source's own token, verbatim and untranslated. (min length 1) |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
Point
| Field | Type | Required | Description |
|---|---|---|---|
coordinates | array<number> | yes | |
type | "Point" | no |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
Polygon
| Field | Type | Required | Description |
|---|---|---|---|
coordinates | array<array<array<number>>> | yes | (min items 1) |
type | "Polygon" | no |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
Quality
How good the source says its own data is. Four ways of saying it, none derived.
confidence is 0..1 and comparable across sources; source_quality is the source's OWN
grade, a free string, because ASTERIX's track quality, AIS's position accuracy flag and a
NATO track's evaluation code are three ordinal scales with no defined mapping between them
and inventing one would be a fusion decision made inside a translator.
uncertainty is a NAMED dict — {"along_track_m": 40.0, "cross_track_m": 12.0} — rather
than a single number, because an error ellipse is not a radius and flattening it loses the
orientation that made it worth sending. Names are the source's; the CDM does not fix a
vocabulary here, and the unit belongs in the key exactly as signal_strength_dbm carries
its own unit in its name.
| Field | Type | Required | Description |
|---|---|---|---|
accuracy_m | number | null | no | Metres, 1-sigma. None = unknown, never 0. Default null. (≥ 0) |
confidence | number | null | no | 0..1. None = unknown; 0 means certainty-that-not, which is a claim. Default null. (≥ 0; ≤ 1) |
source_quality | string | null | no | The source's own grade, verbatim. None = the source stated none. Default null. (min length 1) |
uncertainty | object<string, number> | no | Named components, e.g. along_track_m / cross_track_m. The unit is in the key. Empty = the source named none. |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
Residual
Source information the CDM does not model, kept under the name of the format it came from.
§28's container, and its two rules are load-bearing in opposite directions:
- It MUST identify its origin.
namespaceis the source format's own name — the same string as the adapter'smetadata.format.name— so a reader meeting an unfamiliar key insidedatacan find out which standard's vocabulary it belongs to. An unnamespaced bag of leftovers is the free-form dict this model exists to replace. - It MUST NOT be treated as semantically trusted merely because it survived translation. A residual says "the source said this and the CDM has no home for it". It is a fact about the source RECORD, not an assertion about the world. A consumer MUST NOT promote a residual value into a canonical field, and a later adapter MUST NOT read another adapter's residual as an input — ARCHITECTURE.md §5 states both as normative text.
data preserves the source's own STRUCTURE, which is why it is a dict and not a list of
dotted paths: lossless.residual() learned that the hard way when a two-element list came
back as two keys named affected_constellations[0] and [1], satisfying the never-drop rule
in the letter while destroying the reader's ability to see a list.
THE FOURTEEN ADAPTERS IN THIS REPOSITORY DO NOT USE THIS YET, deliberately. ARCHITECTURE.md
§5 rules that they keep their attributes / payload parking under source_extras through
the whole of Part 1 and declare residual: legacy in their manifests, because the
information is already preserved and paying for a placement change with every golden file and
every downstream consumer buys nothing a reader can use (§29: no breaking change for
stylistic cleanliness). Every Part 2 adapter declares residual: structured and uses this.
| Field | Type | Required | Description |
|---|---|---|---|
data | object | no | The unconsumed source structure, preserved as the source shaped it. |
namespace | string | yes | The source format's name — normally metadata.format.name. Required. (min length 1) |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
SecurityMarking
Handling markings, TRANSPORTED. SC-OES does not interpret or enforce them.
Three propositions 10-security-markings.md states because each is routinely assumed away:
presence of a marking is not authorization, absence is not proof of unclassified status, and
transport is not enforcement. SC-OES is not a cross-domain guard and must not be represented
as one; nothing in this package could enforce a marking, and a deployment that enforces one
does so with its own accredited mechanism, which knows the scheme and is answerable for the
decision.
Every value here is interpreted ONLY relative to scheme, which is why scheme is the one
required field: two markings from different schemes are not comparable, and a classification
with no scheme beside it is a string somebody will compare anyway.
| Field | Type | Required | Description |
|---|---|---|---|
caveats | array<string> | no | As that scheme spells them. |
classification | string | null | no | As that scheme spells it. Transported verbatim. Default null. (min length 1) |
marking_extras | object<string, string> | no | Scheme-specific values with no generic counterpart. Strings, because dimension B checks that marking values are strings and because the block has exactly one generic open bag and it is oes.extensions. |
originator | string | null | no | As that scheme identifies them. Default null. (min length 1) |
releasability | array<string> | no | As that scheme spells them. Never reordered. |
scheme | string | yes | Which marking system these values belong to. Required. (min length 1) |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
Severity
Closed vocabulary — a value outside this list is invalid, and UNKNOWN is a
member rather than a null wherever the enum has one.
| Value |
|---|
INFO |
ADVISORY |
WARNING |
CRITICAL |
SourceHash
A digest of the source record, as the ADAPTER computed it. Carried, never computed here.
Rule 5 asks for "source hash where appropriate", and the appropriateness is the adapter's judgement: a hash of a 3-byte AIS sentence identifies nothing an external id does not, while a hash of a 4 MB NITF segment is how an auditor proves the bytes on the wire were the bytes described. So it is optional, and its absence means the adapter did not compute one.
NO HASHING HAPPENS IN THIS PACKAGE. tests/test_cdm_boundary.py asserts that no module under
synapse_cdm/ imports hashlib or any crypto library, and this model does not change that:
it is a container for a value produced outside the contract layer, exactly as Integrity is
a container for a signature this package does not make. algorithm is therefore required and
free-form — a digest with no algorithm cannot be reproduced by anyone, and an enum would make
the day SHA-3 arrives a MAJOR bump for a string nobody branches on.
| Field | Type | Required | Description |
|---|---|---|---|
algorithm | string | yes | e.g. sha256. Named by the producer. (min length 1) |
value | string | yes | The digest, in the producer's own encoding. (min length 1) |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
SourceId
One external identifier for an object — the provenance mapping.
A list of these, not one, because the same object arrives from several systems: the same vessel is an MMSI to AIS, a track number to STANAG 4676 and a UID to TAK. Fusion joins them later; the adapter's job is to record which name its own system used, and never to overwrite another system's entry.
| Field | Type | Required | Description |
|---|---|---|---|
external_id | string | yes | That system's own identifier. (min length 1) |
system | string | yes | The external system, e.g. PNTMAP, TAK. (min length 1) |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
SourceRef
Which adapter produced this object, from which system, and whether it is real.
synthetic is required and has no default. Every fixture in this repository is synthetic
and every scenario package is too (TR-12), and the platform keeps the synthetic and live
layers apart over one interface — so an object that does not say which layer it belongs to
cannot be filed. A default of false would silently promote exercise data to operational
data, which is the dangerous direction; a default of true would silently demote live
data and hide it from an operator. There is no safe default, so there is no default.
| Field | Type | Required | Description |
|---|---|---|---|
adapter | string | yes | Adapter name, e.g. pntmap. (min length 1) |
adapter_version | string | yes | Adapter semver: MAJOR.MINOR.PATCH, no leading zeroes, nothing else. (pattern ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$; min length 1) |
format_name | string | null | no | The source STANDARD's name, e.g. 'ASTERIX'. Filled from the adapter's own declared metadata.format; None only for an adapter that declares none. Default null. |
format_version | string | null | no | The edition of that standard, e.g. 'Cat 062 ed 1.18'. None = no document in this tree states which edition the adapter targets — a reading, never a gap filled in. Default null. |
observed_at | string | null | no | The instant the SOURCE RECORD states for itself, when it states one and no canonical field already carries it. Event.observed_at stays the event's own time; this is the record's. Default null. (pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$) |
original_id | string | null | no | The source record's OWN identifier, as a first-class provenance field. Distinct from source_ids, which is the identity of the THING; this is the identity of the RECORD that described it. Default null. |
record_index | integer | null | no | Which record of a multi-record payload this object came from, 0-based. None = the payload was not a sequence, or the adapter does not track it. Never -1 and never 0-as-unknown: 0 is the first record. Default null. (≥ 0) |
source_hash | SourceHash | null | no | Digest of the source record, computed by the adapter. Default null. |
synthetic | boolean | yes | true for anything not from a real source (TR-12). |
system | string | yes | The external system this came from. (min length 1) |
transformations | array<string> | no | Rule 5's transformation chain: the TRANSFORMS reasons this adapter applied, in the order it applied them. Empty = nothing was transformed, which is a claim the lossless check can contradict. |
additionalProperties: false — unknown keys are rejected. Source-specific fields
belong in the declared extension bags (Entity.attributes, Event.payload).
Verification
How corroborated the assertion is. NOT confidence — 06-verification-and-confidence.md.
They vary independently and every combination is meaningful: a single high-grade sensor can
be highly confident and entirely uncorroborated, and three weak sources can corroborate each
other and leave the producer unsure. Absence means nothing is asserted about corroboration;
UNVERIFIED is the positive claim that the question was asked and the answer was "no", which
is a different and more informative fact. DISPUTED records that a disagreement exists and
is not a verdict on it.
Closed vocabulary — a value outside this list is invalid, and UNKNOWN is a
member rather than a null wherever the enum has one.
| Value |
|---|
UNVERIFIED |
CORROBORATED |
VALIDATED |
DISPUTED |