Skip to content

conformance: a path-less requestBody assertion pins the whole body - #854

Merged
jeremy merged 3 commits into
mainfrom
fix/conformance-whole-body-request-assertion
Sep 11, 2026
Merged

jeremy merged 3 commits into
mainfrom
fix/conformance-whole-body-request-assertion

Conversation

@jeremy

@jeremy jeremy commented Sep 9, 2026

Copy link
Copy Markdown
Member

Summary

conformance/schema.json declared path optional on a requestBody assertion, and no runner implemented the path-less form: each of the six dereferenced path unconditionally, so a schema-valid fixture produced a different crash or a misleading "key not present" per language.

This takes the first of the issue's two options. A requestBody assertion with no path now means the whole captured body equals expected, exactly — a strictly stronger pin than the per-key form, because a key the SDK adds on its own is a failure instead of an unnoticed extra. All six runners implement it, and conformance/schema.json plus SPEC §19 document both forms.

The other half of the class is closed by the schema rather than by six more branches: every other path-taking assertion type (errorField, headerAbsent, headerInjected, headerPresent, headerValue, requestBodyAbsent, responseBody, responseMeta) has no meaning without a path, so an allOf/if/then now requires it for those. A path-less fixture of that shape fails make conformance-fixtures-check with a message naming the field instead of reaching a runner. A census of conformance/tests/*.json shows the split is already clean: those eight always carry path today, and no other type ever does.

Red-proof

The fixture landed first. schedule_entries_write.json "replace-omission-clears" — whose description already says the raw replace sends exactly what the caller passed — gained a path-less requestBody pinning the whole three-key body. Against the unmodified runners:

Runner Failure
Go Expected request body field "" on request index 0, but it was absent
Python KeyError: 'path'
Ruby runner.rb:1311:in 'TestRunner#fetch_body_key': undefined method 'split' for nil (NoMethodError)
TypeScript TypeError: Cannot read properties of undefined (reading 'split') at lookupBodyPath
Kotlin / Swift navigateJsonPath(body, "") / body.navigate("") look up the empty key and report "key not present in request body"

With the change, all six pass it, and the existing per-key and requestBodyAbsent assertions on the same case stay as they were.

Runner semantics

Shared across the six: no path → whole-body exact equality; a request with no JSON body fails; the failure message names the full expected and actual bodies. Each runner compares with the same helper it already used for the per-key form (jsonEqual, toStrictEqual, ==, compareJsonValues, compareJSON), so number and nesting handling is unchanged.

Fixes #587


Summary by cubic

Fixes #587 by implementing the path-less requestBody assertion that conformance/schema.json allowed but no runner handled. A requestBody assertion without path now means the whole captured body must equal expected exactly, and the other eight path-taking assertion types now require path in the schema.

Details

  • Whole-body pinning is strictly stronger than the per-key form: a key the SDK adds on its own is a failure instead of an unnoticed extra.
  • All seven runners compare with the same helper they already used for the per-key form; Python now uses a shared _json_equal so false and 0 are distinct, matching the other runners' wire-type strictness. A request with no JSON body fails in either form.
  • The schema rejects a path-less fixture of the other types at make conformance-fixtures-check with a message naming the field, and also requires expected on requestBody, which previously was schema-valid with nothing to say.
  • The schema rejects an empty path string: three runners treat "" as absent and four as a lookup of the empty key, so minLength: 1 keeps that disagreement out of any schema-valid fixture.
  • schedule_entries_write.json gained a path-less requestBody pinning the whole three-key body, which previously failed on every runner with different errors, and the Rust SDK's composites harness now takes the same form.

Written for commit a6e6d46. Summary will update on new commits.

Review in cubic

Copilot AI balanced review requested due to automatic review settings September 9, 2026 23:56
@jeremy jeremy added the bug Something isn't working label Sep 9, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-10T21:42:25.081751Z a6e6d46 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

An empty path remains schema-valid but has conflicting semantics across the six runners.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Implements path-less requestBody assertions as exact whole-body comparisons across all six SDK conformance runners and tightens path requirements for other assertions.

Changes:

  • Adds whole-body request assertions to every runner.
  • Updates schema and SPEC semantics.
  • Adds a shared conformance fixture.

[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

File summaries
File Description
SPEC.md Documents assertion semantics.
conformance/schema.json Adds conditional path requirements.
conformance/tests/schedule_entries_write.json Exercises whole-body equality.
conformance/runner/go/main.go Implements Go handling.
conformance/runner/python/runner.py Implements Python handling.
conformance/runner/ruby/runner.rb Implements Ruby handling.
conformance/runner/swift/Sources/ConformanceRunner/Assertions.swift Implements Swift handling.
conformance/runner/typescript/runner.test.ts Implements TypeScript handling.
kotlin/conformance/src/main/kotlin/com/basecamp/sdk/conformance/Main.kt Implements Kotlin handling.
Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread conformance/schema.json Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32f61514b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread conformance/schema.json Outdated
Comment thread conformance/runner/python/runner.py
Comment thread conformance/schema.json
@jeremy

jeremy commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

Converged: CI green on a2ae17f (41 checks), the one review finding (empty path) fixed in the schema and answered, and no further review activity since. Ready for a human look and merge.

@jeremy
jeremy force-pushed the fix/conformance-whole-body-request-assertion branch from a2ae17f to bbff957 Compare September 10, 2026 19:42
@github-actions github-actions Bot added the rust Rust SDK label Sep 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bbff9574d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread conformance/runner/rust/src/assertions.rs
conformance/schema.json declared path optional on requestBody while all six
runners dereferenced it, so a schema-valid fixture crashed or misreported
per language. The path-less form now means whole-body exact equality in
every runner, and the schema requires path on the other path-taking
assertion types, where no path-less form has a meaning.

Fixes #587
…path-less form, Python compares at the JSON level, the schema requires expected

The Rust SDK arrived after this branch. Its conformance runner read an
omitted path as a key named the empty string, and its fixture-driven
composites harness (tests/composites_support) required one outright, so
the new schedule_entries_write assertion failed there alone; both take the
whole-body form now. Python's native equality made {"highlighted": false}
equal to {"highlighted": 0}, which every other runner rejects; both
request-body forms now compare through _json_equal. And a requestBody
assertion with no path had nothing left to require, so
{"type": "requestBody"} was schema-valid and failed differently per
runner; the schema now requires expected on it.
@jeremy
jeremy force-pushed the fix/conformance-whole-body-request-assertion branch from bbff957 to a6e6d46 Compare September 10, 2026 21:38
@jeremy

jeremy commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

Rebased onto main at 95b83dd (#874) — a6e6d46, no content change. CI is green on that head except CodeQL Analyze (java-kotlin), which fails identically on main (its Build (Kotlin) step) and is not this PR's to fix. The one open thread (numeric equality in the Rust runner's whole-body comparison) is answered and deliberately left open as a separate, cross-runner policy call. Converged; independent of #853 and of the #855/#857 stack.

@jeremy
jeremy merged commit de3989c into main Sep 11, 2026
50 of 51 checks passed
@jeremy
jeremy deleted the fix/conformance-whole-body-request-assertion branch September 11, 2026 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working conformance Conformance test suite kotlin rust Rust SDK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Conformance: schema.json declares requestBody.path optional, but all six runners require it

2 participants