Skip to main content

TSD - User registration


Document Control

VersionDateAuthorDescription
1.02025-08-19BA TeamInitial Version
1.1.2025-09-03BA TeamAdded Admin User Creation

Table of Contents

  1. Overview
  2. Technology Stack
  3. System Architecture Overview
  4. Functional Overview
  5. User Interface
  6. Technical Specification
  7. Integration Requirements
  8. Authentication
  9. Security Considerations
  10. Error Handling
  11. Performance Considerations
  12. Testing Strategy
  13. Monitoring and Analytics
  14. Deployment Considerations
  15. Future Enhancements

1. Overview

This document outlines the functional and technical specifications for the user registration process in the OX Agry Platform. The system supports two registration workflows: self-registration for users with digital access, and admin-assisted registration for users visiting offices in person. Both processes use phone number verification via OTP and integrate with JWT-based authentication.

1.1 Purpose

To provide a secure, user-friendly registration process that verifies user identity and integrates seamlessly with the application's technology stack.

1.2 Scope

Self-Registration:

  • User registration via phone number
  • OTP verification via SMS or WhatsApp
  • Get minimum user details (name) for registration
  • Profile completion with Terms & Privacy Policy acceptance
  • JWT-based authentication post-registration

Admin-Assisted Registration:

  • In-office registration assistance for visiting users
  • Duplicate user checking and existing user assistance
  • Admin-supervised OTP verification with privacy protection
  • Consent confirmation for Terms & Privacy Policy

2. Technology Stack

  • Frontend: React, Tanstack Router, Tanstack Form, Apollo Client
  • Backend: NestJS, GraphQL, Prisma ORM
  • Database: PostgreSQL
  • SMS Gateway: Third-party SMS service
  • Authentication: JWT Tokens

3. System Architecture Overview

3.1 Component Interaction Flow

Web App (Tanstack Router) → GraphQL API (NestJS) → Database (PostgreSQL)

SMS Gateway Service

3.2 High-Level Process Flow

Self-Registration:

  1. User enters phone number with country code (dial code, e.g., +91)
  2. System validates input and checks for existing users
  3. OTP is generated and sent via SMS/WhatsApp
  4. User enters OTP for verification
  5. System validates OTP
  6. System request User name for new users
  7. User needs to agree Terms and Privacy Policy
  8. Creates user account
  9. JWT tokens are issued for authenticated session

Admin-Assisted Registration:

  1. Admin checks for existing user by mobile number
  2. If new user, admin initiates OTP process
  3. OTP sent to users's device via selected method
  4. User provides OTP to admin for verification
  5. User provides Name to admin for new users
  6. Admin completes profile with verbal consent confirmation
  7. Account created with admin audit trail

4. Functional Overview

4.1 Self-Registration Flow

4.1.1 Mobile Number Input (FR-01)

Required Fields

  • Phone Number: Primary identifier (with dial code picker)
  • Country Code: Dropdown selection (default +91 for India)

Validation Rules

  • Phone number must be valid international format (+1234567890)
  • Length 15 digits
  • Numeric only (0-9)
  • Check if mobile number already exists in system

Form Behaviour

  • Real-time validation with error messages
  • Loading state during form submission
  • Error handling for network failures

4.1.2 OTP Delivery Method Selection (FR-02)

Available Options

  • SMS: Traditional text message delivery
  • WhatsApp: WhatsApp Business API integration

Selection Logic

  • User can toggle between SMS/WhatsApp for Indian numbers
  • Fallback to SMS if WhatsApp delivery fails
  • For International numbers, user can select only WhatsApp option

4.1.3 OTP Generation and Management

OTP Characteristics

  • Length: 6 digits
  • Numeric only (0-9)
  • Expiration: 15 minutes from generation
  • Single-use: Invalidated after successful verification

OTP Storage

  • Encrypted storage in database
  • Associated with phone number and timestamp
  • Automatic cleanup of expired OTPs

Rate Limiting

  • Maximum 5 OTP requests per phone number in 30 mins
  • 30-second cooldown between consecutive requests
  • Progressive delay for repeated failed attempts

4.1.4 OTP Verification Process (FR-03)

Verification Constraints

  • Maximum 5 verification attempts per OTP
  • Case-sensitive numeric input
  • Automatic account lockout after 5 failed attempts for 30 mins

Security Measures:

  • Attempt tracking per phone number
  • IP-based rate limiting
  • Automatic session cleanup
  • Failed attempt logging for security monitoring

4.1.5 Profile Completion (FR-04)

Required Fields

  • Name: Input Field for name
  • Checkbox: For agreeing to Terms and Privacy Policy
  • Terms & Privacy policy: Link to Terms of Service and Privacy Policy
  • "Complete Registration" button

Validation Rules

  • Length: 1-100 characters
  • Characters: Letters, spaces, hyphens, apostrophes allowed
  • Required: Cannot be empty or whitespace only
  • Terms & Privacy Policy: User need to Accept
  • "Complete Registration" button: work only when the name field is filled and Terms & Privacy policy is agreed

4.1.6 Account Creation (FR-05)

Post-Verification Actions

  • Create user record in database
  • Mark phone number as verified
  • Generate initial JWT access and refresh tokens
  • Send welcome notification
  • Redirect to onboarding flow

User Profile Setup

  • Set account status to 'active'
  • Record registration timestamp and method
  • Initialize user preferences with defaults

4.2 Admin-Assisted Registration Flow

4.2.1 Admin Mobile Entry & OTP Delivery (AFR-02)

Required Fields:

  • Dial code selection (dropdown with country codes)
  • Mobile number (10-digit format for primary Indian market)
  • Delivery method (SMS/WhatsApp radio buttons)

Validation Rules:

  • E.164 international format validation
  • Real-time format checking with visual feedback
  • Check if mobile number already exists in system
  • Admin role permission verification

OTP Generation:

  • Same security characteristics as self-registration
  • Admin-initiated but user-received
  • Delivery confirmation tracking
  • Fallback method handling

4.2.2 Admin OTP Verification (AFR-03)

Security Constraints:

  • Maximum 5 verification attempts per OTP
  • 15-second cooldown between resend requests
  • User enters OTP directly (privacy protection)

Privacy Protection:

  • User provides OTP verbally or enters directly
  • No OTP display in admin interface
  • Screen privacy measures in office environment
  • Audit logging without sensitive data exposure

4.2.3 Admin Profile Completion (AFR-04)

Required Information:

  • Full name (minimum 2 characters)
  • Verbal consent confirmation

Consent Management:

  • Admin checkbox: "I confirm that the user agrees to the Privacy Policy & Terms of Use"
  • Represents in-person verbal agreement
  • Compliance with data protection regulations
  • Audit trail for consent confirmation

4.2.4 Admin Account Creation (AFR-05)

Post-Verification Actions

  • Create user record in database
  • Mark phone number as verified
  • Generate initial JWT access and refresh tokens
  • Send welcome notification
  • Redirect to onboarding flow

User Profile Setup

  • Set account status to 'active'
  • Record registration timestamp and method
  • Initialize user preferences with defaults
  • Comprehensive audit log entry
  • Admin daily creation limit tracking

5. User Interface

5.1 Self-Registration Screens

5.1.1 Mobile Number Entry

  • Input field for phone number with country code picker
  • Buttons for choosing delivery method "SMS" or "WhatsApp"
  • "Send OTP" button

5.1.2 OTP Verification Screen

  • 6-digit input field for OTP
  • "Verify OTP" button
  • Resend button with countdown timer
  • Back button for number correction

5.1.3 Profile Completion Screen

  • Input field for name
  • Check box to accept Terms and Privacy Policy
  • "Complete Registration" button

5.2 Admin Registration Modal

5.2.1 Modal Design Approach

Location: "Add User" button above user list table

5.2.2 Mobile Number Entry

  • Country code dropdown (default +91 for India)
  • Mobile number input with format validation
  • Delivery method buttons

5.2.3 OTP Verification

  • 6-digit input field for OTP
  • "Verify OTP" button
  • Resend button with countdown timer
  • Back button for number correction

5.2.4 Profile Completion

  • Name input field with validation
  • Consent confirmation checkbox
  • Terms & Privacy Policy reference
  • "Complete Registration" button

6. Technical Specification

6.1 Frontend Implementation

6.1.1 Mobile Number Input Screen (FR-01)

Form Fields

FieldTypeValidation
countryCodeDropdownRequired (e.g., +91, +1)
phoneNumberText InputRequired, numeric only
Delivery Method ("SMS", "WhatsApp")Radio groupConditionally required & enabled
Send OTPButtonCall GraphQL sendOtp mutation

Validation Rules

  • Combine countryCode + phoneNumber and validate as E.164
  • Length: 15 digits
  • OTP method:
    • If +91: allow SMS and WhatsApp
    • Else: only allow WhatsApp

UX Behavior Matrix

InputExpected Behavior
+91 + 9999999999Enable both SMS & WhatsApp options
+1 + 4155552671Only WhatsApp enabled
Invalid phone❌ Form shows error before submit
Select disabled❌ Validation blocks submission

Validation Flow

StepValidationResult
Phone formatMust match E.164 regexError if invalid
Dial code checkSMS allowed only for +91Disable otherwise
Method selectionMust match available optionsError on invalid selection
On submitApollo mutation firesNavigate to OTP screen on success

Background Process Flow

  • Validate mobile number format (dial code, numbers only)
  • Check for existing UserRegistration with same mobile number
  • Validate send attempts
  • Create/Update UserRegistration record
    • Set stage: MOBILE_NUMBER_ENTERED
    • Increment otpSendAttempts
    • Set lastOtpSentAt timestamp
    • Collect silently during registration steps.
  • Generate 6-digit numeric OTP
  • Send OTP via SMS/WhatsApp
  • Update record with OTP details
    • Set stage: OTP_SENT
    • Set lastOtpExpiresAt (now + 15 minutes)
    • Set otpDeliveryMethod: SMS/WhatsApp
    • Set otpDeliveryStatus: SENT/PENDING
  • Return success response with expiry time

6.1.2 OTP Verification Screen (FR-02 and FR-03)

Form Fields

Field NameTypeDescription
otpText input6-digit numeric code entered by the user
methodHidden/InputThe delivery method used for the OTP

Validation Rules

  1. otp

    • Type: text, numeric
    • Validation:
      • Required
      • Must be 6 numeric digits
      • Regex: /^\d{6}$/
  2. phoneNumber

    • Type: Typically passed as:
      • A query parameter: /verify-otp?phone=+9198xxxxxx
      • Or hidden field in the form
    • Validation: Must be present and valid E.164 number
  3. method

    • Type: Hidden input or stored in component state
    • Values: 'SMS' or 'WHATSAPP'
    • Used for: Resending OTP through the same medium

Behavior Summary

StateUI
0-30 seconds after load✅ Verify button, ⏳ Resend countdown
After 30 seconds✅ Verify button, ✅ Resend OTP enabled

Test Scenarios

Input / ActionExpected Result
Empty OTP❌ Show "OTP is required"
abc123❌ Show "must be digits"
12345❌ Show "must be 6 digits"
123456 + valid phone✅ Submit to server
Resend OTP before 30s⛔ Button hidden
Resend OTP after 30s✅ Button visible and working

Security Notes

  • JWT token stored in localStorage after successful verification
  • Consider using SecureStore or httpOnly cookies for web/mobile

Backend Process Flow

  1. Find UserRegistration by dialCode + mobileNumber
  2. Validate current stage is OTP_SENT
  3. Check OTP expiry (lastOtpExpiresAt > now)
  4. Validate verification attempts (max 5 per OTP session)
  5. Compare provided OTP with stored value
  6. Update verification tracking
    • Increment otpVerifyAttempts
    • Set lastOtpVerifiedAt (if successful)
  7. Update stage to OTP_VERIFIED (if successful)
  8. Return verification status

6.1.3 Complete Registration Screen (FR-04)

Form Fields

FieldTypeValidation
nameText inputMinimum 2 characters
termsAcceptedCheckboxMust be true to proceed
Complete RegistrationButtonCall GraphQL CompleteRegistration mutation

UX Behavior Summary

FieldValidationFeedback
nameRequired, ≥ 2 charactersInline error shown if invalid
termsAcceptedRequired (true)Error if unchecked on submit
Button enabledOnly when both fields are validDisabled otherwise

Backend Process Flow

  1. Find UserRegistration
    • Query by dialCode + mobileNumber
  2. Validate Current Stage
    • Ensure stage is OTP_VERIFIED
  3. Validate Name Format
    • Length: 1–100 characters
    • Required: Yes
  4. Validate Terms and Policy acceptance
    • Required: Yes
  5. Begin Database Transaction
  6. Create User Record
    • Generate publicId (CUID)
    • Set name
    • set userstatus: ACTIVE
    • set kycstatus: NOT_STARTED
    • set kyclevel: BASIC
    • Set timestamps
  7. Create UserContact Record
    • Link to User via userId
    • Set contactType: MOBILE
    • Set isPrimary: true
    • Set isVerified: true
    • Copy dialCode and mobileNumber
  8. Update UserRegistration
    • Link to User via userId
    • Set stage: USER_CREATED
    • Set enteredName

6.2 Backend Implementation

6.2.1 Database Schema

CREATE TABLE user_registrations (
id BIGSERIAL PRIMARY KEY,
stage VARCHAR(30) NOT NULL DEFAULT 'MOBILE_NUMBER_ENTERED',
user_id BIGINT UNIQUE REFERENCES users(id),
dial_code VARCHAR(5) NOT NULL,
mobile_number VARCHAR(15) NOT NULL,
entered_name VARCHAR(100),
registration_type VARCHAR(20) DEFAULT 'SELF' CHECK (registration_type IN ('SELF', 'ADMIN_ASSISTED')),
created_by_admin_id BIGINT REFERENCES users(id),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
UNIQUE(dial_code, mobile_number)
);


model OtpAttempt {
id BigInt @id @default(autoincrement())
dialCode String @db.VarChar(5)
mobileNumber String @db.VarChar(15)
otpHash String @db.VarChar(255)
purpose OtpPurpose
deliveryMethod DeliveryMethod
deliveryStatus DeliveryStatus @default(PENDING)
deliveryProvider DeliveryProvider
expiresAt DateTime @db.Timestamptz(3)
isUsed Boolean @default(false)
usedAt DateTime? @db.Timestamptz(3)
verificationAttempts Int @default(0) @db.SmallInt
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
userId BigInt?
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@map("otp_attempts")
@@index([dialCode, mobileNumber, purpose], name: "idx_phone_otp_attempts")
@@index([userId, purpose, isUsed], name: "idx_user_otp_attempts")
@@index([expiresAt, isUsed], name: "idx_otp_cleanup")
}

enum OtpPurpose {
REGISTRATION
LOGIN
}

enum DeliveryMethod {
SMS
WHATSAPP
}

enum DeliveryProvider {
MSG91
WHATSAPP
}

enum DeliveryStatus {
PENDING
SENT
DELIVERED
FAILED
}

-- Users table enhancements
ALTER TABLE users ADD COLUMN IF NOT EXISTS created_by_admin_id BIGINT REFERENCES users(id);
ALTER TABLE users ADD COLUMN IF NOT EXISTS registration_type VARCHAR(20) DEFAULT 'SELF';
ALTER TABLE users ADD COLUMN IF NOT EXISTS consent_confirmed_at TIMESTAMPTZ;

6.2.2 GraphQL Schema

Types

enum OtpPurpose {
REGISTRATION
LOGIN
}

enum DeliveryMethod {
SMS
WHATSAPP
}

enum DeliveryStatus {
PENDING
SENT
DELIVERED
FAILED
}


type OtpAttempt {
id: ID!
dialCode: String!
mobileNumber: String!
deliveryStatus: DeliveryStatus!
expiresAt: String!
verificationAttempts: Int!
createdAt: String!
}

type User {
id: ID!
mobileNumber: String!
name: String!
devices: [DeviceInfo!]!
}

type AuthResponse {
token: String!
user: User!
}

type Mutation {
sendOtp(dialCode: String!, mobileNumber: String!, deliveryMethod: DeliveryMethod!): OtpAttempt!
verifyOtp(otp: String!, otpAttemptId: ID!): OtpAttempt!
completeRegistration(otpAttemptId: ID!, name: String!): AuthResponse!
}

7. Integration Requirements

  • SMS/WhatsApp Gateway:
    • Integrate with Msg91/Twilio for SMS; WhatsApp API for WhatsApp
    • Update deliveryStatus via provider callbacks
  • GraphQL:
    • Expose mutations for OTP sending, verification, and registration completion
  • JWT:
    • Validate tokens on protected resolvers using NestJS guards

8. Authentication

JWT Tokens:

  • Issued after successful OTP verification
  • Signed with a secret key, stored in environment variables
  • Expiry: Configurable (e.g., 7 days)

Storage: Frontend stores JWT in secure storage (e.g., AsyncStorage for React Native) Authorization: Include JWT in Authorization: Bearer "Token" header for protected API calls

9. Security Considerations

OTP Security

  • Generate cryptographically secure OTPs
  • Limit OTP attempts (e.g., 5 failed attempts lock out the phone number for 30 minutes)
  • Encrypt sensitive data (e.g., phone numbers, OTP) in transit and at rest

Rate Limiting

  • Implement rate limiting on OTP requests to prevent abuse
  • Use NestJS rate-limiting middleware or SMS gateway limits

Data Validation

  • Validate phone numbers on both frontend (Tanstack Form) and backend
  • Sanitize inputs to prevent injection attacks

Communication Security

  • HTTPS encryption for all API communications
  • SMS delivery confirmation tracking
  • WhatsApp Business API with end-to-end encryption
  • Message template compliance with carrier regulations

JWT Security

  • Use strong secret keys and refresh tokens for long-lived sessions
  • Implement token revocation mechanisms

10. Error Handling

Frontend:

  • Display user-friendly error messages (e.g., "Invalid phone number" or "OTP expired")
  • Handle network errors with retry logic in Apollo Client

Backend:

  • Return descriptive GraphQL errors (e.g., INVALID_OTP, EXPIRED_OTP)
  • Log errors for debugging without exposing sensitive information

11. Performance Considerations

Database:

  • Index phone column in User and Otp tables for faster lookups
  • Periodically clean up expired OTPs to optimize storage

SMS Gateway:

  • Cache API responses where applicable to reduce costs
  • Use bulk SMS APIs for high-volume scenarios

GraphQL:

  • Optimize queries to avoid over-fetching (e.g., select only required fields)
  • Use DataLoader for batching database queries

12. Testing Strategy

12.1 Unit Testing

  • Form validation logic coverage > 90%
  • OTP generation and verification functions
  • Rate limiting algorithm validation
  • Password hashing and encryption utilities

12.2 Integration Testing

  • GraphQL mutation end-to-end testing
  • Database transaction rollback scenarios
  • SMS gateway mock service integration
  • JWT token generation and validation

12.3 User Acceptance Testing

  • Registration completion rates
  • OTP delivery success rates across carriers
  • Cross-device compatibility testing
  • Accessibility compliance validation

13. Monitoring and Analytics

13.1 Key Metrics

  • Registration completion rate
  • OTP delivery success rate by method
  • Time to complete registration flow
  • Failed verification attempt patterns

13.2 Alerting

  • High failure rates for OTP delivery
  • Unusual spikes in registration attempts
  • Database connection issues
  • SMS gateway service degradation

13.3 Logging

  • Structured logging for all registration events
  • PII-safe error logging with correlation IDs
  • Audit trail for successful account creations
  • Performance metrics for optimization insights

14. Deployment Considerations

14.1 Environment Variables

  • SMS gateway API credentials
  • WhatsApp Business API configuration
  • JWT signing keys and expiration settings
  • Database connection strings and pool settings

14.2 Feature Flags

  • OTP delivery method availability toggles
  • Rate limiting thresholds per environment
  • A/B testing for form layout variations
  • Emergency registration disable switch

14.3 Rollback Strategy

  • Database migration rollback procedures
  • API version compatibility maintenance
  • SMS template reversion capabilities
  • Client-side feature flag coordination

15. Future Enhancements

NA