Skip to main contentA-REX Foundation

Decision records · ADR-024

ADR-024: Places in batch metadata are ISO codes (schema 1.3.0)

How is the region of a batch's origin written in the metadata document, and how is the change introduced without invalidating documents whose hashes are already on chain?

**Proposed** (2026-10-30). In schema/batch-metadata.schema.json 1.3.0, unreleased; not accepted: it needs the confirmation of two independent implementers ([GOVERNANCE.md](../GOVERNANCE.md))
Document ID
ADR-024
Decision date
2026-10-30

From schema 1.3.0, origin.region is an ISO 3166-2 subdivision code (or the ISO 3166-1 code of the country where no subdivision applies), checked by pattern; a name for people goes in the optional origin.regionName, which no reader or mapping uses.

FieldValue
IDADR-024
Subject areaMetadata schema, places
StatusProposed (2026-10-30). In schema/batch-metadata.schema.json 1.3.0, unreleased; not accepted: it needs the confirmation of two independent implementers (GOVERNANCE.md)
Date2026-10-30
OwnersA-REX Contributors; requested by the A-REX Platform (owner decision 2026-10-30: places are always ISO codes)
Related requirementsAREX-CORE §3.5 (metadata), §8 (personal data), ADR-006, ADR-008, ADR-019
Supersedes / superseded by—

Context

origin.country has been an ISO 3166-1 alpha-2 code since schema 1.0.0, but origin.region was free text ("First-level administrative region"). The published examples show what that produces: "Buenos Aires, partido de Tres Arroyos", "Mato Grosso". The same state is written in several languages and spellings, a district can slip in next to the state, and nothing stops a farm's town or a plot name from being written there. A reader cannot group lots by region, an EPCIS or UNTP exporter cannot map the value (interop/UNTP.md, Places as codes, maps only codes), and a regulator's regional lists (EUDR country benchmarking, which may classify parts of a country; US state rules) cannot be matched without guessing. The A-REX Platform has stored places as ISO 3166-2 codes since its geo migrations and exports them as codes; its documents still had to declare a version whose region means "any text".

Issue

How is the region of a batch's origin written in the metadata document, and how is the change introduced without invalidating documents whose hashes are already on chain?

Assumptions

  • ISO 3166-2 codes are the country's ISO 3166-1 alpha-2 code, a hyphen and one to three letters or digits (BR-MG, US-NY, AR-B, GB-ENG, FR-75C). ISO maintains them; changes are published in its newsletters.
  • A metadata document is committed by metadataHash and cannot be edited; a correction is a new document (setBatchMetadata).
  • Codes are language-neutral; names belong to the reader's language and are best produced by the reader.

Constraints

  • Every document valid under 1.0.0, 1.1.0 or 1.2.0 stays valid (its schemaVersion keeps its rules).
  • No coordinates, plots or natural-person identifiers (ADR-008), and originRef is never derived from location (ADR-019).
  • JSON Schema cannot compare two fields: that a code belongs to country is checked beside the schema.

Alternatives considered

AlternativeForAgainstOutcome
Keep free text, recommend codes in prosenothing changesnothing is checked; exporters and readers keep guessingRejected
A new field regionCode next to the free-text regionno field changes meaningtwo fields for one fact that can disagree; the text field stays the one people fillRejected
Full ISO 3166-2 code list as an enumexactabout 5,000 codes, updated by ISO several times a year: the schema would need a release for each changeRejected
region is a code from 1.3.0 by pattern, older versions keep text, an optional display nameone field, one meaning; checked; old documents validthe pattern cannot tell that MG is Madagascar and not Minas Gerais: validators check the country prefixProposed

Decision (proposed)

Schema 1.3.0 (together with ADR-017's extensions):

  • origin.region is the ISO 3166-2 code of the subdivision where the goods were produced, normally first level (state, province, department), for example BR-MG. Where no subdivision applies (a city state, a country without subdivisions in ISO 3166-2, or an issuer that knows only the country), it is the ISO 3166-1 alpha-2 code of the country. Pattern: ^[A-Z]{2}(-[A-Z0-9]{1,3})?$, applied when schemaVersion is not 1.0.0, 1.1.0 or 1.2.0.
  • The code belongs to origin.country: its first two letters equal country. A validator SHOULD check this beside the schema.
  • New optional origin.regionName: a display name in any language, informative only. Readers, validators and mappings use the code.
  • A region is never a plot, a farm's town, a name or coordinates.

Migration for 1.2.0 producers: declare "1.3.0", write the code in region (move any name to regionName, and drop anything finer than the subdivision, such as a district or a town). Documents already committed stay as they are; a correction (setBatchMetadata) that declares 1.3.0 carries the code.

Argument

One field with one meaning is easier to fill, check and map than two that can disagree. Tying the rule to the declared schemaVersion keeps every committed document valid, which an immutable metadataHash requires. A pattern instead of the code list keeps the schema stable while ISO updates its list; the country-prefix check catches the one confusion the pattern allows.

Consequences

Positive

  • Lots can be grouped, filtered and matched against regulators' regional lists by code.
  • EPCIS and UNTP exports carry the region without guessing (UNTP characteristics.productionPlace.subdivisionCode).
  • Names are shown in the reader's language from the code.

Negative

  • Producers moving to 1.3.0 must map their region names to codes.
  • The pattern accepts well-formed codes that ISO has not assigned; checking assignment needs the current ISO list.

Obligations it creates

  • Tests in test/metadata-schema.test.mjs (codes accepted, names and malformed codes refused from 1.3.0, free text still valid for 1.0.0 to 1.2.0, the examples' codes belong to their country).
  • The examples declare 1.3.0 with codes.
  • interop/UNTP.md and interop/EPCIS.md map region as a code.

Implementation and evidence

WhatWhere
Schemaschema/batch-metadata.schema.json 1.3.0: origin.region (pattern through if/else on schemaVersion), origin.regionName
Teststest/metadata-schema.test.mjs: "from 1.3.0, origin.region is an ISO 3166-2 code, or the ISO 3166-1 code where no subdivision applies"
Examplesexamples/batch-metadata.example.json (AR-B), batch-metadata.pact-pcf.example.json (BR-MT), batch-metadata.upstream.example.json (AR-B)
First implementerA-REX Platform (places stored as ISO 3166-2 codes; documents declare 1.3.0)
  • ADR-006: open codes for commodities and units; places use the ISO lists the world already uses
  • ADR-008: no coordinates or natural-person identifiers in the batch record
  • ADR-017: extensions, the other addition of schema 1.3.0
  • ADR-019: capabilities in the standard, policy in profiles; originRef is never derived from location