Skip to content

chore: apply rustfmt and silence wit-bindgen clippy lint#4

Merged
mfw78 merged 1 commit into
mainfrom
chore/fmt-clippy-bootstrap
May 30, 2026
Merged

chore: apply rustfmt and silence wit-bindgen clippy lint#4
mfw78 merged 1 commit into
mainfrom
chore/fmt-clippy-bootstrap

Conversation

@mfw78
Copy link
Copy Markdown
Contributor

@mfw78 mfw78 commented May 30, 2026

Summary

  • Apply cargo fmt --all — source had drifted from rustfmt output (collapsed vec! single entries, fluent builder onto one line, two-arg format! call onto one line) and cargo fmt --check would have failed CI.
  • Silence clippy::too_many_arguments at the crate level in modules/example. The wit_bindgen::generate! macro expands to host-import shims whose arity mirrors the WIT signatures; some exceed the lint's default threshold. A targeted crate-level allow with an inline note is cleaner than disabling the lint everywhere.

Test plan

  • cargo fmt --all -- --check — clean
  • cargo clippy --workspace --all-targets --all-features -- -D warnings — clean
  • cargo test --workspace --all-features --no-fail-fast — 0 tests, 0 failures
  • cargo build -p example --target wasm32-wasip2 --release — compiles

CI runs cargo fmt --check and clippy with -D warnings. Two issues
needed addressing before the first PR could go green:

- Source had drifted from rustfmt output (single-call vec!, fluent
  builder chain on one line, etc.). Apply 'cargo fmt --all'.
- modules/example: wit_bindgen::generate! expands to host-import
  shims whose arity matches the WIT signatures, exceeding clippy's
  too-many-arguments threshold. Allow the lint at crate level with
  a comment explaining the source.
@mfw78 mfw78 merged commit 97d7481 into main May 30, 2026
4 checks passed
@mfw78 mfw78 deleted the chore/fmt-clippy-bootstrap branch May 30, 2026 07:43
mfw78 added a commit that referenced this pull request May 31, 2026
The shipped wit/nexum-runtime/types.wit ships 0.1's stringly-typed
`type config = list<tuple<string, string>>`, but five doc locations
plus the migration TL;DR promised a typed `config-value` variant for
0.2 (string/integer/boolean/list). Per architectural triage, defer the
typed variant to 0.3 alongside the manifest parser work — the typing
story lands as one coherent feature.

Updates: docs/00, docs/01, docs/02 (two places), docs/08, migration
guide TL;DR row + 'Typed config' subsection.

Resolves PR #6 finding #4.
mfw78 added a commit that referenced this pull request May 31, 2026
…lities) (#6)

* docs: add 0.1 to 0.2 migration guide

* wit: rename web3:runtime to nexum:runtime, unify error model, add identity/clock/random/http/query-module

* chore: rename crate nxm-engine to nexum-engine; bump to 0.2.0

* build: update justfile and CI for nexum-runtime + nexum-engine rename

* docs: rename to nexum:runtime, unify error model, mark non-server platforms as planned

* runtime: update engine + example to 0.2 WIT

- Engine main.rs targets world `shepherd` (formerly `shepherd-module`),
  generates against nexum:runtime@0.2.0 + shepherd:cow@0.2.0.
- Replaces per-domain error records (JsonRpcError, MsgError, StoreError,
  ApiError, bare String) with unified HostError + HostErrorKind across
  every host impl.
- Adds Identity host stub (was missing in 0.1 despite being doc'd).
- Adds chain::request_batch stub that falls back to per-call dispatch.
- Renames feed_get/feed_set -> read_feed/write_feed.
- Drops separate cow + order interfaces, replaced by single cow_api with
  request and submit_order.
- Block ts in test event is now ms (1_700_000_000_000) per types.wit
  documented unit.
- Example module targets event-module world, matches Event::Tick instead
  of Event::Timer, returns HostError from init/on_event.

* example: drop empty-name guard from init

The guard was inconsistent: missing 'name' key silently defaulted to 'unknown'
and returned Ok, but an explicit empty string returned Err — and both paths
logged a success-shaped 'name=...' line BEFORE the guard ran.

The example is a hello-world; a config-validation guard belongs in a real
module, not a starter. Drop it.

Resolves PR #6 finding #9.

* ci: add wit deps sync check

Both wit/nexum-runtime/ and wit/shepherd-cow/deps/nexum-runtime/ are
committed to the tree; the latter is regenerated by 'just sync-wit'.
Without a CI guard, a contributor can edit one without the other and
the divergence only surfaces at runtime (interface-mismatch on module
instantiation) — not at build time.

The new job re-runs the same copy that 'just sync-wit' does, then fails
if the deps tree differs from the freshly-copied canonical.

Resolves PR #6 finding #8.

* docs/01: align identity::sign to personal_sign semantics

The shipped wit/nexum-runtime/identity.wit defines sign() as
personal_sign — host MUST prepend the EIP-191 prefix
('\x19Ethereum Signed Message:\n<len>') before hashing. docs/01
described it as 'sign raw bytes' which is a transaction-signing
footgun (a raw signer can be tricked into signing EIP-155 / EIP-712
payloads disguised as plain bytes) AND diverges from the WIT — two
compliant hosts implementing different specs produce mutually
unverifiable signatures.

Align docs/01 to the WIT. Note that raw-bytes signing, gated by an
explicit capability, is on the 0.3 roadmap.

Resolves PR #6 finding #1.

* docs: align chain::request-batch and http WIT snippets to shipped types

Both snippets in the migration guide and docs/01 showed
list<tuple<string, string>> shapes that don't match the shipped WIT.
Adopters who copy the doc snippets get wit-bindgen type errors against
the real interfaces.

- chain::request-batch now uses the nominal record rpc-request and
  variant rpc-result (matching wit/nexum-runtime/chain.wit).
- http now uses the nominal record header and adds the timeout-ms field
  (matching wit/nexum-runtime/http.wit), plus *.domain wildcard syntax
  in the allowlist example and the docstring on how non-2xx surfaces.

Resolves PR #6 findings #2 and #3.

* docs: defer typed config-value variant to 0.3

The shipped wit/nexum-runtime/types.wit ships 0.1's stringly-typed
`type config = list<tuple<string, string>>`, but five doc locations
plus the migration TL;DR promised a typed `config-value` variant for
0.2 (string/integer/boolean/list). Per architectural triage, defer the
typed variant to 0.3 alongside the manifest parser work — the typing
story lands as one coherent feature.

Updates: docs/00, docs/01, docs/02 (two places), docs/08, migration
guide TL;DR row + 'Typed config' subsection.

Resolves PR #6 finding #4.

* docs/migration: replace cargo-nexum vapor with real commands

§9 verification checklist referenced 'cargo nexum check' and 'cargo
nexum run --mock'; §11 promised 'cargo nexum migrate --from 0.1' as
shipping with 0.2. None of these exist — there is no cargo-nexum crate
in the workspace.

Rewrite §9 to use real `cargo` + `just` invocations. Drop the §11
codemod promise; the sed cheat sheet in §8 already does the mechanical
work. Add a clear 'no cargo-nexum toolchain in 0.2; coming in 0.3' note
so adopters set the right expectation.

Resolves PR #6 finding #7.

* wit+engine: import clock/random/http in event-module; add host impls

The new 0.2 capability interfaces (clock, random, http) shipped as
standalone WIT files but were not imported by any world, so modules
built against event-module / shepherd could not 'use' them. Their
existence was advertised in the migration guide but was structurally
unreachable.

- event-module.wit: add 'import clock', 'import random', 'import http'
  (grouped as ambient host services after the six core primitives).
  shepherd world inherits via 'include event-module'. query-module
  remains intentionally sandboxed (no caps, no chain, no network).
- Engine: add host impls for clock (SystemTime + monotonic_baseline:
  Instant), random (getrandom 0.4 fill), http (returns Unsupported
  for 0.2; real fetch is 0.3 — allowlist enforcement lands with #6).
- Cargo.toml: add getrandom 0.4, plus serde 1 + toml 1 (for #6).

Resolves PR #6 finding #5.

* engine: minimal nexum.toml manifest parser with [capabilities] enforcement

Per architectural triage, ship minimal manifest enforcement in 0.2 and
defer optional-capability trap stubs to 0.3. The migration guide §3
promised four mechanisms; this commit lands the two security-critical
ones (required-capability check + http allowlist enforcement) plus the
deprecation warning, and explicitly defers per-import trap stubs.

Manifest schema (parsed in crates/nexum-engine/src/manifest.rs):
  [module]        name, version, component (sha256; parsed, not yet verified)
  [capabilities]  required (validated against KNOWN_CAPABILITIES; engine rejects unknown names)
                  optional (parsed + logged; trap-stub fallback is 0.3)
  [capabilities.http]  allow (exact host or *.suffix wildcard)
  [config]        TOML scalars flattened to strings (typed variant on 0.3 roadmap)

CLI: nexum-engine <component.wasm> [<nexum.toml>]. If the second arg is
omitted, the engine looks for nexum.toml next to the .wasm. If neither
exists, it emits the deprecation warning and proceeds with empty config
and empty allowlist (= effectively denies all HTTP).

http::fetch now performs the per-module allowlist check (host extracted
via a stdlib URL parser, exact or *.suffix match). Allowlist denial
returns HostError { kind: Denied }; real network fetch is still 0.3.

Includes unit tests for extract_host and host_allowed.

Resolves PR #6 finding #6.

* style: cargo fmt (nightly)

CI rustfmt (nightly) collapses several multi-line signatures that the
hand-formatted code had as multi-line.

* rename WIT package nexum:runtime -> nexum:host (resolve engine/runtime naming overload)

The 0.2 release shipped two similarly-named things — `nexum-engine` (the
Rust crate hosting WASM components) and `nexum:runtime` (the WIT
package). Both contain 'runtime' or a synonym, but they're at different
layers: engine = implementation, runtime = contract.

Worse, README.md described the engine crate as 'Host runtime —
wasmtime-based component loader' — explicitly calling the *engine*
'runtime' while a sibling directory was literally named `nexum-runtime`.

The word 'runtime' overwhelmingly means 'the thing that runs code' in
programming usage; putting it on the contract side inverted the
convention. Rename the WIT package to `nexum:host` — the host-imports
surface a guest sees. Distinction becomes self-documenting:

  engine (nexum-engine)  = a concrete implementation
  host   (nexum:host)    = the WIT contract every engine implements

Touchpoints:
- wit/nexum-runtime/ -> wit/nexum-host/ (12 files renamed via mv)
- wit/shepherd-cow/deps/nexum-runtime/ -> wit/shepherd-cow/deps/nexum-host/
  (regenerated by 'just sync-wit'; also covered by CI guard)
- Every 'package nexum:runtime@0.2.0' -> 'package nexum:host@0.2.0' (12 files)
- Every 'use nexum:runtime/...' -> 'use nexum:host/...' (shepherd-cow WIT)
- Every 'nexum::runtime::...' -> 'nexum::host::...' (engine + example Rust)
- justfile sync-wit paths
- .github/workflows/ci.yml wit-deps-sync paths
- All design docs (00..08), migration guide
- README.md + docs/00 add an explicit 'Engine vs. host' callout so the
  distinction is directly apparent to a new reader.
- A few stray 'host runtime' prose mentions in docs/05 and docs/07
  changed to 'host engine' for consistency.

Migration guide updated so a 0.1 -> 0.2 reader never encounters the
mid-development 'nexum:runtime' name — the new package is `nexum:host`
end-to-end.

Build + run smoke clean; nightly rustfmt clean.

* wit: drop deps/ vendoring; list both packages explicitly in bindgen

The 0.2 release vendored a copy of wit/nexum-host/ under
wit/shepherd-cow/deps/nexum-host/ because the engine's bindgen target
(shepherd:cow/shepherd) imports from nexum:host via 'include', and
wit-parser's default cross-package resolution looks at <pkg>/deps/.
Maintained by 'just sync-wit' + a CI guard to catch drift.

That whole pipeline was treating the symptom rather than the cause.
Both bindgen macros (wasmtime::component::bindgen! and
wit_bindgen::generate!) accept 'path' as an array of dirs, each
holding one package. Listing both packages explicitly resolves the
cross-package reference natively with no vendored copy.

Changes:
- crates/nexum-engine/src/main.rs: bindgen path is now
  ["../../wit/nexum-host", "../../wit/shepherd-cow"]; world fully
  qualified as "shepherd:cow/shepherd".
- modules/example/src/lib.rs: world fully qualified as
  "nexum:host/event-module". Path stays single (the example doesn't
  import shepherd:cow).
- wit/shepherd-cow/deps/ deleted entirely (12 files).
- justfile: sync-wit recipe removed; build-runtime renamed to
  build-engine (clearer; matches the engine vs host vocabulary
  established earlier); check + run no longer depend on sync-wit.
- .github/workflows/ci.yml: wit-deps-sync job removed (nothing to
  sync, nothing to drift).
- docs/migration/0.1-to-0.2.md: checklist item about vendored deps
  rewritten to point at the new bindgen pattern.

Result: 1 source of truth per WIT package, zero ceremony to keep them
aligned, ~360 fewer lines of vendored bytes in the repo.
@mfw78 mfw78 mentioned this pull request May 31, 2026
48 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant