Skip to content

Basecamp SDK v0.19.0

Choose a tag to compare

@github-actions github-actions released this 16 Sep 21:24
· 125 commits to main since this release
6abe227

Upgrading

Read MIGRATING.md before you bump the version — it lists the breaks a clean build will not catch: the silent ones that change behaviour with no error at all, and the ones that compile and then raise or fail to decode on one particular shape of response.

The notes below are generated from merged pull requests, so a change that merged without one cannot appear in them — MIGRATING.md records consumer-visible changes regardless of how they merged.

Installation

Go

go get github.com/basecamp/basecamp-sdk/go@v0.19.0

TypeScript

npm install @37signals/basecamp@0.19.0

Ruby

gem install basecamp-sdk -v 0.19.0

Swift

.package(url: "https://github.com/basecamp/basecamp-sdk.git", from: "0.19.0")

Kotlin

implementation("com.basecamp:basecamp-sdk:0.19.0")

Requires the GitHub Packages repository and a token — see Kotlin installation.

Python

pip install basecamp-sdk==0.19.0

Rust

cargo add basecamp-sdk@0.19.0

What's Changed

⚠️ Breaking Changes

  • fix(gauges): absorb five spec drifts from the contract bc3 serves by @jeremy in #853
  • fix(retry): converge every Retry-After parser on SPEC §6's table and surface the field in Kotlin and Swift by @jeremy in #857
  • A null list body crashes the Python SDK instead of reading as an empty listing by @jorgemanrubia in #896
  • Account event feed, inbox, and stream tickets: spec operations and generated clients by @jeremy in #898
  • Event feed: split the poll lanes' 410s and give their 400 a reason by @jeremy in #912
  • Bump version to 0.19.0 by @jeremy in #920

Bug Fixes

  • fix(go): FlexibleTime marshals back the form it parsed by @jeremy in #852
  • conformance: a path-less requestBody assertion pins the whole body by @jeremy in #854
  • spec(retry): pin the Retry-After contract, honour it at every retried status, and give conformance a clock by @jeremy in #855
  • Three Python errors crash with a bare TypeError when a caller passes retryable by @jorgemanrubia in #906
  • The retryable regression sweep passes while the invariant leaks by @jorgemanrubia in #909

CI & Infrastructure

  • deps(conformance-ts): bump vitest to 4.1.11 past GHSA-82fw-gwwq-j7x9 by @jeremy in #850
  • Clear the open code-scanning alerts by @jeremy in #851
  • feat(rust): add the Rust SDK by @jeremy in #859
  • Reference in-repo workflows with GitHub's self-repository syntax by @jeremy in #861
  • ci(rust): save the cargo cache from main only by @jeremy in #870
  • Compile the CodeQL Kotlin build with the newest Kotlin CodeQL supports by @jeremy in #875
  • Fail the npm already-published check closed by @jeremy in #876
  • Event feed conformance: three corrections to what tier 2 claims (3/3) by @jeremy in #778
  • Stop a KDoc from refuting itself, and a banner from documenting nothing by @jorgemanrubia in #907

Other

  • chore(rust): describe the crate as the official client for Basecamp by @jeremy in #868
  • Port the seed review's four Rust fixes back from basecamp/sdk#15 by @jeremy in #867
  • Strip the request URL from a reqwest error before it becomes the SDK's by @jeremy in #869
  • fix(swift): project the transport error before it becomes the network cause by @jeremy in #871
  • fix(ruby): classify a read timeout as a network error, not a status error by @jeremy in #874
  • fix(kotlin): project the transport error before it becomes the network message by @jeremy in #872
  • Bump rustls to 0.23.45 for RUSTSEC-2026-0285 by @jorgemanrubia in #890
  • Recording summaries from event pointers, and mention helpers (Go) by @jorgemanrubia in #882
  • Port the recording-summary and mention composites to Swift by @jorgemanrubia in #889
  • A fullwidth digit could suppress a real mention by @jorgemanrubia in #893
  • Follow the Go budget boundary the reference moved to after the port by @jorgemanrubia in #892
  • Evict a discovery claim by identity, not by key by @jorgemanrubia in #891
  • Port the recording-summary and mention composites to Rust by @jorgemanrubia in #886
  • Read a flexible id exactly as Go's ParseInt does by @jorgemanrubia in #895
  • Summarize a recording from an event-feed pointer, in Python by @jorgemanrubia in #888
  • Port the recording-summary and mention composites to Kotlin by @jorgemanrubia in #887
  • Port the recording summary and mention composites to TypeScript by @jorgemanrubia in #884
  • Ruby can't summarize a recording or mention anyone by @jorgemanrubia in #885
  • Eleven ways a gid the reference refuses could forge or lose a mention by @jorgemanrubia in #894
  • Tag the 16 untagged operations (one tag per op) to unblock MCP catalog generation by @jeremy in #878
  • Event feed connector: foundations (1/3) by @jeremy in #777
  • Event feed connector: the run loop and tier-2 driver (2/3) by @jeremy in #705
  • Two SDKs, two exit codes, one condition by @jorgemanrubia in #902
  • Make the pagination trait's cursor style mean something by @jorgemanrubia in #905
  • Close the malformed-trait pass in the two generators that still had it by @jorgemanrubia in #910
  • Type every field of a nested identity, not only the ones the projection reads by @jorgemanrubia in #911
  • The event feed's paging is declared as an absence by @jorgemanrubia in #914
  • Seven SDKs read a person id seven ways, and Go disagreed with itself by @jorgemanrubia in #908
  • Merge-safe writes refuse assignee ids the API really sends by @jorgemanrubia in #913
  • Swift and Rust refuse person shapes the reference writes back by @jorgemanrubia in #916
  • Event feed connector: the inbox lane (4/4) by @jeremy in #897
  • Event feed connector: bind the seams to the generated operations (5/5) by @jeremy in #899
  • Refuse fixture capacities above the schema's ceilings at load by @jeremy in #900
  • Plain generated reads return a person's string id as a string in Ruby, Python and TypeScript by @jorgemanrubia in #917
  • Pin the srv2 filter dimensions and the filtered epoch resume in a tier-2 fixture by @jorgemanrubia in #918
  • Bound the connector's capacities where they are allocated by @jeremy in #919

Full Changelog: v0.18.0...v0.19.0