Skip to content

feat(customers): hashed single-use verification codes and guarded order alerts - #145

Merged
roncodes merged 1 commit into
release/v0.4.25from
feature/sms-guard-phase-1
Oct 13, 2026
Merged

roncodes merged 1 commit into
release/v0.4.25from
feature/sms-guard-phase-1

Conversation

@roncodes

Copy link
Copy Markdown
Member

What

Phase 1 of the SMS guard on the storefront side, on top of #144 (phase 0). Pairs with fleetbase/core-api#307.

  • Hashed single-use codes. Every SMS verification code the storefront sends (request-creation-code, login-with-sms, account-closure, request-phone-verification) is issued with core's hashed option: the row keeps an HMAC, the code expires in 10 minutes, and the plain code exists only in the message.
  • One way to check a code. create, verify-code, confirm-account-closure and verify-phone-number look up the newest live code for the identity or user (findActiveFor / findActiveForSubject), check it with check() (locks after 5 wrong guesses) and use it up with consume(). A code can no longer verify twice, and a leaked table no longer gives away live codes.
  • Order alerts through the guard. StorefrontOrderCreated sends its text through core's SmsServiceChannel (purpose storefront_order_alert), so it is budgeted and on the ledger like every other message.

Compatibility

Works against the current core release: on a core without findActiveFor, consume or SmsServiceChannel (before 1.6.70) the controller falls back to the plain lookups it had, the hashed option is ignored (plaintext codes as today), and the order alert keeps the Twilio channel. Nothing changes for apps in the field; codes in flight at deploy time keep verifying.

Merge order

Based on feature/sms-guard so the diff shows only phase 1. Before merging #144, retarget this PR to release/v0.4.25; otherwise GitHub closes it when the base branch is deleted.

Tests

The notification contract test covers the channel switch and toSms. The code-check paths are exercised by the existing contract tests (plaintext fixture rows still verify through the legacy comparison in check()) and the lockout tests from phase 0. Not run locally (the local runner is silent on this machine); storefront CI does not run for release-branch PRs.

Docs

fleetbase/postman: codes now expire after 10 minutes and verify once. needs-docs, needs-api-spec.

…er alerts

Every SMS code the storefront sends is issued hashed (HMAC on the row, 10
minute expiry, plain code only in the message), and create, verify-code,
confirm-account-closure and verify-phone-number check the newest live code
for the identity or user with core's check() and use it up with consume(), so
a code verifies once and a leaked table gives nothing away. StorefrontOrderCreated
sends its text through core's SmsServiceChannel so order alerts are budgeted
and ledgered. Everything falls back to the old behaviour on a core without
these APIs.
Base automatically changed from feature/sms-guard to release/v0.4.25 October 13, 2026 10:34
@roncodes
roncodes merged commit 5e7d410 into release/v0.4.25 Oct 13, 2026
@roncodes
roncodes deleted the feature/sms-guard-phase-1 branch October 13, 2026 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant