Rust SDK: workspace, generator, generated crate and core runtime
Rust joins the SDK as a Cargo workspace under rust/: a generator (rust/generator) ported from hey-sdk's, the code it emits, and the hand-written runtime the generated code sends through (rust/fizzy-sdk, crate fizzy-sdk). First of a stack; the second PR lands the tests and the clippy-pedantic pass.
Generator. openapi.json + behavior-model.json + rust/generator/names.toml → rust/fizzy-sdk/src/generated/{mod.rs, types.rs, routes.rs, redaction.rs, accessors.rs, services/*.rs}: 142 types, 112 routes, 18 services. The Fizzy deltas from the hey-sdk port:
- Fizzy's OpenAPI tags no operation, so services come from operation ids through
names.toml— Go's suffix rules and overrides (go/cmd/generate-services), so every SDK files an operation under the same service; method names match Go'sOperationRegistry(onlyMoveCarddiffers:moveis a keyword, somove_to_board). An id no rule covers fails generation. - Array query parameters (
column_ids[]=…, 10 of them) areOption<Vec<T>>fields sent as repeated keys; absentreadonlyreads as false;format: password(Smithy@sensitive, six name fields) is sensitive alongsidex-fizzy-sensitive, and the behavior model's redaction map is checked against the emitted schemas so the two cannot disagree. - Per-route retry policy (
Route.retry: Option<Retry>—Nonefor the 26 operations the model sends once) and Link pagination with its page parameter are public data on every route. - The
/{accountId}split: services with account-scoped operations hang offAccountClient, the rest offClient;Identityis mixed and its account-scoped method answers a usage error through the bare client rather than a path with a hole in it. - Request-body types (and everything reachable from them) derive
Defaultand take..Default::default(); every other struct is#[non_exhaustive], so a field Fizzy adds later is not a breaking change. - The model carries no descriptions, so rustdoc is synthesized from the facts it does carry (method, path, retry budget, pagination), and
missing_docsholds under-D warnings. --checkregenerates to a temp dir and diffs, catching stale files and files the generator stopped emitting.
Runtime. Ported from hey-sdk's crate with Fizzy's behaviour: bearer or cookie auth, no OAuth, no refresh (a 401 is final); MagicLinkFlow targets upstream Fizzy — keeps the pending_authentication_token from the create answer and sends it back as the cookie with the code on redeem (the Smithy model and Go's helper disagree with upstream and with each other; filed separately as a spec card). Retries follow the route's policy with the client's max_retries as a ceiling on attempts and max_delay on waits, Retry-After honoured on 429/503 up to max_retry_after (past it the 429 is handed back rather than slept through), POST sent once unless the model says idempotent, and the policy carried across every page of a walk. Link pagination with a same-origin guard and page cap, typed Page<T> plus pages/items streams, raw verbs with get_all on both clients, the nine shared error codes with exit codes, hooks with ChainHooks, the resilience trio, the ETag cache, HTTPS enforcement with credential stripping on cross-origin redirects, and constant-time X-Webhook-Signature verification.
Workspace hygiene per the fleet's Rust standard: rust-toolchain.toml 1.98.1, MSRV 1.88 (rust-version, built on 1.88.0 locally), rustfmt.toml, clippy.toml, deny.toml, [workspace.lints] with pedantic and a reasoned allow-list, forbid(unsafe_code), Cargo.lock committed, crates.io metadata and docs.rs config in Cargo.toml.
Not in this PR: root Makefile targets, CI, release and version plumbing, docs beyond the crate README (a sibling PR carries those); the conformance runner.
Summary by cubic
Adds the Rust SDK as a Cargo workspace under rust/: a generator that turns openapi.json and behavior-model.json into a typed client, the generated fizzy-sdk crate, and the hand-written runtime those calls go through. This is the first of a stack; tests and clippy-pedantic land in a follow-up.
Key details
- The generator derives services from operation ids via
names.toml(OpenAPI tags nothing) and fails on ids no rule covers;--checkdiffs against checked-in output. - The runtime supports bearer and cookie auth, magic-link flow, per-route retries with client ceilings, Link pagination with same-origin guard, hooks, resilience layers, ETag cache, and constant-time webhook signature verification.
- Workspace enforces MSRV 1.88, toolchain 1.98.1, pedantic lints,
forbid(unsafe_code), and a committedCargo.lock.