Skip to content

Flatten all SDK routes to remove nested URL scoping#74

Merged
jeremy merged 25 commits intomainfrom
flat
Feb 27, 2026
Merged

Flatten all SDK routes to remove nested URL scoping#74
jeremy merged 25 commits intomainfrom
flat

Conversation

@jeremy
Copy link
Member

@jeremy jeremy commented Feb 2, 2026

Summary

  • Flatten ~80 Smithy spec operations from deeply-nested paths like /{accountId}/buckets/{projectId}/todos/{todoId} to flat paths like /{accountId}/todos/{todoId} — resources are uniquely identified and don't need parentage context
  • Regenerate all three SDK clients (Go, TypeScript, Ruby) from the flattened OpenAPI spec
  • Remove 67 dead hand-written service files (31 TypeScript, 36 Ruby) that were superseded by generated services
  • Update Go hand-written service layer, removing projectID parameter from methods that no longer need bucket scoping
  • Remove BucketID from OperationInfo and OpenTelemetry span attributes
  • Simplify lineup marker API to match spec (name/date only)
  • Fix card step completion tests to use set_card_step_completion (matches spec's SetCardStepCompletion operation)

Project-scoped operations under /projects/{projectId}/ are retained since those genuinely operate on the project resource.

Test plan

  • make check passes — all Smithy validation, Go (vet + lint + tests), TypeScript (tsc + 307 tests), Ruby (454 tests + RuboCop), and conformance (23/23) green

Copilot AI review requested due to automatic review settings February 2, 2026 22:38
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request flattens the Basecamp API SDK routes by removing nested URL scoping that previously required project_id (bucket ID) parameters. Resources are now accessed directly by their unique IDs rather than through a project hierarchy. The changes span across all three SDK implementations (Go, TypeScript, Ruby), updating generated code, hand-written services, tests, and examples to reflect the simplified API structure.

Changes:

  • Removed project_id/bucketID parameters from ~80 SDK operations across all three languages
  • Updated OpenAPI spec examples to match flattened routes
  • Simplified lineup marker API to use name/date instead of title/starts_on/ends_on/color/description
  • Removed BucketID field from Go's OperationInfo struct and OpenTelemetry span attributes

Reviewed changes

Copilot reviewed 104 out of 233 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
spec/overlays/examples.smithy Updated example inputs to remove projectId parameters
ruby/test/basecamp/services/*.rb (25 files) Removed project_id parameters from test method calls and URL patterns
ruby/lib/basecamp/services/*.rb (36 files) Deleted hand-written service files superseded by generated code
ruby/lib/basecamp/services/base_service.rb Removed bucket_path helper method
go/pkg/basecamp/*.go (multiple files) Removed bucketID parameters from service method signatures
go/pkg/basecamp/observability.go Removed BucketID field from OperationInfo struct
go/pkg/basecamp/otel/*.go Removed bucket ID from OpenTelemetry span attributes
go/pkg/basecamp/lineup*.go Simplified marker request/response to use name/date only
conformance/runner/go/main.go Updated test runner to remove projectId parameters

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 5, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 5, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 5, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
@jeremy jeremy force-pushed the flat branch 3 times, most recently from d175d97 to cdd1aa7 Compare February 8, 2026 08:21
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 8, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 8, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
@jeremy jeremy force-pushed the flat branch 2 times, most recently from d3aa841 to 5fc8024 Compare February 20, 2026 23:19
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 21, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 22, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 22, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 25, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
Copilot AI review requested due to automatic review settings February 26, 2026 16:38
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 88 out of 219 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings February 27, 2026 01:15
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 88 out of 216 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Resources are uniquely identified and don't need parentage context in
their URLs. Remove /buckets/{projectId} prefix and other nested scoping
from ~80 operations, changing paths like:

  /{accountId}/buckets/{projectId}/todos/{todoId}

to flat paths like:

  /{accountId}/todos/{todoId}

Project-scoped operations under /projects/{projectId}/ are retained
since those genuinely operate on the project resource itself.
Remove projectID parameter from all service methods that no longer
need bucket scoping. Retain projectID only for genuinely project-scoped
operations (ListProjectPeople, UpdateProjectAccess).

Also simplifies lineup marker requests to match spec (name/date only),
and removes BucketID from OperationInfo and OpenTelemetry spans.
Remove projectID arguments from test calls, update lineup test
fixtures to use name/date fields, and remove BucketID from
observability test assertions.
Remove /buckets/{projectId} from MSW mock URLs, remove projectId
arguments from service calls, update lineup tests to use name/date
fields, and remove project_id from OpenTelemetry span assertions.
Remove project_id: keyword arguments from service test calls, update
WebMock stub URLs to use flat paths, update lineup tests to use
name/date fields, and fix card step completion tests to use
set_card_step_completion on CardTablesService.
Remove projectId argument from CreateTodo and ListTodos calls in
the conformance test runner.
Nine methods still accepted a bucketID parameter that was silently
discarded — callers would pass a value that got thrown away. Remove
the parameter from: CampfiresService.GetLine, DeleteLine, GetChatbot,
UpdateChatbot, DeleteChatbot; ForwardsService.GetReply;
ClientRepliesService.Get; CardsService.Move; CardStepsService.Reposition.

Also remove dead ProjectPath() and RequireProject() methods from Client.
Clean 121 comment lines across 22 files that referenced bucketID
parameters that no longer exist in function signatures.
Remove /buckets/{projectId} prefix from test path patterns and
projectId from pathParams in pagination, idempotency, and status-code
conformance tests. Update schema.json example accordingly.
Remove projectId arguments from Go, TypeScript, and Ruby README code
examples to match flattened service signatures. Update TS
normalizeUrlPath JSDoc comment. Remove dead bucket_path codegen logic
from Ruby service generator.
The rebase onto main brought in 3 new timesheet entry operations
(Get, Create, Update) with nested /buckets/{projectId}/ URIs.
Flatten these to match the rest of the flat branch, regenerate
all SDK clients, and update the Go service layer and conformance
runner accordingly.
These 31 files were superseded by generated services in
src/generated/services/ but never deleted. The entry point
(src/index.ts) already imports from generated, so these were
unused dead code. Only base.ts and authorization.ts remain
as hand-written services (they talk to different endpoints).

The ts-service branch will address generating a single unified
service layer that matches the ergonomics of these originals.
Update card_steps_service_test.rb to use the regenerated method
name (card_steps.set_completion instead of card_tables.set_card_step_completion).
Remove .plan.md that was accidentally included during rebase.
Post-rebase regeneration to ensure generated files match the
canonical openapi.json built from the Smithy spec.
Flatten the 6 new Boost operation URIs from PR #83 to remove
/buckets/{projectId} nesting, matching the flat branch convention.
Regenerate all SDK clients and update tests for flat paths.

Add web-URL flattening to Go router so it can match Basecamp web URLs
(which still contain /buckets/{projectId}) against the flat route table.
Remove bucketID parameter from all 6 BoostsService methods and
update CreateLine test calls to match flat campfire signatures.
The route table strips .json suffixes during generation, but the
router was matching against the raw path. API URLs like
basecampapi.com/.../boosts.json returned nil because the route
table stores .../boosts without the suffix.

Fix by normalizing .json in extractPath alongside other URL
normalization (scheme, host, query, trailing slash).
Remove /buckets/{projectId} from TS and Ruby webhook test that
was added in PR #85 for the recent_deliveries fixture test.
…erters

The required-fields PR changed all Id fields in generated types from
int64 to *int64. Update all *FromGenerated converter functions to use
derefInt64() for pointer-to-value conversion, and update test struct
literals to pass pointer values.
Rebuild openapi.json from Smithy, then regenerate Ruby, TypeScript,
and Kotlin SDKs. Updates Kotlin conformance tests and TodosServiceTest
for flat URL signatures (projectId removed). Fixes apidiff CI cache
key to include go.mod hash so the tool rebuilds on Go version bumps.
C1: GetProjectTimeline now bucket-scoped at /buckets/{projectId}/timeline.json
C2: GetProjectTimesheet now bucket-scoped at /buckets/{projectId}/timesheet.json
C5: Timesheet entry routes use /timesheet_entries/{entryId} (underscore separator)
C6: ListWebhooks/CreateWebhook now bucket-scoped at /buckets/{bucketId}/webhooks.json

Propagated across Go (generated + hand-written), Ruby, TypeScript, Kotlin, Swift.
Go URL router handles /projects/ → /buckets/ normalization for web URLs.
TS normalizeUrlPath uses context overrides for bucketId vs projectId.
Conformance tests cover all four route fixes (Go 31/31, Kotlin 30/30+1 skip).
- Go README: Add bucketID to webhook Create/List examples
- Go README: Define boardID variable in message board example
- timesheet.go: Remove stale projectID reference from RecordingReport comment
- message_types.go: Update List comment to reflect account-level scope
BC3 serves GetProjectTimeline and GetProjectTimesheet at
/projects/{projectId}/... not /buckets/{projectId}/...
Main branch already had this fix but flat never picked it up.
@jeremy jeremy merged commit 6b4c632 into main Feb 27, 2026
25 checks passed
@jeremy jeremy deleted the flat branch February 27, 2026 23:04
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 27, 2026
Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests
jeremy added a commit to basecamp/basecamp-cli that referenced this pull request Feb 27, 2026
* Migrate CLI to flat SDK routes (basecamp/basecamp-sdk#74)

Update all SDK service calls to use flat URL routing where bucketID/
projectID has been removed from method signatures. This is the CLI-side
companion to basecamp/basecamp-sdk#74 which flattens all SDK routes from
/{accountId}/buckets/{projectId}/resource/{id} to
/{accountId}/resource/{id}.

Key changes:
- Remove bucketID first-arg from ~120 SDK method calls across 25+ files
- Remove project resolution from single-resource commands (show, complete,
  update, etc.) that no longer need project context
- Flatten raw API paths in show.go and resolver.go
- Remove timesheet entry CRUD commands (Get/Create/Update/Trash removed
  from flat SDK) and clock shortcut
- Remove unused project parameters from card column/step and todolist
  group subcommands
- Update command catalog, breadcrumbs, and tests

* Use extractID() instead of extractWithProject() where project is discarded

Addresses PR review: commands that no longer need project context should
use extractID() instead of extractWithProject() with the second return
value discarded.

* Update e2e tests for commands that no longer require project

Remove "without project shows error" tests for events, messagetypes,
recordings visibility, timesheet recording, and webhooks — these
commands no longer require project context with flat SDK routes.

* Upgrade SDK to cdd1aa7 (flat branch, boosts + timesheet flattening)

* Flatten boost commands for flat SDK routes (remove bucketID params)

* Upgrade SDK to c75edff (flat branch, required-fields + derefInt64 fix)

* Upgrade SDK to f857e99 (flat branch, derefInt64 + Smithy regen)

* Migrate TUI data layer to flat SDK routes (remove bucketID params)

* Upgrade SDK to 96abdc8 (flat branch, C1/C2/C5/C6 fixes)

ProjectTimeline and ProjectReport now accept projectID param.
Webhooks List/Create now accept bucketID param.
Timesheet entry route segment fixed (timesheet_entries).

* Wire projectID/bucketID through CLI commands for flat SDK routes

Timesheet: add --project/--in flags, pass projectID to ProjectReport.
Webhooks: add --project/--in flags, pass bucketID to List/Create.
Boost delete: add project resolution (matches list/show/create).
Timeline: pass projectID to ProjectTimeline in both one-shot and watch.

* Pass projectID to TUI ProjectTimeline pool fetch

* Remove dead project resolution from webhook show/update/delete and boost delete

These SDK methods operate by globally-unique ID and don't accept a
bucketID param. The resolution chains were prompting users for a
project that was never used.

* Rename bucketID vars to projectID in TUI resolve layer

* Rename ParsedURL.BucketID to ProjectID (bucket_id → project_id in JSON)

Aligns URL parse output with flat route terminology. Updates unit
tests, e2e tests, and skill documentation.

* Skip project resolution in campfire post when campfire ID is provided

When a campfire ID is passed directly, the flat SDK doesn't need a
project. Only resolve project when deriving campfire from project dock.

* Fix comment interactive fallback to resolve project before picker

The Comment resolver requires a projectID to show the recording picker.
Ensure project is resolved before calling the interactive path.

* Upgrade SDK to main branch (d284e87, timeline/timesheet path fixes)

SDK flat branch merged to main. Bumps from 96abdc8 (flat) to 6b4c632
(main), picking up the /buckets/ → /projects/ path corrections for
GetProjectTimeline and GetProjectTimesheet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants