FrankieOne OneSDK
FrankieOne OneSDK - A comprehensive frontend SDK library for identity verification, onboarding, and document verification flows.
Version: 1.9.13
Node Version: >=18 (npm >=10)
Published as: @frankieone/one-sdk on NPM
---
- Overview
- Architecture
- Module Overview
- Vendor Integrations
- IDV (Identity Verification)
- OCR (Document Recognition)
- Biometrics
- Device Fingerprinting
- Federation
- Form
- Integration Method Reference
- Build & Development
- Deployment
---
This is a hybrid monorepo containing:
1. TypeScript/React Frontend SDK - The main OneSDK library with multiple vendor integrations
2. Go CLI Tool - Interactive CLI for generating OneSDK flows and local HTML preview
| Category | Technologies |
|----------|-------------|
| Frontend | React 18.2, Redux Toolkit 2.2.1, TypeScript 5.7, Webpack 5, Vite 7.2 |
| Styling | TailwindCSS 3.4, Sass, PostCSS |
| Testing | Jest 28, ts-jest |
| Reactive | RxJS 7.5, Zod 3.19 |
| CLI | Go 1.21.5, Charmbracelet (huh, lipgloss, bubbles) |
---
```
OneSDK (index.ts)
│
────┴────
│ │
SDK Common Utils
│ │
└── Modules
├── Individual (F2)
├── Business
├── Device (Sardine, ThreatMetrix)
├── IDV (Onfido, Sumsub, Incode, Daon, Mastercard, Truuth, OcrLabs, IDVerse)
├── OCR (Onfido, Sumsub, Incode, Daon, IDVerse)
├── Biometrics (Onfido, Sumsub, Incode, Daon, OcrLabs, IDVerse)
├── Form (Formio, React, Legacy)
├── Federation (Singpass)
├── Session
└── Frankie-Client (API)
---
| Module | Purpose | Vendors |
|--------|---------|---------|
| IDV | Full identity verification flow | Onfido, Sumsub, Incode, Daon, Mastercard, Truuth, OcrLabs, IDVerse |
| OCR | Document scanning & data extraction | Onfido, Sumsub, Incode, Daon, IDVerse |
| Biometrics | Face capture & liveness detection | Onfido, Sumsub, Incode, Daon, OcrLabs, IDVerse |
| Device | Device fingerprinting | Sardine, ThreatMetrix |
| Federation | Federated identity (OAuth) | Singpass |
| Form | Data entry & review forms | Formio, React, Legacy |
---
#### Onfido
| Aspect | Details | Modes:
|--------|---------|
| Integration Method | Native SDK loaded from CDN |
| SDK Source | https://sdk.onfido.com/v{version} |useOneStep: true
| UI Type | Vendor-provided UI with theme customization |
| Version Support | v14+ (modern) and
- OneStep Mode (): Combined document + face capture in single SDK instance
- Dual Component Mode: Separate OCR → Biometrics chain
Key Features:
- Theme support: 'light' or 'dark' with full customUI configuration
- Cross-device linking: QR code, copy link, SMS options
- Exit button support
- Analytics disabled by default
- Document type configuration: Passport, Drivers License, Medicare
Events Emitted:
- ready, loading, error, detection_complete, detection_failedresults
- , session_closed, session_interrupted, vendor_event
Files:
- modules/idv/vendors/Onfido/index.tsmodules/ocr/vendors/Onfido/
- (onfido.init.ts, onfidoLegacy.init.ts)modules/biometrics/vendors/Onfido/
- modules/common/vendors/onfido/
-
---
#### Sumsub
| Aspect | Details |
|--------|---------|
| Integration Method | SDK Library with iframe UI |
| SDK Source | https://static.sumsub.com/idensic/static/sns-websdk-builder.js |'idv'
| UI Type | Vendor-provided iframe |
| Products | , 'ocr', 'poa' |
Initialization Flow:
`javascript`
snsWebSdk.init(token, refreshTokenCallback)
.withConf({ theme: 'light' })
.withOptions({ addViewportTag: false, adaptIframeHeight: true })
.on('idCheck.onError', errorHandler)
.onMessage(messageHandler)
.build()
.launch(mountElement)
Message Types:
- idCheck.onReady - SDK loadingidCheck.onInitialized
- - UI readyidCheck.onApplicantStatusChanged
- - Review status changes (pending → completed)idCheck.onUploadError
- - Upload failures
Files:
- modules/idv/vendors/Sumsub/index.tsmodules/ocr/vendors/Sumsub/index.ts
- modules/biometrics/vendors/Sumsub/index.ts
- modules/common/vendors/sumsub/
-
---
#### Incode
| Aspect | Details |
|--------|---------|
| Integration Method | Native SDK + Camera (OCR/Biometrics) or Iframe (IDV) |
| SDK Source | https://sdk.incode.com/sdk/onBoarding-{version}.js |
| Default Version | 1.75.2 |
| UI Type | Custom camera UI with document selector |
Camera Types:
- 'front' - Document front side'back'
- - Document back side'selfie'
- - Face capture
Document Type Mapping:
`javascript`
Passport → 'PASSPORT'
DriversLicense → 'DRIVERS_LICENCE'
MedicalCard → 'NATIONAL_HEALTH_ID'
IDV Iframe Mode:
- PostMessage protocol with workflow messages
- Success: { workflow: 'INCODE_COMPLETE' }{ workflow: 'INCODE_ERROR' }
- Error: interviewId
- Session key:
Special Handling:
- Memory out of bounds error detection via console.error override
- Country/region document validation
- Consent reflow fix for iOS WebKit
Files:
- modules/idv/vendors/Incode/index.tsmodules/ocr/vendors/Incode/index.ts
- modules/biometrics/vendors/Incode/index.ts
- modules/common/vendors/incode/
-
---
#### Daon
| Aspect | Details |
|--------|---------|
| Integration Method | Iframe + PostMessage protocol |
| UI Type | Vendor-provided iframe |
| Modules | IDV, OCR, Biometrics |
Message Format:
`javascript
// Success
{ workflow: 'DAON_COMPLETE' }
// Error
{ workflow: 'DAON_ERROR' }
`
Post-Iframe Actions:
- IDV: initProcess (default)initProcessAndEvaluateResults
- OCR: initProcessBiometrics
- Biometrics: (with window event listener)
Check Processing Pool:
- Enabled by default for Daon
- wait_time: 5 secondsmax_attempts: 3
-
Files:
- modules/idv/vendors/Daon/index.tsmodules/ocr/vendors/Daon/index.ts
- modules/biometrics/vendors/Daon/index.ts
-
---
#### Mastercard
| Aspect | Details |
|--------|---------|
| Integration Method | Iframe + JSON PostMessage |
| UI Type | Vendor-provided iframe |
| Session Key | workflowExecutionId |
Message Format (Stringified JSON):
`javascript
// Loaded
{ "payload": { "value": "loaded" } }
// Success
{ "payload": { "value": "success" }, "workflowExecutionId": "..." }
// Error
{ "payload": { "value": "error", "metainfo": { "msg": "..." } } }
`
Key Difference: Mastercard emits its own 'loaded' message (emitOnLoad: false)
Files:
- modules/idv/vendors/Mastercard/index.ts
---
#### Truuth
| Aspect | Details |
|--------|---------|
| Integration Method | Web Component SDK (NOT iframe) |
| SDK Source | https://cdn.truuth.id/kyc/websdk/{version}/truuth-kyc-websdk.js |
| UI Type | custom element |
Event Handling:
`javascript`
window.addEventListener('forwardedTruuthEventForOneSDK', eventListener)
Event Types:
- VERIFICATION_PROCESSING_STARTED → loading + detection_complete + pollingVERIFICATION_COMPLETED
- → initProcess + resultsTERMS_AND_CONDITION_DECLINED
- → input_requiredVERIFICATION_SUBMISSION_ABORTED
- → input_requiredVERIFICATION_PROCESSING_TIMEOUT
- → errorERROR
- → detection_failed + error
Files:
- modules/idv/vendors/Truuth/index.ts
---
#### OcrLabs
| Aspect | Details |
|--------|---------|
| IDV Integration | Server-side action workflow with persistent storage |
| Biometrics Integration | WebSocket + WebRTC (liveness detection) |
| WebSocket URL | wss://engine.au.v3.liveness.idkit.io |
IDV Flow:
1. Check StorageClient for stored action details
2. Workflow states: IDV_SUCCESS or IDV_ERROR
3. Redirect to OcrLabs or start dummy flow
Biometrics Liveness Detection:
``
Face Detection → "Position your face within the frame"
↓
Smile Detection → "Please give us a BIG Smile!"
↓
detection_complete → initProcess
UI Elements Created:
- onesdk_idv_container - Main containeronesdk_idv_video
- - Live video feed (mirrored)onesdk_idv_overlay
- - Overlay containeronesdk_idv_mask
- - Oval face frame with shadowonesdk_idv_instructions
- - Dynamic instructions
Detection Timeout: 7.5 seconds per action
Files:
- modules/idv/vendors/OcrLabs/modules/biometrics/vendors/OcrLabs/
-
---
#### IDVerse
| Aspect | Details |
|--------|---------|
| Integration Method | Web Component + Web Worker |
| SDK Source | ESM module from CDN |
| UI Type | custom element |build_01K7RRTN6RTH4S3MGHEBDDJ3FV
| Build ID | |
Recognizer Types:
- 'id-scan' - Document scanning with front/back capture'face-scan'
- - Biometric face capture with liveness
Web Worker:
- Cross-origin blob worker for image processing
- Created via URL.createObjectURL(blob)
- Manually terminated on SDK destroy
Event Types:
- authenticated - SDK initializedready
- - Web component readyscanSuccess
- - Scan completed successfullyscanFail
- - Scan failed (with error codes)validDocumentConfirmed
- - User confirmed documentfatalError
- - Unrecoverable errorfaceScanClosed
- - Face scan modal closed
Retry Logic:
- Default max retries: 3 (configurable via recipe)
- scanFail increments counter
- SDK destroyed when max retries exceeded
Asset Bundle (~2.2 MB):
- Main bundle: 935 KB
- CSS: 113 KB
- Lottie animations: 700+ KB (20 animations)
- Audio feedback: 75+ KB
- WorkSans font: 354 KB
Files:
- modules/common/vendors/idverse/index.tsmodules/ocr/vendors/IDVerse/index.ts
- modules/biometrics/vendors/IDVerse/index.ts
-
---
OCR vendors share implementations with IDV where applicable. Key differences:
| Vendor | Post-Process Action | Review Screen |
|--------|---------------------|---------------|
| Onfido | initProcessAndEvaluateResults | Feature flag controlled |initProcess
| Sumsub | (product='ocr') | Built-in |initProcessAndEvaluateResults
| Incode | Native camera capture | Validation callback |
| Daon | | Optional form attachment |initProcessAndEvaluateResults
| IDVerse | | Feature flag controlled |
---
| Vendor | Capture Method | Liveness Detection |
|--------|----------------|-------------------|
| Onfido | SDK face step | Motion, video, or standard variants |
| Sumsub | SDK (product='idv') | Built-in |
| Incode | Native camera selfie | SDK-managed |
| Daon | Iframe with window events | Vendor-managed |
| OcrLabs | WebRTC + WebSocket | Face + Smile detection |
| IDVerse | Web Component face-scan | DFA + face matching |
---
#### Sardine
| Aspect | Details |
|--------|---------|
| Integration Method | Remote SDK with context-based configuration |
| SDK Source | https://api.{domain}.sardine.ai/assets/loader.min.js |api.sardine.ai
| Environments | (production), api.sandbox.sardine.ai (sandbox) |
Configuration:
`javascript`
window._Sardine.createContext({
clientId,
sessionKey,
environment: 'production' | 'sandbox',
parentElement: document.body,
flow: activityType,
onDeviceResponse: (data) => { / fingerprint data / }
})
Activity Types:
- REGISTRATION → mapped to SIGNUPLOGIN
- , CRYPTO_DEPOSIT, CRYPTO_WITHDRAWAL, FIAT_DEPOSIT, FIAT_WITHDRAWAL
Events:
- session_data_generateddevice_characteristics_extracted
- value_set
-
Files:
- modules/device/vendors/Sardine.ts
---
#### ThreatMetrix
| Aspect | Details |
|--------|---------|
| Integration Method | Obfuscated SDK (intentionally hidden) |
| SDK Source | Inline vendor file nolint_fp-clientlib-v4.js |h.online-metrix.net
| Domain | |
Initialization:
`javascript`
threatmetrixSdk.profile('h.online-metrix.net', clientID, vendorSessionID)
Technical Details:
- Uses RTCPeerConnection with TURN servers for data collection
- ClientID must be exactly 8 characters
- CSP nonce handling for Content Security Policy compliance
Files:
- modules/device/vendors/Threatmetrix/index.tsmodules/device/vendors/Threatmetrix/nolint_fp-clientlib-v4.js
-
---
#### Singpass (MyInfo)
| Aspect | Details |
|--------|---------|
| Integration Method | OAuth 2.0 Authorization Code Flow |
| Protocol | Browser redirect to Singpass, then code exchange |
Environment URLs:
``
Sandbox: https://sandbox.api.myinfo.gov.sg/com/v3/authorise
Test: https://test.api.myinfo.gov.sg/com/v3/authorise
Production: https://api.myinfo.gov.sg/com/v3/authorise
OAuth Flow:
1. Build authorization URL with client_id, attributes, state, redirect_uri, purposecode
2. Redirect to Singpass
3. User authenticates and consents
4. Redirect back with and stateFederationClient.provideAuthorisation()
5. Validate state (CSRF protection)
6. Submit code to backend via FederationClient.submitCachedData()
7. Receive user data
8. User approves →
Events:
- results - User data with approve callbackdata_extracted_successfully
- - After approvalerror
- - On failures
Validation:
- State parameter must match session ID
- Production redirect_uri must use HTTPS
- No preloaded entities allowed
Files:
- modules/federation/vendors/Singpass.ts
---
#### Form Vendors Overview
| Vendor | Technology | Use Case |
|--------|------------|----------|
| Formio | Form.io SDK | Cloud-based form builder |
| React | Custom React components | Modern, flexible forms |
| Legacy | Legacy UI widgets | Backward compatibility |
---
#### Formio
| Aspect | Details |
|--------|---------|
| SDK Source | https://cdn.form.io/formiojs/formio.full.js |
| CSS Dependencies | Bootstrap 4.6.1, Formio CSS, FontAwesome 4.7 |
Wrapping Modes (feature flag controlled):
- Shadow DOM ('shadow'): Isolated styles via attachShadow({ mode: 'open' })'iframe'
- Iframe (): Complete DOM/CSS isolation'div'
- Div (): Direct DOM insertion (default)
Data Transformation:
``
Individual Data ←→ Formio Schema
│ │
name, DOB basicPiiForm
addresses addressComponentForm
documents documents[]
Document Type Mapping:
- PASSPORT → pass_idNumber, pass_idExpiryDRIVERS_LICENCE
- → dl_region, dl_idNumber, dl_cardNumberNATIONAL_HEALTH_ID
- → medi_idNumber, medi_cardPosition, medi_cardColour, medi_idExpiry
Files:
- modules/form/vendors/formio/
---
#### React Form
| Aspect | Details |
|--------|---------|
| Framework | React 18 + Redux Toolkit + React Hook Form |
| Components | 60+ form components |
| Screens | Welcome, Consent, IdSelection, IdDetails, PersonalDetails, Review, DocumentUpload, Result |
Key Hooks:
- useEventContext - Event hub context provideruseConfigFactory
- - Configuration merginguseFormMapper
- - Field component mappinguseAddressSearch
- - Google Maps autocomplete integration
Field Configuration by Document Type:
Australian Drivers Licence (by state):
| State | License Pattern | Card Pattern |
|-------|-----------------|--------------|
| NSW | 6-8 alphanumeric | 10 numeric |
| VIC | 1-10 numeric | 8 alphanumeric |
| QLD | 8-9 alphanumeric | 10 alphanumeric |
| SA | 6 alphanumeric | 9 alphanumeric |
| WA | 7 numeric | 8-10 alphanumeric |
Validation Rules:
`javascript`
ValidationRulesForForm = {
onlyAlphabets: /^[a-zA-Z]+(\s+[a-zA-Z]+)*$/,
onlyNumbers: /^[0-9]+$/,
alphaNumeric: /^[a-zA-Z0-9]+$/,
emailPattern: /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/
}
Screen Events:
- form:{screenId}:ready - Screen mountedform:{screenId}:loaded
- - Screen loadedform:{screenId}:failed
- - Screen errorform:{screenId}:success
- - Screen completed
Files:
- modules/form/vendors/react/
---
| Method | Vendors | Characteristics |
|--------|---------|-----------------|
| Native SDK | Onfido, Incode | Full control, version management, CDN loading |
| Iframe + PostMessage | Daon, Mastercard, Incode (IDV) | Sandboxed, vendor-managed UI |
| Web Component | IDVerse, Truuth | Custom elements, event-based |
| WebSocket + WebRTC | OcrLabs | Real-time liveness, canvas/video rendering |
| OAuth 2.0 | Singpass | Server-side, browser redirect flow |
| Remote SDK | Sardine, Sumsub | Dynamically loaded from vendor CDN |
| Obfuscated SDK | ThreatMetrix | Inline vendor code, hidden implementation |
| Form Builder | Formio | Cloud service SDK with schema |
| React Components | React Form | Custom component library |
---
`bashDevelopment
npm run dev:cli # Go CLI development mode
$3
| Output | Location | Description |
|--------|----------|-------------|
| UMD |
dist/umd/oneSdk.umd.js | Browser global bundle |
| ESM | dist/esm/modules/index.js | ES Module with types |
| CSS | dist/esm/styles/f1-style.css | TailwindCSS output |
| CLI | dist/cli/{platform}/ | Platform-specific Go binaries |$3
-
darwin-amd64 (macOS Intel)
- darwin-arm64 (macOS Apple Silicon)
- linux-amd64
- linux-arm64
- windows-amd64---
Deployment
Deployments are managed via GitHub Actions using reusable workflows.
$3
-
publish_npm.yml - NPM publication
- feature_pr.yml - Feature branch CI
- develop.yml - Development branch
- main.yml - Main branch deployment
- rollback.yml` - Deployment rollbackFor detailed deployment instructions, see:
- Reusable CICD Github Actions Workflows
- Rollback Frontend Deployment
---
Proprietary - FrankieOne