Skip to content

Commit 2f41d50

Browse files
chore: prepare 0.10.0
1 parent 0bdf1eb commit 2f41d50

4 files changed

Lines changed: 14 additions & 5 deletions

File tree

.beads/issues.jsonl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
{"id":"openapi-generator-0jz","title":"Server codegen: form-exploded object query params arrive as String","description":"Follow-up to GH #27 (openapi-generator-cv4). The client now types form-exploded object query params as structs, but server codegen (src/server/codegen.rs emit_query_struct/emit_method_sig) still keys off ParameterInfo.rust_type which stays String for these params, so handlers see a String they can never receive correctly. Proper fix needs serde(flatten) of the object struct into the per-op Query extractor struct (watch serde_urlencoded flatten limitations with non-string scalars).","design":"ParameterInfo.query_serialization is the shared client/server wire contract. Axum uses RawQuery plus an operation-specific decoder because Query\u003cT\u003e cannot preserve repeated keys or isolate exploded object namespaces. Supported flat object and scalar/string-enum array modes decode into owned generated types; ambiguous/undefined/nested shapes fail server generation. Generated clients and servers share a name[]= zero-cardinality marker so None, Some(empty), and missing required structured parameters remain distinct. explode=false values containing commas fail client serialization with guidance instead of silently corrupting boundaries.","acceptance_criteria":"Generated Axum extraction matches client serialization for required and optional objects, arrays, form explode true and false, and deepObject where defined; unsupported shapes fail or warn during generation; shared style analysis prevents drift; generated client and server round-trip proves typed values.","notes":"Acceptance verified. tests/server_query_roundtrip_test.rs generates a client and Axum server, starts a real TCP listener, and proves exact required/optional scalar, flat-object, deepObject, exploded/compact-array, component-array-alias, URL-escaped, and zero-cardinality values. Missing required structures return 400; comma-delimited loss cases return a client serialization error. Generation errors cover undefined deepObject, arrays of objects, nested objects, unions, additional ambiguity, exploded-key collisions, and deepObject collisions. cargo fmt --check, cargo clippy --all-features -- -D warnings, cargo test --all-features, cargo check --all-features, and git diff --check pass. url and serde_urlencoded requirement reporting is intentionally handled immediately next by blocked child openapi-generator-1sb.1.","status":"closed","priority":3,"issue_type":"bug","assignee":"James Lal","owner":"james@littlebearlabs.io","created_at":"2026-07-12T23:32:23Z","created_by":"James Lal","updated_at":"2026-07-15T17:54:07Z","started_at":"2026-07-15T17:23:59Z","closed_at":"2026-07-15T17:54:07Z","close_reason":"Generated clients and Axum servers now share typed query serialization/extraction for every supported flat object and array mode, reject unsafe shapes, preserve empty/missing semantics, and pass live round-trip plus full regression gates.","labels":["adoption","query","server"],"dependencies":[{"issue_id":"openapi-generator-0jz","depends_on_id":"openapi-generator-1sb","type":"parent-child","created_at":"2026-07-15T08:32:00Z","created_by":"James Lal","metadata":"{}"},{"issue_id":"openapi-generator-0jz","depends_on_id":"openapi-generator-1sb.3","type":"blocks","created_at":"2026-07-15T08:40:36Z","created_by":"James Lal","metadata":"{}"}],"dependency_count":1,"dependent_count":3,"comment_count":0}
8181
{"id":"openapi-generator-vl2","title":"[Client] Selective operations option (parallel to [server].operations)","description":"Today the client generator emits methods for every operation in the spec. For users who only need a subset, a parallel '[client] operations = [\"opId\", ...]' selection would mirror the server-side opt-in.\n\nCombined with model pruning, this becomes the dual scenario: pick the ops you call (client) AND the ops you host (server), prune to the union of both reachable sets. The selector grammar from src/server/selector.rs is reusable as-is.\n\nFor now this is filed under 'maybe useful'. Most client users want every op. But the symmetric server-client design would be cleaner once it exists.","acceptance_criteria":"Opt-in client selectors support operationId, METHOD /path, and tag:Name using shared parser and suggestions; absent client section generates all operations; optional pruning retains transitive selected-client schemas and unions client/server reachability; targeted large-spec clients compile.","notes":"Implementation plan: add deny-unknown [client] config with shared Selector grammar and generate-all compatibility; resolve selections once against analyzed operations with actionable unknown/ambiguous diagnostics; filter generated client operations only when configured; generalize schema reachability pruning so client-only and mixed client/server use the union including analyzer-tracked synthetic schemas; add config/selector/generation/pruning tests and compile representative selective OpenAI client; independently review and run focused plus crate-wide gates before closing. Expected files: src/config.rs, src/generator.rs, src/analysis.rs and/or src/server pruning helpers, tests/selective_client_test.rs, README/config examples as appropriate.\nImplemented strict optional client selection with shared operationId, METHOD /path, and tag selectors; absent/empty compatibility; alias-aware unknown/ambiguous/renamed diagnostics; lockstep filtering of methods, parameter enums, and typed operation errors; client/server/streaming reachability-union pruning including analyzed inline schema ownership; registry remains unfiltered; disabled and registry-only scopes are isolated. Cross-surface hardening adds exact Axum guards for QUERY/custom verbs, lossless custom-method registry variants, and operationId-only SSE validation. Coverage includes config Serde round trips, empty scope, direct API isolation, registry interactions, mixed pruning, canonical SSE aliases, custom server scratch compile, and selective pruned OpenAI client scratch compile. Final gates: fmt, no-default/all-feature all-target checks, production Clippy with warnings denied, rustdoc with warnings denied, and full all-feature test/doc-test suite all pass.\nFinal custom-verb safety: generated Axum servers use one exact QUERY/custom dispatcher per path within a trait, runtime-tested with QUERY and PURGE plus POST=405. Because Axum 0.7 cannot merge custom fallbacks carrying different per-trait states, the cross-primary-tag same-path form now fails at generation time with explicit remediation instead of panicking when build_router is constructed.","status":"closed","priority":3,"issue_type":"feature","assignee":"James Lal","owner":"james@littlebearlabs.io","created_at":"2026-05-11T03:40:20Z","created_by":"James Lal","updated_at":"2026-07-15T16:10:47Z","started_at":"2026-07-15T15:21:19Z","closed_at":"2026-07-15T16:10:47Z","close_reason":"Closed","labels":["adoption","client","pruning"],"dependencies":[{"issue_id":"openapi-generator-vl2","depends_on_id":"openapi-generator-1sb","type":"parent-child","created_at":"2026-07-15T08:32:01Z","created_by":"James Lal","metadata":"{}"},{"issue_id":"openapi-generator-vl2","depends_on_id":"openapi-generator-cwd","type":"blocks","created_at":"2026-07-15T08:39:18Z","created_by":"James Lal","metadata":"{}"}],"dependency_count":1,"dependent_count":4,"comment_count":0}
8282
{"id":"openapi-generator-q3k","title":"[Server] Aggressive model pruning via analyzer-tracked synthetic ownership","description":"The current [server].prune_models implementation walks transitive $refs from picked ops, then keeps every schema not referenced by any $ref anywhere as a 'synthetic'. For OpenAI's spec this yields ~13% reduction because many real spec schemas are reached only via operations or multipart bodies, making 'never $ref'd' a poor synthetic signal.\n\nTo get \u003e50% reduction safely, the analyzer needs to track which synthetic enums/structs belong to which parent schema. Concretely: when analysis registers WebSearchApproximateLocationType as a synthetic of WebSearchApproximateLocation's inline 'type: enum' field, it should record the parent→synthetic edge in DependencyGraph or in AnalyzedSchema (new field 'synthesised_from: Option\u003cString\u003e').\n\nWith that edge tracked, the prune walk becomes: walk transitive $refs from picked ops, then for every kept name, also keep all schemas whose synthesised_from points at it. That's both more aggressive and more correct than the current heuristic.\n\nRelated: the analyzer's existing AnalyzedSchema.dependencies field is also incomplete (Response.deps lists ResponseError but ResponseError.deps is empty even though it has a field of type ResponseErrorCode). Same root cause — analyzer registers synthetic siblings but doesn't track ownership.","notes":"Discovered while implementing prune_models in commit (current). Conservative impl ships; aggressive impl requires analyzer changes.\n2026-07-15 audit during selective-client work: pruning now walks analyzed SchemaType ownership/reference edges and removes the old keep-every-unreferenced-schema heuristic, improving safety and precision. However the selective createResponse fixture pruned 127 of 344 analyzed schemas (36.9%), below this issue greater-than-50-percent target. Leave open until its specific acceptance metric is demonstrated on the intended full OpenAI server selection/corpus.","status":"open","priority":3,"issue_type":"feature","owner":"james@littlebearlabs.io","created_at":"2026-05-11T03:40:12Z","created_by":"James Lal","updated_at":"2026-07-15T16:02:47Z","dependency_count":0,"dependent_count":0,"comment_count":0}
83-
{"id":"openapi-generator-in6","title":"[Server] Anthropic spec missing text/event-stream content type on messages_post","description":"Anthropic's published OpenAPI spec (specs/anthropic.yaml) declares POST /v1/messages 200 response with content-type application/json only. The real API streams when stream:true is set on the request body, but the spec never declares text/event-stream as a valid response content type.\n\nConsequence: 'server list' does not mark messages_post as [SSE], and downstream server codegen will not emit an SSE response variant for it. Both are technically correct given the spec text.\n\nMitigation options:\n1. Use the existing schema-extensions mechanism to overlay a text/event-stream response on /v1/messages.\n2. Add a config knob ('force_stream_for_operations') that promotes nominated ops to streaming regardless of declared response content.\n3. Detect that the request body has a 'stream:bool' field and auto-promote (heuristic — risky).\n\nOption 1 is the path that fits the existing project model. Add an example extension file documenting how to do this, and reference it from the server codegen docs once P6 lands.","notes":"Approach: make server list/add analyze the full generator config including schema_extensions; isolate the Anthropic example crate from the root workspace; make server example tests use Cargo's current binary path; update example docs; add focused regression coverage. Audit server implementation and PR official-client CI for adjacent high-confidence defects before closing.","status":"closed","priority":3,"issue_type":"bug","assignee":"James Lal","owner":"james@littlebearlabs.io","created_at":"2026-05-11T01:54:29Z","created_by":"James Lal","updated_at":"2026-07-26T22:15:26Z","started_at":"2026-07-26T21:52:00Z","closed_at":"2026-07-26T22:15:26Z","close_reason":"Reopened review findings and adjacent server audit issues are fixed: overlay-aware CLI, YAML overlays, reliable examples, official OpenAI/Anthropic SDK PR gates, faithful response semantics, and tag-collision diagnostics. All scoped and full all-features gates pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
83+
{"id":"openapi-generator-in6","title":"[Server] Anthropic spec missing text/event-stream content type on messages_post","description":"Anthropic's published OpenAPI spec (specs/anthropic.yaml) declares POST /v1/messages 200 response with content-type application/json only. The real API streams when stream:true is set on the request body, but the spec never declares text/event-stream as a valid response content type.\n\nConsequence: 'server list' does not mark messages_post as [SSE], and downstream server codegen will not emit an SSE response variant for it. Both are technically correct given the spec text.\n\nMitigation options:\n1. Use the existing schema-extensions mechanism to overlay a text/event-stream response on /v1/messages.\n2. Add a config knob ('force_stream_for_operations') that promotes nominated ops to streaming regardless of declared response content.\n3. Detect that the request body has a 'stream:bool' field and auto-promote (heuristic — risky).\n\nOption 1 is the path that fits the existing project model. Add an example extension file documenting how to do this, and reference it from the server codegen docs once P6 lands.","notes":"Approach: make server list/add analyze the full generator config including schema_extensions; isolate the Anthropic example crate from the root workspace; make server example tests use Cargo's current binary path; update example docs; add focused regression coverage. Audit server implementation and PR official-client CI for adjacent high-confidence defects before closing.\nRelease target: 0.10.0 because corrected response status/SSE variants and wildcard/default payloads change regenerated public server APIs under the documented pre-1.0 policy.","status":"closed","priority":3,"issue_type":"bug","assignee":"James Lal","owner":"james@littlebearlabs.io","created_at":"2026-05-11T01:54:29Z","created_by":"James Lal","updated_at":"2026-07-26T22:22:11Z","started_at":"2026-07-26T21:52:00Z","closed_at":"2026-07-26T22:15:26Z","close_reason":"Reopened review findings and adjacent server audit issues are fixed: overlay-aware CLI, YAML overlays, reliable examples, official OpenAI/Anthropic SDK PR gates, faithful response semantics, and tag-collision diagnostics. All scoped and full all-features gates pass.","dependency_count":0,"dependent_count":0,"comment_count":0}
8484
{"id":"openapi-generator-s42","title":"Propagate target schema nullability through $ref properties","description":"When a $ref points to a schema that is itself anyOf[Object, null] (e.g. OpenAI ResponseError), the property using that $ref should be wrapped in Option\u003c\u003e. Currently we strip the null branch when analyzing the target schema and emit a struct, then properties referencing that struct don't pick up nullability. Real hit: OpenAI Response.error — we currently require nullable_overrides to handle it. Fix would record nullability on AnalyzedSchema and OR it in at the property level when the prop_type is a Reference. Lower priority since the override workaround is documented.","status":"open","priority":3,"issue_type":"bug","owner":"james@littlebearlabs.io","created_at":"2026-05-11T00:13:05Z","created_by":"James Lal","updated_at":"2026-05-11T00:13:05Z","dependency_count":0,"dependent_count":0,"comment_count":0}
8585
{"id":"openapi-generator-tv8","title":"[Q2.5] Optional BTreeSet for uniqueItems arrays (opt-in)","description":"Arrays with uniqueItems: true (13,276 occurrences across specs/) currently emit Vec\u003cT\u003e. Spec-faithful representation is a set. Add [generator.types.shape] unique_items_to_set = false (default) — opt-in to emit BTreeSet\u003cT\u003e instead of Vec\u003cT\u003e. Off by default because flipping this changes the public API of every uniqueItems field across the corpus.\n\n## Context\nFiles: src/type_mapping.rs (Q2.0), src/analysis.rs (array analysis), src/generator.rs. Evidence: 13,276 uniqueItems usages in specs/, today all become Vec. See umbrella gpu-cli/openapi-to-rust#14.","acceptance_criteria":"- [ ] [generator.types.shape] unique_items_to_set toggle works.\n- [ ] When on and item type implements Ord + Eq (primitives, strings, enums, named structs deriving them), array becomes BTreeSet\u003cT\u003e.\n- [ ] When on but item type isn't Ord (e.g. floats, complex unions), fall back to Vec\u003cT\u003e with a stderr warning naming the field.\n- [ ] All 49 specs still compile in default (off) mode.","status":"open","priority":3,"issue_type":"task","owner":"james@littlebearlabs.io","created_at":"2026-05-09T05:36:01Z","created_by":"James Lal","updated_at":"2026-05-09T05:36:01Z","dependencies":[{"issue_id":"openapi-generator-tv8","depends_on_id":"openapi-generator-r36","type":"blocks","created_at":"2026-05-08T23:37:06Z","created_by":"James Lal","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
8686
{"id":"openapi-generator-81u","title":"[Q5] Display for ApiOpError that surfaces the typed body","description":"Today format!('{e}', e: ApiOpError\u003cE\u003e) on an Api variant prints 'API error 404: {full body}'. For a Stripe error that includes a huge param_documentation blob, the message becomes a wall of JSON. Users complain they can't tell at a glance what the typed variant captured. Approach: in ApiError::Display, truncate body to ~500 chars with a '… (truncated)' marker; if typed.is_some(), prepend '(typed: \u003cvariant_name\u003e)' (E: fmt::Debug bound already exists); if parse_error.is_some() and typed.is_none(), append '(parse error: …)'. Full body still accessible via .body field.\n\n## Context\nFiles: src/http_error.rs. Evidence: src/http_error.rs:234 ApiError Display prints body verbatim — for huge JSON bodies this is unreadable; typed.is_some() info is hidden. See umbrella gpu-cli/openapi-to-rust#14.","acceptance_criteria":"- [ ] ApiError Display truncates body at 500 chars (configurable via const).\n- [ ] Typed variant name appears when typed.is_some().\n- [ ] Parse error reason appears when typed parsing failed.\n- [ ] Full body still accessible via .body — no info loss.\n- [ ] Unit test in src/http_error.rs covers all three branches.","notes":"Public contributor issue: https://github.com/gpu-cli/openapi-to-rust/issues/29","status":"open","priority":3,"issue_type":"task","owner":"james@littlebearlabs.io","created_at":"2026-05-08T23:13:13Z","created_by":"James Lal","updated_at":"2026-07-15T19:35:52Z","external_ref":"gh-29","labels":["codegen","good-first-issue","help-wanted","phase4","quality"],"dependency_count":0,"dependent_count":0,"comment_count":0}

0 commit comments

Comments
 (0)