@kamebara/wisy-engine-node
v0.14.0-rc.2
Published
Node.js (N-API) binding for the Wisy cryptographic engine.
Downloads
1,692
Readme
wisy-engine-node
Node.js (N-API) binding for the Wisy cryptographic engine, consumed by the backend (wisy-core) and the
terminal client (wisy-cli). A thin wrapper over wisy-engine — it adds no cryptography, only
marshalling.
Boundary
- The opaque
Engineholds the native engine (identity key + held epoch keys) in native memory. Nothing but ciphertext, signatures, and public metadata crosses to JS; when the JS object is garbage-collected the native engine is dropped and its held keys are zeroized. - Compound values cross as plain JS objects via
serde(Env::to_js_value/from_js_value): keys arecamelCase, byte fields are NodeBuffers, and numbers (epochNumber,pos,createdAt) are plain JSnumbers. - Every instant is a millisecond timestamp bounded by
MAX_INSTANT, which is exactlyNumber.MAX_SAFE_INTEGER.createdAt,notBeforeandnotAfterall carry it, so a record this binding accepts is one a browser peer can read back unchanged. ⚠ N-API carriesu64exactly and hands these back asBigInts — which is why the bound belongs to the protocol rather than to whichever runtime would have noticed. - Every fallible call throws a JS
Erroron failure, carrying the engine's fixed, secret-free message.
Compound params/returns are typed unknown in the generated .d.ts for now; the consumers layer their
own typed wrappers over this surface. The Rust DTOs in wisy_engine::types are the source shape, and the
same serde derives feed the WASM binding — so both bindings marshal identical shapes with no duplicate
structs.
Build
Key generation uses the OS randomness source on the host platform — no special build flag. This binding needs Rust ≥ 1.88, higher than the ≥ 1.85 the pure crates need, because napi-build declares that MSRV.
Watch the compiler version when building inside a prepared image: the napi images ship the Rust that was
current when they were built, and a rust-toolchain.toml asking for stable reuses whatever is already
installed rather than fetching a newer one. The release workflow replaces the toolchain for exactly this
reason.
npm install
npm run build:debug # -> index.js, index.d.ts, wisy-engine.<triple>.node (debug; panics unwind to JS)
npm run build # release build (LTO); note the workspace release profile aborts on panic
npm test # run the binding smoke tests under Node's test runnerindex.js, index.d.ts, and the .node addon are build artifacts and are git-ignored.
Install
npm install @kamebara/wisy-engine-nodeThe addon itself is not in that package. npm resolves one of four per-platform packages instead,
picked by os, cpu and libc, so an install pulls exactly the one binary the machine can load:
| target | what needs it |
|---|---|
| x86_64-unknown-linux-gnu | GitHub's runners — this is what a consumer's CI installs |
| x86_64-unknown-linux-musl | Alpine, which the production container is built from |
| aarch64-apple-darwin | Apple Silicon: development, and the mobile work |
| x86_64-pc-windows-msvc | Windows development |
The two Linux entries are not interchangeable and both are required. A glibc addon inside an Alpine image fails to load at startup, and it fails only there: CI is glibc, so CI stays green the whole way and the first sign of trouble is a container that will not start.
Release
Tag node-v<version> and the release workflow builds all four targets, smoke-tests each on its own
platform, and publishes the per-platform packages together with this one. Running it by hand from the
Actions tab defaults to a rehearsal that builds and packs without publishing anything.
Publishing needs an NPM_TOKEN repository secret. The scope is public, because a private scoped
package needs a paid npm organisation; restricted is offered in the manual run for when that changes.
Nothing here reads a private key or an environment secret, and the published files are the loader, the
type declarations, the compiled addon, and the licence.
