Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion python/client-contract/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ All notable changes to the `dfo-spec-kit-client-contract` Python package will be
- `tools/validate_client_contract.py`, which checks the contract against its schemas, the served document and `registries/codes.json`, checks `client-codes.json` against them and against the reasons the key-lookup rule raises, and checks each scenario's `expect` against the outcomes its exchanges, `actions.json` and `client-codes.json` give, each Search request against the input its steps derive, a sentence lookup's `entity_groups` included, each build's `input.scope` against the narrowing its step names over the spec's bound roles, each build's options against its layout, each Search request's whole body, each download against its artifact's digest, each recorded scenario's commit against `served/SOURCE.json`, each problem document's code against `registries/codes.json` or, for the website proxy's, `proxy-codes.json`, each proxy problem document's content type, members and `retryable: true`, each 202 against an operation that reads `done`, and each absolute URL against the storage host, each ref example's members against the dataset members and downloaded files of the scenario it names, and the scenarios directory against a 16,000,000-byte budget for records and bodies together. A record that ends a run of retries while a retry remains does not fit. The outcomes include each long build's operation id, poll waits and resubmissions, and a `VersionUnavailableError`'s newest version.
- The contract README states that a POST for a build identical to one pending or running returns that operation, so a client that stops waiting posts the same build to join it, and that `fetch` waits for a build with no whole-call deadline by default, with a download that delivers no byte for 30 s a retryable `network_error`.
- A fetch of an answer or a spec leaves out party totals by default: its build posts `without_party_totals: true` in `options`, so the server drops the group totals of the identity's open party roles, and a role the caller binds keeps what it binds. Fetch steps take `party_totals: true` for the client option, `party_totals` in Python and `partyTotals` in TypeScript, false by default, which posts no `without_party_totals`. The wire flag and the ref format are unchanged, and a ref records `without_party_totals: true` for a member fetched with the default. `fetch-spec-party-totals-left-out` and `fetch-spec-party-totals-kept` pin both on DAC2a ODA to Kenya in 2022 with the origin open. A mint and a resumed operation post the plain rendering.
- The `column-order` rule and its vectors: a client presents a dataset's columns with the reading columns first, the time period, provider, recipient, subject, purpose, value, unit, flow type and provenance, each slot filled by the long layout's label or the frame layout's code, the flow type by CRS `crsTypeOfFlow` or else DAC2a `dac2aAidType`, then the rest in the server's order with `stat_var` last. Scenario outcomes give `columns` in that order, and the validator checks it.
- The `reading-order` rule and its vectors, which carry rows: a client presents a dataset's columns with the reading columns first, the time period, provider, recipient, subject, purpose, value, unit, flow type and provenance, each slot filled by the long layout's label or the frame layout's code, the flow type by CRS `crsTypeOfFlow` or else DAC2a `dac2aAidType`, then the columns whose values differ between rows, then those that hold one value, each group in the server's order, with `stat_var` last. It sorts each member's rows by the filled slots without `value` and the time period, then the varying columns, then the time period, ascending with nulls last and ties in served order, so each series' years read together. Scenario outcomes give `columns` in that order, and the validator checks it against the served files.
- The `client-identity` rule and its vectors: every request a client sends to the API carries `X-DFO-Client: <client>/<version> (<runtime>)`, such as `dfo-python/0.1.0 (CPython 3.14)` or `dfo-ts/0.1.0 (Node 22.18)`, and `browser` as the runtime in a browser, with `pattern` matching every well-formed value. A request to another origin, a signed storage URL included, carries none. A caller's headers or header provider naming `X-DFO-Client` in any letter case raises `InvalidRequestError` `header_invalid`, whose condition now says so, and `User-Agent` stays as each client sends it. A scenario replay checks the header on each `path` and `origin_path` request and its absence on each `url` request.
- The `role-keys` rule and its vectors: a caller narrows a spec with `entities=` keyed by `place`, `origin` and `destination`, and a client posts `place` as the wire role `observationAbout`. `Spec.roles`, `specRoles(spec)` and the clients' errors name the caller keys, and a flow spec takes both directions. A key outside the spec's roles raises `InvalidRequestError` `invalid_argument` naming the key and the spec's roles, so `observationAbout` on GDP is refused naming `place` and `financingRecipient` on a flow spec naming `origin` and `destination`. A spec that names no role posts `place` as `observationAbout` and other keys as typed, and refuses `observationAbout` naming `place`.
- The client rules and their vectors: the credentials path and file format, the key lookup order, with an empty `api_key` refused as `key_empty` and an empty profile key as `profile_without_key`, the key format check, the base URL order, `base_url_invalid` for an invalid value, and the cache directory and layout.
- The `base-url` rule states the whole validity rule, and seven new vectors pin it: no query, fragment, `.` or `..` segment, character outside visible ASCII, empty userinfo or non-decimal IPv4 host; trailing slashes dropped; a relative URL valid only in a TypeScript client inside a browser page.

[unreleased]: https://github.com/DevelopmentFinanceObservatory/spec-kit/commits/main/python
Loading
Loading