Set, lay out and remove a project's wallpaper

RO
1h ago
+3050-85

Lets every SDK upload, replace and remove a project's wallpaper, change how it is laid out, and read it from a project.

Card: Add ability to add/remove wallpaper
bc3: https://github.com/basecamp/bc3/pull/14062 (unmerged; it serves these routes)
CLI: https://github.com/basecamp/basecamp-cli/pull/948

What changed

  • New operations:
    • UpdateProjectWallpaper is PUT /projects/{id}/wallpaper.json. It takes a multipart wallpaper and an optional mode query parameter.
    • RemoveProjectWallpaper is DELETE on the same path.
  • Project gains an optional wallpaper (url, mode), and UpdateProjectInput gains wallpaper_mode.
  • In Go, the new methods are Projects.UpdateWallpaper(ctx, projectID, r, filename, contentType, *UpdateProjectWallpaperOptions) and Projects.RemoveWallpaper. The logo upload and the wallpaper upload now build their multipart body in one shared helper.
  • The TypeScript, Ruby and Python generators sent only the path and the file on a multipart upload. As a result, mode was accepted and never sent. They now send query parameters too. The account logo upload regenerates byte-identical.

Scope

  • mode is a documented string (fill/tile), the same idiom as ProjectStatus, not an enum. A future mode does not break the strict Swift, Kotlin and Rust decoders.
  • The SDK validates no format, size or mode. bc3 is the authority, and the CLI checks before it sends.
  • spec/bc3-route-allowlist.yml carries both routes until the repin past bc3 #14062, following the CreateEmbed precedent.

Blast radius

The change is additive: two operations, an optional response field and an optional request field. The generator change affects only multipart operations, and the logo upload is the only existing one.

Verification

  • make passes on Linux. The macOS-only Swift targets did not run, so the Swift test is written but not compiled here; CI on macOS runs it.
  • Breaking the Go wrapper three ways (dropping mode, dropping wallpaper_mode, blanking the decoded mode) turns four tests red.
  • End to end, basecamp-cli on this commit was run against bc3 #14062 locally. Set, mode, replace, remove, and the server's 422 all behaved, read back from the API.