Open specification questions¶
Where the ONE Record specification is ambiguous or inconsistent, this page records the question, where it appears, what NE:ONE does, and what this package chose. Entries are added as they are met; none is removed, only resolved.
| # | Question | Where | NE:ONE | Our choice |
|---|---|---|---|---|
| 1 | PATCH /logistics-objects/{id} success status: the 2.2 status table says 201 Created, its examples show 204 No Content. |
API 2.2 Update a Logistics Object; fixed to 201 in 2.3 | 201 | 201 with Location and Type |
| 2 | Denied access to a logistics object: 403 Forbidden per the access-control page, but 403 confirms the object exists. | Access control, Get a Logistics Object | 403 | 403 by default; an AccessPolicy may answer hide, which yields 404. Filed as IATA-Cargo/ONE-Record#457 |
| 3 | Embedded-object identifiers: the spec recommends internal:<uuid5> but leaves the scheme to the implementor. |
Implementation guidelines, blank nodes | neone:<n> |
internal:<uuid5>; the RDF comparer treats both prefixes as blank nodes. IATA-Cargo/ONE-Record#444 confirms embedded nodes must carry an @id. An id a client chose for an embedded node (https:, urn:, neone:) is replaced by the server-minted one when the object is stored; the client learns it from the next read |
| 4 | Changing embedded objects: new embedded objects are blank nodes in operations, existing ones are addressed by embedded id. | Update a Logistics Object examples C2–C4 | Supported | Implemented as specified; earlier Lambda Twelve code refused such changes. worked through in IATA-Cargo/ONE-Record#355 (example C4 now uses the internal id) |
| 5 | Numeric literal forms: 20.0, "20.0"^^xsd:double and 2.0E1 are the same RDF value with different lexical forms. |
JSON-LD/RDF | Stores lexical form as received | Comparison normalises by datatype; storage keeps the lexical form as received |
| 6 | ?at= and audit-trail timestamps use YYYYMMDDThhmmssZ while bodies use RFC 3339. |
Retrieve a historical Logistics Object | Basic ISO format | Accept both forms on input; emit the spec's basic format in links |
| 7 | The audit-trail example uses api:REQUEST_STATUS_ACCEPTED, which does not exist in the ontology. |
Get Audit Trail example D1 | api:REQUEST_ACCEPTED |
Ontology names (api:REQUEST_ACCEPTED) |
| 8 | hasSupportedOntology must be unversioned IRIs per the guidelines, but the server-information example lists versioned ones. |
Server information example A1 vs Versioning | Versioned | Unversioned in hasSupportedOntology, versioned in hasSupportedOntologyVersion. open as IATA-Cargo/ONE-Record#403; IATA leans towards dropping the split and keeping versioned IRIs in hasSupportedOntology. Our comment states what we emit and asks for a deprecation rather than a removal |
| 9 | Access delegation isRequestedFor: a list in 2.2, exactly one organisation in 2.3; yet the 2.3 example still writes a one-element list. |
Access delegations, example | List | Read as list or single value at either version; written as a list, as both editions' examples do |
| 10 | Content-Type version parameter: the spec requires echoing the negotiated version; NE:ONE ignores the parameter and answers ;charset=UTF-8. |
Versioning | Ignores | Echo the negotiated version; accept partners that do not |
| 11 | Data-model mapping questions for forwarders: unit IRIs (code-lists/MeasurementUnitCode#KGM vs UN/CEFACT), currency IRIs on the open CurrencyCode list, countries and airports as CodeListElement, party placement (shipment vs waybill), booking reference (shippingRefNo vs Booking), pieces vs piece groups. |
Data model 3.2/3.3 | n/a | Left to the mapping layer in wrappers; the SDK supports every form |
| 12 | IATA's release tags (2025-07, 2026-07) carry release-candidate ontologies (3.2-rc2, 3.3.0 RC1); the <edition>-standard folders were corrected on master after tagging. |
Repository tags vs master | Builds from its own copy | Ontologies pinned to master commit ad5f40d5… (versionInfo 3.2 / 3.3.0); specification text and examples pinned to the tags. Filed as IATA-Cargo/ONE-Record#458 |
| 13 | Several published example documents are defective: AuditTrail*.json (2025-07) are not JSON (placeholder text), AuditTrail*.json (2026-07) carry a _comment key, Piece_with_id*.json and Shipment_with_Piece.embedded.json have a leading space in @id, ChangeRequest_with_error.json (2025-07) writes api#errors for api:hasError, Subscriptions_example2.json types the object with a bare Subscription and no @vocab, VerificationRequest.json uses xsd:anyURI without declaring xsd. A general JSON-LD processor silently drops most of these; this package rejects them. |
Documentation_website/docs/API-Security/examples/ at both tags |
n/a | Listed as known defects in tests/Unit/JsonLd/SpecExamplesTest.php so an upstream fix is noticed; every other example round-trips. Worth reporting to IATA.. the AuditTrail and ChangeRequest examples were reported as IATA-Cargo/ONE-Record#423 (one fixed, the two placeholders still open) |
| 14 | What api:hasRevision on a Change means: the ontology says "starting with 0 for changing the initial revision", the examples carry the current revision of the object. |
API ontology api:hasRevision; Update a Logistics Object examples C1–C5 |
Requires it to equal the object's current revision; the result is revision + 1 | Same as NE:ONE. IATA-Cargo/ONE-Record#325 settled that objects start at revision 1, which supports the examples' reading |
| 15 | Adding a value that is already present, or deleting one that is absent, is not specified. | Update a Logistics Object | Rejects the change | Rejected with code 422 on the ChangeRequest, so a stale diff cannot be half-applied silently |
| 16 | Who may PATCH /logistics-objects/{id}: the endpoint table lists no permission, the permission model names PATCH_LOGISTICS_OBJECT. |
Update a Logistics Object vs Access control | Requires the permission | The permission is required; a change request from an unknown party would otherwise be a free write queue |
| 17 | GET /subscriptions?topicType&topic answers one api:Subscription; what if the host has several interests (with and without the body, say)? |
Get Subscription information as Publisher | One | One offer is answered as an api:Subscription; none or several as an api:Collection of subscriptions |
| 18 | The response to an illegal action-request transition: 2.3 specifies 422 for a revocation that is not possible; 2.2 says nothing, and the same question arises for PATCH ?status= on a final request. |
Action requests | 400 | 422 at 2.3.0, 400 at 2.2.0, for every impossible transition. IATA-Cargo/ONE-Record#373 proposes 422 for DELETE in a non-revocable state, matching this choice |
| 19 | Visibility of action requests: the spec says the requestor and the holder may read one; nothing about the delegate of an access delegation or the subscriber of a subscription set up by the holder. | Action requests | Requestor and holder | Parties a request is about may read it too; anyone else is answered 404 so existence is not leaked |
| 20 | api:hasChangedProperty in an update notification when the change edited an embedded node (a cargo:Value inside grossWeight). |
Notifications | Operation predicates | The object's own property the embedded node hangs off (cargo:grossWeight), so a subscriber can act on it. Filed as IATA-Cargo/ONE-Record#453 |
| 21 | NE:ONE lists every superclass in @type (a Piece is also PhysicalLogisticsObject and LogisticsObject); the spec's examples declare the one class. |
Logistics objects examples; NE:ONE changelog #248 | Adds superclasses | Declared classes are kept as given; comparisons use the most specific classes; ChangeBuilder never emits type operations, so a diff against a NE:ONE object does not try to delete inferred types. resolved by IATA-Cargo/ONE-Record#331 (approved 2026-06-08): @type may list the superclasses, the Type header carries only the most specific class |
| 22 | Which properties a server sets on a received logistics event: NE:ONE writes cargo:creationDate, cargo:eventFor and cargo:recordingOrganization itself. |
Logistics events | Sets all three | eventFor is implied by the path and written on read; creationDate is kept as posted (the server's receipt time is created on the model); recordingOrganization is the poster's business, not the server's |
| 23 | Whether PATCH /action-requests/{id}?status= takes effect within the request. NE:ONE answers 204 and applies the decision on its evaluation timer, so a GET right after may still say pending. |
Action requests | Asynchronous | Applied within the request; clients of other servers should poll, which the interop suite does |
| 24 | Response bodies as flattened JSON-LD: NE:ONE answers with a top-level @graph whenever an object has embedded nodes, and @vocab for the cargo namespace. The spec's examples are nested. |
JSON-LD examples; NE:ONE jsonld.mode |
Flattened | Nested bodies written; a top-level @graph accepted on read and rooted at the object asked for |
| 25 | Does an accepted subscription with sendLogisticsObjectBody keep authorising disclosure of the body after the subscriber's read permission is revoked? The access-control and subscription sections each define their own grant and say nothing about the interaction. |
Access Control, Subscriptions | Sends the body while the subscription is accepted | Settled. IATA (2026-10-05): the notification is subject to the access policy and the body is shared only with a recipient that has access to the object; a clarifying sentence will be added. Our behaviour already matches: the access policy is consulted per recipient at fan-out time; without read permission the notification carries the URI only, under a hiding policy nothing is sent. A host that wants push authorisation independent of read access must say so in its policy. Filed as IATA-Cargo/ONE-Record#454 |
| 26 | Does api:isTriggeredBy on a notification name the event's cause (the ChangeRequest) or the subscription the recipient can revoke (the SubscriptionRequest)? The unsubscribe text wants a revocable locator; the model says ActionRequest. |
Notifications, Subscriptions: Unsubscribe | ChangeRequest for updates | Open. Interim: updates name the change request, creations and events name the subscription request; a subscriber may not be able to read the change request it is pointed at (question 19). raised from the other side in IATA-Cargo/ONE-Record#401, which also wants isTriggeredBy to be the revocable locator. Our comment asks whether isTriggeredBy is the cause or the subscription |
| 27 | Which JSON-LD representations must every ONE Record implementation accept: only the nested shape of the examples, flattened @graph (NE:ONE), expanded arrays, @set, scoped contexts? No normative profile exists. |
JSON-LD examples; JSON-LD 1.1 | Flattened | Open. This package reads nested documents and a top-level @graph, writes nested, and refuses the rest with a precise error (subset). Filed as IATA-Cargo/ONE-Record#451. IATA's answer (2026-10-05): JSON-LD 1.1 at the specification level, while every implementation they have seen uses the two shapes we accept, nested compacted and flattened @graph; a written profile was suggested again; IATA's current reading is full JSON-LD 1.1 and the question goes to the working group. We keep the documented subset and refuse other serialisations with an explicit error until there is a ruling |
| 28 | What identifies a notification across retries, and what must a receiver deduplicate on? The model has no notification id and the delivery text no retry rule. | Notifications | None | Open. Interim: an Idempotency-Key header carrying the sender's outbox id; receivers see it on NotificationReceived. Filed as IATA-Cargo/ONE-Record#452. IATA's answer (2026-10-05): the receiver stores the notification under its own id and duplicates are considered harmless; after the lost-response case was laid out, the proposed rule (one delivery identifier for every attempt of the same notification) was put on IATA's backlog for the working group |
| 29 | How are language-tagged strings and non-XSD datatypes represented in an api:Operation? api:hasDatatype names one IRI and api:hasValue one string; there is no place for a language tag. |
API ontology OperationObject |
Writes xsd:string |
Open. This package refuses to build a change for a language-tagged literal rather than drop the tag silently. Filed as IATA-Cargo/ONE-Record#456 (labelled enhancement, api by IATA on 2026-10-05: taken as a change to the API rather than a clarification) |
| 30 | Who may revoke a SubscriptionRequest a third party created? The subscriptions section tells the subscriber to revoke its request to unsubscribe; the action-request section restricts revocation to the requestor and the holder. | Subscriptions with 3rd parties, Action Requests: using | Requestor and holder | IATA (2026-10-05) agrees the point is worth raising: whether the subscriber may revoke when it differs from the creator is to be put to the working group. Interim: the subscriber of a SubscriptionRequest may revoke it, as the only direct way to stop notifications it never asked for; delegates of a shared AccessDelegationRequest get no such right (question 19, AR-028). adjacent to IATA-Cargo/ONE-Record#381 (role wording), #401 and #449 (the subscriber learns the request's location only from isTriggeredBy). Filed as IATA-Cargo/ONE-Record#455 |
| 31 | Does a subscription on a type (topicType TYPE) match objects of its subclasses, or only objects that list that class in @type? The spec does not say; a holder that writes only the most specific class and a subscriber asking for cargo:Shipment disagree silently when the object is a subclass. |
Subscriptions; IATA-Cargo/ONE-Record#412 | Declared types only | Declared @type values only, IATA's current reading in #412. Holders that want hierarchy matching list the superclasses in @type (question 21 allows it). Our comment records the declared-types reading and the access-first fan-out |
| 32 | A status-change notification for an AccessDelegationRequest over several objects: api:hasLogisticsObject is at most one. Which, if any? |
API ontology Notification; IATA-Cargo/ONE-Record#437 |
First object | None when the request concerns more than one object; the request in isTriggeredBy lists them all. IATA considers raising the cardinality. Our comment describes this choice and two workable shapes |
| 33 | A POST body may nest a logistics object inside another (example A2 posts a Company with a Person): the text says logistics objects are never embedded, and IATA says a server should recognise the nested object and give it a URI of its own (IATA-Cargo/ONE-Record#444). | Create a Logistics Object example A2; IATA-Cargo/ONE-Record#444 | Keeps it embedded | Interim: creation over HTTP accepts the nested object and keeps it embedded with an internal id, as before; a change or an event may not introduce one, and a change to anything else leaves it in place. Splitting a nested logistics object into an object of its own is not implemented |
| 34 | A client may give an embedded object an @id of its own (https:, urn:, NE:ONE's neone:). The spec says embedded objects get server-assigned ids (internal: recommended) but not what a server does with a client-supplied one: keep it, replace it, or refuse the document. |
Implementation guidelines, embedded objects; Create a Logistics Object; IATA-Cargo/ONE-Record#459 | Keeps the id as given | Replaces it with a server-minted internal: id when the object is first stored, since the id is addressable afterwards and must be stable and the server's own; the client learns it from the next read. Asked in IATA-Cargo/ONE-Record#459 |
| 35 | A node that states only @id and @type ({"@id": "…/piece-2", "@type": "cargo:Piece"}) is not defined: a typed reference to another object, or an embedded object with no properties yet? The examples use both bare {"@id"} references and embedded objects with properties, never this shape. |
Data model embedded vs. referenced objects; Create a Logistics Object examples; IATA-Cargo/ONE-Record#460 | Stores what it is given | A reference whatever its class: the class must exist (data model class or code list) and fit the property's range, the node keeps its id, and a change cannot describe it in place. Asked in IATA-Cargo/ONE-Record#460 |