Use this runbook for a wallet that sees more than one verified UMP token for a presentation or recovery hash, or for a disputed phone-number transfer. Never pin an outpoint merely because a requester supplies it. Preserve the ticket, the candidate set, the operator identity, and the final action without copying presentation keys, OTPs, admin tokens, or full phone numbers into broad logs.
umpTokenOutpoint, phone_change_sessions, and
phone_change_history has completed.WAB_ADMIN_TOKEN is at least 32 random characters and comes from the
deployment secret manager. If it is absent, /admin/* intentionally returns
404; if it is non-empty but shorter, WAB refuses to start.Verify the support requester through the approved account-support process.
Obtain the presentation/recovery hash and candidate outpoints from the wallet's redacted diagnostics. These values are not wallet keys.
Query ls_users by that hash and confirm every candidate independently.
Inspect the referenced output and lineage. Select only an outpoint returned
by the overlay and owned by the supported account.
Set the pin by canonical phone identity (or by presentation key inside the restricted operator environment):
curl --fail-with-body --request POST "${WAB_SUPPORT_URL}/admin/ump-pin" \
--header "Authorization: Bearer ${WAB_ADMIN_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{
"methodType": "TwilioPhone",
"payload": { "phoneNumber": "+12065550100" },
"outpoint": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef.0"
}'Ask the user to retry ordinary sign-in. The client first attempts normal verified lineage resolution. It applies the pin only if ambiguity remains and the pinned outpoint is in its verified candidate set.
Record the ticket ID, redacted account identifier, selected outpoint, WAB deployment version, operator, and validation result.
Clear a pin after the account has a single healthy current UMP token:
curl --fail-with-body --request POST "${WAB_SUPPORT_URL}/admin/ump-pin" \
--header "Authorization: Bearer ${WAB_ADMIN_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{
"methodType": "TwilioPhone",
"payload": { "phoneNumber": "+12065550100" },
"outpoint": null
}'An incorrect or stale pin does not authorize an unknown token; the client ignores it and keeps reporting ambiguity.
The wallet must already be authenticated. It sends the current presentation key to WAB and proves possession of the requested number through Twilio OTP. WAB commit then stages the association and replacement key while retaining the current key. The wallet publishes a new UMP token that spends the current token and calls WAB finalize. The staged commit:
changeId.Finalize promotes the pending key and clears the previous UMP pin. The authorization token is hashed at rest, expires after ten minutes, and is single-use. Retrying commit, UMP publication, or finalize is idempotent for the same change. If the app restarts between phases, verified authentication returns both current and pending keys. The wallet uses whichever key is backed by the verified UMP token and finalizes when the pending key is live. If the current key is still live, repeating OTP verification returns the already staged key and change ID so the wallet can resume without a second commit.
Freeze further automated support changes for the disputed identities.
Verify the incident through a second support channel. Do not rely on the disputed phone alone.
In a read-only database session, locate the most recent unrestored
phone_change_history.id for the canonical number and verify its target,
prior owner, replacement method, timestamp, and ticket evidence.
Restore that exact record:
curl --fail-with-body --request POST "${WAB_SUPPORT_URL}/admin/phone-change/restore" \
--header "Authorization: Bearer ${WAB_ADMIN_TOKEN}" \
--header 'Content-Type: application/json' \
--data '{ "changeId": 1234 }'Confirm the claimed phone is again linked to the prior owner and the target's replaced phone is linked to the target. The restore refuses to proceed if a later ownership change makes either update unsafe; escalate that state for manual database recovery from the encrypted backup.
The target's on-chain UMP update is not reversed. Determine whether the target needs a WAB pin, account recovery, or another verified phone change.
Roll out in this order:
@bsv/overlay-topics 1.7.0 through the protected package workflow
and merge its generated infrastructure dependency-sync PR;Validate an ordinary existing login, a clean new account, an ambiguity login with a valid pin, rejection of a pin absent from candidates, same-number rotation, different-number rotation, takeover, and restore in a non-production environment before production enablement.
The previous overlay and WAB binaries ignore the additive reservation and history data, so an image rollback can retain both schemas. Do not run the WAB down migration after any phone change, because it destroys automatic restore history. Disable phone-change UI first if WAB must roll back. Retain the UMP reservation collection unless a reviewed database recovery plan explicitly reconstructs ownership.