fix(review): harden the E2E-gap fixes after security/regression review

Addresses findings from an independent review of the gap-closing commits:

- R1 (regression): add #[serde(default)] to HttpDispatchPayload.method so
  async-HTTP outbox rows enqueued before the field existed still decode
  after upgrade instead of dead-lettering on "missing field `method`".
  Adds a regression test for the missing-key path.
- method case: uppercase ctx.request.method at the orchestrator boundary
  so it honors its documented "uppercased" contract for extension verbs.
  Route matching is already case-insensitive, so matching is unaffected.
- CLI hardening: percent-encode free-form path segments (app slug, topic
  name, ids, secret name) in the reqwest client so a value containing
  `/ ? #` can't break out of its URL segment. Adds a `seg()` helper +
  unit test and applies it uniformly across all path-interpolating
  methods (new and pre-existing).
- S1 (docs): correct the users::email_available enumeration framing — it
  adds no new vector vs. create's uniqueness error, but is cheaper and
  unthrottled; there is no built-in throttle/CAPTCHA primitive, so the
  honest mitigation is a kv-based counter. Updated SDK doc-comments,
  trait docs, and stdlib-reference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-13 09:59:24 +02:00
parent 30bad27711
commit a91b134285
9 changed files with 156 additions and 4 deletions

View File

@@ -10,6 +10,9 @@
//! // for anonymous public scripts.
//! let free = users::email_available("a@b"); // bool — anonymous-safe pre-check
//! // for self-serve registration.
//! // Leaks only "exists/doesn't" but
//! // is cheap + unthrottled: throttle
//! // the route if enumeration matters.
//! users::update(id, #{ display_name: "Alicia" });
//! let removed = users::delete(id); // bool
//! let page = users::list(#{ "$limit": 50, cursor: () });