Skip to main content

Registration Overview

User registration in boop network involves three key steps:
  1. Creating a user account
  2. Scanning palm biometrics
  3. Setting initial attributes and consent

Registration Methods

Method 1: Mobile App Registration

1

Download boop App

Download the boop mobile app from App Store or Google Play
2

Create Account

// App initiates registration
const response = await fetch('https://api.boop.network/v1/register', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    device_id: deviceId,
    platform: 'ios',
    app_version: '1.0.0'
  })
});

const { user_id, session_token } = await response.json();
3

Generate QR Code

App displays QR code for PVS scanning:
const qrData = {
  action: 'register',
  user_id: userId,
  session_token: sessionToken,
  timestamp: Date.now()
};

QRCode.generate(JSON.stringify(qrData));
4

Scan Palm at PVS

User scans QR code at any boop-enabled PVS terminal
5

Complete Registration

App receives confirmation and prompts for initial attributes

Method 2: PVS-Direct Registration

For users without smartphones:
1

Initiate at PVS

Touch “Register New User” on PVS screen
2

Provide Contact Info

Enter email or phone number for account recovery
3

Scan Palm

Follow on-screen instructions to capture palm
4

Receive Credentials

Get printed receipt with account details

Method 3: Web Portal Registration

2

Create Account

Fill in basic information
3

Receive Intent Link

Get registration link via email/SMS
4

Complete at PVS

Use link at any PVS terminal within 24 hours

Palm Scanning Process

Quality Requirements

The system requires high-quality palm captures:
class PalmQualityChecker:
    MIN_QUALITY_SCORE = 80
    REQUIRED_SAMPLES = 3

    def validate_scan(self, palm_image):
        checks = {
            'contrast': self.check_contrast(palm_image),
            'sharpness': self.check_sharpness(palm_image),
            'position': self.check_position(palm_image),
            'completeness': self.check_completeness(palm_image)
        }

        score = sum(checks.values()) / len(checks) * 100
        return score >= self.MIN_QUALITY_SCORE

Multiple Scan Collection

The system captures 3-5 scans to ensure accuracy and create a robust template
// PVS scan collection process
async function collectPalmScans(userId) {
  const scans = [];
  let attempts = 0;

  while (scans.length < 3 && attempts < 10) {
    const scan = await capturePalmScan();

    if (scan.quality >= 80) {
      scans.push(scan);
      showProgress(scans.length, 3);
    } else {
      showError('Please adjust hand position');
    }

    attempts++;
  }

  if (scans.length >= 3) {
    return createTemplate(scans);
  } else {
    throw new Error('Unable to capture sufficient quality scans');
  }
}

User Experience Flow

Mobile App UI

// React Native registration flow
const RegistrationFlow = () => {
  const [step, setStep] = useState('welcome');
  const [userId, setUserId] = useState(null);

  const steps = {
    welcome: <WelcomeScreen onNext={() => setStep('terms')} />,
    terms: <TermsScreen onAccept={() => setStep('createAccount')} />,
    createAccount: <CreateAccountScreen onComplete={(id) => {
      setUserId(id);
      setStep('scanInstructions');
    }} />,
    scanInstructions: <ScanInstructionsScreen
      userId={userId}
      onReady={() => setStep('showQR')}
    />,
    showQR: <QRCodeScreen
      userId={userId}
      onScanned={() => setStep('complete')}
    />,
    complete: <CompletionScreen />
  };

  return steps[step];
};

PVS Terminal UI

<!-- PVS Registration Interface -->
<div class="registration-screen">
  <div class="step-indicator">
    <div class="step active">1. Position</div>
    <div class="step">2. Scan</div>
    <div class="step">3. Verify</div>
    <div class="step">4. Complete</div>
  </div>

  <div class="scan-area">
    <video id="palm-preview"></video>
    <div class="guide-overlay">
      <div class="palm-outline"></div>
      <div class="instructions">Place palm within guide</div>
    </div>
  </div>

  <div class="quality-indicators">
    <div class="indicator" data-quality="position">✓ Position</div>
    <div class="indicator" data-quality="lighting">✓ Lighting</div>
    <div class="indicator" data-quality="stability">✓ Stable</div>
  </div>

  <button class="capture-btn" onclick="captureScan()">
    Capture Palm
  </button>
</div>

API Implementation

Registration Endpoint

POST /api/v1/register
Content-Type: application/json

Request:
  {
    "device_id": "string",
    "platform": "ios|android|web",
    "app_version": "string",
    "timezone": "string",
    "language": "string"
  }

Response:
  {
    "user_id": "usr_abc123",
    "session_token": "token_xyz",
    "registration_url": "intent://register#session_id=abc",
    "qr_code": "base64_image",
    "expires_at": "2024-01-01T12:00:00Z"
  }

WebSocket Registration Flow

class RegistrationWebSocket {
  constructor(sessionToken) {
    this.ws = new WebSocket('wss://api.boop.network/register');
    this.sessionToken = sessionToken;
  }

  async connect() {
    this.ws.onopen = () => {
      this.ws.send(JSON.stringify({
        type: 'authenticate',
        token: this.sessionToken
      }));
    };

    this.ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      this.handleMessage(message);
    };
  }

  handleMessage(message) {
    switch(message.type) {
      case 'scan_started':
        this.onScanStarted();
        break;

      case 'scan_progress':
        this.updateProgress(message.scans_completed, message.scans_required);
        break;

      case 'quality_feedback':
        this.showQualityFeedback(message.issues);
        break;

      case 'registration_complete':
        this.onComplete(message.user_id);
        break;

      case 'error':
        this.handleError(message.error);
        break;
    }
  }
}

Security Considerations

Registration Security

Registration sessions expire after 15 minutes for security. Users must complete the process in one session.
class RegistrationSecurity:
    def __init__(self):
        self.max_attempts = 5
        self.session_timeout = 900  # 15 minutes
        self.rate_limiter = RateLimiter(max_per_hour=10)

    def validate_session(self, session_id):
        session = self.get_session(session_id)

        # Check expiration
        if session.created_at < time.time() - self.session_timeout:
            raise SessionExpiredException()

        # Check attempts
        if session.attempts >= self.max_attempts:
            raise TooManyAttemptsException()

        # Check rate limit
        if not self.rate_limiter.allow(session.device_id):
            raise RateLimitedException()

        return True

Anti-Spoofing Measures

// Liveness detection during registration
const livenessChecks = {
  checkBloodFlow: async (palmImage) => {
    // Detect pulsatile blood flow
    const flowPattern = await analyzeBloodFlow(palmImage);
    return flowPattern.isLive;
  },

  checkTemperature: async (thermalData) => {
    // Verify body temperature range
    return thermalData.temp >= 32 && thermalData.temp <= 37;
  },

  check3DDepth: async (depthMap) => {
    // Verify 3D structure
    return depthMap.hasValidPalmStructure();
  }
};

Common Issues & Solutions

Problem: User took too long to complete registrationSolution:
// Restart registration with new session
const newSession = await startRegistration();
showMessage('Session expired. Starting fresh registration.');
Problem: PVS cannot capture clear palm imageSolutions:
  • Clean scanner surface
  • Improve lighting conditions
  • Remove jewelry from palm
  • Ensure hand is dry
Problem: User trying to register againSolution:
// Check if palm already registered
if (error.code === 'PALM_ALREADY_REGISTERED') {
  const choice = await showDialog(
    'This palm is already registered. Would you like to:',
    ['Login instead', 'Register other palm', 'Reset account']
  );
  handleUserChoice(choice);
}
Problem: Connection lost during registrationSolution:
// Implement retry with exponential backoff
async function retryRegistration(attempt = 1) {
  try {
    await completeRegistration();
  } catch (error) {
    if (attempt < 5) {
      await wait(Math.pow(2, attempt) * 1000);
      return retryRegistration(attempt + 1);
    }
    throw error;
  }
}

Post-Registration Setup

Setting Initial Attributes

// After successful registration
async function setupUserProfile(userId) {
  const attributes = {
    email: await promptEmail(),
    notifications: await promptNotificationPreferences(),
    language: navigator.language,
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
  };

  await setUserAttributes(userId, attributes);
}
// Initial consent setup
async function setupInitialConsent(userId) {
  const consents = [
    {
      type: 'terms_of_service',
      version: '1.0',
      accepted: true
    },
    {
      type: 'privacy_policy',
      version: '1.0',
      accepted: true
    },
    {
      type: 'biometric_storage',
      purpose: 'authentication',
      accepted: true
    }
  ];

  await recordConsent(userId, consents);
}

Testing Registration

Mock Registration for Development

# Using mock-user CLI
cargo run --bin mock-user -- \
  http://localhost:40401 \
  register "intent:///#Intent;session_id=test123;end"

# Using mock-pvs with seed for consistent results
cargo run --bin mock-pvs -- \
  --api-addr http://localhost:40401 \
  --seed "test-user-1" \
  register

Best Practices

For Users

  • Register both palms for backup
  • Use good lighting conditions
  • Keep contact info updated
  • Enable MFA for account recovery

For Developers

  • Validate all inputs
  • Implement proper error handling
  • Use secure session management
  • Log registration events

Next Steps