28 lines
5.9 KiB
Markdown
28 lines
5.9 KiB
Markdown
# External Worker SDKs
|
|
|
|
Compiler authors: the private [native release workflow](native-release.md) builds and signs Dever runtime packs. It is separate from these external-language Worker SDKs and from application configuration.
|
|
|
|
These are stdio Worker libraries for Python, JavaScript (Node), and Go. The compiler remains the sole owner of Port schemas. Each checked external Adapter exposes `ExternalWorkerContract::sdk_manifest()`, including the exact identity and recursive setting, input, output and declared-error types. The managed Python and JavaScript runners package this manifest and bind each Port operation to a same-named function exported by the Adapter entry; JavaScript accepts ESM named exports or CommonJS `module.exports` properties. Application code does not maintain a second registration table. Python uses `Worker.from_manifest(manifest, handlers)`, JavaScript uses `Worker.fromManifest(manifest, handlers)`, and Go uses `NewFromManifest(manifest)` followed by `RegisterHandlers(handlers)`. These paths decode inputs and validate results and declared business-error payloads from the same compiler-generated contract. The SDK checks the identity during `hello` and never adopts a schema supplied by the supervisor.
|
|
|
|
The lower-level `Contract`/`Worker` registration API remains available for protocol fixtures. The setting decoder runs before `ready`; it receives only the `hello.setting` value. Handlers return JSON-compatible values or a declared `BusinessError`. Python handlers are async; JavaScript handlers receive an `AbortSignal`; Go handlers receive a `context.Context`. A cooperative cancellation receives one `dever.cancelled` protocol error and discards its handler result. If a handler ignores cancellation for one second, the Worker fails and admits no further calls. The supervisor owns the Worker process and its stdin lifetime; an in-process Go `Serve` caller must close or unblock its own `io.Reader` when returning.
|
|
|
|
The three `example` entries use the same fixture identity and contract to demonstrate the lower-level API. `fixture-schema-v1` and `test/external-sdk/typed_contract.json` are test data, not production Port hashes. Worker stdout is reserved for 4-byte big-endian length-prefixed UTF-8 JSON frames. Diagnostics go to stderr. The libraries use no external packages and do not read environment variables or `PATH`. A managed Worker entry reads only its explicitly packaged manifest path. Managed Python packs require fixed `-I -S -B` flags; the runner imports its packaged SDK before exposing Adapter source and dependencies on `sys.path`.
|
|
|
|
Run the opt-in host SDK check with explicit absolute runtime paths, for example:
|
|
|
|
```text
|
|
/usr/bin/python3 -B test/external-sdk/check.py --python /usr/bin/python3 --node /absolute/path/to/node --go /absolute/path/to/go
|
|
```
|
|
|
|
Omitted runtime paths report `unavailable`; the script never discovers language runtimes through `PATH`. It builds the Go fixtures in a temporary offline cache. This check exercises both the lower-level and compiler-manifest-shaped typed paths on host interpreters. Managed runtime packaging and execution on a machine without host language runtimes require separate acceptance.
|
|
|
|
Managed dependencies use `dever-lock-v5`. Python extras and selected wheel METADATA, npm nested instances/peers/optional/bundled dependencies, and authenticated Go module evidence are part of the exact lock. Native Python wheels install into the packaged interpreter prefix and must satisfy its signed tags, extension ABI and loader closure.
|
|
|
|
Cross builds select the application platform explicitly: `dever lib update <project> --target linux-aarch64`, followed by `dever build <project> --target linux-aarch64 --output <new-file>`. Worker source and Port contracts stay unchanged. Locks, interpreters, native dependencies and sandbox assets must match that target. A Go runtime pack additionally declares `build.host` for its compiler/linker/analyzer; `build.goos/goarch` and standard-library object headers describe the output architecture. The tools run with a cleared environment and must have the correct target baked in. Missing target assets are errors, with no host runtime fallback. `run` and ordinary tests remain host operations.
|
|
|
|
Only explicit Lib preparation may build Python sdists or run npm registry installation hooks. The shared build owner uses signed compiler/header/sysroot/frontend packs in a Linux sandbox with no network, immutable inputs and owned writable scratch space. Python PEP 517 build requirements have their own exact lock; each hook has a fresh process, and the parent retains the metadata snapshot used to validate the final wheel. npm uses its packaged lifecycle runner for `preinstall`, `install` and `postinstall`, including dependency bins and node-gyp. Missing tools do not fall back to host `PATH`.
|
|
|
|
Build receipts bind sources, target runtimes, tools, frontend, dependency graph and final output hashes. Worker preparation replays those outputs offline without running installation hooks. Every npm `.node` output is classified by target/loader checks and an isolated Node load probe; only admitted addons enter the immutable Worker tree, including trees used by threads or child processes. Rejected platform/ABI variants remain in the locked archive. Runtime native dependencies must come from that tree or the signed OS library set, never the compiler sysroot. These rules do not change the Port protocol or require an application-side registration layer.
|
|
|
|
A generated addon that fails admission fails the build; a pure JavaScript fallback is not evidence of successful native compilation. Build subprocesses have a five-minute deadline and separate 16 MiB stdout/stderr limits. Scratch usage is checked every 250 ms against 512 MiB and 65,536 entries, with owned-process cleanup on failure. This periodic check is not a kernel disk quota and may observe overshoot between checks. The final Worker installation remains limited to 256 MiB and 65,536 entries.
|