Add MoveRecordingToVault: move a document, upload or vault between vaults

Merged
JE
25d ago
+1345-17

Card: https://app.basecamp.com/2914079/buckets/46292715/card_tables/cards/10225840195

bc3#13644 (merged and in production) documented POST /recordings/:id/filing.json in doc/api/sections/vaults.md: move a document, upload or vault into another vault in the same project, or change its position in the vault it's in. The item moves in place, so its id, comments and history stay with it.

What this adds

  • MoveRecordingToVault on the Recordings service, at the flat path. It is shaped after MoveCard: POST, 204, parent_id required, and position optional and 1-indexed (omitted means first). Like MoveCard, it is not marked idempotent, so every SDK sends it once.
  • Errors as bc3 sends them: 400 for a missing parent_id (BadRequestError), 403 and 404 as bare heads, and 422 as ValidationError. Only the position and vault-cycle 422s carry an error message; the operation doc says so.
  • Generated methods: every SDK spells it moveToVault / move_to_vault and reports resource type recording.
  • Go: Recordings().MoveToVault(ctx, recordingID, vaultID, opts). It omits position when it is zero and refuses a negative one before the request. The grouped generated client exposes it beside Trash/Archive.
  • Tests: Go, TypeScript, Ruby and Python (sync and async) fake-server tests assert the flat POST path and the exact body, with and without a position, plus refusals with and without a body. Go also covers the negative-position refusal and the 403/404 mapping. Rust's recordings service already has its happy-path and error case.

Decisions

  • The name. I didn't use MoveRecording because bc3 already routes POST /recordings/:id/moves, the Move menu's cross-project move. That move copies the recording to a new id and runs asynchronously. Jeremy asked for it to be revived (card comment), so MoveRecording should stay free for it.
  • No repin. The route is documented after the provenance pin (66d387b62f). spec/bc3-route-allowlist.yml carries it as a documented-elsewhere waiver, with the route draw, controller and API test cited, the same way as PollEvents. Delete the waiver at the next repin.
  • No conformance fixture. Cross-SDK conformance would mean wiring the operation into seven runners. MoveCard has none either. The generated method in each SDK comes from the same spec as the Go path, and the Go tests cover the wire shape.

make check passes locally.

breaking label: the API Compatibility gate counts the methods this adds to the generated Go ClientInterface / ClientWithResponsesInterface as incompatible, because an outside implementer of those interfaces would no longer compile. Every operation addition does this, and #883 and #877 carried the same label for the same reason. Nothing existing changes.