basecamp / basecamp/basecamp-sdk
Cards: update and updateVerbatim are now pure duplicates — collapse them
- Dominant language
- Go
- Stars
- 49
- Forks
- 12
- Avg merge
- 20h 47m
- Merged PRs (30d)
- 89
Description
Follow-up to the presence-aware card fix (`fix/card-due-on-explicit-clear`, absorbing basecamp/bc3#12521).
## What happened
The Cards composite `update` existed for exactly one reason: BC3 built card update params as `{ due_on: nil }.merge(card_params)`, so any body omitting `due_on` erased the date. `update` defended against that with a read-modify-write; `updateVerbatim` was the escape hatch for callers who wanted the single request and would manage `due_on` themselves.
bc3#12521 made the JSON representation presence-aware, so omission now means "leave unchanged". The defence has nothing left to defend, and the preservation GET was removed. **The two methods are now behaviourally identical in all six SDKs** — same arguments, same single PUT, same body. Go's is literally:
```go
func (s *CardsService) Update(ctx context.Context, cardID int64, req *UpdateCardRequest) (result *Card, err error) {
return s.UpdateVerbatim(ctx, cardID, req)
}
```
Three language lanes flagged this independently while implementing the fix (Ruby, Python, Kotlin), which is a good signal that it reads as duplication rather than as intent.
## Why it wasn't collapsed in that PR
Collapsing is a breaking public-API change and reaches into all six generators' method-name override tables (`METHOD_NAME_OVERRIDES` and its per-language equivalents), plus the `UpdateCardVerbatim` conformance operation name and SPEC §5's composite roster. That is a different review than an urgent production-correctness fix, so both names were kept with the relationship documented.
## Why it should be done
The duplication is now **pure** — not "similar", not "differs in an edge case". `updateVerbatim` no longer describes a distinct behaviour, so the name actively misleads: it implies a sharper, less safe path that no longer exists. Every SDK ships two public methods where one would do, and every consumer reading the API has to work out that the distinction is historical.
## Scope
- Decide the surviving name (`update` reads correctly now; `updateVerbatim` is the one whose meaning evaporated).
- Six generators' name-override tables.
- `UpdateCardVerbatim` conformance operation + `conformance/tests/cards_write.json` case 1.
- SPEC.md §5 "Current composites" — Cards would stop being a composite entry entirely.
- Breaking-change note + migration guidance; coordinate with the MIGRATING.md lane (#642).
Related: the same collapse question does **not** apply to Todos, Todolists, Documents or Schedule entries — those endpoints are genuinely full-replace, so their `update`/`replace` split still carries meaning.
Contributor guide
Research direction
Start with the six generators' method-name override tables and trace the Cards update methods, then inspect the UpdateCardVerbatim conformance operation and conformance/tests/cards_write.json case 1. Review SPEC.md §5 and the breaking-change guidance, coordinating migration wording with MIGRATING.md and issue #642. Done means one surviving Cards update API is reflected consistently across SDKs, conformance, specification, and migration documentation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, kotlin, python, ruby
- Domain
- api, backend-api-design
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100