feat(sidecar): forward the asset manifest, the pixels and the body pass (Phase 3) #43

Merged
whitlocktech merged 1 commits from feat/asset-bridge-p3 into edge 2026-09-10 23:57:57 +00:00
Member

Three routes for Asset Bridge phase 3, forwarded verbatim like everything else on this link:

GET  /assets/manifest?family=&cursor=
POST /assets/fetch
POST /assets/bodies

This repo was not in the phase table, and that was a mistake in the plan

v8.md §16 listed phase 3 as servuo-plugins, module-uo. web.rs routes every command explicitly — there is no generic /assets/* forwarder — so link is in the phase. The docs PR corrects both places.

The two POSTs are reads

The method is the request body, not a side effect: a few hundred asset keys do not belong in a query string. They are the only reads on this link that take one, which is worth a reviewer's eye.

assets_call is event_call's shape with one difference that matters: it responds through respond_assets, so bridge.busy maps to 425 rather than being read as an idempotency collision. On this plane busy is the ordinary answer during an import — the shard serves one asset request at a time on purpose, because its outbound queue is bounded in lines rather than bytes — and a caller that treated it as an error would abandon a perfectly healthy transfer.

422 gains a second meaning

Alongside "the shard has that file and cannot decode it", it is now also the mid-import guard. A manifest reply carries a catalog id the shard derives from its own client files; passing it back on a fetch makes the shard refuse if those files moved in between. Without it, an operator who patches their client halfway through an import gets one asset set stitched out of two, with no error anywhere.

Verified against the live shard

Request Status
GET /assets/manifest 200, 787 rows, cut: "end", 734 ms
GET /assets/manifest?family=static 400this shard serves the 'body' asset family only
POST /assets/fetch with a stale catalog 422 — names both ids and says to start again
POST /assets/bodies with 101 types 400 — names the cap
POST /assets/bodies × 5 chunks (455 types) 200 each, ~190 ms

cargo build clean; 64 tests pass.

Review notes

  • No PROTOCOL_VERSION change — phase 1 already took it to 8, and nothing here changes an existing message shape.
  • Companion PRs: servuo-plugins, Module-uo, docs.

AI disclosure

  • This contribution was AI-assisted (Claude Code).

🤖 Generated with Claude Code

https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4

Three routes for Asset Bridge phase 3, forwarded verbatim like everything else on this link: ``` GET /assets/manifest?family=&cursor= POST /assets/fetch POST /assets/bodies ``` ### This repo was not in the phase table, and that was a mistake in the plan [`v8.md`](https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/link/v8.md) §16 listed phase 3 as `servuo-plugins, module-uo`. `web.rs` routes every command **explicitly** — there is no generic `/assets/*` forwarder — so `link` is in the phase. The docs PR corrects both places. ### The two POSTs are reads The method is the request body, not a side effect: a few hundred asset keys do not belong in a query string. They are the only reads on this link that take one, which is worth a reviewer's eye. `assets_call` is `event_call`'s shape with **one difference that matters**: it responds through `respond_assets`, so `bridge.busy` maps to **425** rather than being read as an idempotency collision. On this plane busy is the *ordinary* answer during an import — the shard serves one asset request at a time on purpose, because its outbound queue is bounded in lines rather than bytes — and a caller that treated it as an error would abandon a perfectly healthy transfer. ### 422 gains a second meaning Alongside "the shard has that file and cannot decode it", it is now also **the mid-import guard**. A manifest reply carries a `catalog` id the shard derives from its own client files; passing it back on a fetch makes the shard refuse if those files moved in between. Without it, an operator who patches their client halfway through an import gets one asset set stitched out of two, with no error anywhere. ### Verified against the live shard | Request | Status | |---|---| | `GET /assets/manifest` | 200, 787 rows, `cut: "end"`, 734 ms | | `GET /assets/manifest?family=static` | **400** — `this shard serves the 'body' asset family only` | | `POST /assets/fetch` with a stale `catalog` | **422** — names both ids and says to start again | | `POST /assets/bodies` with 101 types | **400** — names the cap | | `POST /assets/bodies` × 5 chunks (455 types) | 200 each, ~190 ms | `cargo build` clean; **64 tests pass**. ### Review notes - No `PROTOCOL_VERSION` change — phase 1 already took it to 8, and nothing here changes an existing message shape. - Companion PRs: `servuo-plugins`, `Module-uo`, `docs`. ## AI disclosure - [x] This contribution was AI-assisted (Claude Code). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
wtclaude added 1 commit 2026-09-10 23:42:25 +00:00
feat(sidecar): forward the asset manifest, the pixels and the body pass (Phase 3)
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 2m24s
143f424867
Three routes, forwarded verbatim like everything else on this link:

  GET  /assets/manifest?family=&cursor=
  POST /assets/fetch
  POST /assets/bodies

**The two POSTs are reads.** The method is the request body, not a side
effect -- a few hundred asset keys do not belong in a query string, and these
are the only reads on this link that take one. `assets_call` is `event_call`'s
shape with one difference that matters: it responds through `respond_assets`,
so `bridge.busy` is a 425 rather than an idempotency collision. On this plane
busy is the ORDINARY answer during an import, and a caller that read it as an
error would abandon a healthy transfer.

422 gains a second meaning here alongside "the shard cannot decode that file":
the mid-import guard. A manifest reply carries a `catalog` id the shard derives
from its own client files, and passing it back on a fetch makes the shard refuse
if those files moved in between -- without which an operator patching their
client halfway through an import gets one asset set stitched out of two, with no
error anywhere.

v8.md §16 listed phase 3 as servuo-plugins + module-uo. That was wrong: web.rs
routes every command explicitly and has no generic /assets/* forwarder, so this
repo is in the phase. The doc now says so.

64 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
whitlocktech merged commit baa04e1a76 into edge 2026-09-10 23:57:57 +00:00
whitlocktech deleted branch feat/asset-bridge-p3 2026-09-10 23:57:58 +00:00
Sign in to join this conversation.
No description provided.