Archive and restore a project

JE
7d ago
+395-5

basecamp projects archive <id> takes a project off the active list, and basecamp projects unarchive <id> brings it back.

Why

[CLI] Archive and unarchive a project: the SDK has had these two operations since basecamp-sdk#679, and the coverage report (basecamp-sdk#1055) lists them as unreached by the CLI. recordings archive goes through the generic ArchiveRecording, not the project endpoints, which are the ones that answer 403 where the admin pro pack restricts archiving.

What changed

OperationCommand
ArchiveProjectbasecamp projects archive <id>
UnarchiveProjectbasecamp projects unarchive <id>
  • Both answer {id, status}. Each offers projects show as a follow-up, and archive also offers projects unarchive to undo it, carrying --profile and --account where the run needed them. unarchive offers no undo, because the project may have come from the trash and archiving it wouldn't put it back. The endpoints return 204 with no body, so neither re-reads the project; projects delete answers the same way.
  • unarchive also restores a project from the trash, as the API does, and fails with limit_exceeded at the account's project limit. Its help and agent notes say both, as do archive's for the admin pro pack's 403.
  • Catalog entry, .surface, an API-COVERAGE.md row with the summary counts, and a short note in skills/basecamp/SKILL.md. That note is two lines because the skill has a 16 KB limit and was 156 bytes under it; the rest is in leaf help.

Builds on

Main at 5f88c4f2, whose pinned SDK (v0.33.0) has both operations. No bump in this PR.

Left out

ArchiveRecording, the third operation the planner found on the card: main already reaches it through recordings archive.

Tests

  • Unit (internal/commands/projects_archive_test.go): the request each command sends, its output and follow-ups (none offering archive after unarchive), follow-ups keeping scope, the 403 and the 507 reported as errors with nothing on stdout, a bad ID refused before any request.
  • e2e (e2e/projects.bats): missing and non-numeric IDs, the help text on restoring from the trash.
  • Smoke (e2e/smoke/smoke_projects_write.bats): archive then unarchive in the project lifecycle, checked with projects show. Written but not run: smoke needs a live account.

make -k check on thelio passes everything except TestHardenConfigDir in internal/cli (symlinked ancestor is not followed, regular file is not chmod'd). Those two subtests fail the same way on a clean checkout of 5f88c4f2 on that machine, this PR touches nothing there, and main's CI is green, so remote CI on this PR is the check for them. They're worth a separate look: the test exists to prove hardening doesn't follow a symlinked ancestor or chmod a regular file.

Gap card

https://app.basecamp.com/2914079/buckets/48521764/card_tables/cards/10447983764