Skip to content

A wallet alert can be raised but never resolved #8

Description

@OliverD25

GET /v1/admin/wallet-alerts lists wallet receives that match no deposit
payment — coins in custody that no user has been credited for. It filters on
WalletTxoAlert.status == "open"
(src/crypto_processing_api/api/admin.py:147).

Nothing in the codebase ever sets that status to anything else, and nothing
ever sets resolved_at.
The column exists
(src/crypto_processing_api/ledger/models.py:498); the only writer is the
insert in src/crypto_processing_api/workers/reconciliation.py:287.

So an operator who does the work — reads
docs/runbook-usdt-attribution.md,
finds the user, credits them through the review queue — has no way to clear the
alert. The queue only grows, and a queue that only grows stops being read,
which is exactly how the next real one gets missed.

What to build

POST /v1/admin/wallet-alerts/{id}/resolve, taking a short note, setting
status and resolved_at, and recording the acting key id.

Constraints

  • This must move no money. It records that a human looked. Crediting a user
    is a separate action that already exists
    (POST /v1/admin/deposits/{id}/resolve), and the two must not be fused — an
    operator clearing an alert must not be able to mint a balance by accident.
  • Reuse the shape of the existing admin write endpoints in
    src/crypto_processing_api/api/admin.py: admin scope, key.key_id as the
    actor, 409 if it is already resolved.
  • The route needs a response model and an operation_id like every other route
    (src/crypto_processing_api/api/schemas.py). Adding one means running
    python scripts/export_openapi.py and committing the result, or CI fails.
  • Add the new response to the byte corpus in
    tests/integration/test_wire_bytes.py — regenerate it with
    WIRE_GOLDEN_WRITE=1. A route with no pinned bytes fails
    test_every_route_has_an_operation_id_and_pinned_bytes.

Worth deciding

Whether a resolved alert stays listable (?status=resolved). An audit trail an
operator cannot read back is not much of one.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: apiHTTP surface: routers, schemas, middlewarearea: opsOperator surface: alerts, health, reconciliation, runbooksgood first issueGood for newcomers

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions