Access Codes
Phone-number verification for signup and phone changes: POST /request-access-code sends a 6-digit code by SMS and POST /validate-access-code exchanges the code for a validation_token that CreateUser requires. Both are called by the Cloudflare Workers in the edge repo. Records live in the access-codes table, keyed by phone number; error bodies are the AccessCodeError schema in the API Specification.
Request
-
Resolve the phone number:
user_idin the body means an authenticated phone change and uses the number on file (400 PHONE_NUMBER_NOT_FOUND); otherwisephone_numberis required (400 MISSING_IDENTIFIER), reduced to digits, must be 10 digits (400 INVALID_PHONE_NUMBER) and must not belong to an existing user (409 PHONE_NUMBER_EXISTS). -
Load the existing record for the number and apply the backoff; a caller inside the wait window gets
425withnext_request_availableseconds. -
Generate a 6-digit
access_codeand a 6-digitoob_code, and write the record conditionally: no record may exist, orcreated_onmust still match the record just read. A conflict from a concurrent request is answered as425. -
Queue the SMS on
{env}-user-service-sms({request_id, phone_number, message: "Your FloatMe Access Code is <code>."}) for delivery. If the send fails the record is rolled back to the previous one (or deleted) so the failed attempt does not throttle the retry, and the response is500. -
201withoob_codeandnext_request_available.
SMS Delivery
The {env}-user-service-sms-worker Lambda consumes {env}-user-service-sms one message at a time and sends message to phone_number through the Twilio Messages API, using the {env}/twilio secret (account_sid, auth_token, from_number).
-
phone_numbermust be exactly 10 digits and is sent as+1<number>;messagemust be non-empty. Anything else is rejected without a Twilio call. -
A rejected message or a failed send is reported as a batch item failure. The queue redrives to
{env}-user-service-sms-dlqafter one failed receive, so a failed code is never resent; the user requests a new one. -
Every attempt emits the
user.sms.sendmetric with asuccesstag.
Source: pkg/sms/, cmd/sms-worker/
Validate
-
phone_numbermust be 10 digits (400 INVALID_PHONE_NUMBER) and have a record (404 ACCESS_CODE_NOT_FOUND). -
A record older than 15 minutes is
400 ACCESS_CODE_EXPIRED. -
Five failed guesses lock the code:
403 ACCESS_CODE_LOCKEDuntil a new code is requested. -
A wrong code is
400 INVALID_ACCESS_CODE; the failed attempt is persisted with a conditional write (retried up to 3 times on conflict). -
A correct code stores a 10-hex-character
validation_tokenandvalidate_onon the record and returns the token (200).
CreateUser compares its validation_token with the record for the signup phone number; the token is not consumed.