space-data-module-sdk 0.2.6 → 0.2.8
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 +73 -0
- package/package.json +5 -1
- package/schemas/PluginManifest.fbs +10 -0
- package/src/bundle/constants.js +4 -1
- package/src/bundle/wasm.js +30 -2
- package/src/compliance/index.js +2 -1
- package/src/compliance/pluginCompliance.js +391 -2
- package/src/deployment/index.d.ts +224 -0
- package/src/deployment/index.js +1552 -0
- package/src/generated/orbpro/manifest/plugin-manifest.d.ts +10 -3
- package/src/generated/orbpro/manifest/plugin-manifest.js +32 -6
- package/src/generated/orbpro/manifest/plugin-manifest.ts +42 -5
- package/src/generated/orbpro/manifest/protocol-spec.d.ts +35 -3
- package/src/generated/orbpro/manifest/protocol-spec.js +120 -6
- package/src/generated/orbpro/manifest/protocol-spec.ts +191 -1
- package/src/index.d.ts +138 -3
- package/src/index.js +4 -0
- package/src/manifest/index.js +7 -0
- package/src/manifest/normalize.js +82 -11
- package/src/manifest/typeRefs.js +143 -0
- package/src/runtime/constants.js +14 -0
- package/src/runtime/index.d.ts +2 -0
- package/src/testing/index.d.ts +86 -0
- package/src/testing/index.js +473 -0
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@ A module built with this SDK is a `.wasm` artifact with:
|
|
|
34
34
|
- an exported `_start` entry when the artifact supports WASI command mode
|
|
35
35
|
- optional `sds.bundle` custom-section payloads for:
|
|
36
36
|
- manifest bytes
|
|
37
|
+
- resolved deployment plans and input bindings
|
|
37
38
|
- deployment authorization
|
|
38
39
|
- detached signatures
|
|
39
40
|
- encrypted transport envelopes
|
|
@@ -81,6 +82,14 @@ outputs. The reference invoke examples live in
|
|
|
81
82
|
- `manifest.hybrid.json`
|
|
82
83
|
- `module.c`
|
|
83
84
|
|
|
85
|
+
Input and output ports can independently declare regular `flatbuffer` payloads
|
|
86
|
+
or `aligned-binary` layouts. Mixed contracts are valid. When a port advertises
|
|
87
|
+
an `aligned-binary` layout, it must also advertise a regular `flatbuffer`
|
|
88
|
+
fallback for the same schema in the same accepted type set. A module can accept
|
|
89
|
+
a regular `OMM.fbs` request and emit an aligned-binary `StateVector.fbs`
|
|
90
|
+
response, provided the output port also declares the regular `StateVector.fbs`
|
|
91
|
+
fallback and the aligned type ref carries the correct layout metadata.
|
|
92
|
+
|
|
84
93
|
## Runtime Portability
|
|
85
94
|
|
|
86
95
|
The module format is language-neutral. A host can load modules from this SDK
|
|
@@ -115,6 +124,39 @@ This repo currently includes:
|
|
|
115
124
|
- a reference Node host and sync `sdn_host` bridge for the first hostcall
|
|
116
125
|
surface
|
|
117
126
|
|
|
127
|
+
## Testing
|
|
128
|
+
|
|
129
|
+
This repo now exposes a manifest-driven harness generator from
|
|
130
|
+
`space-data-module-sdk/testing` and two complementary integration suites:
|
|
131
|
+
|
|
132
|
+
- `npm run test:runtime-matrix`
|
|
133
|
+
- cross-language runtime smoke across the same WASM in Node.js, Go, Python,
|
|
134
|
+
Rust, Java, C#, and Swift
|
|
135
|
+
- covers method calling, aligned-binary envelope metadata preservation,
|
|
136
|
+
stdin/stdout/stderr, args, env, preopened filesystem access, and basic WASI
|
|
137
|
+
clock/time smoke
|
|
138
|
+
- `npm run test:host-surfaces`
|
|
139
|
+
- authoritative Node-host coverage for HTTP, TCP, UDP, TLS, WebSocket, MQTT,
|
|
140
|
+
process execution, timers, filesystem, and the sync `sdn_host` ABI
|
|
141
|
+
|
|
142
|
+
The detailed edge cases and the current WASI-vs-host portability boundary are
|
|
143
|
+
documented in
|
|
144
|
+
[`docs/testing-harness.md`](./docs/testing-harness.md).
|
|
145
|
+
|
|
146
|
+
If a manifest declares `runtimeTargets: ["wasi"]`, this SDK now treats that as
|
|
147
|
+
"standalone WASI, no host wrapper required." In practice that currently means:
|
|
148
|
+
|
|
149
|
+
- the artifact must declare the `command` invoke surface
|
|
150
|
+
- declared capabilities must stay within the pure WASI subset:
|
|
151
|
+
`logging`, `clock`, `random`, `filesystem`, `pipe`
|
|
152
|
+
- hosted protocols may only use `wasi-pipe` transport
|
|
153
|
+
|
|
154
|
+
For maximum server-side portability with guest-owned network services, use
|
|
155
|
+
`runtimeTargets: ["wasmedge"]`. That target is intended for WasmEdge
|
|
156
|
+
environments with socket/TLS extensions, while plain `wasi` remains the strict
|
|
157
|
+
no-wrapper baseline. The Node-RED-oriented parity map lives in
|
|
158
|
+
[`docs/node-red-default-node-parity.md`](./docs/node-red-default-node-parity.md).
|
|
159
|
+
|
|
118
160
|
## Install
|
|
119
161
|
|
|
120
162
|
```bash
|
|
@@ -161,8 +203,36 @@ import { createDeploymentAuthorization } from "space-data-module-sdk/auth";
|
|
|
161
203
|
import { encryptJsonForRecipient } from "space-data-module-sdk/transport";
|
|
162
204
|
import { compileModuleFromSource } from "space-data-module-sdk/compiler";
|
|
163
205
|
import { createSingleFileBundle } from "space-data-module-sdk/bundle";
|
|
206
|
+
import { validateDeploymentPlan } from "space-data-module-sdk/deployment";
|
|
207
|
+
import { generateManifestHarnessPlan } from "space-data-module-sdk/testing";
|
|
164
208
|
```
|
|
165
209
|
|
|
210
|
+
## Protocol Installation
|
|
211
|
+
|
|
212
|
+
Modules can declare hosted protocol contracts in `manifest.protocols`.
|
|
213
|
+
|
|
214
|
+
Those declarations are for stable artifact identity:
|
|
215
|
+
|
|
216
|
+
- `wireId`
|
|
217
|
+
- `transportKind`
|
|
218
|
+
- `role`
|
|
219
|
+
- `specUri`
|
|
220
|
+
- hosting hints like `defaultPort` and `requireSecureTransport`
|
|
221
|
+
|
|
222
|
+
Concrete multiaddrs, peer IDs, and producer routing do not belong in the
|
|
223
|
+
canonical manifest. They belong in deployment metadata attached to the final
|
|
224
|
+
package or bundle.
|
|
225
|
+
|
|
226
|
+
This repo exposes that deployment surface from
|
|
227
|
+
`space-data-module-sdk/deployment`. Use it to:
|
|
228
|
+
|
|
229
|
+
- validate resolved protocol installations
|
|
230
|
+
- describe input bindings from producers to module ports
|
|
231
|
+
- attach a deployment plan to `sds.bundle`
|
|
232
|
+
|
|
233
|
+
The full contract split is documented in
|
|
234
|
+
[`docs/protocol-installation.md`](./docs/protocol-installation.md).
|
|
235
|
+
|
|
166
236
|
## Single-File Bundles
|
|
167
237
|
|
|
168
238
|
`sds.bundle` keeps module delivery to one file without changing WebAssembly
|
|
@@ -179,6 +249,9 @@ The reference path lives in
|
|
|
179
249
|
- the `go` and `python` directories show non-JS readers against the same
|
|
180
250
|
bundle contract
|
|
181
251
|
|
|
252
|
+
Standard bundle payloads now include the optional `deployment-plan` JSON entry
|
|
253
|
+
for resolved protocol installations and producer input bindings.
|
|
254
|
+
|
|
182
255
|
## Module Publication
|
|
183
256
|
|
|
184
257
|
Packages that publish SDN modules now use the canonical `sdn-module`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "space-data-module-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Module SDK for building, validating, signing, and deploying WebAssembly modules on the Space Data Network.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
"./compiler": "./src/compiler/index.js",
|
|
21
21
|
"./compiler/emception": "./src/compiler/emception.js",
|
|
22
22
|
"./bundle": "./src/bundle/index.js",
|
|
23
|
+
"./deployment": "./src/deployment/index.js",
|
|
23
24
|
"./invoke": "./src/invoke/index.js",
|
|
24
25
|
"./runtime": "./src/runtime/index.js",
|
|
26
|
+
"./testing": "./src/testing/index.js",
|
|
25
27
|
"./standards": "./src/standards/index.js",
|
|
26
28
|
"./schemas/*": "./schemas/*"
|
|
27
29
|
},
|
|
@@ -32,6 +34,8 @@
|
|
|
32
34
|
],
|
|
33
35
|
"scripts": {
|
|
34
36
|
"test": "node --test",
|
|
37
|
+
"test:host-surfaces": "node --test test/node-host.test.js test/host-abi.test.js",
|
|
38
|
+
"test:runtime-matrix": "SPACE_DATA_MODULE_SDK_ENABLE_RUNTIME_MATRIX=1 node --test test/runtime-matrix.test.js",
|
|
35
39
|
"start:lab": "node ./lab/server.js",
|
|
36
40
|
"check:compliance": "node ./bin/space-data-module.js check --repo-root .",
|
|
37
41
|
"generate:vectors": "node ./examples/single-file-bundle/generate-vectors.mjs",
|
|
@@ -134,6 +134,15 @@ table ProtocolSpec {
|
|
|
134
134
|
input_port_id: string;
|
|
135
135
|
output_port_id: string;
|
|
136
136
|
description: string;
|
|
137
|
+
wire_id: string;
|
|
138
|
+
transport_kind: string;
|
|
139
|
+
role: string;
|
|
140
|
+
spec_uri: string;
|
|
141
|
+
auto_install: bool = true;
|
|
142
|
+
advertise: bool = false;
|
|
143
|
+
discovery_key: string;
|
|
144
|
+
default_port: uint16;
|
|
145
|
+
require_secure_transport: bool = false;
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
/// Build artifact emitted by the plugin toolchain.
|
|
@@ -170,6 +179,7 @@ table PluginManifest {
|
|
|
170
179
|
build_artifacts: [BuildArtifact];
|
|
171
180
|
abi_version: uint32 = 1;
|
|
172
181
|
invoke_surfaces: [InvokeSurface];
|
|
182
|
+
runtime_targets: [string];
|
|
173
183
|
}
|
|
174
184
|
|
|
175
185
|
root_type PluginManifest;
|
package/src/bundle/constants.js
CHANGED
|
@@ -5,4 +5,7 @@ export const DEFAULT_HASH_ALGORITHM = "sha256";
|
|
|
5
5
|
export const DEFAULT_MANIFEST_EXPORT_SYMBOL = "plugin_get_manifest_flatbuffer";
|
|
6
6
|
export const DEFAULT_MANIFEST_SIZE_SYMBOL =
|
|
7
7
|
"plugin_get_manifest_flatbuffer_size";
|
|
8
|
-
|
|
8
|
+
export const SDS_DEPLOYMENT_SECTION_NAME = "sds.deployment";
|
|
9
|
+
export const SDS_DEPLOYMENT_ENTRY_ID = "deployment-plan";
|
|
10
|
+
export const SDS_DEPLOYMENT_MEDIA_TYPE =
|
|
11
|
+
"application/vnd.space-data.module.deployment+json";
|
package/src/bundle/wasm.js
CHANGED
|
@@ -3,11 +3,14 @@ import { decodePluginManifest, encodePluginManifest } from "../manifest/index.js
|
|
|
3
3
|
import { toUint8Array } from "../runtime/bufferLike.js";
|
|
4
4
|
import { sha256Bytes } from "../utils/crypto.js";
|
|
5
5
|
import { bytesToHex } from "../utils/encoding.js";
|
|
6
|
+
import { createDeploymentPlanBundleEntry } from "../deployment/index.js";
|
|
6
7
|
import {
|
|
7
8
|
DEFAULT_MANIFEST_EXPORT_SYMBOL,
|
|
8
9
|
DEFAULT_MANIFEST_SIZE_SYMBOL,
|
|
9
10
|
SDS_BUNDLE_SECTION_NAME,
|
|
10
11
|
SDS_CUSTOM_SECTION_PREFIX,
|
|
12
|
+
SDS_DEPLOYMENT_ENTRY_ID,
|
|
13
|
+
SDS_DEPLOYMENT_SECTION_NAME,
|
|
11
14
|
} from "./constants.js";
|
|
12
15
|
import {
|
|
13
16
|
decodeModuleBundle,
|
|
@@ -268,6 +271,9 @@ function normalizeStandardEntries(options = {}) {
|
|
|
268
271
|
description: "Transport envelope metadata.",
|
|
269
272
|
});
|
|
270
273
|
}
|
|
274
|
+
if (options.deploymentPlan !== undefined) {
|
|
275
|
+
entries.push(createDeploymentPlanBundleEntry(options.deploymentPlan));
|
|
276
|
+
}
|
|
271
277
|
return entries.filter((entry) => entry.payload !== null);
|
|
272
278
|
}
|
|
273
279
|
|
|
@@ -282,7 +288,12 @@ function normalizeAdditionalEntries(entries = []) {
|
|
|
282
288
|
}
|
|
283
289
|
|
|
284
290
|
async function withSha256(entry) {
|
|
285
|
-
const payloadBytes =
|
|
291
|
+
const payloadBytes =
|
|
292
|
+
toUint8Array(entry.payload) ??
|
|
293
|
+
((entry.payloadEncoding === "json-utf8" ||
|
|
294
|
+
moduleBundleEncodingToName(entry.payloadEncoding) === "json-utf8")
|
|
295
|
+
? canonicalBytes(entry.payload)
|
|
296
|
+
: normalizeBytes(entry.payload, `entry "${entry.entryId}" payload`));
|
|
286
297
|
return {
|
|
287
298
|
...entry,
|
|
288
299
|
payload: payloadBytes,
|
|
@@ -315,6 +326,17 @@ function buildParsedEntries(bundle) {
|
|
|
315
326
|
parsedEntry.decodedManifest = null;
|
|
316
327
|
}
|
|
317
328
|
}
|
|
329
|
+
if (
|
|
330
|
+
parsedEntry.entryId === SDS_DEPLOYMENT_ENTRY_ID ||
|
|
331
|
+
parsedEntry.sectionName === SDS_DEPLOYMENT_SECTION_NAME
|
|
332
|
+
) {
|
|
333
|
+
parsedEntry.decodedDeploymentPlan =
|
|
334
|
+
parsedEntry.payloadEncodingName === "json-utf8" &&
|
|
335
|
+
parsedEntry.decodedPayload &&
|
|
336
|
+
typeof parsedEntry.decodedPayload === "object"
|
|
337
|
+
? parsedEntry.decodedPayload
|
|
338
|
+
: null;
|
|
339
|
+
}
|
|
318
340
|
return parsedEntry;
|
|
319
341
|
});
|
|
320
342
|
}
|
|
@@ -432,16 +454,22 @@ export async function parseSingleFileBundle(bytes, options = {}) {
|
|
|
432
454
|
manifest = null;
|
|
433
455
|
}
|
|
434
456
|
}
|
|
457
|
+
const deploymentEntry =
|
|
458
|
+
parsedEntries.find(
|
|
459
|
+
(entry) =>
|
|
460
|
+
entry.entryId === SDS_DEPLOYMENT_ENTRY_ID ||
|
|
461
|
+
entry.sectionName === SDS_DEPLOYMENT_SECTION_NAME,
|
|
462
|
+
) ?? null;
|
|
435
463
|
return {
|
|
436
464
|
wasmBytes,
|
|
437
465
|
bundleBytes,
|
|
438
466
|
bundle,
|
|
439
467
|
entries: parsedEntries,
|
|
440
468
|
manifest,
|
|
469
|
+
deploymentPlan: deploymentEntry?.decodedDeploymentPlan ?? null,
|
|
441
470
|
customSections,
|
|
442
471
|
canonicalWasmBytes: canonical.canonicalWasmBytes,
|
|
443
472
|
canonicalModuleHash: canonical.hashBytes,
|
|
444
473
|
canonicalModuleHashHex: canonical.hashHex,
|
|
445
474
|
};
|
|
446
475
|
}
|
|
447
|
-
|
package/src/compliance/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
loadManifestFromFile,
|
|
6
6
|
loadComplianceConfig,
|
|
7
7
|
RecommendedCapabilityIds,
|
|
8
|
+
StandaloneWasiCapabilityIds,
|
|
8
9
|
resolveManifestFiles,
|
|
9
10
|
validatePluginArtifact,
|
|
10
11
|
validatePluginManifest,
|
|
@@ -49,8 +50,8 @@ export {
|
|
|
49
50
|
loadManifestFromFile,
|
|
50
51
|
loadComplianceConfig,
|
|
51
52
|
RecommendedCapabilityIds,
|
|
53
|
+
StandaloneWasiCapabilityIds,
|
|
52
54
|
resolveManifestFiles,
|
|
53
55
|
validatePluginArtifact,
|
|
54
56
|
validatePluginManifest,
|
|
55
57
|
};
|
|
56
|
-
|