Methodology

How sdmx-readiness decides whether an SDMx endpoint is ready to move from SDMx 2.1 straight to SDMx 3.1, and why each choice was made. Read this before changing a rule or comparing two organisations' reports. The rules themselves are in RULES.md; open validation questions are in RULES_REVIEW.md.

1. What "SDMx 3.1 readiness" means here

SDMx 3.0 is not a target. Changes introduced in 3.0 still count, because 3.1 contains them. Readiness has two independent parts:

Axis Question Measured by
Content Can the structures we publish as SDMx 2.1 (codelists, DSDs, dataflows, constraints, ...) be expressed in SDMx 3.1 without loss, and can they adopt semantic versioning? Rules (RULES.md) on every maintainable artefact, plus a per-artefact migration plan
Platform Does our web service already speak SDMx 3.1? Capability probes (sdmx_readiness/capabilities.py)

The tool does not produce a single score. Organisations differ in size and practice, and a percentage would hide what matters most: which artefacts need a decision.

Scope so far: public dissemination endpoints. Authenticated endpoints are supported (auth = "bearer" or "dotstat-adfs") but have not been the focus.

2. Pipeline

flowchart LR
  A[endpoints.toml] --> B[plan_queries<br/>one query per<br/>resource x format]
  B --> C[Fetcher<br/>HTTP + auth]
  C --> D[(raw/ + manifest.json)]
  D --> E[parse<br/>SDMX-ML 2.1 / 3.1]
  E --> F[Inventory 2.1<br/>primary]
  E --> G[Inventory 3.1<br/>if served]
  F --> H[rules]
  G --> H
  F --> I[migration plan]
  H --> I
  F --> J[capability probes]
  H --> K[report: report.html,<br/>summary.md, CSVs, report.xlsx]
  I --> K
  J --> K

--from-cache <previous output folder> restarts from raw/. A report can therefore be rebuilt (e.g. after a rule change) without calling the endpoint again.

3. What is fetched, and why

4. Parsing

sdmx_readiness/parse.py turns each message into Artefact and Reference objects.

5. Version grammar

sdmx_readiness/versions.py is the only place that knows the grammar. It follows the SDMX-ML 3.1 schema (SDMXCommonReferences.xsd):

Kind Example 3.1 schema type
semver-stable 1.2.0 SemanticVersionNumberType
semver-extended 1.2.0-draft SemanticVersionNumberType
legacy 1.2, 2 LegacyVersionNumberType (0|[1-9]\d*)(\.(0|[1-9]\d*))?: no leading zeros
wildcard (references only) 1.2+.0, 2+.0.0, 1.2.0+, * SemanticVersionReferenceType, WildcardType
invalid 1.03, 01.0, 1.0.0.0, 1.0.0+build, 1.*, 1.2+.0-draft none

SDMX-ML 2.1 accepted any dotted number ([0-9]+(\.[0-9]+)*). Versions such as 1.03 are therefore valid today and invalid in 3.1 (VER-001).

6. Severity, basis, change

Every rule carries three labels, defined in sdmx_readiness/rules/engine.py:

7. Conversions deliberately not reported

Every 2.1 DSD contains these constructs, and any converter must rewrite them:

Reporting them would flag every DSD and say nothing about any one of them. Some of the value mappings are not documented in the standard; they are listed for validation in RULES_REVIEW.md §6.

8. Metrics (summary.md "Headline")

9. Migration plan

migration_plan.csv has one row per artefact; the columns are defined in sdmx_readiness/migration.py.

10. Platform probes

One sample dataflow is used, preferably one with an Actual constraint (i.e. one that holds data). It is requested once per media type, and only the response headers are read. The SDMx 3.1 media types come from sdmx-rest v2.2.2:

Content Media types
Structure structure+xml;version=3.1.0, structure+json;version=2.1.0
Availability structure+xml;version=3.1.0
Data data+csv;version=2.1.0, data+xml;version=3.1.0, data+json;version=2.1.0

One SDMX-ML 2.1 probe is kept as a baseline. Results mean:

Result Meaning
supported 200, and the Content-Type echoes the requested version
fallback 200 with another version, or none: the server ignored the request (SPC answers an SDMX-CSV 2.1 request with SDMX-CSV 1.0)
not supported 406 / 415 / 501

11. Known limitations

12. Changes from loop_artefacts_and_versions.py

The original OECD script is in git history (first commit). The side-by-side run is in reports/comparison.

Original behaviour Consequence Now
Rules fire only when the parent is X.Y.Z or a reference contains - An endpoint fully on X.Y (SPC) gets "No invalid reference versions found", which reads as "ready" Adoption, finality, model changes, DSD checks and a migration plan are reported for every endpoint
2.1 concept references (maintainableParentVersion) ignored DSD -> concept-scheme violations only found in the 3.0 pass Item references mapped to their scheme
3.0 pass matched tags by 2.1 resource names 3.0 DataConstraint / Hierarchy silently skipped 3.0 dropped; 3.1 output compared by class
Every URN in any descendant text treated as a reference Annotation URNs reported as violations Separate annotation kind (REF-002, INFO)
Semver Categorisations checked Reported although 3.1 removes their version Categorisations excluded from semver rules
^\d+\.\d+\.\d+$ as the semver test Accepts 01.0.0 3.1 schema grammar
isFinal defaults to false in 3.0 Every 3.0 artefact treated as non-final 2.1 schema defaults; 3.1 has no isFinal
No structure checks Time-dimension position, measure dimensions, attachment groups, MSD targets ... not seen DSD-, MSD-, MOD-*
?references=all for each of 7 types Same artefacts downloaded up to 7 times (7.5 min on SPC) One query per type, 4 at a time (5-15 s on SPC; 15-20 s one at a time)
Token read once at start-up Long scans fail when the token expires Token requested per call
Hard-coded endpoint, output in ./tests/ Code had to be edited to change endpoint endpoints.toml, reports/<endpoint>/<date>/

Rule mapping:

13. Sources