Skip to content

feat(host): switch the generic interfaces to fault end to end#215

Open
mfw78 wants to merge 1 commit into
feat/fault-vocabularyfrom
feat/fault-generic-interfaces
Open

feat(host): switch the generic interfaces to fault end to end#215
mfw78 wants to merge 1 commit into
feat/fault-vocabularyfrom
feat/fault-generic-interfaces

Conversation

@mfw78

@mfw78 mfw78 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #208 (part of the typed-fault train stacked on the epic-80 stack, epic #206; merges in stack order after #213, feat/fault-vocabulary).

Moves the four generic host interfaces (local-store, remote-store, identity, messaging) from the unified host-error envelope to the typed fault vocabulary end to end: WIT signatures, host implementations, the SDK host trait and macro conversion ladder, mocks, and the one raw wit-bindgen module fixture that needs its own converter.

Changes

Each of wit/nexum-host/{local-store,remote-store,identity,messaging}.wit moves every function from result<_, host-error> to result<_, fault> and pulls in use types.{fault} (messaging keeps message alongside it).
identity.wit also updates its doc comment: rejection is now described as fault.denied.
Chain, the event-module and query-module exports, and logging are untouched, since they are out of scope for this sub-issue.

crates/nexum-runtime/src/host/error.rs retargets From<StorageError> from HostError to Fault (Fault::Internal carrying err.to_string()), with the module doc reworded to describe both shapes side by side.
HostError constructors stay live, since chain and cow-api impls still return them.

The four host impls under crates/nexum-runtime/src/host/impls/ return the Fault associated error type.
Local-store maps StorageError through the retargeted From; the three deferred backends (remote-store, identity, messaging) return Fault::Unsupported carrying the same detail string the prior unimplemented() used.
accounts/query continue to return an empty Ok.

crates/nexum-sdk/src/host.rs changes LocalStoreHost to Result<_, Fault> and adds impl From<Fault> for HostError, which is the bridge that lets module strategies still returning a unified HostError call the now-fault-typed store methods with a mechanical ?.
The Host doctest is updated to match.

crates/nexum-sdk/src/wit_bindgen_macro.rs adds convert_fault, mapping the wit-bindgen-generated Fault to the SDK Fault (including the RateLimit field), and routes the LocalStoreHost impl through it.
Macro-level docs list the new symbol.

crates/nexum-sdk/src/chain/chainlink.rs updates the test StubHost store methods to return Fault.

crates/nexum-sdk-test/src/lib.rs and crates/shepherd-sdk-test/src/lib.rs move MockLocalStore/MockHost store methods, fail_on, check_injected_error, error_patterns, and the max-entries error path onto Fault, with the two crate-internal unit tests updated to match.

modules/fixtures/flaky-bomb/src/lib.rs is a raw wit-bindgen module without the SDK macro, so it gets its own small store_fault helper that folds the local-store fault back into the export host-error so the counter reads and writes still compose with ?.

Test plan

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo doc --workspace --no-deps with RUSTDOCFLAGS=-D warnings
  • All 11 module wasms rebuilt for wasm32-wasip2 --release, in-tree, so supervisor e2e/boot tests resolve fresh artefacts
  • cargo test --workspace --all-features
  • cargo test -p nexum-runtime --all-features (196 passed, 0 failed, 0 skipped), including supervisor::tests::restart_flaky_module_recovers_after_backoff, which drives the flaky-bomb guest's local_store::get/set across the wasm boundary against the new result<_, fault> wire type

Notes for reviewer

From<Fault> for HostError in nexum-sdk is new and is the one deliberate aggregation seam in this change.
Module strategies (twap-monitor, ethflow-watcher, balance-tracker, stop-loss) each return a single Result<_, HostError> while mixing a now-fault-typed store call with still-host-error chain and cow-api calls, so the bridge keeps ? mechanical across roughly thirty call sites without touching their signatures.
It disappears once chain, cow-api, and the export boundary also migrate to fault.

Fault deliberately omits domain/code.
Every prior detail string is preserved verbatim in the fault payload (deferred-backend messages, StorageError display output, mock injected-error messages); the dropped fields were always static per-interface constants that are redundant once the interface itself is the WASI domain tag.

flaky-bomb hand-rolls its converter because it uses raw wit-bindgen rather than the SDK macro, and keeps domain: "local-store" since it constructs the export HostError directly.

Left for a follow-up: prose in docs/00-overview.md, docs/07-rpc-namespace-design.md, docs/08-platform-generalisation.md, docs/adr/0009, and docs/migration/0.1-to-0.2.md still describes a single unified host-error model. A partial edit here would leave those pages internally inconsistent mid-migration, so a coherent doc pass is deferred until chain, cow-api, and the exports also move.

AI Assistance: Claude Code (Opus 4.8 implementation and adversarial review, Sonnet 5 PR authoring) used for the full change.

Move local-store, remote-store, identity and messaging off the unified
host-error and onto the per-interface fault vocabulary. These four only
ever produced generic kinds, so the interface is now the failure domain
and the seven fault cases carry the cause directly.

The WIT fns return result<_, fault>; the runtime host impls construct
fault cases (store StorageError folds to internal, the deferred backends
report unsupported); the nexum-sdk LocalStoreHost trait returns
Result<_, Fault> and a From<Fault> bridge lets a strategy aggregate a
store fault and a chain host-error into one return; the bind macro grows
convert_fault; the nexum-sdk-test and shepherd-sdk-test store mocks and
the raw flaky-bomb call sites move with it. Chain, cow-api and the module
exports stay on host-error until their own migration.
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