Send the activity feed's day and filters
Why
Basecamp's account-wide activity feed, GET /reports/progress.json, serves one day per request. Without date it serves today, and paging stops at midnight. The web steps back a day at a time, and narrows the feed with its "Showing [All projects] by [Everyone]" dropdowns, which send project_ids[] and people_ids[].
Every SDK could send only page. So no caller could read yesterday's activity, and the CLI's TUI activity feed is empty just after midnight. Requested on the CLIs card [SDK] Pass the activity date and filters through.
What changed
GetProgressReportInputgainsdate(ISO8601Date),projectIds(wire nameproject_ids[]) andpeopleIds(people_ids[]), regenerated into all seven SDKs.- Go's
TimelineService.Progresstakes a new*ProgressOptions(Limit,Page,Date,ProjectIDs,PeopleIDs) in place of*TimelineListOptions. It refuses an impossibleDateand a non-positive ID with a usage error before the wire. ProjectTimelineandPersonProgresskeepTimelineListOptionsand gain nothing. bc3 ignores these parameters on those routes (projects/timelines_controller.rb,users/timelines_controller.rb).MIGRATING.mdnotes the Go break.spec/api-gaps/activity-timeline-filters.mdrecords the parameters as absorbed ahead of bc3's doc, with the doc change bc3 owes.
Two server behaviours the docs now carry
Read in bc3 at 9c09e30bc9 (master), in Timeline::Filters and Timeline::ActivityViewScoped:
- Omitted is not "everything". Each ID list, when omitted, falls back to the filter the user last saved in the web's activity view.
- A list with no visible ID clears that saved filter.
reset_laterenqueuesResetActivityTimelineJob, and that request returns no events. So a GET with a stale ID changes the user's web view. Every member's doc says to send only IDs the API just returned.
bc3 also reads an unparseable date as today, silently. Go refuses an invalid Date for that reason. The other SDKs take date as a string and pass it through.
Scope
- No
filterparameter (starred projects). The card didn't ask for it. - bc3's
doc/api/sections/timeline.mddoesn't list these parameters yet. The route is documented and already modelled, so no route-parity waiver is needed. The api-gaps entry says what the doc should add.
Blast Radius
- Go: breaking. Source that passes
&basecamp.TimelineListOptions{...}toProgressstops compiling. Rename the type.LimitandPagebehave as before. basecamp-cli has two such call sites, and its follow-up PR moves them. - Rust: breaking for struct literals.
GetProgressReportParams { page: Some(2) }stops compiling; add..Default::default().MIGRATING.mdsays so. - TypeScript, Ruby, Python, Kotlin and Swift only gain optional parameters.
Release notes: breaking and enhancement.
Verification
Repro. The first commit adds only tests, run against main's product code:
- TypeScript:
expected null to be '2026-08-30'. The option was dropped, so nothing was sent. - Ruby:
ArgumentError: unknown keywords: :date, :project_ids, :people_ids. - Python:
TypeError: ReportsService.progress() got an unexpected keyword argument 'date'. - Rust:
struct GetProgressReportParams has no field named date. Kotlin:No parameter with name 'date' found. - Go:
undefined: ProgressOptions.
Fix. With the second commit, all of those tests pass. Each one asserts the decoded query bc3 reads: date=2026-08-30, project_ids[]=27, project_ids[]=45144734, people_ids[]=49285301, page=2, with no bare project_ids key. They also assert that an unfiltered call sends no query string.
Mutants. I broke Go's param builder three ways: dropped the date, let a zero ID through, and skipped the date check. Each one failed a test (3 of 3).
Against bc3. I ran a local bc3 with seeded history: 5 events today, 8 the day before. Unfiltered progress.json returned today's 5, and page=2 was empty. date=2026-10-22 returned 8. One project gave 4, two projects gave 7, one person gave 3, and project plus person gave 2. The basecamp-cli follow-up drives this end to end through its CLI and TUI.
Not run locally. The Swift tests. This SDK's Swift target doesn't build on Linux (CFAbsoluteTimeGetCurrent), so Swift generation ran in the swift:6.2 image and the Swift tests are left to CI's macOS job.
make -k check on Linux passed every target but rs-deny. That one fails on RUSTSEC-2026-0385 against ctutils 0.4.2, which this PR doesn't touch. It fails the same way on main, and CI's required Conformance Tests check waits on it. https://github.com/basecamp/basecamp-sdk/pull/1039 bumps ctutils. Once it merges, this PR needs a rebase onto main.