Skip to content

api: implement PATCH /decks/{id} for partial deck updates #4

Description

@jeff-arn

Context

Deck CRUD is implemented but PATCH /decks/{id} is missing. Currently the
only ways to mutate a deck are: hit POST /decks to create a new one (no
in-place edits) or DELETE /decks/{id} (soft delete). Real users will need
to edit deck names, swap cards in/out of the pool, and add/remove loadouts
without recreating the entire deck.

Why deferred

Partial updates need a thoughtful field-level merge protocol — a "PUT with
all fields" replaces too much (you lose any client/server fields the client
did not know about), while a naive "merge whatever you sent" creates
ambiguity around how to clear optional fields, replace lists, etc.
RFC 7396 (JSON Merge Patch) and RFC 6902 (JSON Patch) are both options;
neither is one-line wiring.

Decisions to make

  • Patch format: JSON Merge Patch (simpler, less expressive) vs JSON
    Patch (full granularity, more verbose) vs a custom shape per resource.
  • List-shaped fields: how do clients add/remove individual pool entries
    vs replace the whole pool? The natural merge of a list is full
    replacement, but for big pools that becomes expensive.
  • Loadouts as nested resources: do we treat each loadout as
    individually addressable (e.g. PATCH /decks/{id}/loadouts/{loadoutId})
    or merge them as a list under the deck?
  • Concurrent updates: do we need optimistic concurrency (e.g.
    If-Match with an etag/version) before two clients can race?

Scope

  • Pick a patch format
  • Add PATCH /decks/{id} handler
  • DB layer: update_deck plus child-table reconciliation, in a transaction
  • Update updated_at on every successful patch
  • Auth: owner-only (consistent with DELETE)
  • Add integration tests in tests/api_decks.rs
  • Regenerate openapi.json

Pointers

  • Existing handlers: src/api/decks.rs::create_deck and delete_deck
  • DB layer: src/db/deck.rs (no UPDATE queries today)
  • Schema: migrations/20260502120000_decks.sql

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions