broker-api-changelog-diffing-tool · v3.0.0 · 2026-08-14 · sha256 2aa1303018308233
broker-api-changelog-diffing-tool v3.0.0A
Immutable. This exact content is served forever at /api/v1/blob/2aa1303018308233.
--- name: broker-api-changelog-diffing-tool description: Use when updating broker SDKs or API integrations to diff release-over-release OpenAPI schemas, resolving $ref models and detecting breaking endpoint removals, removed response codes and content types, requirement changes, direction-aware enum mutations, and type changes before production deployment. domain: algorithmic-trading subdomain: broker-integration tags: - broker-integration - api-changelog - schema-diffing - openapi - breaking-changes - ci-cd brokers_frameworks: - OpenAPI 3.x - Swagger 2.0 (reference resolution only) version: "3.0.0" author: algo-trading-skills-contributors license: Apache-2.0 --- ## When to Use Invoke this before upgrading a broker SDK version or pulling a new API specification (Binance, Coinbase, IBKR Client Portal and similar publish OpenAPI documents). Broker releases introduce silent breaking changes — a removed nested response field, a parameter that quietly became mandatory, a new order status the state machine has never seen. This skill diffs two schema snapshots and classifies what changed, so a CI job can fail the build before the change reaches an order path. The tool is a **gate**, and its failure modes are asymmetric: a false positive costs a developer a few minutes, a false negative ships a broken integration. Everything about its classification is biased accordingly. ## When NOT to Use - **As proof a release is safe.** It compares structure only. Rate limits, auth scope changes, altered matching-engine behaviour, changed rounding, new error codes returned in a 200 body — none are expressible in a schema, and none will appear in the report. A clean diff means "nothing structural broke", not "safe to deploy". - **On specifications it cannot fully resolve.** Only local (`#/...`) references are followed. External and remote `$ref`s are reported as `UNRESOLVED_REF` — that region was *not compared*, and treating the report as complete when one is present is a mistake. - **As a Swagger 2.0 differ.** `#/definitions/...` references resolve, but Swagger 2.0's body parameters and top-level `consumes`/`produces` are not modeled; the request-body logic assumes OpenAPI 3.x `requestBody.content`. Convert 2.0 documents to 3.x first. - **As a file loader.** It takes parsed Python dictionaries. Reading and parsing JSON or YAML is the caller's job. - **For composition keywords.** `oneOf`, `anyOf`, `allOf` and `discriminator` are not evaluated; schemas using them will diff only at the level the tool can see. ## Prerequisites - Baseline (older) and target (newer) API schemas, parsed into dictionaries. - Both documents complete, including the `components`/`definitions` sections the `$ref`s point at — a spec split across files must be bundled first, or references will come back unresolved. ## Workflow 1. **Load both documents and let the differ reject unusable input.** `diff_schemas` raises `SchemaDiffError` when a document is not a mapping or has no `paths`. This is deliberate: a failed download or a wrong path yields an empty document, and a differ that shrugs and reports zero changes turns the gate green at exactly the moment it matters. 2. **Diff endpoints.** Removed paths and removed methods are `CRITICAL_BREAKING`. Only real HTTP methods are treated as operations — a Path Item Object also legally carries `parameters`, `servers`, `summary`, `description` and `$ref`, and path-level `parameters` are diffed as shared across every operation. 3. **Resolve `$ref` before comparing anything.** Real broker specs describe payloads almost entirely through references, and a `$ref` schema carries no `type`, `properties` or `enum` of its own. Resolution follows `#/components/schemas/...` and `#/definitions/...` against the document each side came from, with cycle protection for self-referential models. 4. **Treat absence as a change.** A removed response status code, a removed request or response content type, and a removed `requestBody` are all breaking and all invisible to a differ that walks only the keys present on both sides. 5. **Check requirement transitions in both directions.** A request field or parameter moving *into* `required` breaks callers that omit it. A response field moving *out of* `required` breaks parsers that assume it is present. Both matter; they are not the same check. 6. **Classify enums by direction.** A request enum constrains what the client may send, so *removing* a value is breaking. A response enum constrains what the client must handle, so *adding* a value is breaking — a new order status silently breaks an exhaustive state machine. Newly imposing a request constraint, and dropping a response constraint, are breaking too. 7. **Gate the build.** `report.exit_code` is 0 when compatible and 1 otherwise; `report.format_report()` renders the findings severity-first. `is_compatible` is False if any change is `MEDIUM_BREAKING` or higher. > Full procedure: see `references/workflows.md`. > Severity matrix and classification rationale: see `references/standards.md`. > Printable pre-flight checklist: see `assets/checklist.md`. ## Common Pitfalls - **Comparing `$ref` schemas without resolving them.** Both sides look like empty objects, every check is skipped, and a release that deleted an entire response model reports clean. This is the single most likely way to get a false green. - **Ignoring an `UNRESOLVED_REF` finding.** It is informational in severity but it means a region of the schema was never compared. Bundle the spec and re-run. - **Only diffing keys present on both sides.** Removals are the breaking changes; a loop written as `if key in new: compare(...)` cannot see any of them. - **Treating enum changes as direction-agnostic.** Flagging every set difference raises false alarms on request widenings while missing the response additions that actually break consumers. - **Assuming a scalar `type`.** OpenAPI 3.1 allows `type: ["object", "null"]` where 3.0 used `nullable: true`. An equality test against the literal `"object"` silently skips property diffing, and comparing the two spellings reports a mutation that never happened. - **Treating every key under a path as an HTTP method.** `parameters` is a list and `summary` is a string; calling `.get()` on them raises on a perfectly valid document. - **Letting an empty or malformed document produce a clean report.** - **Unbounded recursion on self-referential models.** `Order.parent → Order` is ordinary, and resolving references without a cycle guard hangs the build. - **Reading a clean report as deployment approval.** Structure is not behaviour. ## Verification - Run the unit suite and confirm every test passes: `python -m unittest discover -s skills/broker-api-changelog-diffing-tool/scripts` - Build a fixture whose response model sits behind a `$ref`, delete a field from the referenced component, and confirm `REMOVED_RESPONSE_FIELD` is reported. A differ that passes every inline-schema test can still fail this one, which is the case that matters. - Confirm two empty documents raise `SchemaDiffError` rather than reporting compatible. - Confirm a self-referential model terminates. - Confirm direction-aware enum behaviour: adding a response enum value is breaking; adding a request enum value is not. - Confirm a Path Item Object carrying `parameters` and `summary` does not raise. - Mutate fixtures by deep-copying a baseline and changing exactly one thing, so a test for one change cannot accidentally introduce another. ## Related Skills - `broker-api-versioning-migration-playbook` - `broker-api-deprecation-notice-monitoring` - `sandbox-vs-production-endpoint-drift` - `broker-agnostic-adapter-interface`