space-data-module-sdk 0.8.12 → 0.8.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/bin/space-data-module.js +52 -0
- package/docs/flatsql-host-contract.md +34 -1
- package/docs/module-publication-standard.md +7 -3
- package/docs/propagator-abi.md +477 -0
- package/include/orbpro/orbpro_propagator_abi.h +312 -0
- package/package.json +9 -3
- package/schemas/PluginManifest.fbs +46 -1
- package/schemas/orbpro/Propagator.fbs +161 -3
- package/src/bundle/index.js +1 -0
- package/src/bundle/sigdomain.js +22 -0
- package/src/capabilities.js +53 -1
- package/src/compliance/index.js +6 -0
- package/src/compliance/pluginCompliance.js +76 -16
- package/src/flow/flowCompiler.js +30 -14
- package/src/generated/orbpro/manifest/plugin-family.d.ts +9 -1
- package/src/generated/orbpro/manifest/plugin-family.js +8 -0
- package/src/generated/orbpro/manifest/plugin-family.ts +8 -0
- package/src/generated/orbpro/propagator-abi.js +118 -0
- package/src/generated/orbpro/propagator-abi.ts +199 -0
- package/src/manifest/normalize.js +113 -4
- package/src/scaffold/copyTemplate.js +71 -0
- package/src/scaffold/index.js +150 -0
- package/src/scaffold/tokens.js +90 -0
- package/templates/propagator-module/README.md +99 -0
- package/templates/propagator-module/build.js +103 -0
- package/templates/propagator-module/package.json +19 -0
- package/templates/propagator-module/plugin-manifest.json +66 -0
- package/templates/propagator-module/src/__MODULE_NAME_SNAKE__.cpp +450 -0
- package/templates/propagator-module/tests/module.build.test.mjs +103 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/* ===========================================================================
|
|
2
|
+
* GENERATED FILE — DO NOT EDIT.
|
|
3
|
+
*
|
|
4
|
+
* Source of truth : schemas/orbpro/Propagator.fbs
|
|
5
|
+
* Generator : scripts/generate-propagator-abi.mjs
|
|
6
|
+
* Drift gate : scripts/check-propagator-abi.mjs (runs in `npm test`)
|
|
7
|
+
* Contract : docs/propagator-abi.md
|
|
8
|
+
*
|
|
9
|
+
* Edit the .fbs and regenerate. A hand edit here is erased by the next run and
|
|
10
|
+
* failed by the gate in between — which is the point: this file existing in
|
|
11
|
+
* five hand-maintained copies is the drift that
|
|
12
|
+
* graph/findings/official-harness-shapes.md §3 forbids.
|
|
13
|
+
* ===========================================================================
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
#ifndef ORBPRO_PROPAGATOR_ABI_H
|
|
17
|
+
#define ORBPRO_PROPAGATOR_ABI_H
|
|
18
|
+
|
|
19
|
+
#include <stdint.h>
|
|
20
|
+
#include <stddef.h> /* offsetof */
|
|
21
|
+
|
|
22
|
+
/* The ABI locks below must compile in both C and C++ — first-party
|
|
23
|
+
* modules are C++ (sgp4_plugin.cpp, poly_coverage_module.cpp) while the
|
|
24
|
+
* reference module and the header's own examples are C. */
|
|
25
|
+
#if defined(__cplusplus)
|
|
26
|
+
#define ORBPRO_ABI_STATIC_ASSERT(cond, msg) static_assert(cond, msg)
|
|
27
|
+
#else
|
|
28
|
+
#define ORBPRO_ABI_STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#ifdef __cplusplus
|
|
32
|
+
extern "C" {
|
|
33
|
+
#endif
|
|
34
|
+
|
|
35
|
+
/* ========================================================================= */
|
|
36
|
+
/* ReferenceFrame */
|
|
37
|
+
/* ========================================================================= */
|
|
38
|
+
|
|
39
|
+
/** ReferenceFrame */
|
|
40
|
+
typedef enum {
|
|
41
|
+
ORBPRO_FRAME_TEME = 0,
|
|
42
|
+
ORBPRO_FRAME_J2000 = 1,
|
|
43
|
+
ORBPRO_FRAME_ICRF = 2,
|
|
44
|
+
ORBPRO_FRAME_ECEF = 3,
|
|
45
|
+
ORBPRO_FRAME_MCI = 4,
|
|
46
|
+
ORBPRO_FRAME_MCMF = 5,
|
|
47
|
+
} OrbProReferenceFrame;
|
|
48
|
+
|
|
49
|
+
/* ========================================================================= */
|
|
50
|
+
/* StateFlags */
|
|
51
|
+
/* ========================================================================= */
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* StateVector.flags is a BITFIELD carrying any OR-combination of these, so it
|
|
55
|
+
* is declared `uint` on the struct rather than typed to this enum. The C
|
|
56
|
+
* enumerators are generated from here anyway — they are the contract.
|
|
57
|
+
*/
|
|
58
|
+
typedef enum {
|
|
59
|
+
ORBPRO_STATE_NONE = 0,
|
|
60
|
+
ORBPRO_STATE_VALID = 1,
|
|
61
|
+
ORBPRO_STATE_IN_ECLIPSE = 2,
|
|
62
|
+
ORBPRO_STATE_DECAYED = 4,
|
|
63
|
+
ORBPRO_STATE_MANEUVERING = 8,
|
|
64
|
+
ORBPRO_STATE_EXTRAPOLATED = 16,
|
|
65
|
+
ORBPRO_STATE_HAS_COVARIANCE = 32,
|
|
66
|
+
} OrbProStateFlags;
|
|
67
|
+
|
|
68
|
+
/* ========================================================================= */
|
|
69
|
+
/* OrbProStateVector — 64 bytes, 8-byte aligned */
|
|
70
|
+
/* ========================================================================= */
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Orbital state vector — 64 bytes, 8-byte aligned. Mirrors
|
|
74
|
+
* `OrbProStateVector` in orbpro-integration/sdk/include/orbpro_propagator.h
|
|
75
|
+
* byte for byte:
|
|
76
|
+
*
|
|
77
|
+
* 0 8 epoch (Julian date, float64)
|
|
78
|
+
* 8 24 position (METERS)
|
|
79
|
+
* 32 24 velocity (METERS/SECOND)
|
|
80
|
+
* 56 1 reference_frame (ubyte)
|
|
81
|
+
* 57 3 padding, MUST be zero
|
|
82
|
+
* 60 4 flags (uint32)
|
|
83
|
+
*
|
|
84
|
+
* NORMATIVE UNITS: position METERS, velocity METERS/SECOND. There is no km
|
|
85
|
+
* variant and no host-side conversion — the engine hands these straight to
|
|
86
|
+
* Cesium Cartesian3, whose unit is metres, and both shipped propagators emit
|
|
87
|
+
* meters. The C header used to declare `reference_frame` as a uint32 at
|
|
88
|
+
* offset 56, wire-identical to this ubyte+padding only by little-endian
|
|
89
|
+
* accident; it now declares ubyte + 3 reserved so the two agree by
|
|
90
|
+
* construction.
|
|
91
|
+
*
|
|
92
|
+
* Ruling: graph/findings/official-harness-shapes.md §4.1 / §4.2
|
|
93
|
+
*
|
|
94
|
+
* Binary layout (derived from the IDL, not hand-written):
|
|
95
|
+
*
|
|
96
|
+
* Offset Size Field
|
|
97
|
+
* ------ ---- -----------------------------------------
|
|
98
|
+
* 0 8 epoch
|
|
99
|
+
* 8 24 position
|
|
100
|
+
* 32 24 velocity
|
|
101
|
+
* 56 1 reference_frame
|
|
102
|
+
* 57 3 (alignment padding — MUST be written as zero)
|
|
103
|
+
* 60 4 flags
|
|
104
|
+
*/
|
|
105
|
+
typedef struct {
|
|
106
|
+
double epoch; /**< Julian date of this state. */
|
|
107
|
+
double position[3]; /**< Position [x, y, z] in METERS. */
|
|
108
|
+
double velocity[3]; /**< Velocity [vx, vy, vz] in METERS PER SECOND. */
|
|
109
|
+
uint8_t reference_frame; /**< Reference frame of position/velocity. One byte; the three bytes that follow are alignment padding and MUST be written as zero. */
|
|
110
|
+
uint8_t _reserved[3]; /**< Alignment padding at offset 57. MUST be 0. */
|
|
111
|
+
uint32_t flags; /**< StateFlags bitfield. */
|
|
112
|
+
} OrbProStateVector;
|
|
113
|
+
|
|
114
|
+
ORBPRO_ABI_STATIC_ASSERT(sizeof(OrbProStateVector) == 64,
|
|
115
|
+
"OrbProStateVector must be 64 bytes");
|
|
116
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProStateVector, epoch) == 0,
|
|
117
|
+
"OrbProStateVector.epoch must be at offset 0");
|
|
118
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProStateVector, position) == 8,
|
|
119
|
+
"OrbProStateVector.position must be at offset 8");
|
|
120
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProStateVector, velocity) == 32,
|
|
121
|
+
"OrbProStateVector.velocity must be at offset 32");
|
|
122
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProStateVector, reference_frame) == 56,
|
|
123
|
+
"OrbProStateVector.reference_frame must be at offset 56");
|
|
124
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProStateVector, flags) == 60,
|
|
125
|
+
"OrbProStateVector.flags must be at offset 60");
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Zero an entire OrbProStateVector, INCLUDING its alignment padding.
|
|
129
|
+
* Start every write here — see the note above about scratch buffers.
|
|
130
|
+
*/
|
|
131
|
+
static inline void orbpro_state_init(OrbProStateVector* value) {
|
|
132
|
+
for (size_t i = 0; i < sizeof(*value); ++i) {
|
|
133
|
+
((unsigned char*)value)[i] = 0;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Set OrbProStateVector.reference_frame AND clear the 3 padding byte(s)
|
|
139
|
+
* that follow it. USE THIS instead of assigning the field directly.
|
|
140
|
+
*/
|
|
141
|
+
static inline void orbpro_state_set_reference_frame(OrbProStateVector* value, OrbProReferenceFrame v) {
|
|
142
|
+
value->reference_frame = (uint8_t)v;
|
|
143
|
+
((unsigned char*)value)[57] = 0;
|
|
144
|
+
((unsigned char*)value)[58] = 0;
|
|
145
|
+
((unsigned char*)value)[59] = 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* ========================================================================= */
|
|
149
|
+
/* OrbProOrbitalElements — 64 bytes, 8-byte aligned */
|
|
150
|
+
/* ========================================================================= */
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Keplerian orbital elements — the OPTIONAL initialization input accepted by
|
|
154
|
+
* `plugin_init_elements`. 64 bytes, 8-byte aligned.
|
|
155
|
+
*
|
|
156
|
+
* UNITS NOTE: `semi_major_axis` is KILOMETRES. That is deliberate and it is
|
|
157
|
+
* NOT an inconsistency with StateVector's metres: this is an INPUT element
|
|
158
|
+
* set, not an output state vector, and the two are different structs on
|
|
159
|
+
* different sides of the call. Do not "unify" them — see the normative units
|
|
160
|
+
* block in the generated C header.
|
|
161
|
+
*
|
|
162
|
+
* Binary layout (derived from the IDL, not hand-written):
|
|
163
|
+
*
|
|
164
|
+
* Offset Size Field
|
|
165
|
+
* ------ ---- -----------------------------------------
|
|
166
|
+
* 0 8 semi_major_axis
|
|
167
|
+
* 8 8 eccentricity
|
|
168
|
+
* 16 8 inclination
|
|
169
|
+
* 24 8 raan
|
|
170
|
+
* 32 8 arg_periapsis
|
|
171
|
+
* 40 8 true_anomaly
|
|
172
|
+
* 48 8 epoch
|
|
173
|
+
* 56 8 reserved
|
|
174
|
+
*/
|
|
175
|
+
typedef struct {
|
|
176
|
+
double semi_major_axis; /**< Semi-major axis in KILOMETRES. */
|
|
177
|
+
double eccentricity; /**< Orbital eccentricity (0 = circular, <1 = ellipse). */
|
|
178
|
+
double inclination; /**< Inclination in RADIANS. */
|
|
179
|
+
double raan; /**< Right ascension of the ascending node in RADIANS. */
|
|
180
|
+
double arg_periapsis; /**< Argument of periapsis in RADIANS. */
|
|
181
|
+
double true_anomaly; /**< True anomaly in RADIANS. */
|
|
182
|
+
double epoch; /**< Epoch as a Julian date. */
|
|
183
|
+
double reserved; /**< Reserved, MUST be written as 0. */
|
|
184
|
+
} OrbProOrbitalElements;
|
|
185
|
+
|
|
186
|
+
ORBPRO_ABI_STATIC_ASSERT(sizeof(OrbProOrbitalElements) == 64,
|
|
187
|
+
"OrbProOrbitalElements must be 64 bytes");
|
|
188
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOrbitalElements, semi_major_axis) == 0,
|
|
189
|
+
"OrbProOrbitalElements.semi_major_axis must be at offset 0");
|
|
190
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOrbitalElements, eccentricity) == 8,
|
|
191
|
+
"OrbProOrbitalElements.eccentricity must be at offset 8");
|
|
192
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOrbitalElements, inclination) == 16,
|
|
193
|
+
"OrbProOrbitalElements.inclination must be at offset 16");
|
|
194
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOrbitalElements, raan) == 24,
|
|
195
|
+
"OrbProOrbitalElements.raan must be at offset 24");
|
|
196
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOrbitalElements, arg_periapsis) == 32,
|
|
197
|
+
"OrbProOrbitalElements.arg_periapsis must be at offset 32");
|
|
198
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOrbitalElements, true_anomaly) == 40,
|
|
199
|
+
"OrbProOrbitalElements.true_anomaly must be at offset 40");
|
|
200
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOrbitalElements, epoch) == 48,
|
|
201
|
+
"OrbProOrbitalElements.epoch must be at offset 48");
|
|
202
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOrbitalElements, reserved) == 56,
|
|
203
|
+
"OrbProOrbitalElements.reserved must be at offset 56");
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Zero an entire OrbProOrbitalElements, INCLUDING its alignment padding.
|
|
207
|
+
* Start every write here — see the note above about scratch buffers.
|
|
208
|
+
*/
|
|
209
|
+
static inline void orbpro_elements_init(OrbProOrbitalElements* value) {
|
|
210
|
+
for (size_t i = 0; i < sizeof(*value); ++i) {
|
|
211
|
+
((unsigned char*)value)[i] = 0;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* ========================================================================= */
|
|
216
|
+
/* OrbProOMMRecord — 88 bytes, 8-byte aligned */
|
|
217
|
+
/* ========================================================================= */
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Binary OMM record — the mean-element ingest struct. 88 bytes, 8-byte
|
|
221
|
+
* aligned.
|
|
222
|
+
*
|
|
223
|
+
* !! THIS STRUCT IS ALSO AN ON-DISK FORMAT !!
|
|
224
|
+
* -----------------------------------------------------------------------
|
|
225
|
+
* It crosses the ABI (`plugin_init_omm`, `plugin_entity_add_omm`) AND is
|
|
226
|
+
* persisted verbatim as a SQLite BLOB by the first-party SGP4 module
|
|
227
|
+
* (`sgp4_plugin.cpp`, `sqlite3_bind_blob(..., &omm, sizeof(OrbProOMMRecord), ...)`).
|
|
228
|
+
* Until W1.1 it carried NO size or offset lock anywhere in the stack, so the
|
|
229
|
+
* layout that every stored blob depends on was held only by the field order
|
|
230
|
+
* of one hand-written C struct in one module.
|
|
231
|
+
*
|
|
232
|
+
* The layout declared here is that layout, EXACTLY as it has been written to
|
|
233
|
+
* disk — the four trailing padding bytes at offset 84 included. This is a
|
|
234
|
+
* description of the wire as it already exists, not a redesign of it; the
|
|
235
|
+
* generated locks now pin it. Migrating the format is explicitly out of
|
|
236
|
+
* scope and would invalidate every stored blob.
|
|
237
|
+
*
|
|
238
|
+
* UNITS: angles in DEGREES, mean motion in REV/DAY, bstar in 1/earth-radii.
|
|
239
|
+
* These are the SDS $OMM units, carried through unconverted.
|
|
240
|
+
*
|
|
241
|
+
* Binary layout (derived from the IDL, not hand-written):
|
|
242
|
+
*
|
|
243
|
+
* Offset Size Field
|
|
244
|
+
* ------ ---- -----------------------------------------
|
|
245
|
+
* 0 8 epoch_jd
|
|
246
|
+
* 8 8 mean_motion
|
|
247
|
+
* 16 8 eccentricity
|
|
248
|
+
* 24 8 inclination
|
|
249
|
+
* 32 8 ra_of_asc_node
|
|
250
|
+
* 40 8 arg_of_pericenter
|
|
251
|
+
* 48 8 mean_anomaly
|
|
252
|
+
* 56 8 bstar
|
|
253
|
+
* 64 8 mean_motion_dot
|
|
254
|
+
* 72 8 mean_motion_ddot
|
|
255
|
+
* 80 4 norad_cat_id
|
|
256
|
+
* 84 4 (alignment padding — MUST be written as zero)
|
|
257
|
+
*/
|
|
258
|
+
typedef struct {
|
|
259
|
+
double epoch_jd; /**< Epoch as a Julian date (callers convert ISO 8601 -> JD). */
|
|
260
|
+
double mean_motion; /**< Mean motion in REV/DAY. */
|
|
261
|
+
double eccentricity; /**< Eccentricity (unitless). */
|
|
262
|
+
double inclination; /**< Inclination in DEGREES. */
|
|
263
|
+
double ra_of_asc_node; /**< Right ascension of the ascending node in DEGREES. */
|
|
264
|
+
double arg_of_pericenter; /**< Argument of pericenter in DEGREES. */
|
|
265
|
+
double mean_anomaly; /**< Mean anomaly in DEGREES. */
|
|
266
|
+
double bstar; /**< B* drag term in 1/earth-radii. */
|
|
267
|
+
double mean_motion_dot; /**< First derivative of mean motion, REV/DAY^2. */
|
|
268
|
+
double mean_motion_ddot; /**< Second derivative of mean motion, REV/DAY^3. */
|
|
269
|
+
uint32_t norad_cat_id; /**< NORAD catalog number — the identity authority for this record. */
|
|
270
|
+
uint8_t _reserved[4]; /**< Alignment padding at offset 84. MUST be 0. */
|
|
271
|
+
} OrbProOMMRecord;
|
|
272
|
+
|
|
273
|
+
ORBPRO_ABI_STATIC_ASSERT(sizeof(OrbProOMMRecord) == 88,
|
|
274
|
+
"OrbProOMMRecord must be 88 bytes");
|
|
275
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, epoch_jd) == 0,
|
|
276
|
+
"OrbProOMMRecord.epoch_jd must be at offset 0");
|
|
277
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, mean_motion) == 8,
|
|
278
|
+
"OrbProOMMRecord.mean_motion must be at offset 8");
|
|
279
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, eccentricity) == 16,
|
|
280
|
+
"OrbProOMMRecord.eccentricity must be at offset 16");
|
|
281
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, inclination) == 24,
|
|
282
|
+
"OrbProOMMRecord.inclination must be at offset 24");
|
|
283
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, ra_of_asc_node) == 32,
|
|
284
|
+
"OrbProOMMRecord.ra_of_asc_node must be at offset 32");
|
|
285
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, arg_of_pericenter) == 40,
|
|
286
|
+
"OrbProOMMRecord.arg_of_pericenter must be at offset 40");
|
|
287
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, mean_anomaly) == 48,
|
|
288
|
+
"OrbProOMMRecord.mean_anomaly must be at offset 48");
|
|
289
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, bstar) == 56,
|
|
290
|
+
"OrbProOMMRecord.bstar must be at offset 56");
|
|
291
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, mean_motion_dot) == 64,
|
|
292
|
+
"OrbProOMMRecord.mean_motion_dot must be at offset 64");
|
|
293
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, mean_motion_ddot) == 72,
|
|
294
|
+
"OrbProOMMRecord.mean_motion_ddot must be at offset 72");
|
|
295
|
+
ORBPRO_ABI_STATIC_ASSERT(offsetof(OrbProOMMRecord, norad_cat_id) == 80,
|
|
296
|
+
"OrbProOMMRecord.norad_cat_id must be at offset 80");
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Zero an entire OrbProOMMRecord, INCLUDING its alignment padding.
|
|
300
|
+
* Start every write here — see the note above about scratch buffers.
|
|
301
|
+
*/
|
|
302
|
+
static inline void orbpro_omm_init(OrbProOMMRecord* value) {
|
|
303
|
+
for (size_t i = 0; i < sizeof(*value); ++i) {
|
|
304
|
+
((unsigned char*)value)[i] = 0;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
#ifdef __cplusplus
|
|
309
|
+
} /* extern "C" */
|
|
310
|
+
#endif
|
|
311
|
+
|
|
312
|
+
#endif /* ORBPRO_PROPAGATOR_ABI_H */
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "space-data-module-sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.14",
|
|
4
|
+
"license": "Apache-2.0",
|
|
4
5
|
"description": "Module SDK for building, validating, signing, and deploying WebAssembly modules on the Space Data Network.",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"types": "./src/index.d.ts",
|
|
@@ -29,6 +30,8 @@
|
|
|
29
30
|
"types": "./src/licensing/index.d.ts",
|
|
30
31
|
"default": "./src/licensing/index.js"
|
|
31
32
|
},
|
|
33
|
+
"./include/*": "./include/*",
|
|
34
|
+
"./generated/propagator-abi": "./src/generated/orbpro/propagator-abi.js",
|
|
32
35
|
"./compiler": "./src/compiler/index.js",
|
|
33
36
|
"./compiler/emception": "./src/compiler/emception.js",
|
|
34
37
|
"./bundle": "./src/bundle/index.js",
|
|
@@ -75,6 +78,7 @@
|
|
|
75
78
|
"files": [
|
|
76
79
|
"bin/",
|
|
77
80
|
"docs/",
|
|
81
|
+
"include/",
|
|
78
82
|
"parity/",
|
|
79
83
|
"schemas/",
|
|
80
84
|
"src/",
|
|
@@ -98,13 +102,15 @@
|
|
|
98
102
|
"check:nav": "node scripts/check-sdn-stack-nav.mjs module-sdk docs/index.html docs/styles.css",
|
|
99
103
|
"check:compliance": "node ./bin/space-data-module.js check --repo-root .",
|
|
100
104
|
"check:generated-bindings": "node scripts/check-generated-bindings.mjs",
|
|
105
|
+
"check:propagator-abi": "node scripts/check-propagator-abi.mjs",
|
|
106
|
+
"generate:propagator-abi": "node scripts/generate-propagator-abi.mjs",
|
|
101
107
|
"generate:vectors": "node ./examples/single-file-bundle/generate-vectors.mjs",
|
|
102
108
|
"prepublishOnly": "npm test && npm run check:compliance"
|
|
103
109
|
},
|
|
104
110
|
"dependencies": {
|
|
105
111
|
"flatbuffers": "^25.9.23",
|
|
106
112
|
"flatc-wasm": "^26.1.32",
|
|
107
|
-
"flatsql": "^
|
|
113
|
+
"flatsql": "^2.0.0",
|
|
108
114
|
"hd-wallet-wasm": "2.0.28",
|
|
109
115
|
"sdn-emception": "1.0.0",
|
|
110
116
|
"spacedatastandards.org": "https://github.com/DigitalArsenal/spacedatastandards.org/archive/06deda5079204a46bd97a7ce6ac2868e991c6b8f.tar.gz"
|
|
@@ -116,4 +122,4 @@
|
|
|
116
122
|
"engines": {
|
|
117
123
|
"node": ">=20.0.0"
|
|
118
124
|
}
|
|
119
|
-
}
|
|
125
|
+
}
|
|
@@ -7,6 +7,24 @@ include "TypedArenaBuffer.fbs";
|
|
|
7
7
|
namespace orbpro.manifest;
|
|
8
8
|
|
|
9
9
|
/// Canonical plugin family.
|
|
10
|
+
///
|
|
11
|
+
/// APPEND-ONLY. Ordinals are wire and MUST never be renumbered or reused.
|
|
12
|
+
///
|
|
13
|
+
/// This enum is a PROJECTION of the authoritative SDS vocabulary
|
|
14
|
+
/// `pluginCategory` (spacedatastandards.org `schema/PLG/main.fbs`). SDS is the
|
|
15
|
+
/// source of truth for what families exist; this enum is what the SDK code
|
|
16
|
+
/// dispatches on. The two DO NOT share ordinals — they diverge from index 5
|
|
17
|
+
/// onward (SDK `COMMS = 5`, SDS `EW = 5`) — so the SDK↔SDS mapping is BY NAME,
|
|
18
|
+
/// declared explicitly in `src/manifest/normalize.js`
|
|
19
|
+
/// (`sdsPluginCategoryByFamily`). Never convert one to the other numerically.
|
|
20
|
+
///
|
|
21
|
+
/// Unknown family strings used to be silently coerced to `ANALYSIS`, which
|
|
22
|
+
/// mislabelled 19 first-party modules and made family-typed resolution work
|
|
23
|
+
/// for propagators only. `normalizePluginFamily()` now REFUSES an unknown
|
|
24
|
+
/// family, naming it and the valid vocabulary.
|
|
25
|
+
///
|
|
26
|
+
/// Ruling: graph/findings/official-harness-shapes.md §4.7 / §8.3
|
|
27
|
+
/// Task: graph/tasks/harness-w0-immediate-fixes.md (W0.3)
|
|
10
28
|
enum PluginFamily : ubyte {
|
|
11
29
|
SENSOR = 0,
|
|
12
30
|
PROPAGATOR = 1,
|
|
@@ -18,7 +36,34 @@ enum PluginFamily : ubyte {
|
|
|
18
36
|
SDF = 7,
|
|
19
37
|
INFRASTRUCTURE = 8,
|
|
20
38
|
FLOW = 9,
|
|
21
|
-
BRIDGE = 10
|
|
39
|
+
BRIDGE = 10,
|
|
40
|
+
/// Maneuver planning, targeting and trajectory optimization.
|
|
41
|
+
/// Projects onto SDS `pluginCategory.Maneuver`.
|
|
42
|
+
MANEUVER = 11,
|
|
43
|
+
/// Orbit determination: fitting an orbit to observations/ephemerides.
|
|
44
|
+
/// SDS has NO dedicated member yet — this projects onto
|
|
45
|
+
/// `pluginCategory.Analysis` until Themis mints one. That gap is filed as
|
|
46
|
+
/// graph/tasks/sds-plugin-category-projection-gaps.md.
|
|
47
|
+
ORBIT_DETERMINATION = 12,
|
|
48
|
+
/// Foundational math / utility library module (frames, time, numerics,
|
|
49
|
+
/// attitude, splines). Projects onto SDS `pluginCategory.Foundation`.
|
|
50
|
+
FOUNDATION = 13,
|
|
51
|
+
/// Parses raw upstream bytes into canonical SDS records.
|
|
52
|
+
/// Projects onto SDS `pluginCategory.Parser`.
|
|
53
|
+
PARSER = 14,
|
|
54
|
+
/// Validates records (integrity, physical bounds, continuity).
|
|
55
|
+
/// Projects onto SDS `pluginCategory.Validator`.
|
|
56
|
+
VALIDATOR = 15,
|
|
57
|
+
/// Exports records to external formats (CSV, etc.).
|
|
58
|
+
/// Projects onto SDS `pluginCategory.Exporter`.
|
|
59
|
+
EXPORTER = 16,
|
|
60
|
+
/// Publication: PNM signing + pub/sub announcement.
|
|
61
|
+
/// Projects onto SDS `pluginCategory.Publisher`.
|
|
62
|
+
PUBLISHER = 17,
|
|
63
|
+
/// Astrodynamics simulation / dynamics modelling.
|
|
64
|
+
/// Projects onto SDS `pluginCategory.Basilisk` (a legacy vocabulary key
|
|
65
|
+
/// retained there for wire compatibility).
|
|
66
|
+
BASILISK = 18
|
|
22
67
|
}
|
|
23
68
|
|
|
24
69
|
/// Host capability requested by a plugin.
|
|
@@ -2,7 +2,64 @@ include "BaseTypes.fbs";
|
|
|
2
2
|
|
|
3
3
|
namespace orbpro.propagator;
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// =============================================================================
|
|
6
|
+
// THE PROPAGATOR ABI LIVES HERE. THIS FILE IS THE SINGLE SOURCE OF TRUTH.
|
|
7
|
+
// =============================================================================
|
|
8
|
+
//
|
|
9
|
+
// Every struct below marked `(abi)` is a BINARY CONTRACT that crosses the
|
|
10
|
+
// WASM boundary between a third-party propagator module and the OrbPro engine.
|
|
11
|
+
// The C header, the TypeScript byte-offset bindings and the size/offset locks
|
|
12
|
+
// are all GENERATED from these declarations:
|
|
13
|
+
//
|
|
14
|
+
// node scripts/generate-propagator-abi.mjs # regenerate
|
|
15
|
+
// node scripts/check-propagator-abi.mjs # the drift gate (runs in npm test)
|
|
16
|
+
//
|
|
17
|
+
// Do NOT hand-write a mirror of these structs anywhere. Five hand-vendored
|
|
18
|
+
// copies of `StateVector` is what this lane exists to end, and the units
|
|
19
|
+
// contradiction W0.1 fixed (km in the field comments, METERS in the layout
|
|
20
|
+
// block three lines below) lived for months precisely because there was no
|
|
21
|
+
// mechanical link between the IDL and the header.
|
|
22
|
+
//
|
|
23
|
+
// Contract document: docs/propagator-abi.md
|
|
24
|
+
// Ruling: graph/findings/official-harness-shapes.md §3 / §7 SHIP-1
|
|
25
|
+
// Task: graph/tasks/harness-w1-propagator-abi-and-reference.md (W1.1)
|
|
26
|
+
|
|
27
|
+
/// Marks a struct or enum as part of the binary propagator ABI. Generated
|
|
28
|
+
/// artifacts are derived from exactly the declarations carrying this.
|
|
29
|
+
attribute "abi";
|
|
30
|
+
|
|
31
|
+
/// The C type name a generated ABI declaration takes. Part of the contract:
|
|
32
|
+
/// third-party sources say `OrbProStateVector`, not `orbpro_propagator_StateVector`.
|
|
33
|
+
attribute "abi_c_name";
|
|
34
|
+
|
|
35
|
+
/// The C enumerator prefix for a generated ABI enum (ReferenceFrame's members
|
|
36
|
+
/// are `ORBPRO_FRAME_*`, StateFlags' are `ORBPRO_STATE_*`).
|
|
37
|
+
attribute "abi_c_prefix";
|
|
38
|
+
|
|
39
|
+
/// The C helper-function prefix for a generated ABI struct: the generator emits
|
|
40
|
+
/// `<prefix>init()` and a padding-clearing `<prefix>set_<field>()` for every
|
|
41
|
+
/// enum field. Writing these by hand is how padding bytes go stale.
|
|
42
|
+
attribute "abi_c_helper_prefix";
|
|
43
|
+
|
|
44
|
+
// !! FOUR INCOMPATIBLE `ReferenceFrame` VOCABULARIES CROSS THIS SEAM !!
|
|
45
|
+
// This is the `orbpro.propagator` one. Its NUMERIC values are NOT
|
|
46
|
+
// interchangeable with the others; translate by NAMED TOKEN at every seam.
|
|
47
|
+
//
|
|
48
|
+
// (A) orbpro.propagator (THIS) TEME=0 J2000=1 ICRF=2 ECEF=3 MCI=4 MCMF=5
|
|
49
|
+
// (B) orbpro.plugins ECI=0 ECEF=1 TEME=2 ICRF=3
|
|
50
|
+
// (PropagatorState.fbs / "PRST" — the wire the compiled sgp4, hpop,
|
|
51
|
+
// conjunction-assessment and sensor-shader modules already emit)
|
|
52
|
+
// (C) Cesium.ReferenceFrame FIXED=0 INERTIAL=1
|
|
53
|
+
// (D) ConjunctionCommon.fbs ECI=1
|
|
54
|
+
//
|
|
55
|
+
// ECI==0, TEME==0 and FIXED==0 all collide, and ECEF is 1 in (B) but 3 here.
|
|
56
|
+
// (B)'s values are frozen by compiled WASM artifacts in the field, so
|
|
57
|
+
// collapsing (A) and (B) is a wire break, not a Wave-0 edit — see
|
|
58
|
+
// graph/tasks/sdk-reference-frame-enum-unification.md. The reference pattern
|
|
59
|
+
// for a correct seam is propagator.hpop/index.js createSourceFromState.
|
|
60
|
+
//
|
|
61
|
+
// Ruling: graph/findings/official-harness-shapes.md §4.2 / §8.2
|
|
62
|
+
enum ReferenceFrame : ubyte (abi, abi_c_name: "OrbProReferenceFrame", abi_c_prefix: "ORBPRO_FRAME_") {
|
|
6
63
|
TEME = 0,
|
|
7
64
|
J2000 = 1,
|
|
8
65
|
ICRF = 2,
|
|
@@ -11,7 +68,10 @@ enum ReferenceFrame : ubyte {
|
|
|
11
68
|
MCMF = 5
|
|
12
69
|
}
|
|
13
70
|
|
|
14
|
-
|
|
71
|
+
/// StateVector.flags is a BITFIELD carrying any OR-combination of these, so it
|
|
72
|
+
/// is declared `uint` on the struct rather than typed to this enum. The C
|
|
73
|
+
/// enumerators are generated from here anyway — they are the contract.
|
|
74
|
+
enum StateFlags : uint (abi, abi_c_name: "OrbProStateFlags", abi_c_prefix: "ORBPRO_STATE_") {
|
|
15
75
|
NONE = 0,
|
|
16
76
|
VALID = 1,
|
|
17
77
|
IN_ECLIPSE = 2,
|
|
@@ -42,14 +102,112 @@ enum PropagatorSourceKind : ubyte {
|
|
|
42
102
|
SDP8 = 12
|
|
43
103
|
}
|
|
44
104
|
|
|
45
|
-
|
|
105
|
+
/// Orbital state vector — 64 bytes, 8-byte aligned. Mirrors
|
|
106
|
+
/// `OrbProStateVector` in orbpro-integration/sdk/include/orbpro_propagator.h
|
|
107
|
+
/// byte for byte:
|
|
108
|
+
///
|
|
109
|
+
/// 0 8 epoch (Julian date, float64)
|
|
110
|
+
/// 8 24 position (METERS)
|
|
111
|
+
/// 32 24 velocity (METERS/SECOND)
|
|
112
|
+
/// 56 1 reference_frame (ubyte)
|
|
113
|
+
/// 57 3 padding, MUST be zero
|
|
114
|
+
/// 60 4 flags (uint32)
|
|
115
|
+
///
|
|
116
|
+
/// NORMATIVE UNITS: position METERS, velocity METERS/SECOND. There is no km
|
|
117
|
+
/// variant and no host-side conversion — the engine hands these straight to
|
|
118
|
+
/// Cesium Cartesian3, whose unit is metres, and both shipped propagators emit
|
|
119
|
+
/// meters. The C header used to declare `reference_frame` as a uint32 at
|
|
120
|
+
/// offset 56, wire-identical to this ubyte+padding only by little-endian
|
|
121
|
+
/// accident; it now declares ubyte + 3 reserved so the two agree by
|
|
122
|
+
/// construction.
|
|
123
|
+
///
|
|
124
|
+
/// Ruling: graph/findings/official-harness-shapes.md §4.1 / §4.2
|
|
125
|
+
struct StateVector (abi, abi_c_name: "OrbProStateVector", abi_c_helper_prefix: "orbpro_state_") {
|
|
126
|
+
/// Julian date of this state.
|
|
46
127
|
epoch:double;
|
|
128
|
+
/// Position [x, y, z] in METERS.
|
|
47
129
|
position:orbpro.Vec3;
|
|
130
|
+
/// Velocity [vx, vy, vz] in METERS PER SECOND.
|
|
48
131
|
velocity:orbpro.Vec3;
|
|
132
|
+
/// Reference frame of position/velocity. One byte; the three bytes that
|
|
133
|
+
/// follow are alignment padding and MUST be written as zero.
|
|
49
134
|
reference_frame:ReferenceFrame;
|
|
135
|
+
/// StateFlags bitfield.
|
|
50
136
|
flags:uint;
|
|
51
137
|
}
|
|
52
138
|
|
|
139
|
+
/// Keplerian orbital elements — the OPTIONAL initialization input accepted by
|
|
140
|
+
/// `plugin_init_elements`. 64 bytes, 8-byte aligned.
|
|
141
|
+
///
|
|
142
|
+
/// UNITS NOTE: `semi_major_axis` is KILOMETRES. That is deliberate and it is
|
|
143
|
+
/// NOT an inconsistency with StateVector's metres: this is an INPUT element
|
|
144
|
+
/// set, not an output state vector, and the two are different structs on
|
|
145
|
+
/// different sides of the call. Do not "unify" them — see the normative units
|
|
146
|
+
/// block in the generated C header.
|
|
147
|
+
struct OrbitalElements (abi, abi_c_name: "OrbProOrbitalElements", abi_c_helper_prefix: "orbpro_elements_") {
|
|
148
|
+
/// Semi-major axis in KILOMETRES.
|
|
149
|
+
semi_major_axis:double;
|
|
150
|
+
/// Orbital eccentricity (0 = circular, <1 = ellipse).
|
|
151
|
+
eccentricity:double;
|
|
152
|
+
/// Inclination in RADIANS.
|
|
153
|
+
inclination:double;
|
|
154
|
+
/// Right ascension of the ascending node in RADIANS.
|
|
155
|
+
raan:double;
|
|
156
|
+
/// Argument of periapsis in RADIANS.
|
|
157
|
+
arg_periapsis:double;
|
|
158
|
+
/// True anomaly in RADIANS.
|
|
159
|
+
true_anomaly:double;
|
|
160
|
+
/// Epoch as a Julian date.
|
|
161
|
+
epoch:double;
|
|
162
|
+
/// Reserved, MUST be written as 0.
|
|
163
|
+
reserved:double;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/// Binary OMM record — the mean-element ingest struct. 88 bytes, 8-byte
|
|
167
|
+
/// aligned.
|
|
168
|
+
///
|
|
169
|
+
/// !! THIS STRUCT IS ALSO AN ON-DISK FORMAT !!
|
|
170
|
+
/// -----------------------------------------------------------------------
|
|
171
|
+
/// It crosses the ABI (`plugin_init_omm`, `plugin_entity_add_omm`) AND is
|
|
172
|
+
/// persisted verbatim as a SQLite BLOB by the first-party SGP4 module
|
|
173
|
+
/// (`sgp4_plugin.cpp`, `sqlite3_bind_blob(..., &omm, sizeof(OrbProOMMRecord), ...)`).
|
|
174
|
+
/// Until W1.1 it carried NO size or offset lock anywhere in the stack, so the
|
|
175
|
+
/// layout that every stored blob depends on was held only by the field order
|
|
176
|
+
/// of one hand-written C struct in one module.
|
|
177
|
+
///
|
|
178
|
+
/// The layout declared here is that layout, EXACTLY as it has been written to
|
|
179
|
+
/// disk — the four trailing padding bytes at offset 84 included. This is a
|
|
180
|
+
/// description of the wire as it already exists, not a redesign of it; the
|
|
181
|
+
/// generated locks now pin it. Migrating the format is explicitly out of
|
|
182
|
+
/// scope and would invalidate every stored blob.
|
|
183
|
+
///
|
|
184
|
+
/// UNITS: angles in DEGREES, mean motion in REV/DAY, bstar in 1/earth-radii.
|
|
185
|
+
/// These are the SDS $OMM units, carried through unconverted.
|
|
186
|
+
struct OMMRecord (abi, abi_c_name: "OrbProOMMRecord", abi_c_helper_prefix: "orbpro_omm_") {
|
|
187
|
+
/// Epoch as a Julian date (callers convert ISO 8601 -> JD).
|
|
188
|
+
epoch_jd:double;
|
|
189
|
+
/// Mean motion in REV/DAY.
|
|
190
|
+
mean_motion:double;
|
|
191
|
+
/// Eccentricity (unitless).
|
|
192
|
+
eccentricity:double;
|
|
193
|
+
/// Inclination in DEGREES.
|
|
194
|
+
inclination:double;
|
|
195
|
+
/// Right ascension of the ascending node in DEGREES.
|
|
196
|
+
ra_of_asc_node:double;
|
|
197
|
+
/// Argument of pericenter in DEGREES.
|
|
198
|
+
arg_of_pericenter:double;
|
|
199
|
+
/// Mean anomaly in DEGREES.
|
|
200
|
+
mean_anomaly:double;
|
|
201
|
+
/// B* drag term in 1/earth-radii.
|
|
202
|
+
bstar:double;
|
|
203
|
+
/// First derivative of mean motion, REV/DAY^2.
|
|
204
|
+
mean_motion_dot:double;
|
|
205
|
+
/// Second derivative of mean motion, REV/DAY^3.
|
|
206
|
+
mean_motion_ddot:double;
|
|
207
|
+
/// NORAD catalog number — the identity authority for this record.
|
|
208
|
+
norad_cat_id:uint;
|
|
209
|
+
}
|
|
210
|
+
|
|
53
211
|
table PropagatorDescribeSourcesBatchRequest {
|
|
54
212
|
catalogHandle:uint = 0;
|
|
55
213
|
sourceHandles:[uint];
|
package/src/bundle/index.js
CHANGED
|
@@ -11,6 +11,7 @@ export {
|
|
|
11
11
|
CONTENT_HASH_SIZE as SIGNATURE_STATEMENT_CONTENT_HASH_SIZE,
|
|
12
12
|
DOMAIN_MODULE_PUBLICATION_V1,
|
|
13
13
|
DOMAIN_UPDATE_MANIFEST_V1,
|
|
14
|
+
DOMAIN_UPDATE_SIGNAL_V1,
|
|
14
15
|
SignatureDomainError,
|
|
15
16
|
describe as describeSignatureDomain,
|
|
16
17
|
domains as registeredSignatureDomains,
|
package/src/bundle/sigdomain.js
CHANGED
|
@@ -61,6 +61,24 @@ export const DOMAIN_MODULE_PUBLICATION_V1 = "SDN-MODULE-PUBLICATION-V1";
|
|
|
61
61
|
*/
|
|
62
62
|
export const DOMAIN_UPDATE_MANIFEST_V1 = "SDN-UPDATE-MANIFEST-V1";
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* An UPDATE SIGNAL: the small pub/sub nudge a publisher emits after an artifact
|
|
66
|
+
* is on the update feed, telling the fleet that a new version exists and where
|
|
67
|
+
* to fetch it (owner ruling 2026-08-09, "pushing an update signal to all
|
|
68
|
+
* installs to upgrade in place").
|
|
69
|
+
*
|
|
70
|
+
* A separate domain from {@link DOMAIN_UPDATE_MANIFEST_V1} even though the same
|
|
71
|
+
* bonded key signs both, and the separation is load-bearing in one direction: a
|
|
72
|
+
* signal is a POINTER, a manifest is an AUTHORIZATION. A signal signature is
|
|
73
|
+
* cheap, frequent and broadcast to anyone listening, so if the two shared a
|
|
74
|
+
* preimage space one could be replayed as authorization for bytes. The signal
|
|
75
|
+
* grants nothing — everything it names is re-fetched and re-verified against the
|
|
76
|
+
* signed manifest before a byte is swapped. Registered here so the JS registry
|
|
77
|
+
* still mirrors the node's exactly; a module verifier must REFUSE it, which the
|
|
78
|
+
* shared vectors pin.
|
|
79
|
+
*/
|
|
80
|
+
export const DOMAIN_UPDATE_SIGNAL_V1 = "SDN-UPDATE-SIGNAL-V1";
|
|
81
|
+
|
|
64
82
|
/**
|
|
65
83
|
* The CLOSED set of statement domains this SDK will verify. The map value is a
|
|
66
84
|
* short human description: this table is the answer to "what can the bonded
|
|
@@ -76,6 +94,10 @@ const REGISTRY = new Map([
|
|
|
76
94
|
DOMAIN_UPDATE_MANIFEST_V1,
|
|
77
95
|
"update manifest, canonical manifest SHA-256 (reserved; no producer yet)",
|
|
78
96
|
],
|
|
97
|
+
[
|
|
98
|
+
DOMAIN_UPDATE_SIGNAL_V1,
|
|
99
|
+
"update signal, canonical signal SHA-256 (advisory pub/sub nudge; authorizes nothing)",
|
|
100
|
+
],
|
|
79
101
|
]);
|
|
80
102
|
|
|
81
103
|
const domainTextEncoder = new TextEncoder();
|