sdn-flow 0.2.0

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.
Files changed (69) hide show
  1. package/.claude/SKILLS.md +7 -0
  2. package/.claude/skills/sdn-plugin-abi-compliance/SKILL.md +56 -0
  3. package/.claude/todo/001-js-host-startup-and-deno.md +85 -0
  4. package/LICENSE +21 -0
  5. package/README.md +223 -0
  6. package/bin/sdn-flow-host.js +169 -0
  7. package/docs/.nojekyll +0 -0
  8. package/docs/ARCHITECTURE.md +200 -0
  9. package/docs/HOST_CAPABILITY_MODEL.md +317 -0
  10. package/docs/PLUGIN_ARCHITECTURE.md +145 -0
  11. package/docs/PLUGIN_COMPATIBILITY.md +61 -0
  12. package/docs/PLUGIN_COMPLIANCE_CHECKS.md +82 -0
  13. package/docs/PLUGIN_MANIFEST.md +94 -0
  14. package/docs/css/style.css +465 -0
  15. package/docs/index.html +218 -0
  16. package/docs/js/app.mjs +751 -0
  17. package/docs/js/editor-panel.mjs +203 -0
  18. package/docs/js/flow-canvas.mjs +515 -0
  19. package/docs/js/flow-model.mjs +391 -0
  20. package/docs/js/workers/emception.worker.js +146 -0
  21. package/docs/js/workers/pyodide.worker.js +134 -0
  22. package/native/flow_source_generator.cpp +1958 -0
  23. package/package.json +67 -0
  24. package/schemas/FlowRuntimeAbi.fbs +91 -0
  25. package/src/auth/canonicalize.js +5 -0
  26. package/src/auth/index.js +11 -0
  27. package/src/auth/permissions.js +8 -0
  28. package/src/compiler/CppFlowSourceGenerator.js +475 -0
  29. package/src/compiler/EmceptionCompilerAdapter.js +244 -0
  30. package/src/compiler/SignedArtifactCatalog.js +152 -0
  31. package/src/compiler/index.js +8 -0
  32. package/src/compiler/nativeFlowSourceGeneratorTool.js +144 -0
  33. package/src/compliance/index.js +13 -0
  34. package/src/compliance/pluginCompliance.js +11 -0
  35. package/src/deploy/FlowDeploymentClient.js +532 -0
  36. package/src/deploy/index.js +8 -0
  37. package/src/designer/FlowDesignerSession.js +158 -0
  38. package/src/designer/index.js +2 -0
  39. package/src/designer/requirements.js +184 -0
  40. package/src/generated/runtimeAbiLayouts.js +544 -0
  41. package/src/host/appHost.js +105 -0
  42. package/src/host/autoHost.js +113 -0
  43. package/src/host/browserHostAdapters.js +108 -0
  44. package/src/host/compiledFlowRuntimeHost.js +703 -0
  45. package/src/host/constants.js +55 -0
  46. package/src/host/dependencyRuntime.js +227 -0
  47. package/src/host/descriptorAbi.js +351 -0
  48. package/src/host/fetchService.js +237 -0
  49. package/src/host/httpHostAdapters.js +280 -0
  50. package/src/host/index.js +91 -0
  51. package/src/host/installedFlowHost.js +885 -0
  52. package/src/host/invocationAbi.js +440 -0
  53. package/src/host/normalize.js +372 -0
  54. package/src/host/packageManagers.js +369 -0
  55. package/src/host/profile.js +134 -0
  56. package/src/host/runtimeAbi.js +106 -0
  57. package/src/host/workspace.js +895 -0
  58. package/src/index.js +8 -0
  59. package/src/runtime/FlowRuntime.js +273 -0
  60. package/src/runtime/MethodRegistry.js +295 -0
  61. package/src/runtime/constants.js +44 -0
  62. package/src/runtime/index.js +19 -0
  63. package/src/runtime/normalize.js +377 -0
  64. package/src/transport/index.js +7 -0
  65. package/src/transport/pki.js +7 -0
  66. package/src/utils/crypto.js +7 -0
  67. package/src/utils/encoding.js +65 -0
  68. package/src/utils/wasmCrypto.js +69 -0
  69. package/tools/run-plugin-compliance-check.mjs +153 -0
@@ -0,0 +1,200 @@
1
+ # Architecture
2
+
3
+ ## Package Boundary
4
+
5
+ `sdn-flow` is the portable layer between:
6
+
7
+ - UI flow authoring
8
+ - host-side runtime execution
9
+ - signed artifact dependency resolution
10
+ - generated C++ bundle compilation
11
+ - deployment authorization
12
+ - deployment transport
13
+
14
+ It is intentionally host-agnostic so different applications and runtimes can
15
+ consume the same contracts.
16
+
17
+ ## Core Rule
18
+
19
+ A deployable flow is a compiled single WASM runtime artifact.
20
+
21
+ The source graph exists for authoring, validation, tracing, and compilation.
22
+ It is not the deployable unit.
23
+ There is no separate interpreted deployment engine.
24
+ There is no JS source generator on the deploy path; source synthesis happens in
25
+ a native C++ generator compiled to WASM.
26
+
27
+ ## Single Plugin Rule
28
+
29
+ A single plugin invocation is modeled as a one-node flow with optional triggers
30
+ and zero or more sinks. There is no separate deployment path for "just a
31
+ plugin."
32
+
33
+ ## Package Layers
34
+
35
+ ### Runtime Contracts
36
+
37
+ The runtime layer defines normalized manifest/program objects used by authoring,
38
+ validation, and host integration:
39
+
40
+ - plugin manifests declare methods, ports, stream limits, and drain policies
41
+ - flow programs declare nodes, edges, triggers, and trigger bindings
42
+ - deployed execution lives in the generated C++ runtime, not in package JS
43
+
44
+ ### Designer
45
+
46
+ The designer layer is UI-facing but DOM-free. It owns:
47
+
48
+ - graph mutation helpers
49
+ - external input/output and capability summaries for visual editors
50
+ - single-plugin flow creation
51
+ - compile orchestration through an injected compiler adapter
52
+ - deployment orchestration through an injected deployment client
53
+
54
+ ### Host Planning
55
+
56
+ The host-planning layer owns portable hosted-runtime description:
57
+
58
+ - runtime kind (`flow`, `plugin`, `service`)
59
+ - startup phase (`bootstrap`, `early`, `session`, `on-demand`)
60
+ - local vs remote authority
61
+ - runtime dependencies
62
+ - transport bindings (`same-app`, `direct`, `webrtc`, `sdn-protocol`, `http`)
63
+
64
+ This keeps startup-only services such as local licensing in the same runtime
65
+ model as any other flow/plugin deployment.
66
+
67
+ See also:
68
+
69
+ - [Host Capability Model](./HOST_CAPABILITY_MODEL.md)
70
+
71
+ ### Compiler
72
+
73
+ The compiler layer owns:
74
+
75
+ - signed artifact catalog resolution
76
+ - single-source C++ runtime generation
77
+ - native C++ source-generator tool compilation and invocation
78
+ - `emception`-compatible compile planning
79
+ - artifact assembly back into the deploy contract
80
+
81
+ ### Authorization
82
+
83
+ Deployment permissions are explicit signed envelopes, designed for SDN HD-wallet
84
+ signatures.
85
+
86
+ The package defines:
87
+
88
+ - canonical payload encoding
89
+ - deploy authorization payload shape
90
+ - signer and verifier contracts
91
+ - scope checks against target, artifact, and required capabilities
92
+
93
+ ### Transport
94
+
95
+ Remote deployment payloads may be encrypted with PKI. The transport layer
96
+ provides:
97
+
98
+ - X25519 ephemeral key agreement
99
+ - HKDF-derived AES-256-GCM content encryption
100
+ - JSON payload helpers for deployment envelopes
101
+
102
+ ### Deploy
103
+
104
+ The deploy layer only ships compiled artifacts. It does not accept raw flow
105
+ graphs as the deployment boundary.
106
+
107
+ ## Artifact Contract
108
+
109
+ A compiled flow artifact contains:
110
+
111
+ - `artifactId`
112
+ - `programId`
113
+ - `format`
114
+ - `wasm`
115
+ - `manifestBuffer`
116
+ - `manifestExports.bytesSymbol`
117
+ - `manifestExports.sizeSymbol`
118
+ - `entrypoint`
119
+ - `graphHash`
120
+ - `requiredCapabilities`
121
+ - `pluginVersions`
122
+ - `schemaBindings`
123
+ - `abiVersion`
124
+
125
+ The compile plan that produces that artifact may also include:
126
+
127
+ - generator request bytes consumed by the native generator WASM tool
128
+ - generated `main.cpp`
129
+ - generated runtime topology descriptors and mutable node-state storage
130
+ - signed plugin artifact dependency descriptors
131
+ - signed plugin manifest bytes
132
+ - the exact `em++` command issued to `emception`
133
+
134
+ ## Editor And Capability Model
135
+
136
+ Programs may declare:
137
+
138
+ - `externalInterfaces`
139
+ - `artifactDependencies`
140
+ - `editor` layout metadata
141
+
142
+ Plugin manifests may declare:
143
+
144
+ - `capabilities`
145
+ - `externalInterfaces`
146
+
147
+ The designer layer can merge those declarations with trigger bindings and
148
+ resolved plugin manifests so the operator can see:
149
+
150
+ - which network, timer, protocol, filesystem, and database bindings are needed
151
+ - which capabilities must be approved and signed
152
+ - which signed plugin artifacts must exist before compilation
153
+
154
+ ## Host Integration
155
+
156
+ Hosts are expected to provide adapters for:
157
+
158
+ - graph validation against host capabilities
159
+ - manifest building into canonical FlatBuffer bytes
160
+ - invoking the native C++ source generator tool
161
+ - compilation via `emception` or equivalent
162
+ - local deployment/install
163
+ - remote deployment endpoint verification and installation
164
+ - protocol/pubsub registration and network transport
165
+
166
+ Hosts may also use the portable host-planning surface to describe early-start
167
+ services, same-app loopback bindings, or WebRTC-connected local runtimes
168
+ without changing the flow/plugin ABI.
169
+
170
+ Capability gaps must be documented at the host-profile level. Do not solve a
171
+ missing runtime capability by inventing a second deploy/runtime model.
172
+
173
+ This package deliberately leaves those host integrations outside the portable
174
+ core.
175
+
176
+ ## Manifest Rule
177
+
178
+ Every plugin and every compiled flow artifact must embed a FlatBuffer manifest
179
+ buffer and expose a callable export for it. The default flow export names are:
180
+
181
+ - `flow_get_manifest_flatbuffer`
182
+ - `flow_get_manifest_flatbuffer_size`
183
+
184
+ The default plugin export names are:
185
+
186
+ - `plugin_get_manifest_flatbuffer`
187
+ - `plugin_get_manifest_flatbuffer_size`
188
+
189
+ ## Example
190
+
191
+ The repo includes a concrete example in
192
+ [examples/flows/iss-proximity-oem/flow.json](../examples/flows/iss-proximity-oem/flow.json)
193
+ that:
194
+
195
+ - streams OMMs from SDN pubsub
196
+ - ingests them into a FlatSQL storage plugin
197
+ - queries objects within `50 km` of object `25544`
198
+ - propagates `90` samples for one orbit
199
+ - generates OEMs
200
+ - writes and republishes those OEMs through explicit sink nodes
@@ -0,0 +1,317 @@
1
+ # Host Capability Model
2
+
3
+ ## Purpose
4
+
5
+ This document defines how compiled `sdn-flow` runtimes consume the canonical
6
+ module-level host capability model from `space-data-module-sdk` and project it
7
+ onto flow-level runtime artifacts.
8
+
9
+ The canonical module-facing capability vocabulary, module-facing hostcall ABI,
10
+ and single-module conformance rules live in `space-data-module-sdk`.
11
+ This document focuses on how `sdn-flow` composes those module contracts into
12
+ compiled flow runtimes.
13
+
14
+ The goal is to keep one runtime model across OrbPro, `sdn-js`, Go SDN, and
15
+ WASI-style hosts without creating a different flow runtime model or a different
16
+ deploy shape for each environment.
17
+
18
+ ## Hard Rules
19
+
20
+ 1. Every deployable unit is one compiled WASM runtime artifact.
21
+ 2. Every module is a flow. A "single plugin" is a degenerate one-node flow,
22
+ but its standalone artifact contract still comes from `space-data-module-sdk`.
23
+ 3. Hosts provide capabilities and placement, not business logic.
24
+ 4. Capability requirements must be explicit in manifests, flow programs,
25
+ hosted-runtime plans, or deployment envelopes. Do not hide them in ad hoc
26
+ host config or implicit imports.
27
+ 5. Use the minimum host-adapter set needed to cover environment families.
28
+ Do not add a new harness just because one runtime exposes a feature
29
+ differently.
30
+ 6. Generic "WASI" is not a sufficient capability claim. If a flow needs more
31
+ than the portable baseline, the required host profile and imports must be
32
+ documented explicitly.
33
+ 7. If there is no compiled-host path for a required feature in a target
34
+ environment, treat that as a release-blocking alert. Do not paper over it
35
+ with loose JS wrappers, host cron jobs, or sidecar-only glue.
36
+
37
+ ## Capability Declaration Surfaces
38
+
39
+ Use the surfaces below together. They solve different problems.
40
+
41
+ | Surface | Purpose | Example |
42
+ | ----------------------------------------------- | ------------------------------------------ | ------------------------------------------------- |
43
+ | `manifest.capabilities` | coarse approval/signing scope | `["timers", "http", "storage_write"]` |
44
+ | `manifest.externalInterfaces` | concrete plugin-level bindings | outbound HTTP, FlatSQL adapter, filesystem path |
45
+ | `program.externalInterfaces` | flow-level bindings beyond a single plugin | shared HTTPS listener, shared pubsub topic |
46
+ | `program.triggers` | trigger ownership | timer, protocol request, HTTP request |
47
+ | hosted-runtime plan `requiredCapabilities` | runtime placement/startup requirements | early local service needs `protocol_handle` |
48
+ | deployment authorization `requiredCapabilities` | signed approval at deploy time | remote install allowed to use `pubsub` and `ipfs` |
49
+
50
+ Keep capability IDs coarse and stable. Put transport-specific details in the
51
+ interface object, not in a proliferating list of near-duplicate capability
52
+ strings.
53
+
54
+ ## Canonical Capability Guidance
55
+
56
+ Recommended coarse capability IDs:
57
+
58
+ - `clock`
59
+ - `random`
60
+ - `timers`
61
+ - `http`
62
+ - `network`
63
+ - `filesystem`
64
+ - `pipe`
65
+ - `pubsub`
66
+ - `protocol_handle`
67
+ - `protocol_dial`
68
+ - `database`
69
+ - `storage_adapter`
70
+ - `storage_query`
71
+ - `storage_write`
72
+ - `wallet_sign`
73
+ - `ipfs`
74
+ - `scene_access`
75
+ - `render_hooks`
76
+
77
+ Guidance:
78
+
79
+ - Use `network` for raw sockets, TCP, UDP, QUIC, or similar transport access.
80
+ - Use `http` for HTTP client/server semantics instead of encoding HTTP as a
81
+ special case of raw sockets.
82
+ - Use `filesystem` for path-backed storage and `database` for logical database
83
+ interfaces such as FlatSQL.
84
+ - Use `pipe` for stdin/stdout/stderr, named pipes, or stream-style host I/O.
85
+ - Keep `ipfs` coarse. Pinning, block get/put, and publish behavior belong in
86
+ interface metadata.
87
+ - Compute-only infrastructure plugins such as DA FlatBuffers usually need no
88
+ host capability at all. `hd-wallet-wasm` style plugins should only declare
89
+ host capabilities such as `random` or `wallet_sign` when they genuinely need
90
+ host-provided entropy or resident key material.
91
+
92
+ ## External Interface Patterns
93
+
94
+ External interfaces carry the precise runtime binding details. Keep the
95
+ interface kinds small and use `properties` for specialization.
96
+
97
+ ### Timer / Clock / Randomness
98
+
99
+ - Timers normally enter through `program.triggers`.
100
+ - If a plugin needs direct time or entropy outside trigger scheduling, declare
101
+ `clock` and `random` capabilities explicitly.
102
+ - Do not let native code silently reach into browser globals or host globals.
103
+ Entropy and time should enter through explicit host capabilities.
104
+
105
+ ### HTTP
106
+
107
+ Use `kind: "http"` for both outbound requests and inbound handlers.
108
+
109
+ Example:
110
+
111
+ ```json
112
+ {
113
+ "interfaceId": "celestrak-fetch",
114
+ "kind": "http",
115
+ "direction": "output",
116
+ "capability": "http",
117
+ "resource": "https://celestrak.org",
118
+ "required": true,
119
+ "properties": {
120
+ "methods": ["GET"],
121
+ "purpose": "Fetch OMM updates"
122
+ }
123
+ }
124
+ ```
125
+
126
+ ### Raw Network / TCP / UDP
127
+
128
+ Use `kind: "network"` and put socket details in `properties`.
129
+
130
+ Example:
131
+
132
+ ```json
133
+ {
134
+ "interfaceId": "udp-observation-ingest",
135
+ "kind": "network",
136
+ "direction": "input",
137
+ "capability": "network",
138
+ "resource": "udp://0.0.0.0:40123",
139
+ "required": true,
140
+ "properties": {
141
+ "transport": "udp",
142
+ "mode": "listen"
143
+ }
144
+ }
145
+ ```
146
+
147
+ This avoids separate ABIs for TCP, UDP, raw sockets, and runtime-specific
148
+ socket APIs.
149
+
150
+ ### Filesystem / Pipes
151
+
152
+ Use `kind: "filesystem"` for path-backed files and `kind: "pipe"` for stream
153
+ or pipe semantics.
154
+
155
+ Example:
156
+
157
+ ```json
158
+ {
159
+ "interfaceId": "oem-export-dir",
160
+ "kind": "filesystem",
161
+ "direction": "output",
162
+ "capability": "filesystem",
163
+ "resource": "file:///var/lib/sdn/oem",
164
+ "required": true,
165
+ "properties": {
166
+ "access": "read-write"
167
+ }
168
+ }
169
+ ```
170
+
171
+ ```json
172
+ {
173
+ "interfaceId": "stderr-log",
174
+ "kind": "pipe",
175
+ "direction": "output",
176
+ "capability": "pipe",
177
+ "resource": "stderr",
178
+ "required": false
179
+ }
180
+ ```
181
+
182
+ ### Database / FlatSQL
183
+
184
+ Storage engines remain plugins or explicit host services, not hidden host
185
+ subsystems.
186
+
187
+ - Use `kind: "database"` for the logical database surface seen by the flow.
188
+ - Use `kind: "host-service"` when the flow needs a host-provided storage
189
+ adapter contract.
190
+
191
+ ### IPFS / SDS Protocol / Other Services
192
+
193
+ If a function is logically a networked platform service rather than a raw
194
+ socket, prefer `kind: "host-service"`, `kind: "protocol"`, or `kind: "pubsub"`
195
+ plus explicit `resource`, `protocolId`, `topic`, or `properties`.
196
+
197
+ Examples:
198
+
199
+ - IPFS pinning service
200
+ - SDS PNM notification channel
201
+ - local orbit-determination service runtime
202
+ - same-app licensing runtime
203
+
204
+ ## Environment Profiles
205
+
206
+ The canonical model is shared, but capability availability differs by host
207
+ profile. Document the profile. Do not claim "runs anywhere" unless it is true
208
+ for the declared interfaces.
209
+
210
+ ### OrbPro Browser Host
211
+
212
+ Portable expectations:
213
+
214
+ - `clock`, `random`, `timers`
215
+ - outbound HTTP
216
+ - same-app bindings
217
+ - browser-managed storage surfaces
218
+ - scene/render integration
219
+ - `sdn-js` protocol/pubsub integration when configured
220
+
221
+ Non-portable or unavailable by default:
222
+
223
+ - raw TCP/UDP sockets
224
+ - arbitrary listen sockets
225
+ - unrestricted filesystem access
226
+ - OS pipes
227
+
228
+ If a flow needs those features, place that runtime in a different host profile
229
+ instead of pretending the browser host can satisfy them.
230
+
231
+ ### Node / Deno / Bun Through The `sdn-js` Host Family
232
+
233
+ Expected direction:
234
+
235
+ - keep one `sdn-js` host family for browser-capable and JS-capable runtimes
236
+ - expose files, pipes, outbound HTTP, protocol/pubsub, IPFS, and local
237
+ listeners through the same capability model
238
+ - document unsupported features per runtime instead of creating a new plugin
239
+ ABI for each JS engine
240
+
241
+ If one engine cannot provide a capability in compiled-host form, mark that
242
+ capability unsupported for that profile.
243
+
244
+ ### Go SDN Host
245
+
246
+ This is the preferred profile for long-running service flows such as:
247
+
248
+ - timer-triggered OMM sync
249
+ - FlatSQL-backed local storage
250
+ - HTTPS serving
251
+ - IPFS publish and pin
252
+ - SDS protocol notifications
253
+ - local orbit determination and association jobs
254
+
255
+ The flow still deploys as one compiled WASM artifact. The Go host supplies the
256
+ bindings.
257
+
258
+ ### Generic WASI Runtime
259
+
260
+ Treat generic WASI as a narrow portability baseline only.
261
+
262
+ Portable assumptions:
263
+
264
+ - startup entrypoint
265
+ - stdio-like behavior
266
+ - linear memory/exported symbol access
267
+ - whatever explicit imported host functions the host provides
268
+
269
+ Do not assume from "WASI" alone:
270
+
271
+ - outbound HTTP
272
+ - sockets
273
+ - persistent filesystem semantics
274
+ - timers beyond what the host explicitly exposes
275
+ - pubsub, protocol, IPFS, or database services
276
+
277
+ ### WasmEdge / Wasmtime / Wasmer / Wazero
278
+
279
+ Vendor or runtime extensions may be used, but they do not change the canonical
280
+ flow ABI.
281
+
282
+ Rules:
283
+
284
+ - declare the same capability IDs and interface shapes
285
+ - document the exact host profile or extension required
286
+ - do not describe the result as generic-WASI portable unless the same compiled
287
+ contract is actually supported elsewhere
288
+
289
+ ## Alert Conditions
290
+
291
+ Treat these as architecture failures:
292
+
293
+ - a host-side cron job driving loose plugin calls instead of a timer trigger
294
+ - JSON moving between compiled plugins on flow edges
295
+ - separate deployment of "scheduler" and "plugins" as different runtime models
296
+ - a browser-only JS implementation and a different Go/WASI implementation for
297
+ the same canonical feature
298
+ - a claim that a module runs on "any WASI runtime" when it actually needs
299
+ custom imports or a vendor extension
300
+ - sidecar metadata or sidecar policy as the only source of runtime truth
301
+
302
+ ## Example Deployment Shape
303
+
304
+ The following workload is valid in the canonical model:
305
+
306
+ 1. A timer-triggered flow wakes on a declared interval.
307
+ 2. It fetches OMMs from CelesTrak over an explicit HTTP interface.
308
+ 3. It writes aligned records through a FlatSQL storage plugin/runtime.
309
+ 4. It exposes a declared HTTPS interface for download.
310
+ 5. It publishes content to IPFS and requests pinning through declared host
311
+ services.
312
+ 6. It notifies peer SDN nodes over a declared SDS protocol binding.
313
+ 7. It kicks off downstream association and orbit-analysis nodes.
314
+
315
+ This still compiles to one signed deployable WASM artifact. Local and remote
316
+ deployment may wrap that artifact in the same signed and optionally encrypted
317
+ deployment envelope.
@@ -0,0 +1,145 @@
1
+ # Plugin Architecture
2
+
3
+ ## Scope
4
+
5
+ This document defines how `sdn-flow` consumes the standalone plugin
6
+ architecture sourced from `space-data-module-sdk`.
7
+
8
+ It covers:
9
+
10
+ - plugin identity and manifest rules
11
+ - streaming method contracts
12
+ - external interface declarations
13
+ - callable manifest exports
14
+ - the relationship between plugins and flows
15
+ - local and remote deployment expectations
16
+
17
+ ## Core Rule
18
+
19
+ The runtime does not distinguish between "a plugin" and "a flow" at deployment
20
+ time. A single plugin invocation is a one-node flow.
21
+
22
+ That means:
23
+
24
+ - single-plugin execution uses the same deploy model as multi-node graphs
25
+ - compiled deployment is always one WASM runtime artifact
26
+ - trigger, queueing, and drain semantics stay uniform
27
+
28
+ ## Plugin Contract
29
+
30
+ Every plugin participates in the flow system through a manifest-defined method
31
+ surface.
32
+
33
+ A method declares:
34
+
35
+ - stable `methodId`
36
+ - one or more input ports
37
+ - zero or more output ports
38
+ - accepted schema sets per port
39
+ - stream-count limits
40
+ - `maxBatch`
41
+ - `drainPolicy`
42
+
43
+ Methods are invoked over schema-tagged frame streams, not ad hoc JSON payloads.
44
+
45
+ Plugins may also declare `externalInterfaces` so visual editors and deployment
46
+ tooling can show the real network, protocol, filesystem, database, or host
47
+ service bindings required to make the graph run.
48
+
49
+ Keep capability IDs coarse and portable. Use interface metadata to capture
50
+ runtime-specific details such as:
51
+
52
+ - HTTP method sets
53
+ - TCP/UDP/raw-socket transport mode
54
+ - filesystem sandbox or mount location
55
+ - pipe or stream direction
56
+ - IPFS or SDS service operation
57
+
58
+ Storage engines follow the same rule. A FlatSQL database should be represented
59
+ as a storage plugin/runtime that:
60
+
61
+ - ingests aligned FlatBuffer records
62
+ - exposes query methods
63
+ - declares whether it is backed by transient memory or a host-provided storage
64
+ adapter
65
+
66
+ The host should not hide a second engine-owned SQL source of truth behind that
67
+ plugin surface.
68
+
69
+ Infrastructure libraries follow the same rule. If a deployable flow depends on
70
+ `hd-wallet-wasm`, DA FlatBuffers, or similar runtime libraries for signing,
71
+ envelope encryption, field-level encryption, schema transforms, or repacking,
72
+ those surfaces should appear as normal manifest-defined plugins. Do not hide
73
+ them behind host-only helper code.
74
+
75
+ For the canonical host capability rules and environment profiles, see:
76
+
77
+ - [Host Capability Model](./HOST_CAPABILITY_MODEL.md)
78
+
79
+ ## Manifest Rule
80
+
81
+ Every plugin must embed a FlatBuffer manifest buffer and expose callable exports
82
+ for it.
83
+
84
+ Default export names:
85
+
86
+ - `plugin_get_manifest_flatbuffer`
87
+ - `plugin_get_manifest_flatbuffer_size`
88
+
89
+ Compiled flow artifacts follow the same rule with flow-scoped export names:
90
+
91
+ - `flow_get_manifest_flatbuffer`
92
+ - `flow_get_manifest_flatbuffer_size`
93
+
94
+ The manifest is part of the runtime contract. Sidecar metadata files are not
95
+ sufficient for deployable artifacts.
96
+
97
+ ## Streaming Model
98
+
99
+ Each input port accepts one or more streams of schema-tagged frames.
100
+
101
+ Each frame carries runtime type identity:
102
+
103
+ - `schemaName`
104
+ - `fileIdentifier`
105
+ - optional `schemaHash`
106
+ - `streamId`
107
+ - `sequence`
108
+ - `traceId`
109
+
110
+ If a method only processes one frame per invocation, the runtime keeps invoking
111
+ it until the backlog is drained or the scheduler yields.
112
+
113
+ ## Plugin Families
114
+
115
+ `sdn-flow` does not hardcode host-specific plugin classes. Common families
116
+ include:
117
+
118
+ - propagators
119
+ - sensors
120
+ - analyzers
121
+ - publishers
122
+ - responders
123
+ - infrastructure plugins
124
+
125
+ Examples of infrastructure plugins include FlatSQL storage, `hd-wallet-wasm`
126
+ sign/encrypt nodes, and DA FlatBuffers schema/field transform nodes.
127
+
128
+ All of them enter the runtime through the same manifest + method contract.
129
+
130
+ ## Host Boundary
131
+
132
+ Hosts are responsible for:
133
+
134
+ - manifest decoding
135
+ - plugin loading and registration
136
+ - capability enforcement
137
+ - editor integration for external interface inspection and approval
138
+ - compilation of flow graphs into deployable WASM artifacts
139
+ - installation and execution of those artifacts
140
+
141
+ `sdn-flow` owns the portable runtime and deployment model, not host-specific
142
+ loading code.
143
+
144
+ Host-specific runtime differences must stay in capability bindings and hosted
145
+ runtime plans. They must not fork the plugin ABI.