Astro~/0.4
** Conformance
** Astro * Conformance
** /conformance/tmdl-ecss

TM Space Data Link (ECSS)

ECSS-E-ST-50-03C conformance statement for the TM frame protocol.

Conformance Statement for pkg/tmdl, ECSS-E-ST-50-03C


A1 GENERAL INFORMATION

A1.1 Identification

FieldValue
Date of Statement (DD/MM/YYYY)25/08/2026
Serial NumberASTRO-ECSS5003C-CONF-001
System Conformance Statement Cross-ReferenceThis document

A1.2 Identification of Implementation Under Test

FieldValue
Implementation Nameastro/pkg/tmdl
Implementation VersionSee go.mod / latest commit on main
Special ConfigurationNone
Other InformationGo library implementing the TM Space Data Link Protocol. This document audits it against the European profile rather than against CCSDS 132.0-B; the CCSDS statement is the CCSDS 132.0-B-3 PICS.

A1.3 Identification of Supplier

FieldValue
SupplierRavi Suhag
Contact Point for QueriesGitHub, github.com/ravisuhag/astro
Implementation Name(s) and Version(s)astro/pkg/tmdl (Go package)
System Name(s)Astro

A1.4 Identification of Specification

FieldValue
SpecificationECSS-E-ST-50-03C, Space data links, Telemetry transfer frame protocol, 31 July 2008
Relationship to CCSDSThe European profile of the CCSDS TM Space Data Link Protocol (CCSDS 132.0-B). It defines no new frame; it adopts the CCSDS frame and constrains its options.
Obtained fromhttps://ecss.nl/wp-content/uploads/standards/ecss-e/ECSS-E-ST-50-03C31July2008.pdf, public, no registration required
Have any exceptions been required?No, the five gaps of the first pass were closed on 23/08/2026, and the idle-packet fill gap the second pass found was closed on 25/08/2026; see A3

A note on the version. "ECSS-E-ST-50-03C Rev.1" is sometimes cited, but no such revision is published. The active document on ecss.nl is ECSS-E-ST-50-03C dated 31 July 2008, whose own change log records the 2008 issue as an editorial renumbering of the 6 November 2007 text. This audit is against that document.


A2 REQUIREMENTS MATRIX

Every numbered clause of the normative sections (clause 5.1 to clause 5.6) appears below, one row each. Section 4 is the informative overview and contains no numbered requirements.

Inventory total: 135 clauses. Matrix rows: 135.

Verdicts use four values:

VerdictMeaning
conformsthe code always behaves as the clause requires
configurablethe code can be operated within the profile; the row states the configuration
gapthe code cannot satisfy the clause as written
out-of-scopethe clause targets a layer this package does not own

Requirement text is paraphrased. ECSS documents are copyrighted; clause identifiers plus a paraphrase are enough to find the original.

5.1 General

ReqRequirement (paraphrase)What it constrainsVerdictpkg/tmdl evidence
5.1aThe TM Transfer Frame shall encompass the major fields, positioned contiguously if present, in the sequence shown in...field order in the frameconforms
5.1bThe maximum length for a TM Transfer Frame shall be 2048 octets.maximum frame length 2048 octetsconfigurable
5.1cThe TM Transfer Frame shall be of constant length throughout a specific mission phase.constant frame length per mission phaseconfigurable
5.1dThe TM Transfer Frame length shall be in conformance with the specifications contained in the standard for telemetry...conformance with the channel coding standardout-of-scope
5.1eTM Transfer Frames shall be transferred over a physical channel at a constant rate.constant transmission rateout-of-scope
5.1fIn order to assure correct decoding at the receiving end, the same telemetry channel coding options shall be applied...same coding options across the channelout-of-scope
5.1gAt the receiving end, TM Transfer Frames containing detected errors need not be delivered.errored frames need not be deliveredconforms
5.1hThe handling of TM Transfer Frames containing detected errors shall be specified for each mission or mission phase.mission-specified handling of errored framesconfigurable
5.1iAll TM Transfer Frames with the same Master Channel Identifier on a physical channel shall constitute a master...frames sharing an MCID form a master channelconforms
5.1jA master channel shall consist of between one to eight virtual channels.one to eight virtual channels per master channelconforms
5.1kOn a physical channel that carries TM Transfer Frames, all the frames shall have the same Transfer Frame Version...one Transfer Frame Version Number per physical channelconforms

5.2 Transfer Frame Primary Header

ReqRequirement (paraphrase)What it constrainsVerdictpkg/tmdl evidence
5.2.1aThe Transfer Frame Primary Header shall always be present in a TM Transfer Frame.primary header always presentconforms
5.2.1bThe Transfer Frame Primary Header shall consist of six fields, positioned contiguously, in the following sequence:six fields in sequenceconforms
5.2.2.1aThe Master Channel Identifier shall always be present in a Transfer Frame Primary Header.Master Channel Identifier, bits 0-11, two subfieldsconforms
5.2.2.1bThe Master Channel Identifier shall be contained within bits 0-11 of the Transfer Frame Primary Header.Master Channel Identifier, bits 0-11, two subfieldsconforms
5.2.2.1cThe Master Channel Identifier shall consist of two fields, positioned contiguously, in the following sequence:Master Channel Identifier, bits 0-11, two subfieldsconforms
5.2.2.2aThe Transfer Frame Version Number shall always be present in a Master Channel Identifier.Transfer Frame Version Number present, bits 0-1conforms
5.2.2.2bThe Transfer Frame Version Number shall be contained within bits 0-1 of the Transfer Frame Primary Header.Transfer Frame Version Number present, bits 0-1conforms
5.2.2.2cThe Transfer Frame Version Number shall be set to '00'.version number set to '00'conforms
5.2.2.3aThe Spacecraft Identifier shall always be present in a Master Channel Identifier.Spacecraft Identifier present, bits 2-11conforms
5.2.2.3bThe Spacecraft Identifier shall be contained within bits 2-11 of the Transfer Frame Primary Header.Spacecraft Identifier present, bits 2-11conforms
5.2.2.3cThe Spacecraft Identifier shall provide the identification of the spacecraft which is associated with the data...Spacecraft Identifier present, bits 2-11conforms
5.2.2.3dThe Spacecraft Identifier shall be static throughout all mission phases.SCID static across all mission phasesconfigurable
5.2.3aThe Virtual Channel Identifier shall always be present in a Transfer Frame Primary Header.Virtual Channel Identifier present, bits 12-14conforms
5.2.3bThe Virtual Channel Identifier shall be contained within bits 12-14 of the Transfer Frame Primary Header.Virtual Channel Identifier present, bits 12-14conforms
5.2.3cThe Virtual Channel Identifier shall provide the identification of the virtual channel to which the TM Transfer...VCID identifies the virtual channelconforms
5.2.4aThe Operational Control Field Flag shall always be present in a Transfer Frame Primary Header.OCF Flag present, bit 15conforms
5.2.4bThe Operational Control Field Flag shall be contained in bit 15 of the Transfer Frame Primary Header.OCF Flag present, bit 15conforms
5.2.4cThe Operational Control Field Flag shall indicate the presence or absence of the Operational Control Field, as...OCF Flag signals presence of the OCFconforms
5.2.4dThe Operational Control Field Flag shall be static in the associated master channel or virtual channel throughout a...OCF Flag static per channel throughout a phaseconfigurable
5.2.5aThe Master Channel Frame Count shall always be present in a Transfer Frame Primary Header.Master Channel Frame Count present, bits 16-23conforms
5.2.5bThe Master Channel Frame Count shall be contained within bits 16-23 of the Transfer Frame Primary Header.Master Channel Frame Count present, bits 16-23conforms
5.2.5cThe Master Channel Frame Count shall contain a sequential binary count (modulo 256) of each TM Transfer Frame...sequential count modulo 256 per master channelconfigurable
5.2.5dThe Master Channel Frame Count shall not be reset before reaching 255 unless there is a major system reset.count not reset before 255conforms
5.2.6aThe Virtual Channel Frame Count shall always be present in a Transfer Frame Primary Header.Virtual Channel Frame Count present, bits 24-31conforms
5.2.6bThe Virtual Channel Frame Count shall be contained within bits 24-31 of the Transfer Frame Primary Header.Virtual Channel Frame Count present, bits 24-31conforms
5.2.6cThe Virtual Channel Frame Count shall contain a sequential binary count (modulo 256) of each TM Transfer Frame...sequential count modulo 256 per virtual channelconfigurable
5.2.6dThe Virtual Channel Frame Count shall not be reset before reaching 255 unless there is a major system reset.count not reset before 255conforms
5.2.7.1aThe Transfer Frame Data Field Status shall always be present in a Transfer Frame Primary Header.Data Field Status present, bits 32-47, five subfieldsconforms
5.2.7.1bThe Transfer Frame Data Field Status shall be contained within bits 32-47 of the Transfer Frame Primary Header.Data Field Status present, bits 32-47, five subfieldsconforms
5.2.7.1cThe Transfer Frame Data Field Status shall consist of five fields, positioned contiguously, in the following sequence:Data Field Status present, bits 32-47, five subfieldsconforms
5.2.7.2aThe Transfer Frame Secondary Header Flag shall always be present in a Transfer Frame Data Field Status.Secondary Header Flag present, bit 32conforms
5.2.7.2bThe Transfer Frame Secondary Header Flag shall be contained in bit 32 of the Transfer Frame Primary Header.Secondary Header Flag present, bit 32conforms
5.2.7.2cThe Transfer Frame Secondary Header Flag shall indicate the presence or absence of the Transfer Frame Secondary...flag signals presence of the secondary headerconforms
5.2.7.2dThe Transfer Frame Secondary Header Flag shall be static in a specific master channel, throughout a mission phase,...flag static per master or virtual channelconfigurable
5.2.7.2eThe Transfer Frame Secondary Header Flag shall be static in a specific virtual channel, throughout a mission phase,...flag static per master or virtual channelconfigurable
5.2.7.3aThe Synchronization Flag shall always be present in a Transfer Frame Data Field Status.Synchronization Flag present, bit 33conforms
5.2.7.3bThe Synchronization Flag shall be contained in bit 33 of the Transfer Frame Primary Header.Synchronization Flag present, bit 33conforms
5.2.7.3cThe Synchronization Flag shall signal the formatting of the Transfer Frame Data Field, as follows:flag signals data field formattingconforms
5.2.7.3dThe Synchronization Flag shall be static in a specific virtual channel throughout a mission phase.flag static per virtual channel throughout a phaseconfigurable
5.2.7.4aThe Packet Order Flag shall always be present in a Transfer Frame Data Field Status.Packet Order Flag present, bit 34conforms
5.2.7.4bThe Packet Order Flag shall be contained in bit 34 of the Transfer Frame Primary Header.Packet Order Flag present, bit 34conforms
5.2.7.4cIf the Synchronization Flag is set to '0', the Packet Order Flag shall be set to '0'.Sync Flag '0' forces Packet Order Flag '0'conforms
5.2.7.5aThe Segment Length Identifier shall always be present in a Transfer Frame Data Field Status.Segment Length Identifier present, bits 35-36conforms
5.2.7.5bThe Segment Length Identifier shall be contained in bits 35-36 of the Transfer Frame Primary Header.Segment Length Identifier present, bits 35-36conforms
5.2.7.5cIf the Synchronization Flag is set to '0', the Segment Length Identifier shall be set to '11'.Sync Flag '0' forces Segment Length Identifier '11'conforms
5.2.7.6aThe First Header Pointer shall always be present in a Transfer Frame Data Field Status.First Header Pointer present, bits 37-47conforms
5.2.7.6bThe First Header Pointer shall be contained in bits 37-47 of the Transfer Frame Primary Header.First Header Pointer present, bits 37-47conforms
5.2.7.6cIf the Synchronization Flag is set to '0', the First Header Pointer shall contain information on the data in the...FHP carries data field information when Sync Flag is '0'conforms
5.2.7.6dIf at least one packet starts in the Transfer Frame Data Field, the First Header Pointer shall contain the location...FHP gives the location of the first packet headerconforms
5.2.7.6eThe locations of the octets in the Transfer Frame Data Field shall be numbered in ascending order starting with '0'.octets numbered from zeroconforms
5.2.7.6fIf no packet starts in the Transfer Frame Data Field, the First Header Pointer shall be set to '11111111111'.no packet starts, FHP '11111111111'conforms
5.2.7.6gIf the Transfer Frame Data Field contains only idle data, the First Header Pointer shall be set to '11111111110'.idle data only, FHP '11111111110'conforms

5.3 Transfer Frame Secondary Header

ReqRequirement (paraphrase)What it constrainsVerdictpkg/tmdl evidence
5.3.1aIf present, the Transfer Frame Secondary Header shall follow, without gap, the Transfer Frame Primary Header.secondary header follows the primary without gapconforms
5.3.1bThe presence or absence of the Transfer Frame Secondary Header shall be signalled by the Transfer Frame Secondary...presence signalled by the Secondary Header Flagconforms
5.3.1cIf present, the Transfer Frame Secondary Header shall comprise an integral number of octets: between 2 and 64 octets.secondary header total 2 to 64 octetsconforms
5.3.1dThe Transfer Frame Secondary Header shall be associated with either a master channel or a virtual channel.associated with one channel, fixed length throughout a phaseconfigurable
5.3.1eThe Transfer Frame Secondary Header shall have a fixed length in the associated master channel or in the associated...associated with one channel, fixed length throughout a phaseconfigurable
5.3.1fThe Transfer Frame Secondary Header shall consist of two fields, positioned contiguously, in the following sequence:two fields: identification then dataconforms
5.3.1gThe Transfer Frame Secondary Header shall be used to carry fixed length data defined at mission level.carries fixed-length mission-defined dataconforms
5.3.1hThe Transfer Frame Secondary Header may be used to provide an extended virtual channel frame count as specified in...may carry an extended virtual channel frame countconfigurable
5.3.2.1aThe Transfer Frame Secondary Header Identification shall always be present in a Transfer Frame Secondary Header.identification present, bits 0-7, two subfieldsconforms
5.3.2.1bThe Transfer Frame Secondary Header Identification shall be contained in bits 0-7 of the Transfer Frame Secondary...identification present, bits 0-7, two subfieldsconforms
5.3.2.1cThe Transfer Frame Secondary Header Identification shall comprise two fields, positioned contiguously, in the...identification present, bits 0-7, two subfieldsconforms
5.3.2.2aThe Transfer Frame Secondary Header Version Number shall always be present in a Transfer Frame Secondary Header...secondary header version present, bits 0-1conforms
5.3.2.2bThe Transfer Frame Secondary Header Version Number shall be contained in bits 0-1 of the Transfer Frame Secondary...secondary header version present, bits 0-1conforms
5.3.2.2cThe Transfer Frame Secondary Header Version Number shall be set to '00'.secondary header version set to '00'conforms
5.3.2.3aThe Transfer Frame Secondary Header Length shall always be present in a Transfer Frame Secondary Header...length field present, bits 2-7conforms
5.3.2.3bThe Transfer Frame Secondary Header Length shall be contained in bits 2-7 of the Transfer Frame Secondary Header.length field present, bits 2-7conforms
5.3.2.3cThe Transfer Frame Secondary Header Length shall contain the total length of the Transfer Frame Secondary Header in...length field is TOTAL secondary header octets minus oneconforms
5.3.2.3dThe value of the Transfer Frame Secondary Header Length shall be static within a specific master channel or a...length static per channel throughout a phaseconfigurable
5.3.3aThe Transfer Frame Secondary Header Data Field shall always be present in a Transfer Frame Secondary Header.data field present, follows the identification, carries the dataconforms
5.3.3bThe Transfer Frame Secondary Header Data Field shall follow, without gap, the Transfer Frame Secondary Header...data field present, follows the identification, carries the dataconforms
5.3.3cThe Transfer Frame Secondary Header Data Field shall contain the Transfer Frame Secondary Header data.data field present, follows the identification, carries the dataconforms
5.3.4.2aThe length of the Transfer Frame Secondary Header shall be 32 bits.extended count needs a 32-bit secondary headerconforms
5.3.4.2bThe Transfer Frame Secondary Header Data Field shall contain the 24-bit extension to the virtual channel frame count.24-bit extension counting roll-overs of the 8-bit countconfigurable
5.3.4.2cThe extension to the virtual channel frame count shall be a binary count of the roll-overs of the 8-bit value...24-bit extension counting roll-overs of the 8-bit countconfigurable
5.3.4.2dThe use of the extended virtual channel frame count shall be associated with either a master channel or a virtual...extended count associated with a channel and staticconfigurable
5.3.4.2eThe use of the extended virtual channel frame count shall be static in the associated master channel or in the...extended count associated with a channel and staticconfigurable

5.4 Transfer Frame Data Field

ReqRequirement (paraphrase)What it constrainsVerdictpkg/tmdl evidence
5.4.2aThe Transfer Frame Data Field shall always be present in a TM Transfer Frame.data field always presentconforms
5.4.2bThe Transfer Frame Data Field shall follow, without gap, one of the following:data field follows the secondary or primary header without gapconforms
5.4.2cIf a Transfer Frame Secondary Header is present, the Transfer Frame Secondary.data field follows the secondary or primary header without gapconforms
5.4.2dIf a Transfer Frame Secondary Header is not present, the Transfer Frame Primary.data field follows the secondary or primary header without gapconforms
5.4.2eThe length of the Transfer Frame Data Field shall be an integral number of octets and be constrained by the length...integral octets, constrained by the frame lengthconforms
5.4.3.3aA packet handled by the packet processing and extraction functions shall have a defined Packet Version Number in...packet version number conformanceout-of-scope
5.4.3.3bAn idle packet shall be either:idle packet definitionconforms
5.4.3.4aThe packet processing function shall be applied independently for each virtual channel.packet processing applied per virtual channelconforms
5.4.3.4bThe packet processing function shall place packets contiguously into the Transfer Frame Data Field.packets placed contiguouslyconforms
5.4.3.4cIf the length of a packet exceeds the available space in the Transfer Frame Data Field, the packet processing...packets longer than the space are split across framesconforms
5.4.3.4dThe packet processing function shall set the First Header Pointer as specified in clause 5.2.7.6.First Header Pointer set per 5.2.7.6conforms
5.4.3.4ePackets with different Packet Version Numbers may be transmitted within a virtual channel.packets of different versions may share a virtual channelconforms
5.4.3.4fA Transfer Frame Data Field containing only idle data may be created.a data field of only idle data may be createdconforms
5.4.3.4gOne or more idle packets may be created to fill space in a Transfer Frame Data Field.idle packets may fill spare spaceconforms
5.4.3.5aThe packet extraction function shall be applied independently for each virtual channel.packet extraction applied per virtual channelconforms
5.4.3.5bThe packet extraction function shall extract the packets from a Transfer Frame Data Field using the value of the...extraction uses the First Header Pointerconforms
5.4.3.5cA Transfer Frame Data Field containing idle data shall be discarded.a data field of idle data is discardedconforms
5.4.3.5dAny idle packets extracted from Transfer Frame Data Fields shall be discarded.extracted idle packets are discardedconforms
5.4.4.2aThe stored data shall be in the form of standard TM Transfer Frames.playback data is whole recorded frames placed in real-time data fieldsconfigurable
5.4.4.2bAt playback time, the recorded TM Transfer Frames shall be placed into the Transfer Frame Data Field of real-time TM...playback data is whole recorded frames placed in real-time data fieldsconfigurable
5.4.4.2cThe asynchronous insertion may be made in either the forward or the reverse mode.forward or reverse insertion modeconfigurable
5.4.4.2dIf forward insertion mode is used, then any recorded attached synchronization markers shall use the alternative...alternative synchronization marker for forward modeout-of-scope
5.4.4.2eA dedicated virtual channel shall be used for the playback data.a dedicated virtual channel for playbackconfigurable
5.4.4.2fAt the receiving end, the real-time virtual channel used for the playback data shall be processed and its contents...receiving end stores and later retrieves playback framesconfigurable
5.4.4.2gIn the later off-line processing, the recorded TM Transfer Frames shall be retrieved in the correct,...receiving end stores and later retrieves playback framesconfigurable
5.4.4.2hAny Communications Link Control Word (see clause 5.5.3) extracted from the Operational Control Field of a recorded...CLCWs from recorded frames must not drive the live linkout-of-scope

5.5 Operational Control Field

ReqRequirement (paraphrase)What it constrainsVerdictpkg/tmdl evidence
5.5.1aIf present, the Operational Control Field shall occupy the four octets following, without gap, the Transfer Frame...OCF occupies the four octets after the data fieldconforms
5.5.1bThe presence or absence of the Operational Control Field shall be signalled by the Operational Control Field Flag in...presence signalled by the OCF Flagconforms
5.5.1cThe Operational Control Field shall be associated with a master channel or a virtual channel.OCF associated with a channel and present in every frame of itconfigurable
5.5.1dThe Operational Control Field shall be present in every TM Transfer Frame transmitted through the associated master...OCF associated with a channel and present in every frame of itconfigurable
5.5.1eBit 0 of the Operational Control Field shall contain a Type Flag which indicates the contents of the field.bit 0 of the OCF is a Type Flagconfigurable
5.5.2aThe Type Flag shall always be present in an Operational Control Field.Type Flag present in bit 0 and set by content typeconfigurable
5.5.2bThe Type Flag shall be contained in bit 0 of the Operational Control Field.Type Flag present in bit 0 and set by content typeconfigurable
5.5.2cThe Type Flag shall be set as follows:Type Flag present in bit 0 and set by content typeconfigurable
5.5.2dThe Type Flag may vary between TM Transfer Frames on the same virtual channel.the Type Flag may vary between framesconforms
5.5.3aIf the Type Flag is '0', the Operational Control Field shall contain a Type-1-Report.Type Flag '0' means a Type-1-Reportconfigurable
5.5.3bA Type-1-Report shall contain a Communications Link Control Word in conformance with ECSS-E-ST-50-04, clause 6.3.Type-1-Report carries a CLCW per ECSS-E-ST-50-04out-of-scope
5.5.4aIf the Type Flag is '1', the Operational Control Field shall contain a Type-2-Report.Type Flag '1' means a Type-2-Report and its first bit gives its useconfigurable
5.5.4bThe value of the first bit of a Type-2-Report (i.e. bit 1 of the Operational Control Field) shall indicate the use...Type Flag '1' means a Type-2-Report and its first bit gives its useconfigurable
5.5.4cThe value of the first bit of a Type-2-Report may vary between TM Transfer Frames on the same virtual channel.the first bit may vary between framesconforms

5.6 Frame Error Control Field

ReqRequirement (paraphrase)What it constrainsVerdictpkg/tmdl evidence
5.6.1aIf present, the Frame Error Control Field shall occupy the two octets following, without gap, one of the following:FECF occupies the two octets after the OCF or data fieldconforms
5.6.1bThe Frame Error Control Field shall be present in a TM Transfer Frame if the TM Transfer Frame is not Reed-Solomon...FECF present when the frame is not Reed-Solomon encodedconforms
5.6.1cIf present, the Frame Error Control Field shall occur within every TM Transfer Frame transmitted within the same...FECF consistently present or absent across the physical channelconforms
5.6.2aThe encoding procedure shall be as follows:encoding procedure, CRC-16 with generator X^16+X^12+X^5+1, preset to onesconforms
5.6.3aThe decoding procedure shall use an error detection syndrome, S(X), given by S(X) = [(X16 ⋅ C*(X)) + (Xn ⋅ L(X))]...decoding uses the error detection syndromeconforms
5.6.3bThe Frame Error Control Field shall not be used for error correction.the FECF is not used for error correctionconforms

A3 GAPS, ALL CLOSED

The audit of 23/08/2026 found five gaps, fixed the same day in fix(tmdl): correct four ECSS-E-ST-50-03C conformance defects. A second pass on 25/08/2026 found that the first pass had itself overstated two rows, and the underlying defect was fixed then. This section records all of them, since the reasoning is worth keeping and several describe a failure mode this codebase has now hit repeatedly.

5.4.3.3b / 5.4.3.4g, raw 0xFF fill sold as "idle packets" (second pass)

The first pass marked both rows conforms with padDataField's raw 0xFF fill as evidence. That was wrong twice over: 0xFF fill is not an idle packet, and a conformant receiver parses the fill as a packet header (0x7FF in the first two octets reads as the idle APID, but the length field is garbage) and loses packet sync. The in-repo receiver survived only through a nonstandard all-0xFF heuristic no other implementation shares.

Now: Flush fills spare data field space with a real SPP idle packet (APID 0x7FF) built by idleFillPacket, spanning into following frames when the spare space is under the seven-octet minimum packet size, and Receive discards extracted idle packets by APID per 5.4.3.5d. The raw-0xFF heuristic remains only as decode-side leniency for streams from older versions of this package.

Alongside that fix, three rows the first pass graded conforms were re-graded configurable, because the property holds only under caller wiring: 5.2.5c and 5.2.6c (counts are sequential only when one shared FrameCounter feeds every service and the idle-frame path) and 5.1c (length constancy holds only under a set FrameLength, which the codec now enforces on encode and decode).

5.3.2.3c. The secondary header length field was one too small

Clause 5.3.2.3c requires the six-bit field to hold the total secondary header length in octets minus one, the total being the identification octet plus the data field. So for an N-octet data field the field reads N.

The code required it to equal len(DataField)-1 and decoded with the same offset. A four-octet header went out saying 2 where the standard wants 3.

Encoder and decoder agreed, so every round trip passed and the package's own tests were silent, one of them asserted the wrong value outright, which is how the defect looked deliberate. A conforming receiver reading 2 computes a three-octet total and starts the Transfer Frame Data Field an octet early, corrupting every frame with a secondary header.

The same wording is in CCSDS 132.0-B-3 clause 4.1.3.2.2.3, so this was never an ECSS-only defect.

Now: the field equals the data field length, SetDataField derives it, and the test asserts the octet on the wire plus the offset a receiver would compute from it.

5.3.4.2a, the extended virtual channel frame count inherited it

Clause 5.3.4.2a fixes the secondary header at 32 bits when it carries the extended count: four octets, so the field must read 3. Closed by the fix above.

5.2.7.6g, idle frames used the wrong First Header Pointer

Clause 5.2.7.6 gives two codes to two conditions: 11111111111 (0x7FF) when no packet starts in the data field, 11111111110 (0x7FE) when the field holds only idle data. NewIdleFrame filled with idle and then set 0x7FF, and IsIdleFrame matched on 0x7FF, so OID frames were mislabelled and conformant ones from other senders went unrecognised.

Fixing this exposed a second defect the audit had not found: the packet service had the two codes swapped on both paths at once. It discarded continuation frames as idle (losing payload) and appended idle fill into the reassembly buffer. Consistent on both sides, so round trips passed here too.

Now: both codes are named constants, FHPNoPacketStart and FHPOnlyIdleData, and the service uses each for its own condition.

5.3.1c. The secondary header could exceed 64 octets

Clause 5.3.1c caps the whole secondary header at 64 octets. A 63-value length field with a 64-octet data field encoded to 65, and nothing rejected it.

Now: MaxSecondaryHeaderSize is enforced by Validate.

5.6.1c. The Frame Error Control Field could not be omitted

Clause 5.6.1b makes the field mandatory when the frame is not Reed-Solomon encoded, and its NOTE makes it optional inside a code block, which already protects the frame. Clause 5.6.1c requires the choice to hold across the physical channel.

Only "always present" was supported: Encode always appended the field, DecodeTransferFrame always verified it, and ChannelConfig.HasFEC was never consulted by the frame codec. A Reed-Solomon mission omitting the field ( a normal configuration) could not use the package.

Now: EncodeWithConfig and DecodeTransferFrameWithConfig honour HasFEC. The original entry points keep the field, so existing callers are unaffected, and VirtualChannelFrameService.SetChannelConfig carries the choice through the pass-through path.

And one that was recorded as configurable

Clause 5.1b caps the frame at 2048 octets and nothing enforced it. It is still configurable rather than a gap (the caller sets FrameLength, and a CCSDS-only mission may legitimately exceed the European ceiling) but ChannelConfig.Validate now checks it for missions that care.


A4 SUMMARY

VerdictCountShare
conforms9570%
configurable3324%
out-of-scope75%
gap0-
Total135

Inventory total 135, matrix rows 135. The two numbers are stated here so the check is self-contained.

Reading the result

pkg/tmdl conforms to the European TM transfer frame profile. Every mandatory clause is either satisfied outright or satisfiable by configuration, and the rows that say configurable name the configuration.

The five gaps the first pass of this audit found were all closed on the same day, and the idle-packet fill defect the second pass found was closed on 25/08/2026. Three of them had been putting wrong bytes on the wire, and all were the kind that hide: the secondary header length was self-consistent within the library, the idle-frame pointer sat in a field most tests do not assert, and the raw fill was survivable only by this package's own receiver. Fixing the pointer exposed a further defect of the same shape in the packet service.

That is the pattern worth carrying forward. Three separate defects in this codebase (the PN randomizer, this length field, and the swapped pointer codes ) were each perfectly symmetric and perfectly wrong. A round trip cannot catch any of them. Assert the octet.

On the 24% "configurable" share

This audit holds itself to a threshold: if configurable rows exceed 20% of the matrix, the result is a hedge and the reasoning has to be shown rather than shipped as a clean pass. This matrix is at 24%, so the threshold is crossed and the reasoning belongs here rather than buried.

The threshold guards against guessing. These rows are not guesses. They fall into three groups, and every one names its exact configuration:

  • Operational constancy (14 rows). Clauses of the form "shall be static in the associated master channel throughout a mission phase", 5.2.2.3d, 5.2.4d, 5.2.7.2d, 5.2.7.2e, 5.2.7.3d, 5.3.1d, 5.3.1e, 5.3.2.3d, 5.3.4.2d, 5.3.4.2e and their neighbours. A stateless frame codec cannot be static across a mission phase; only the system operating it can. Marking these "conforms" would be the dishonest answer.
  • Opaque fields the caller fills (9 rows). The Operational Control Field is four octets pkg/tmdl carries without interpreting (frame.go TMTransferFrame.OperationalControl), so the Type Flag clauses 5.5.1e through 5.5.4b are satisfied by whatever the caller puts there. The CLCW content itself belongs to pkg/cop.
  • Caller-supplied values and policies (10 rows). The 2048-octet frame limit (5.1b), frame-length constancy (5.1c), the shared frame counters (5.2.5c, 5.2.6c), playback handling (5.4.4.2), and the extended count's placement in the secondary header data.

None of these needed mission context I did not have. Had any been genuinely ambiguous it would appear as a gap with the ambiguity stated, not as a hedge.

Coverage boundary

Seven clauses are out-of-scope, and all seven point somewhere real:

ClauseBelongs to
5.1d, 5.1e, 5.1fchannel coding and the physical layer, pkg/tmsc
5.4.3.3apacket formats, pkg/spp
5.4.4.2dsynchronization markers, pkg/tmsc
5.4.4.2h, 5.5.3bthe CLCW, pkg/cop

None was silently dropped.


A5 METHOD

  • The standard was read in full; every numbered clause under clause 5 was extracted mechanically, giving 135. Section 4 is informative and contributes none.
  • Each clause was mapped by reading frame.go, service.go, channel.go, physical.go and errors.go. Every verdict but out-of-scope carries a pkg/tmdl file and symbol; the first pass cited line numbers, which drifted within a day of the audit, so the second pass replaced them with symbols.
  • Four clauses were checked by building frames in a temporary probe rather than by reading: 5.3.2.3c, 5.3.1c, 5.2.7.6g and 5.1b. All four findings above come from what the probe actually produced. The probe was deleted; this audit changed no code.
  • Evidence is as of the working tree on 25/08/2026, which carries the uncommitted idle-packet fill, counter-threading, and frame-length enforcement changes.

Wire test vectors

The octets backing this statement live in the vector corpus — 29 vectors. Each vector names the clause it comes from and carries the derivation that produced it.

File
tmdl/header.json21 vectors
tmdl/interop.json8 vectors, captured from spacepackets 0.32.0

These are data files, so any implementation can check itself against the same octets. See CONTRACT.md for how, and how this is verified for what rests on a published vector versus a reading of the clause.