feat(projects): set and remove a project's logo
Merged
RO
17h ago+686+686+012345678901234567890123456789-29-29-01234567890123456789
Why
basecamp/bc3#14174 lets API clients set and remove a project's logo, the image beside its name, and basecamp-sdk wraps it as of v0.30.0. The CLI has had no way to do either, which is what basecamp/basecamp-sdk#977 asks for.
What changed
basecamp projects logo set <file>uploads or replaces the logo. It takes PNG, JPEG, GIF, WebP, AVIF, HEIF or HEIC files up to 5 MB, and refuses any other type before uploading.basecamp projects logo removeremoves it, and succeeds when there's no logo.projects showreturnslogoin JSON, and the detail view says whether one is set.- The file check and project read-back that wallpaper used are now shared by both images.
Scope
- This is stacked on #973, which moves the SDK to v0.31.0. Merge it after #973.
- There's no download command, because the SDK doesn't wrap the logo endpoint's redirect. Wallpaper has none either.
Verification
bin/cipasses.- Against a local bc3 server with the logo API, I set a logo from a real PNG and checked that the stored image's bytes match the file. Then I removed it, and the project read back with no logo. SVG, text and oversized files were refused before anything was sent.
- An independent GPT-6.1-sol review found nothing to fix.
Summary by cubic
Adds projects logo set and logo remove so the CLI can set and remove a project's logo, which previously was only possible through the API.
projects logo set <file>uploads or replaces the logo; accepts PNG, JPEG, GIF, WebP, AVIF, HEIF, or HEIC up to 5 MB and rejects other types before uploading.projects logo removeclears the logo and succeeds when the project has none.projects shownow returnslogoin JSON and the detail view reports whether a logo is set.- The wallpaper file validation and project read-back helpers are now shared by both image types.
- Merges in the latest
card-moves-cross-projectbase branch. - Addresses basecamp/basecamp-sdk#977, stacked on the SDK v0.31.0 bump in #973.