Skip to main content

Crate brazen

Crate brazen 

Source
Expand description

brazen — the engine behind the bz command, and the pure, fully-tested core of a stateless LLM adapter.

cargo install brazen builds the bz binary (this crate’s [[bin]]); the library is that binary’s engine, published alongside it in case it is useful as a dependency. Its API is not yet a stability contract — pin an exact version if you build on it.

This crate holds the canonical model (the single source of truth every provider/protocol projects to and from) and the traits behind which all impurity (network, clock, credentials, browser) is injected. The bz binary and src/native/ own the native impls; the library reaches 100% coverage on its own because nothing here touches IO — a boundary tests/purity.rs keeps real now that the bin and the library share one crate.

Beyond the canonical model and error model (the dependency root), this crate defines the seams the rest of the pipeline plugs into: the Protocol, Auth, Transport, CredStore, and Clock traits, the data records they exchange (WireRequest, Provider, Cred, …), and the Registry that dispatches by id without ever matching a vendor name (§4 of the architecture). It also holds the pure pipeline — input resolution, canonical-in parsing, and the output projections + pump loop (§5). Concrete protocol/auth/transport impls land via their own tasks; the shared test doubles live in [testing].

Structs§

AmbientSpec
An ambient credential source as row DATA (auth §5.5): path is the source LOCATOR the bz impl reads — a ~/$HOME-expanded filesystem path for a file format, an environment-variable NAME for api_key_env — and format selects the pure parser that maps its bytes to a Cred. Neither lives in core code, so deleting the row’s ambient block deletes the capability (severability).
Args
The injected process inputs handed to run: the program arguments (excluding argv[0]), a snapshot of the environment, and the one bit of terminal state the pure lib can’t observe — whether stdin is an interactive tty (§5.5). main builds it from std::env/isatty; tests build it from literals — so run is exercised end-to-end without touching the real process state (arch §6.5, §9.6).
CachedModels
One provider’s cache document (§5.1): the ORDERED list plus last_used, the local observation of which id this provider last served a 2xx for. Two DIFFERENT facts in one file, never two representations of one: models is MEMBERSHIP (which ids this row can serve — read by partial matching and by routing’s ownership tier, config §7), last_used is RECENCY (which of them to default to on an empty seed, §4 rung 2). The pointer is never a permutation of the list — §5.4’s “append, never reorder” stands.
CanonicalError
A normalized error, carried in-band as Event::Error (§3.3). It stores only what cannot be computed: retryable and the exit code are queries over kind, never fields that could drift.
CanonicalRequest
The single canonical request. A field set on the wire is used as-is; a field it omits defaults (getConfigValue fills it later — §6.1). extra is the long-tail valve: an unmodelled top-level key is forwarded verbatim.
CountIo
The injected seams + writers for one bz --count-tokens — the sibling of ListIo, with a reader (the count op CONSUMES a request, unlike the listing verb). Reuses the data-plane Transport/CredStore/ModelCache/Clock: the model seed is placed against the same cache (READ-only — no write), and the one round-trip goes through the same Auth::apply. stdout gets the count; any error goes to stderr.
EnvSnapshot
A snapshot of the process environment, injected by main. A newtype over a BTreeMap so the projection is deterministic and pure (config §3.4).
EnvelopeHead
What Brazen reads off a delegate’s response head (spec §5.2): the status every transport already carries, the ONE response header it already keeps — retry-after, verbatim (arch §3.3) — and where the BODY starts in the buffer, so bytes that arrived alongside the head stream on as the first chunk instead of being buffered to end. Widening the header set stays additive.
ExecSpec
The wire request + the three delivery facts it carries (wire.rs): the HTTP Method, the subprocess ExecSpec, and the Envelope its pipes carry. A subprocess target a WireRequest may name instead of an HTTP one (claude-code spec §3.1): the native transport spawns program args…, writes wire.body to the child’s stdin, and streams the child’s stdout as the response body. Data on the one struct already crossing the transport seam — like Method/Timeouts, never a new send parameter. Envelope says what the child’s pipes CARRY, which is the only thing the two subprocess uses differ in.
HeaderSpec
The auth-header shape as data (auth §2): the only thing that names the auth header, so ApiKey/Bearer share one data-driven header write.
Host
The five impure data-plane seams, bundled (arch §1, §6.5) — the sibling of the verbs’ ListIo/LoginIo IO bundles. Every round-trip the generation path makes goes through exactly these: the Transport (the one ureq user), the credential store, the model cache, the clock (auth-refresh expiry), and the fail-open replay stash (ingress §5 — read/written only by the --in/--serve masquerade shell; generate never touches it). The writers stay separate from the Host because run borrows stdout/stderr mutably AND simultaneously when it builds the sink — a seam reference is shared, a writer reference is exclusive, so they cannot live in one struct.
IngressError
A decode_request failure. ALWAYS ErrorKind::ParseInput (ingress.md §2) — the kind is a query over this type, never a stored field — framed in the CLIENT dialect’s error envelope at the edge (§9). message names the offending key/shape, per the adapt-or-reject ladder’s rung 4 (§3).
ListIo
The injected seams + writers for one bz --list-models (model-discovery §2), the sibling of LoginIo. The verb writes its listing to stdout and any error to stderr, reuses the data-plane Transport/CredStore/Clock for the one GET (auth/refresh and all, through the same Auth::apply seam), and is the WHOLESALE writer of the cache — it puts the decoded list the generation path later reads, which that path then appends learned ids to on success (§5, §5.4).
LoginIo
The injected control-plane seams + RNG for one bz --login (auth §7.2).
Message
A transcript message. content is ALWAYS a Vec<Content>; a bare wire string decodes to vec![Text(..)] (the string-vs-list distinction dies at decode). Deserialize is hand-rolled in request_de: a user turn bearing any tool_result decodes as Role::Tool (§2.2, the Anthropic packing normalized).
Model
One available model, the canonical projection of a provider list entry (§3). Ordered position in the returned Vec IS the provider’s suggested order — the single source the heuristics read, so there is no rank field. default is CARRIED, not invented: a dialect that flags one sets it; today none does, so it is false and §4’s first-in-list rule governs — the seam stays so a provider that DOES flag one needs no code change.
ModelsOverride
The [provider.models] per-row model-discovery override (config §4.4, model-discovery §3.2): the bz --list-models GET’s path/query and the response list keys, OVERRIDING the protocol’s default ModelsShape (§3.1). Every key is optional — an omitted one inherits the protocol default — and the whole block is optional (absent ⇒ pure protocol default). deny_unknown_fields makes a typo’d key a MalformedFile (config §2.3), like oauth. strip is NOT here: it is protocol-only (Google’s leading models/), never row-overridable. query mirrors authorize_params (a Vec<(k, v)> URL-encoded by the same codec, auth §7.4); the skip_serializing_if keeps an omitted key out of a --dump-config round-trip and off the TOML serializer’s no-None path.
OAuthConfig
The OAuth auth-row as data (auth §7.1): endpoints, client_id, scope, and the auth-mode-dependent beta_headers (e.g. anthropic-beta: oauth-…). The provider NAME is deliberately absent — it lives once, as the row key / store_key. The pure OAuth builders take &OAuthConfig, so no vendor policy is compiled into the core. Like the [[provider]] row (config §2.3), deny_unknown_fields makes a typo’d or MISPLACED key a MalformedFile rather than a silent drop — a TOP-LEVEL row key (e.g. unsupported_body_keys) typed under [provider.oauth] would otherwise vanish and the strip never fire (bl-9649).
Provider
A resolved provider row (arch §4.2). Pure data: name is a table key never matched on in the pipeline; protocol/auth are registry keys; model_aliases drives the computed alias→wire-id lookup. Sparse user/file rows fold onto the embedded defaults before a complete Provider is resolved (config §3.2).
ProvidersIo
The injected seams + writers for one bz --list-providers (config §6.1), the deliberately-thin sibling of ListIo. There is no Transport, no Clock, and no ModelCache: the verb reads the merged config, the credential store, and any row’s ambient file, and that is the whole of its reach.
RedirectSpec
The loopback redirect endpoint as data (auth §10.1). The default reproduces today’s literal — 127.0.0.1 (RFC 8252), an ephemeral port (None ⇒ :0), and /callback — so deleting the block restores it (severability). A provider whose registered redirect differs (OpenAI: localhost:1455/auth/callback) names it here as data; the socket still binds the IPv4 loopback 127.0.0.1.
ReplayStash
The stash directory, rooted at the injected XDG cache root. Payloads are opaque bytes to this module — the canonical-JSON block(s) for one turn.
ResolvedConfig
The one config the pipeline runs on (config §7). model is the alias- resolved WIRE id, so ProviderCtx.model is final and encode has no model logic (arch §4.1). Each gen scalar already carries the routed row’s body_defaults beneath flag/env/file (folded at resolve, config §4.1).
Secret
A plaintext secret whose Debug/Display redact and whose only plaintext reads are expose() (the single audited site) and Serialize (reached only by CredStore::put writing the 0600 file) — auth §5.3.
ServeIo
The injected seams + writers for one bz --serve (ingress §7) — the sibling of ListIo/LoginIo. The data-plane seams carry Sync here because the connection threads share them (each thread rebuilds the ordinary Host view); bind yields the listener; stash is the §5 replay stash.
Timeouts
The per-request transport budgets (config §4.3), in WHOLE SECONDS; each None leaves that bound unset (the transport’s own default). ureq’s three phase budgets — the seam’s internal vocabulary, NOT the config surface: the resolved config carries ONE timeout (the silence budget), and ResolvedConfig::timeouts() FANS it onto all three here (all equal, or all None), so the collapse to one knob is a surface fact and the fan is observable at this seam (arch §13.15). Carried on the WireRequest — the one thing crossing the seam — so config- sourced policy reaches the impure transport without widening the send signature. The one number lives in config (floor data/defaults.toml), never as magic in the bin (severability — policy in config, not core).
TransportResponse
The peeked HTTP status (read even under --raw, for exit-code correctness) plus the blocking, incremental body stream (arch §4.1).
TransportSpec
The [provider.transport] delegate block (transport spec §4.2): the operator’s own HTTP/TLS implementation, spawned per request and spoken to over the stdio HTTP envelope (spec §5). program is a PATH name or an absolute path; args are passed VERBATIM — the operator’s vocabulary, never inspected here, so no client identity is compiled into Brazen. deny_unknown_fields makes a typo’d key a MalformedFile (config §2.3), like [provider.models]; the whole block folds with Option::or across layers (replaced, never merged).
Usage
Token accounting (§3.2). Every field is Option: a provider that never reports a counter leaves it None (0 would be a lie), never fabricated. Token-explicit names — these count tokens (Anthropic input_tokens/…, OpenAI prompt_tokens/…) — frozen with the rest of the v=1 vocabulary.
WireRequest
The wire request + the three delivery facts it carries (wire.rs): the HTTP Method, the subprocess ExecSpec, and the Envelope its pipes carry. The HTTP request that flows encode → auth → transport (arch §4.1). encode builds the body + non-auth headers; Auth::apply adds the auth headers in place; Transport::send consumes it. Header names match case-insensitively so an auth overwrite never duplicates a header. method is Post for every generation request (the default — encode builds POSTs via new) and Get for the list-models verb’s GET (§6). timeouts is the per-request transport policy (config §4): encode leaves it at the Default (all unset) and run stamps the resolved config onto it before send, so a config-driven bound reaches the impure transport without a wider send signature. exec declares a SUBPROCESS target (claude-code spec §3): None = HTTP (every prior dialect, byte-identical); Some routes the native transport to the spawn — url/method/headers are inert on that path.

Enums§

AmbientFormat
Which foreign credential format an AmbientSpec names (auth §5.5). A closed enum, not a JSON-pointer DSL: each shape needs a parser anyway, so one variant per known source is less mechanism than a speculative mapping language. The variant ALSO tells the bz discover impl where to read: a file (ClaudeCode) or a process env var (ApiKeyEnv).
AuthId
Which auth model a provider uses (arch §4.2, §4.4). A registry key. ApiKey and Bearer differ only in HeaderScheme; both ship, plus OAuth2 and None. None is a keyless row (e.g. local Ollama): no credential is read and no auth header is written, so it carries no api_header — a resolve invariant mirroring the way an OAuth2 row carries an oauth block.
Content
A piece of content. Text is expressible as a bare string or a {"type":"text",…} object; other variants are tagged objects. Thinking/RedactedThinking payloads and the two server-tool variants (CR-4) round-trip verbatim — provider-executed blocks carried untouched, mirroring the RedactedThinking rule.
ContentKind
What kind of content block is opening (§3.2). Externally tagged so it renders {"text":{}} / {"tool_use":{…}} exactly as the §5.2 sample shows.
Cred
The stored secret bundle for one provider (auth §5.1). The variant IS the token-kind discriminant; expires_at is ABSOLUTE unix-seconds; there is no is_valid flag (freshness is the now + SKEW >= expires_at query) and no provider name (the file path is the name).
Delta
A streamed content fragment (§3.2). Externally tagged so a newtype variant renders {"text_delta":"Hel"}. Tool arguments ride JsonDelta as text fragments, never a parsed Value.
DocumentSource
A document source — the Image analogue for PDFs/files, kind-tagged exactly like ImageSource; a dialect that can’t express a source rejects at encode (providers §9).
Envelope
The wire request + the three delivery facts it carries (wire.rs): the HTTP Method, the subprocess ExecSpec, and the Envelope its pipes carry. What a spawned child’s stdin/stdout carry (transport spec §4.1) — the ONE discriminator between the two subprocess uses, so WireRequest never grows a second exec field and a row can never be both by construction.
ErrorKind
The taxonomy every failure normalizes to (§3.3). Provider carries the HTTP status so retryable/exit derive without a second table. Other is the forward-compat escape hatch (§3.2 v=1 contract): an error event carries no v handshake, so a future kind cannot be version-gated — instead an unrecognized snake_case kind decodes here verbatim (mirroring FinishReason::Other) so a 0.1.0-pinned consumer degrades instead of failing. Serde is hand-rolled (below) to route the unknown tag, not derived.
Event
FinishReason
Why generation stopped (§3.2). Carried flattened into Event::Finish, keyed on reason. Refusal is a Finish, never an Error. Other preserves any unknown reason string so decode never panics on a new value.
HeaderScheme
How the secret is written into the header value (auth §2). Two arms cover every shipped wire convention; a match on it is value formatting, not vendor dispatch.
ImageSource
IngressId
The closed set of ingress dialects — the registry key, mirroring ProtocolId (arch §4.4). A dialect is always named EXPLICITLY (the --in flag, or under --serve the route path); structural sniffing stays forbidden (ingress.md §2).
Method
The wire request + the three delivery facts it carries (wire.rs): the HTTP Method, the subprocess ExecSpec, and the Envelope its pipes carry. The HTTP verb a WireRequest carries (model-discovery §6): every generation request is a Post (the default — encode is unchanged), the list-models verb’s GET a Get. Data on the one struct already crossing the transport seam (mirrors timeouts), not a new send parameter — the impure HttpTransport reads it to pick the verb, MockTransport records it.
OutMode
The output projection (arch §5.1): --text default, --json → Ndjson, --raw → Raw. The single enum behind both PartialConfig.output and ResolvedConfig.output — one home for “which projection” (config §7).
OutputFormat
A PORTABLE structured-output intent — one canonical knob every structured-output- capable dialect spells differently, lifted out of extra so each adapter owns its projection (the same rule as ToolChoice/reasoning). Internally tagged on type ({"type":"json"} / {"type":"json_schema",...}), so it rides the wire and config the same way. name/strict feed only the dialects whose wire has them (OpenAI); Anthropic/Google/Ollama read only schema (providers.md §6).
ProtocolId
Which wire dialect a provider speaks (arch §4.2). A registry key, never a match target; the explicit rename keeps the config spelling (openai_chat) stable regardless of the Rust identifier.
ReasoningEffort
A PORTABLE reasoning-effort intent — one canonical knob every reasoning-capable dialect spells differently, lifted out of extra so each adapter owns its projection (the same rule as ToolChoice/parallel_tool_calls). serde lowercase, so "low"/"medium"/"high" on the wire and in config (providers.md §6).
Role
Route
Which control plane the bz shim should wire (§5.10.1). Computed by the ONE authoritative [parse_args], so the coverage-excluded shim never hand-rolls an argv scan and can never disagree with the lib on flag-vs-prompt: a value whose text looks like a control flag (--system=--login) is the value, and any word after -- is the prompt, so neither is ever mistaken for a route.
ServiceTier
A PORTABLE PROCESSING-LANE intent — the FIFTH lifted knob (providers.md §6.2): spend the provider’s priority lane on this request, or demand the standard one. An ENUM, not a bool: “which lane” is a value, and a bool would be the lossy “is this fact present” projection of it (AGENTS.md) — OpenAI speaks default|flex|priority, Anthropic auto|standard_only, and a further rung (Flex) is additive later under #[non_exhaustive]. serde lowercase, so "priority"/"standard" on the wire and in config; None = absent, the key omitted and the provider’s own default lane taken (the empty-set path).
Tool
A declared tool — an OPEN SET (brazen enumerates none, registers none). The enum distinguishes only NORMALIZE vs CARRY, and the harness declares which by the shape it hands over: a wire object with no type key is Custom, one with a type key is Provider (hand-rolled serde in request_de, keyed on type).
ToolChoice
All four tool-use intents, lifted explicitly rather than left in extra.

Constants§

EVENT_SCHEMA_VERSION
Event-schema version stamped into the first MessageStart (§3.2). The one handshake a harness pins to; a backward-incompatible change to the Event vocabulary bumps it (an additive kind/event does NOT — see the module doc).
VERSION
The crate’s own version (Cargo.toml’s [package] version, via Cargo’s compile-time env var). Re-exported at the crate root as brazen::VERSION so a downstream that links brazen reads the linked crate’s version DIRECTLY — the linked crate is the source of truth — instead of mirroring the pin by parsing a manifest. The sibling [VERSION_LINE] is the bz CLI’s rendering of this same fact; concat! takes only literals, so both derive from env!("CARGO_PKG_VERSION") rather than one from the other.

Traits§

Bind
The bind seam: the resolved [ingress].listen address becomes a listener. The shim wires the OS TCP bind; tests wire in-memory queues.
BrowserLauncher
Open url in the user’s browser (auth §7.2). Real impl Command::spawns the browser_argv; the fake records the argv and never execs.
Clock
The one injected time source in the data plane (auth §5.4): unix seconds. The library never calls SystemTime::now; bz wires SystemClock, tests wire FakeClock.
CodeReceiver
Capture the loopback redirect (auth §7.2, §10.1). bind binds the listener on 127.0.0.1 at the requested port (None ⇒ an OS-assigned ephemeral port, RFC 8252 §7.3) and returns the ACTUALLY-bound port, which browser_flow substitutes into the redirect_uri — single-sourcing the port through the receiver whether fixed or ephemeral. await_query then blocks until the redirect arrives and returns its raw code=…&state=… query, which parse_callback validates.
CredStore
Persist and retrieve one secret bundle per provider (auth §5.2, §5.5). get returns None for a missing cred (the no-creds path), never an error; refresh is OAuth2::apply using get+put (freshness is a query); list/delete are control-plane. discover is the third primitive (auth §5.5): read a foreign credential source named by an AmbientSpec — a file (Claude Code’s ~/.claude/…) or a process env var (a vendor key alias) — into a brazen Cred. The IO — a file read with $HOME expansion, or an env read — lives in the bz impl; the format parse is the pure parse_ambient; a store with no ambient backing returns None.
Listener
The accept seam (ingress §7): blocks for the next connection; None ends the loop. The native impl accepts forever (SIGINT/SIGTERM end the process, the repo’s default-disposition signal convention); test doubles script a finite queue, which is what keeps the loop’s shutdown testable.
ModelCache
The per-provider model-list cache (model-discovery §5.1) — filesystem state, so like CredStore it lives behind an injected trait; the pure lib never touches the disk. A SIBLING of CredStore, not folded into it: a secret and a regenerable model list are different facts with different files. The bz bin backs it with one JSON file per provider under $XDG_CACHE_HOME/brazen/models/<provider>.json (the {"models":[{id,default}]} shape list-models --json emits, reused); the in-memory double lives in testing.
Pacer
Pace the device-flow poll loop (auth §7.3): the real bin sleeps secs; the test fake records the interval and returns instantly — so the whole flow runs offline with no real time. A control-plane concern only, kept off the data-plane Clock.
ServeConn
One accepted client connection: a blocking byte stream both ways. Send so the accept loop can hand it to its connection thread (ingress §7).
Transport
The single network seam (arch §4.1). Object-safe; Send + Sync so an impl is shareable. Exactly one round-trip per process — a caller wanting N concurrent requests spawns N bz.

Functions§

browser_argv
The argv to open url in the user’s default browser on the build target (arch §7.3). A thin pass of the compile-time OS to the pure argv_for; the caller (bz --login --browser) Command::spawns the result.
count_tokens
Run bz --count-tokens and return the POSIX exit code (§5.10.1). Reads the request from reader (stdin / --input) or the positional prompt, resolves provider/model as the data plane does, does ONE round-trip, and prints {"input_tokens": N} under --json else the bare N. A failure is written to stderr and mapped to its exit (usage 64 / no-input 66 / config 78 / auth 77 / non-2xx 69-70 / malformed body 70).
decode_request
Client-dialect request bytes → the canonical request (ingress.md §2). Pure; the dialect dispatches by a total match on the closed enum — the ingress mirror of Registry::protocol (arch §4.4), never a match on a vendor name.
envelope_error
A malformed envelope as the seam’s Transport error (→69). The message names a REASON and never echoes head bytes: a broken — or hostile — delegate that echoed the request back must not be able to make bz print the credential (spec §6).
envelope_head
Parse the response head out of however much of the delegate’s stdout has arrived (spec §5.2). Ok(None) = still incomplete, read more; Ok(Some(head)) = parsed, with head.body_start splitting the buffer; Err = malformed or oversized (spec §6, → exit 69). Caller-owned buffer, so the codec stays a pure function of the bytes so far — no hidden state, and every arm is reachable from a table test.
envelope_request
Render the request the delegate must perform (spec §5.1): an absolute-form request line (RFC 9112 §3.2.2 — what a proxy receives, so the child needs no second URL channel), then wire.headers VERBATIM in order, then the body.
generate
Generate against a resolved config (arch §1): drive ONE round-trip and yield the canonical event stream, terminated by a single End. THE pure typed core — run wraps it in byte I/O, an embedder consumes the events directly. The model SEED is resolved against the per-provider cache here (a local file read via host.cache, model-discovery §5.2), then the request is encoded, authenticated, and sent over the one Transport. Every failure is an in-band Event::Error, so the call is total. This is the normalized-in / canonical-out composition — [send_encoded] (the request half) then [canonical_events] (the response half); the --raw=out variant reuses send_encoded under a RawSink (arch §5.4, §13.14).
list_models
Run bz --list-models and return the POSIX exit code (model-discovery §2). Reuses the full flag parser + into_resolved(None, …) to pick the provider (an explicit --provider, else the row owning a configured model; neither → NoProvider/78), does ONE GET to models_path, and prints — --json the {"models":[…]} object, else the ids one per line with (default) on the default. The listing goes to stdout; any failure is written to stderr and mapped to its exit (config 78 / auth 77 / non-2xx 69-70 / a malformed body 70 — the same run-level table).
list_providers
Run bz --list-providers and return the POSIX exit code (config §6.1). Reuses the full flag parser and the SAME fold a run does — flags.or(env).or(file).or(defaults()) — then completes EVERY row instead of routing to one, so the built-in floor is visible. Rows print in providers order, which IS routing priority (arch §4.3.1): the head is the row a bare bz "q" reaches. Always exit 0 on a config that completes; a malformed file / bad env scalar / incomplete row is the usual 78.
login
Run bz --login and return the POSIX exit code (auth §7). Resolves the provider’s OAuthConfig, runs the selected flow, and persists the resulting Cred::OAuth2. Any failure is written to STDERR and mapped to its exit (login failure → 77, unresolvable / no-oauth / no-device-endpoint provider → 78, bad flag → 64).
parse_ambient
Map a foreign credential source’s bytes to a brazen Cred (auth §5.5) — the pure half of discovery, so the bz impl does only the IO. None for malformed or incomplete input (the no-creds path, like get). The claude_code case reads claudeAiOauth into a Cred::OAuth2: expiresAt is MILLISECONDS, divided to absolute unix-seconds once here (the single home for that unit mismatch), and scopes join into the scope string (None when empty); account_id is None (Anthropic binds no account id). The api_key_env case is the env var’s value as a raw Cred::ApiKey (trimmed; empty/non-UTF-8 ⇒ None).
query_from_request_line
Extract the query string from an HTTP request line, e.g. GET /callback?code=x&state=y HTTP/1.1 → code=x&state=y (auth §7.4). PURE, so the bin’s loopback receiver reads the line over the socket and defers the parse here; None when the request-target carries no ?query.
route
Read the routing decision from argv (§5.10.1). A parse error (an unknown flag, two combined control ops) routes to Route::Run, whose lib entry re-parses and surfaces the same error as the authoritative 64 — so routing owns no error path.
run
The binary in one call (arch §1). Resolves config, reads the request (positional XOR stdin), encodes, authenticates, sends one round-trip, decodes the framed response into canonical events, and projects them through the mode’s sink — returning the POSIX exit code (main materializes the ExitCode).
serve
Run bz --serve and return the POSIX exit code (ingress §7). Pre-loop failures are fatal and stderr-only, exactly like every control op: flag parse 64, config (no/invalid [ingress] table) 78, a bind failure 69. Once the loop runs, every failure is a per-connection concern answered in the client dialect (§9) — the process stays up.

Type Aliases§

Bytes
One transport body chunk. An alias, so the framers’ Vec<u8> and the body stream speak the same type.