Astro~/0.4
** Conformance / NDM * PAGE 30 / 30
** Astro * Conformance
** /conformance/ndm

NDM Combined Instantiation

Coverage matrix: what this package implements, clause by clause.

Conformance Statement for pkg/ndm, CCSDS 505.0-B-3 clause 4.11

CCSDS 505.0-B-3 ships no Implementation Conformance Statement proforma. What follows takes the shape the navigation standards use, applied to clause 4.11, the NDM combined instantiation.

This package implements that clause and nothing else in the document. The rest of CCSDS 505.0-B-3 — the element naming, the header and body structure, the units attribute — is implemented by pkg/odm, pkg/adm, pkg/tdm and pkg/cdm, each in its own conformance statement, because it is what their own standards' XML sections point at.


A1 IDENTIFICATION

FieldValue
Date of Statement (DD/MM/YYYY)04/09/2026
ICS Serial NumberASTRO-NDM-ICS-001
Implementation Nameastro/pkg/ndm
Implementation VersionSee go.mod / latest commit on main
SupplierRavi Suhag
Contact Point for QueriesGitHub, github.com/ravisuhag/astro
SpecificationCCSDS 505.0-B-3 (XML Specification for Navigation Data Messages, Blue Book, May 2023)
AlsoCCSDS 502.0-B-3 clause 8.12 and CCSDS 504.0-B-2 clause 7.8, which repeat the rules for their own messages
Have any exceptions been required?Yes [X] No [ ], see A3

A2 REQUIREMENTS

FeatureReferenceStatusSupport
<ndm></ndm> root element4.11.3MY
Standard attributes on the root4.11.4MY: xmlns:xsi, xmlns:ndm, xsi:noNamespaceSchemaLocation
Neither id nor version on the root4.11.4MY: a root carrying either is refused
Only id and version on a constituent tag4.11.5MY: written that way, and a location found on a constituent is discarded in favour of the root's
Constituents from table 3-14.11.6MP: the nine messages this repository implements, see A3
Any combination of message types4.11.7MY: the standards may be mixed in one file
At least one constituent message4.11.8OY: a should, so an empty file is read rather than refused
<COMMENT> elements under the root4.11.9, figure 4-2OY
Constituents validated as whole messages4.11.5, and each message's own standardMY: each is handed to its own package's decoder
Schema instance namespace, exactly as given4.3.3MY: http, not https — the string names a namespace
Schema location as one unbroken string4.3.6OY

A3 EXCEPTIONS AND UNSUPPORTED FEATURES

The Re-entry Data Message is not a constituent this package reads. Clause 4.11.6 draws the constituents from table 3-1, which lists the RDM of CCSDS 508.1 alongside the nine implemented here. That standard has no package in this repository, so a file carrying an <rdm> is refused outright with ErrUnknownMessageType rather than half-read. A combined file is all-or- nothing on purpose: returning the eight messages a reader understood and silently dropping the ninth would misrepresent the file.

The qualified schema set is not used. Clause 4.3.5 offers qualified and unqualified element forms and clause 4.3.6 a schema location for each. This package writes the unqualified form, which every worked example in every navigation standard uses. An instantiation that arrives qualified is not rejected on that ground — the decoder does not look at namespace prefixes — but re-encoding it produces the unqualified form.

One file names one master schema. Clause 4.11.4 puts a single xsi:noNamespaceSchemaLocation on the root, and each navigation standard names a different master: CCSDS 502.0-B-3 gives 3.0 and CCSDS 504.0-B-2 gives 4.0. A file mixing their messages can only name one, and the documents do not settle which — figure 7-3 of CCSDS 504.0-B-2 writes the 4.0 master over a file of ADM messages and its own figure G-12 writes the 3.0 master over another. This package carries whatever the file had and defaults a new one to the schema its first message names. A caller who needs a different one sets Combined.Schema.

There is no key-value equivalent. Aggregation is defined for XML only. Clause 5.2.2 of CCSDS 504.0-B-2 says a sequence of ACMs "may be aggregated into a single Navigation Data Message (NDM) XML file", and neither standard defines a way to do it in the keyword = value notation. Nothing is missing here; there is nothing to implement.

A constituent is re-serialised on the way in and out. Each message is written as a document of its own and handed to its package's decoder, and back again on encode. That costs a serialise and a parse per message. It is deliberate: it means there is one decoder per message type rather than two, so a message cannot be accepted inside a combined file and refused outside it.


A4 IMPLEMENTATION LIMITS

LimitValueSource
Constituents per filebounded by the input
Constituent message types9
Nestingone level
Whole file in memoryyes

Wire test vectors

The files backing this statement live in the vector corpus — 2 decode vectors and 2 corpus files.

File
ndm/combined.json2 vectors
ndm/combined-omm.xmlfigure G-21 of CCSDS 502.0-B-3, published text
ndm/combined-mixed.xmlan orbit and an attitude message in one file — derived, not published

The first is published text: figure G-21 of CCSDS 502.0-B-3 prints it. The second is this package's own output, and is marked as derived in the corpus note, because no figure in either standard prints a file that mixes the standards even though clause 4.11.7 allows one.

What the vectors assert is the structure the wrapping adds: how many messages a file holds, of what types, in what order, and which master schema the root names. The constituents themselves are asserted by the vectors of pkg/odm, pkg/adm, pkg/tdm and pkg/cdm — a message inside a combined file is the same message, read by the same decoder.

See CONTRACT.md for how to consume these, and how this is verified for what rests on a published vector versus a reading of the clause.