Skip to content

remote-store: real Swarm backend via a Bee node#477

Open
mfw78 wants to merge 1 commit into
feat/m5-ghcr-image-alignfrom
feat/m5-swarm-remote-store
Open

remote-store: real Swarm backend via a Bee node#477
mfw78 wants to merge 1 commit into
feat/m5-ghcr-image-alignfrom
feat/m5-swarm-remote-store

Conversation

@mfw78

@mfw78 mfw78 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

What

Implements the nexum:host/remote-store interface against a real Swarm backend: a RemoteStore handle (crates/nexum-runtime/src/host/remote_store_bee.rs) wrapping a bee-rs HTTP client, wired through ComponentsBuilder/Components/HostState alongside the existing chain/store/logs seams. upload/download hit Bee's /bytes API; read-feed/write-feed hit the single-owner feed API, stripping/prepending the canonical timestamp prefix and signing writes with the configured feed key. A new [remote_store] config table (api, optional postage_batch, optional feed_key) drives it; absent config or an absent batch/key degrades individual operations to unsupported rather than failing boot. RemoteStoreError projects onto Fault by HTTP status (429 to rate-limited, 402/403 to denied, timeout to timeout, 404/malformed to not-found/internal).

Why

All four remote-store functions were stubs returning Unsupported. Content-addressed module and adapter distribution (doc 03) and the M4 infrastructure remit need a real Bee-backed implementation.

Testing

cargo test -p nexum-runtime covers the new remote_store_bee unit suite (wiremock-backed: upload/download happy paths and misses, feed read/write incl. missing batch/key, malformed reference, disabled handle, bad config at boot) and the config table's parse + feed-key redaction test; existing supervisor/test_utils fixtures updated for the new remote component slot.

AI Assistance

Implemented with Claude Code assistance; reviewed by a human before merge.

Closes #151

Replace the four unsupported remote-store stubs with a Bee-backed
backend behind the component seam: a shared RemoteStore handle built
from the new [remote_store] engine table (API URL, postage batch,
feed-signing key), threaded through Components and every module store.
Uploads and feed updates are stamped with the configured batch; feed
updates are signed host-side. Faults classify by failure: missing
configuration is unsupported, malformed guest input invalid-input, a
lookup miss unavailable, HTTP 429 rate-limited, 402/403 denied, and a
transport timeout timeout. An absent table leaves every call
unsupported so guests can probe-then-skip.

@lgahdl lgahdl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid work overall — verified feed-key handling never leaks into logs (no Debug derive on Backend, manual Debug impls redact it), the config redaction test is a real assertion (not a tautology), graceful degradation uses .ok_or(...)? everywhere with no unwrap-on-None, and HTTP status-to-Fault mapping is exhaustive except that RateLimited always drops any Retry-After header (minor, can't confirm without bee-rs source whether the header is even exposed).

One thing worth resolving before merge, flagged with appropriate uncertainty since it depends on bee-rs's internal behavior I couldn't fully confirm from its docs:

let result = backend
.client
.file()
.update_feed(batch, key, &topic, &data)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

write_feed passes data straight through to update_feed with no timestamp prefix visibly prepended in this code, but read_feed (line 177) unconditionally strips the first FEED_TIMESTAMP_LEN (8) bytes of whatever comes back. If bee-rs's update_feed does NOT prepend that prefix itself (i.e. the caller is symmetrically responsible for it on both read and write, matching how the read side's stripping is handled by this crate rather than the library), then every write-then-read round trip silently eats the first 8 bytes of the guest's own payload — silent data corruption on the primary write path of new infrastructure. I wasn't able to fully confirm from bee-rs's published docs whether the timestamp is applied library-side on write, so this may already be handled correctly — but regardless of which is true, there's no test that chains a real write_feed call into a read_feed call to prove the round trip is intact (write_feed_signs_the_next_update only checks the returned reference; read_feed_strips_the_timestamp_prefix hand-constructs a payload that already has the prefix, so the two paths are never exercised together). Worth adding that round-trip test before merge — it will immediately confirm or rule this out either way.

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.

2 participants