Astro~/0.4
** Conformance / CSTS * PAGE 20 / 30
** Astro * Conformance
** /conformance/csts

Cross Support Transfer Service

PICS proforma: what this package implements, clause by clause.

Conformance Statement for pkg/csts, CCSDS 921.1-B-2

Read this first. Annex A1.1 of CCSDS 921.1-B-2 says the framework is not meant to be implemented on its own: its prime intent is to provide a framework for the specification of Cross Support Transfer Services, and a service specification "will provide a specification for all elements that are left abstract in this document". The annex ships a Requirements List with a blank support column, which service specifications are expected to import and profile.

So conformance is properly claimed by a service — the Monitored Data service of CCSDS 922.1-B-2, say — and not by the framework. What follows states which of the framework's protocol elements this package encodes and decodes, which is what a service built on it would need. It is not a claim to implement a CSTS.


A1 IDENTIFICATION

FieldValue
Date of Statement (DD/MM/YYYY)04/09/2026
ICS Serial NumberASTRO-CSTS-ICS-001
Implementation Nameastro/pkg/csts
Implementation VersionSee go.mod / latest commit on main
SupplierRavi Suhag
Contact Point for QueriesGitHub, github.com/ravisuhag/astro
SpecificationCCSDS 921.1-B-2 (Cross Support Transfer Service—Specification Framework, Blue Book, February 2021)
Underlying protocolCCSDS 913.1-B-2 (ISP1), implemented by pkg/sle
Have any exceptions been required?Yes [X] No [ ], see A3

A2 REQUIREMENTS

Framework protocol data unit, annex F3.15

FeatureReferenceStatusSupport
The 20 CHOICE alternatives and their context tagsF3.15MY: all 20, pinned against the module
Implicit tagging — the context tag replaces the type's ownF3.15, and every module's IMPLICIT TAGSMY: alternatives declared X ::= StandardReturnHeader carry no SEQUENCE inside the context tag
A tag outside the 20F3.15Y: refused, not passed along
A primitive alternative tagF3.15Y: refused — every alternative is a SEQUENCE

Common operations, clause 3 and annex F3.4

FeatureReferenceStatusSupport
Standard invocation header3.3.2, F3.3MY: credentials, invoke-id, procedure-name
Standard return header3.3.2, F3.3MY: credentials, invoke-id, the result CHOICE and its diagnostic
Standard acknowledge header3.3.2, F3.3MY: the same type as the return header, told apart by the PDU tag per the note under 3.3.1.3
PEER-ABORT has no header3.3.1.1MY: the one exception, and Header reports none for it
The invoke-id is copied unchanged into a response3.3.2.4.2MY: carried; pairing invocations with responses is the caller's, as the association machine is
BIND, UNBIND, PEER-ABORT3.4–3.6, F3.5MY
START, STOP3.7, 3.8, F3.4MY
TRANSFER-DATA3.9, F3.4MY
PROCESS-DATA3.10, F3.4MY
NOTIFY3.11, F3.4MY
GET3.12, F3.4MY: the parameter list is carried encoded, see A3
EXECUTE-DIRECTIVE3.13, F3.4MP: the acknowledgement and return are the standard header; the invocation is carried as octets, see A3

Common types, annex F3.3

FeatureReferenceStatusSupport
Credentials CHOICE, and the SIZE (8..256) on the used alternativeF3.3MY: checked on encode as well as decode
ProcedureName: type, and the three-way role CHOICEF3.3, 3.3.2.5MY
Secondary procedure instance number is IntPosF3.3MY: zero refused
Diagnostic, four defined alternativesF3.3MY
Diagnostic extension [100]F3.3OY: carried as octets — its syntax is named by the procedure, not by this document
Extended CHOICE, notUsed defaultF2.1, F3.3MY: written as notUsed
AuthorityIdentifier SIZE (3..16)F3.3MY
IdentifierString excludes the blankF3.3MY: VisibleString (FROM (ALL EXCEPT " "))
IntUnsigned 0..2³²−1, IntPos 1..2³²−1F3.3MY: Go's int64 holds values neither permits, so the range is checked
ServiceInstanceIdentifierF3.2MY: three OIDs and an instance number

Object identifiers, annex F3.1

FeatureReferenceStatusSupport
The framework arc, {1 3 112 4 4 1 1}F3.1MY
The 18 operation identifiersF3.1MY
The 7 procedure types and 3 derived proceduresF3.1MY: a derived procedure sits under the one it derives from, not beside it
A procedure type outside the framework's ownF3.1OY: carried and reported by OID, not named — see A3

PEER-ABORT diagnostic partition, annex F3.5

FeatureReferenceStatusSupport
The 12 Association Control values, 40–513.6.2.2, F3.5MY
forwardBufferTooLarge (70)F3.5OY
otherReason (126)F3.5MY
Values allocated by SLE, ISP1 and the applicationF3.5Y: the origin is reported; the value is not named, see A3

A3 EXCEPTIONS AND UNSUPPORTED FEATURES

Conformance belongs to a service, not to this package. Annex A1.1 says so directly, and it is the first thing on this page for that reason. This package is a codec for the framework's protocol elements; a CSTS is what a service specification defines on top of them.

The procedures are not state machines here. Section 4 specifies twelve procedures with their own states, timers and rules. This package reads and writes their messages and runs none of them. That is the same split pkg/sle makes — pure codecs, and an association machine the caller pumps — and for the same reason: a library that owned timers would own a scheduling policy the standard does not specify.

Three PDU alternatives are carried as octets. The EXECUTE-DIRECTIVE invocation, whose directive qualifier is a four-way CHOICE over SANA-registered identifiers; and the forward and return buffers, which belong to the Buffered Data Processing and Buffered Data Delivery procedures rather than to the common operations of annex F3.4. Their octets are kept and re-encode unchanged, so nothing is lost by decoding one.

Several fields are carried as encoded octets. A Time, a Name, an EventValue, a ListOfParametersEvents, a TypeAndValue. Each is built from identifiers registered with SANA rather than fixed by this document. A Go type for them would be a type for a registry that changes without this package, and the registry is where their meaning lives.

Values outside the framework's own registrations are not named. A procedure type a service defines comes back as an OID; a PEER-ABORT diagnostic in the application range comes back with its origin and its number. Naming either would mean guessing which service is on the other end, which is exactly what pkg/sle refuses to do when it demands --service.

Credentials are carried, not computed. Annex F3.3 says the structure depends on the algorithm and does not specify it; clause 2.6 says an implementation over ISP1 uses that document's algorithm. So the octets are the ones pkg/sle builds, and a caller that needs them reaches for that package.

The extension mechanism is written as notUsed. Clause F2.1 makes that the value when the capability is unused, and every extension point in the framework is defined by a procedure or a service rather than here. An extension that arrives on decode is not refused; it is read past.

The vectors are derived, not published. CCSDS 921.1-B-2 prints no worked example and no octets — it is an abstract specification with an ASN.1 annex. Each vector carries its derivation from annex F octet by octet in its note, so the derivation can be checked against the module rather than against this package. That is a weaker footing than the navigation packages have, where annex G prints files, and it is stated rather than glossed over.


A4 IMPLEMENTATION LIMITS

LimitValueSource
PDU alternatives20Annex F3.15
Credentials length8 to 256 octetsAnnex F3.3 SIZE constraint
Authority identifier3 to 16 characters, no blanksAnnex F3.3
Logical port name1 to 128 characters, no blanksAnnex F3.3
Appellation1 to 128 charactersAnnex F3.3
Integer range0 to 2³²−1, or 1 to 2³²−1 for IntPosAnnex F3.3
PEER-ABORT diagnostic1 octetAnnex F3.5, which notes ISP1 allows no more
BER length ceiling16 MiB by defaultinternal/ber, shared with pkg/sle

Wire test vectors

The files backing this statement live in the vector corpus — 10 vectors, 5 encode and 5 decode.

File
csts/framework.json10 vectors

These are derived, not published, and the corpus note says so. CCSDS 921.1-B-2 prints no octets at all. Each vector's note carries its derivation from annex F octet by octet, which is the most a reader can be given: it lets the derivation be checked against the module instead of against this package.

What they pin hardest is the implicit tagging. A CHOICE alternative's context tag replaces the tag of the type beneath it, so an alternative declared X ::= StandardReturnHeader encodes with no SEQUENCE inside its context tag. Writing one there as well produces a PDU one level too deep — which round-trips perfectly against itself, and against nothing else.

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.