@glideidentity/web-client-sdk 5.1.2 → 6.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/README.md +337 -526
  2. package/dist/browser/web-client-sdk.min.js +1 -1
  3. package/dist/cjs/adapters/index.js +15 -0
  4. package/dist/cjs/adapters/react.js +192 -0
  5. package/dist/cjs/adapters/vanilla.js +38 -0
  6. package/dist/cjs/adapters/vue.js +187 -0
  7. package/dist/cjs/browser.js +58 -0
  8. package/dist/cjs/client/http.js +159 -0
  9. package/dist/cjs/client/index.js +19 -0
  10. package/dist/cjs/client/logger.js +135 -0
  11. package/dist/cjs/client/phone-auth-client.js +439 -0
  12. package/dist/cjs/client/strategies/polling.js +177 -0
  13. package/dist/cjs/core/errors.js +204 -0
  14. package/dist/cjs/core/index.js +83 -0
  15. package/dist/cjs/core/type-guards.js +196 -0
  16. package/dist/cjs/core/types.js +25 -0
  17. package/dist/{core/phone-auth/validation-utils.js → cjs/core/validators.js} +70 -23
  18. package/dist/cjs/index.js +81 -0
  19. package/dist/cjs/ui/index.js +11 -0
  20. package/dist/{core/phone-auth → cjs}/ui/mobile-debug-console.js +149 -78
  21. package/dist/cjs/ui/modal.js +1122 -0
  22. package/dist/esm/adapters/index.js +11 -0
  23. package/dist/esm/adapters/react.js +182 -0
  24. package/dist/esm/adapters/vanilla.js +29 -0
  25. package/dist/esm/adapters/vue.js +177 -0
  26. package/dist/esm/browser.js +30 -11
  27. package/dist/esm/client/http.js +156 -0
  28. package/dist/esm/client/index.js +11 -0
  29. package/dist/esm/client/logger.js +131 -0
  30. package/dist/esm/client/phone-auth-client.js +435 -0
  31. package/dist/esm/client/strategies/polling.js +174 -0
  32. package/dist/esm/core/errors.js +193 -0
  33. package/dist/esm/core/index.js +60 -0
  34. package/dist/esm/core/type-guards.js +181 -0
  35. package/dist/esm/core/types.js +22 -1
  36. package/dist/esm/core/{phone-auth/validation-utils.js → validators.js} +66 -21
  37. package/dist/esm/index.js +45 -17
  38. package/dist/esm/ui/index.js +5 -0
  39. package/dist/esm/{core/phone-auth/ui → ui}/mobile-debug-console.js +149 -78
  40. package/dist/esm/ui/modal.js +1117 -0
  41. package/dist/types/adapters/index.d.ts +10 -0
  42. package/dist/types/adapters/index.d.ts.map +1 -0
  43. package/dist/types/adapters/react.d.ts +70 -0
  44. package/dist/types/adapters/react.d.ts.map +1 -0
  45. package/dist/types/adapters/vanilla.d.ts +29 -0
  46. package/dist/types/adapters/vanilla.d.ts.map +1 -0
  47. package/dist/types/adapters/vue.d.ts +71 -0
  48. package/dist/types/adapters/vue.d.ts.map +1 -0
  49. package/dist/types/browser.d.ts +27 -0
  50. package/dist/types/browser.d.ts.map +1 -0
  51. package/dist/types/client/http.d.ts +41 -0
  52. package/dist/types/client/http.d.ts.map +1 -0
  53. package/dist/types/client/index.d.ts +10 -0
  54. package/dist/types/client/index.d.ts.map +1 -0
  55. package/dist/types/client/logger.d.ts +36 -0
  56. package/dist/types/client/logger.d.ts.map +1 -0
  57. package/dist/types/client/phone-auth-client.d.ts +91 -0
  58. package/dist/types/client/phone-auth-client.d.ts.map +1 -0
  59. package/dist/types/client/strategies/polling.d.ts +36 -0
  60. package/dist/types/client/strategies/polling.d.ts.map +1 -0
  61. package/dist/types/core/errors.d.ts +71 -0
  62. package/dist/types/core/errors.d.ts.map +1 -0
  63. package/dist/types/core/index.d.ts +38 -0
  64. package/dist/types/core/index.d.ts.map +1 -0
  65. package/dist/types/core/type-guards.d.ts +118 -0
  66. package/dist/types/core/type-guards.d.ts.map +1 -0
  67. package/dist/types/core/types.d.ts +534 -0
  68. package/dist/types/core/types.d.ts.map +1 -0
  69. package/dist/types/core/validators.d.ts +63 -0
  70. package/dist/types/core/validators.d.ts.map +1 -0
  71. package/dist/types/index.d.ts +40 -0
  72. package/dist/types/index.d.ts.map +1 -0
  73. package/dist/types/ui/index.d.ts +6 -0
  74. package/dist/types/ui/index.d.ts.map +1 -0
  75. package/dist/{esm/core/phone-auth → types}/ui/mobile-debug-console.d.ts +1 -0
  76. package/dist/types/ui/mobile-debug-console.d.ts.map +1 -0
  77. package/dist/types/ui/modal.d.ts +87 -0
  78. package/dist/types/ui/modal.d.ts.map +1 -0
  79. package/package.json +48 -34
  80. package/dist/adapters/angular/client.service.d.ts +0 -7
  81. package/dist/adapters/angular/client.service.js +0 -30
  82. package/dist/adapters/angular/index.d.ts +0 -3
  83. package/dist/adapters/angular/index.js +0 -18
  84. package/dist/adapters/angular/phone-auth.service.d.ts +0 -38
  85. package/dist/adapters/angular/phone-auth.service.js +0 -130
  86. package/dist/adapters/react/index.d.ts +0 -9
  87. package/dist/adapters/react/index.js +0 -28
  88. package/dist/adapters/react/useClient.d.ts +0 -26
  89. package/dist/adapters/react/useClient.js +0 -121
  90. package/dist/adapters/react/usePhoneAuth.d.ts +0 -23
  91. package/dist/adapters/react/usePhoneAuth.js +0 -95
  92. package/dist/adapters/vanilla/client.d.ts +0 -8
  93. package/dist/adapters/vanilla/client.js +0 -33
  94. package/dist/adapters/vanilla/index.d.ts +0 -3
  95. package/dist/adapters/vanilla/index.js +0 -18
  96. package/dist/adapters/vanilla/phone-auth.d.ts +0 -46
  97. package/dist/adapters/vanilla/phone-auth.js +0 -138
  98. package/dist/adapters/vue/index.d.ts +0 -10
  99. package/dist/adapters/vue/index.js +0 -36
  100. package/dist/adapters/vue/useClient.d.ts +0 -115
  101. package/dist/adapters/vue/useClient.js +0 -131
  102. package/dist/adapters/vue/usePhoneAuth.d.ts +0 -94
  103. package/dist/adapters/vue/usePhoneAuth.js +0 -103
  104. package/dist/browser.d.ts +0 -7
  105. package/dist/browser.js +0 -31
  106. package/dist/core/client.d.ts +0 -22
  107. package/dist/core/client.js +0 -77
  108. package/dist/core/logger.d.ts +0 -130
  109. package/dist/core/logger.js +0 -370
  110. package/dist/core/phone-auth/api-types.d.ts +0 -593
  111. package/dist/core/phone-auth/api-types.js +0 -215
  112. package/dist/core/phone-auth/client.d.ts +0 -189
  113. package/dist/core/phone-auth/client.js +0 -1441
  114. package/dist/core/phone-auth/error-utils.d.ts +0 -110
  115. package/dist/core/phone-auth/error-utils.js +0 -350
  116. package/dist/core/phone-auth/index.d.ts +0 -7
  117. package/dist/core/phone-auth/index.js +0 -50
  118. package/dist/core/phone-auth/status-types.d.ts +0 -107
  119. package/dist/core/phone-auth/status-types.js +0 -31
  120. package/dist/core/phone-auth/strategies/desktop.d.ts +0 -122
  121. package/dist/core/phone-auth/strategies/desktop.js +0 -596
  122. package/dist/core/phone-auth/strategies/index.d.ts +0 -11
  123. package/dist/core/phone-auth/strategies/index.js +0 -15
  124. package/dist/core/phone-auth/strategies/link.d.ts +0 -89
  125. package/dist/core/phone-auth/strategies/link.js +0 -384
  126. package/dist/core/phone-auth/strategies/ts43.d.ts +0 -32
  127. package/dist/core/phone-auth/strategies/ts43.js +0 -151
  128. package/dist/core/phone-auth/strategies/types.d.ts +0 -18
  129. package/dist/core/phone-auth/strategies/types.js +0 -6
  130. package/dist/core/phone-auth/type-guards.d.ts +0 -143
  131. package/dist/core/phone-auth/type-guards.js +0 -198
  132. package/dist/core/phone-auth/types.d.ts +0 -237
  133. package/dist/core/phone-auth/types.js +0 -93
  134. package/dist/core/phone-auth/ui/mobile-debug-console.d.ts +0 -25
  135. package/dist/core/phone-auth/ui/modal.d.ts +0 -88
  136. package/dist/core/phone-auth/ui/modal.js +0 -598
  137. package/dist/core/phone-auth/validation-utils.d.ts +0 -44
  138. package/dist/core/types.d.ts +0 -62
  139. package/dist/core/types.js +0 -2
  140. package/dist/core/version.d.ts +0 -1
  141. package/dist/core/version.js +0 -5
  142. package/dist/esm/adapters/angular/client.service.d.ts +0 -7
  143. package/dist/esm/adapters/angular/client.service.js +0 -27
  144. package/dist/esm/adapters/angular/index.d.ts +0 -3
  145. package/dist/esm/adapters/angular/index.js +0 -4
  146. package/dist/esm/adapters/angular/phone-auth.service.d.ts +0 -38
  147. package/dist/esm/adapters/angular/phone-auth.service.js +0 -127
  148. package/dist/esm/adapters/react/index.d.ts +0 -9
  149. package/dist/esm/adapters/react/index.js +0 -8
  150. package/dist/esm/adapters/react/useClient.d.ts +0 -26
  151. package/dist/esm/adapters/react/useClient.js +0 -116
  152. package/dist/esm/adapters/react/usePhoneAuth.d.ts +0 -23
  153. package/dist/esm/adapters/react/usePhoneAuth.js +0 -92
  154. package/dist/esm/adapters/vanilla/client.d.ts +0 -8
  155. package/dist/esm/adapters/vanilla/client.js +0 -29
  156. package/dist/esm/adapters/vanilla/index.d.ts +0 -3
  157. package/dist/esm/adapters/vanilla/index.js +0 -4
  158. package/dist/esm/adapters/vanilla/phone-auth.d.ts +0 -46
  159. package/dist/esm/adapters/vanilla/phone-auth.js +0 -134
  160. package/dist/esm/adapters/vue/index.d.ts +0 -10
  161. package/dist/esm/adapters/vue/index.js +0 -11
  162. package/dist/esm/adapters/vue/useClient.d.ts +0 -115
  163. package/dist/esm/adapters/vue/useClient.js +0 -127
  164. package/dist/esm/adapters/vue/usePhoneAuth.d.ts +0 -94
  165. package/dist/esm/adapters/vue/usePhoneAuth.js +0 -100
  166. package/dist/esm/browser.d.ts +0 -7
  167. package/dist/esm/core/client.d.ts +0 -22
  168. package/dist/esm/core/client.js +0 -70
  169. package/dist/esm/core/logger.d.ts +0 -130
  170. package/dist/esm/core/logger.js +0 -359
  171. package/dist/esm/core/phone-auth/api-types.d.ts +0 -593
  172. package/dist/esm/core/phone-auth/api-types.js +0 -203
  173. package/dist/esm/core/phone-auth/client.d.ts +0 -189
  174. package/dist/esm/core/phone-auth/client.js +0 -1404
  175. package/dist/esm/core/phone-auth/error-utils.d.ts +0 -110
  176. package/dist/esm/core/phone-auth/error-utils.js +0 -338
  177. package/dist/esm/core/phone-auth/index.d.ts +0 -7
  178. package/dist/esm/core/phone-auth/index.js +0 -8
  179. package/dist/esm/core/phone-auth/status-types.d.ts +0 -107
  180. package/dist/esm/core/phone-auth/status-types.js +0 -26
  181. package/dist/esm/core/phone-auth/strategies/desktop.d.ts +0 -122
  182. package/dist/esm/core/phone-auth/strategies/desktop.js +0 -590
  183. package/dist/esm/core/phone-auth/strategies/index.d.ts +0 -11
  184. package/dist/esm/core/phone-auth/strategies/index.js +0 -7
  185. package/dist/esm/core/phone-auth/strategies/link.d.ts +0 -89
  186. package/dist/esm/core/phone-auth/strategies/link.js +0 -380
  187. package/dist/esm/core/phone-auth/strategies/ts43.d.ts +0 -32
  188. package/dist/esm/core/phone-auth/strategies/ts43.js +0 -147
  189. package/dist/esm/core/phone-auth/strategies/types.d.ts +0 -18
  190. package/dist/esm/core/phone-auth/strategies/types.js +0 -5
  191. package/dist/esm/core/phone-auth/type-guards.d.ts +0 -143
  192. package/dist/esm/core/phone-auth/type-guards.js +0 -185
  193. package/dist/esm/core/phone-auth/types.d.ts +0 -237
  194. package/dist/esm/core/phone-auth/types.js +0 -76
  195. package/dist/esm/core/phone-auth/ui/modal.d.ts +0 -88
  196. package/dist/esm/core/phone-auth/ui/modal.js +0 -594
  197. package/dist/esm/core/phone-auth/validation-utils.d.ts +0 -44
  198. package/dist/esm/core/types.d.ts +0 -62
  199. package/dist/esm/core/version.d.ts +0 -1
  200. package/dist/esm/core/version.js +0 -2
  201. package/dist/esm/index.d.ts +0 -12
  202. package/dist/index.d.ts +0 -12
  203. package/dist/index.js +0 -55
package/README.md CHANGED
@@ -1,43 +1,16 @@
1
1
  # Glide Web Client SDK
2
2
 
3
- The official web SDK for integrating Glide's carrier-grade phone verification into your web applications. Supports React, Vue, Angular, and vanilla JavaScript/TypeScript.
3
+ The official web SDK for integrating Glide's carrier-grade phone verification into your web applications.
4
4
 
5
5
  ## Features
6
6
 
7
- - 🚀 **Instant Verification**: Direct carrier verification without SMS
8
- - 🔐 **Fraud Resistant**: Can't be intercepted or spoofed like SMS codes
9
- - **Real-time Progress**: Track verification steps with detailed state management
10
- - 📱 **Multi-Strategy Support**: Desktop QR code, mobile App Clips, and Android deep links
11
- - 🎯 **Extended Mode**: Granular control over authentication flow
12
- - 🔄 **Unified API**: Consistent interface for all authentication strategies
13
- - 🌐 **Framework Support**: React, Vue 3, Angular, and vanilla JS/TS
14
- - 🛡️ **Type Safe**: Full TypeScript support with type guards and IntelliSense
15
- - 🎯 **Developer Friendly**: Clear error messages and browser compatibility checks
16
-
17
- ## What's New in v4.4
18
-
19
- ### 🎉 Enhanced Control & Better DX
20
- - **Extended Mode**: More control with `executionMode: 'extended'` for granular authentication flow
21
- - **Prevent Default UI**: Use `preventDefaultUI: true` to disable all SDK modals
22
- - **Type Guards**: Helper functions for type-safe result handling
23
- - **Unified Trigger Pattern**: Consistent `trigger()` function for all strategies
24
- - **Auto-Trigger Support**: Automatic App Clip opening with retry capability
25
- - **TypeScript Enhancements**: Full IntelliSense and type safety
26
- - **Faster Timeout**: Polling timeout reduced to 1 minute for better UX
27
- - **Dual-Platform QR**: Support for iOS and Android specific QR codes
28
-
29
- ## Table of Contents
30
-
31
- - [Installation](#installation)
32
- - [Development](#development)
33
- - [Quick Start](#quick-start)
34
- - [Extended Mode - Advanced Control](#extended-mode---advanced-control)
35
- - [Authentication Strategies](#authentication-strategies)
36
- - [Framework Examples](#framework-examples)
37
- - [Error Handling](#error-handling)
38
- - [Browser Support](#browser-support)
39
- - [API Reference](#api-reference)
40
- - [Documentation](#documentation)
7
+ - 🚀 **Instant Verification** - Direct carrier verification without SMS delays
8
+ - 🔐 **Fraud Resistant** - Can't be intercepted or spoofed like SMS codes
9
+ - 📱 **Multi-Platform** - Desktop QR codes, iOS App Clips, Android deep links
10
+ - 🎨 **Customizable UI** - Built-in modal with themes and view modes
11
+ - 🔧 **Flexible Architecture** - Use the full SDK or just the core types
12
+ - 🌐 **Framework Support** - React, Vue, Angular, and vanilla JavaScript
13
+ - 📦 **Tree-Shakeable** - Import only what you need
41
14
 
42
15
  ## Installation
43
16
 
@@ -45,617 +18,455 @@ The official web SDK for integrating Glide's carrier-grade phone verification in
45
18
  npm install @glideidentity/web-client-sdk
46
19
  ```
47
20
 
48
- ## Development
49
-
50
- ### Using Docker (Recommended)
21
+ ## Quick Start
51
22
 
52
- ```bash
53
- # Build the SDK
54
- docker compose run --rm build
23
+ ### High-Level API (Recommended)
55
24
 
56
- # Run tests
57
- docker compose run --rm test
25
+ The simplest way to integrate phone verification:
58
26
 
59
- # Interactive development shell
60
- docker compose run --rm dev
61
- ```
62
-
63
- ### Without Docker
27
+ ```javascript
28
+ import { PhoneAuthClient, USE_CASE } from '@glideidentity/web-client-sdk';
64
29
 
65
- ```bash
66
- # Install dependencies
67
- npm install
30
+ const client = new PhoneAuthClient({
31
+ endpoints: {
32
+ prepare: '/api/phone-auth/prepare',
33
+ process: '/api/phone-auth/process',
34
+ }
35
+ });
68
36
 
69
- # Build the SDK
70
- npm run build
37
+ // Get a phone number
38
+ const result = await client.authenticate({
39
+ use_case: USE_CASE.GET_PHONE_NUMBER
40
+ });
41
+ console.log('Phone:', result.phone_number);
71
42
 
72
- # Run tests
73
- npm test
43
+ // Or verify a specific number
44
+ const verified = await client.authenticate({
45
+ use_case: USE_CASE.VERIFY_PHONE_NUMBER,
46
+ phone_number: '+14155551234'
47
+ });
48
+ console.log('Verified:', verified.verified);
74
49
  ```
75
50
 
76
- ## Quick Start
51
+ ### Granular API
77
52
 
78
- ### React Example
53
+ For more control over the authentication flow:
79
54
 
80
- ```jsx
81
- import React, { useState } from 'react';
82
- import { PhoneAuthClient } from '@glideidentity/web-client-sdk';
55
+ ```javascript
56
+ import { PhoneAuthClient, USE_CASE } from '@glideidentity/web-client-sdk';
83
57
 
84
- function PhoneVerification() {
85
- const [phoneAuth] = useState(() => new PhoneAuthClient({
86
- pollingInterval: 2000,
87
- maxPollingAttempts: 30,
88
- debug: false
89
- }));
58
+ const client = new PhoneAuthClient({
59
+ endpoints: {
60
+ prepare: '/api/phone-auth/prepare',
61
+ process: '/api/phone-auth/process',
62
+ }
63
+ });
90
64
 
91
- const handleGetPhoneNumber = async () => {
92
- try {
93
- // Prepare the request
94
- const prepareResult = await phoneAuth.preparePhoneRequest({
95
- use_case: 'GetPhoneNumber'
96
- });
97
-
98
- // Invoke authentication (SDK handles UI by default)
99
- const credential = await phoneAuth.invokeSecurePrompt(prepareResult);
100
-
101
- // Process the credential
102
- const result = await phoneAuth.getPhoneNumber(
103
- credential,
104
- prepareResult.session
105
- );
106
-
107
- console.log('Phone number:', result.phone_number);
108
- } catch (error) {
109
- console.error('Verification failed:', error);
110
- }
111
- };
65
+ // Step 1: Prepare the request
66
+ const prepared = await client.prepare({
67
+ use_case: USE_CASE.VERIFY_PHONE_NUMBER,
68
+ phone_number: '+14155551234'
69
+ });
112
70
 
113
- const handleVerifyPhoneNumber = async () => {
114
- try {
115
- // Prepare with phone number
116
- const prepareResult = await phoneAuth.preparePhoneRequest({
117
- use_case: 'VerifyPhoneNumber',
118
- phone_number: '+14155551234'
119
- });
120
-
121
- // Invoke authentication
122
- const credential = await phoneAuth.invokeSecurePrompt(prepareResult);
123
-
124
- // Verify the number
125
- const result = await phoneAuth.verifyPhoneNumber(
126
- credential,
127
- prepareResult.session
128
- );
129
-
130
- console.log('Verified:', result.verified);
131
- } catch (error) {
132
- console.error('Verification failed:', error);
133
- }
134
- };
71
+ // Step 2: Invoke authentication (shows UI based on strategy)
72
+ const invokeResult = await client.invokeSecurePrompt(prepared);
73
+ const credential = await invokeResult.credential;
135
74
 
136
- return (
137
- <div>
138
- <button onClick={handleGetPhoneNumber}>
139
- Get Phone Number
140
- </button>
141
- <button onClick={handleVerifyPhoneNumber}>
142
- Verify Phone Number
143
- </button>
144
- </div>
145
- );
146
- }
147
- ```
75
+ // Step 3: Process the credential
76
+ const result = await client.verifyPhoneNumber(credential, invokeResult.session);
148
77
 
149
- ## Extended Mode - Advanced Control
78
+ console.log('Verified:', result.verified);
79
+ ```
150
80
 
151
- The SDK supports an **Extended Mode** that provides granular control over the authentication flow. This mode returns an `ExtendedResponse` object with additional methods and data for custom implementations.
81
+ ## Configuration
152
82
 
153
- ### When to Use Extended Mode
83
+ ### Client Options
154
84
 
155
- | Use Case | Standard Mode | Extended Mode |
156
- |----------|--------------|---------------|
157
- | Simple verification | ✓ Best choice | Use if needed |
158
- | Custom retry logic | Limited | ✓ Full control |
159
- | Progressive UI updates | No | ✓ Real-time status |
160
- | Custom polling control | No | ✓ Start/stop control |
161
- | Multiple auth attempts | Manual | ✓ Built-in retry |
85
+ ```typescript
86
+ const client = new PhoneAuthClient({
87
+ // Required: Your backend endpoints
88
+ endpoints: {
89
+ prepare: '/api/phone-auth/prepare', // Prepare request endpoint
90
+ process: '/api/phone-auth/process', // Process credential endpoint
91
+ polling: '/api/phone-auth/status', // Optional: Status polling endpoint
92
+ },
93
+
94
+ // Polling configuration
95
+ pollingInterval: 2000, // Polling interval in ms (default: 2000)
96
+ maxPollingAttempts: 30, // Max attempts before timeout (default: 30)
97
+ timeout: 30000, // API request timeout in ms (default: 30000)
98
+
99
+ // Debug options
100
+ debug: false, // Enable console logging (default: false)
101
+ devtools: {
102
+ showMobileConsole: false // Show on-screen console on mobile (default: false)
103
+ }
104
+ });
105
+ ```
162
106
 
163
- ### Extended Mode Example
107
+ ### Invoke Options
164
108
 
165
- ```javascript
166
- // Enable extended mode for granular control
167
- const result = await phoneAuth.invokeSecurePrompt(prepareResult, {
168
- executionMode: 'extended',
169
- preventDefaultUI: true // Optional: disable all SDK UI
170
- });
109
+ Customize the authentication UI and behavior:
171
110
 
172
- // Extended response provides more control
173
- if (result.strategy === 'desktop') {
174
- // Custom QR display
175
- displayQR(result.qr_code_data.ios_qr_image);
176
-
177
- // Start polling when ready (only if preventDefaultUI was true)
178
- if (result.start_polling) {
179
- const credential = await result.start_polling();
180
- }
181
-
182
- // Or wait for credential
183
- const credential = await result.credential;
111
+ ```typescript
112
+ const result = await client.invokeSecurePrompt(prepared, {
113
+ // Prevent SDK from showing any UI (use your own)
114
+ preventDefaultUI: false,
184
115
 
185
- // Cancel if needed
186
- result.cancel();
187
- }
188
-
189
- if (result.strategy === 'link') {
190
- // Re-trigger app opening
191
- result.trigger();
116
+ // Polling configuration (overrides client config)
117
+ pollingInterval: 2000,
118
+ maxPollingAttempts: 30,
192
119
 
193
- // Check polling status
194
- if (result.is_polling) {
195
- console.log('Currently polling...');
120
+ // Modal customization (for desktop QR strategy)
121
+ modalOptions: {
122
+ theme: 'auto', // 'dark' | 'light' | 'auto'
123
+ viewMode: 'toggle', // 'toggle' | 'dual' | 'pre-step'
124
+ title: 'Scan to Verify', // Custom title text
125
+ description: '', // Optional subtitle
126
+ showCloseButton: true, // Show X button
127
+ closeOnBackdropClick: true, // Close on outside click
128
+ closeOnEscape: true, // Close on Escape key
196
129
  }
197
-
198
- // Wait for completion
199
- const credential = await result.credential;
200
- }
201
-
202
- if (result.strategy === 'ts43') {
203
- // Trigger when user is ready
204
- await result.trigger();
205
-
206
- // Get credential
207
- const credential = await result.credential;
208
- }
130
+ });
209
131
  ```
210
132
 
211
- ### Extended Response Types
133
+ ## Modal Customization
212
134
 
213
- ```typescript
214
- interface ExtendedResponse {
215
- strategy: 'desktop' | 'link' | 'ts43';
216
- session: SessionInfo;
217
- credential: Promise<AuthCredential>;
218
- cancel: () => void;
219
- }
135
+ The SDK provides a built-in modal for desktop QR code display.
220
136
 
221
- interface DesktopExtendedResponse extends ExtendedResponse {
222
- qr_code_data: {
223
- ios_qr_image?: string;
224
- android_qr_image?: string;
225
- qr_code?: string;
226
- };
227
- start_polling?: () => Promise<AuthCredential>;
228
- is_polling?: boolean;
229
- }
137
+ ### View Modes
230
138
 
231
- interface LinkExtendedResponse extends ExtendedResponse {
232
- data: {
233
- app_url: string;
234
- };
235
- trigger: () => void;
236
- start_polling?: () => Promise<AuthCredential>;
237
- is_polling?: boolean;
238
- }
139
+ | Mode | Description | Best For |
140
+ |------|-------------|----------|
141
+ | `toggle` | Single QR with iOS/Android switch | Clean, minimal UI (default) |
142
+ | `dual` | Side-by-side QR codes | Users who may not know their OS |
143
+ | `pre-step` | OS selection screen first | Guided experience |
239
144
 
240
- interface TS43ExtendedResponse extends ExtendedResponse {
241
- trigger: () => Promise<void>;
242
- }
243
- ```
145
+ ### Themes
146
+
147
+ | Theme | Description |
148
+ |-------|-------------|
149
+ | `auto` | Follows system preference (default) |
150
+ | `dark` | Dark background with light text |
151
+ | `light` | Light background with dark text |
244
152
 
245
- ### Prevent Default UI
153
+ ### Custom UI
246
154
 
247
- Use `preventDefaultUI: true` to completely disable SDK modals and handle all UI yourself:
155
+ To use your own UI instead of the built-in modal:
248
156
 
249
157
  ```javascript
250
- // Desktop: No QR modal shown
251
- const result = await phoneAuth.invokeSecurePrompt(prepareResult, {
252
- executionMode: 'extended',
158
+ const result = await client.invokeSecurePrompt(prepared, {
253
159
  preventDefaultUI: true
254
160
  });
255
161
 
256
- // You must display QR yourself
162
+ // For desktop strategy, display your own QR code
257
163
  if (result.strategy === 'desktop') {
258
- showYourCustomQR(result.qr_code_data);
164
+ // Access QR data from the prepare response
165
+ const qrData = prepared.data;
166
+ displayYourQRCode(qrData.ios_qr_image, qrData.android_qr_image);
259
167
 
260
- // Start polling manually (required when preventDefaultUI is true)
261
- const credential = await result.start_polling();
168
+ // Wait for credential
169
+ const credential = await result.credential;
170
+
171
+ // Or cancel if needed
172
+ result.cancel?.();
262
173
  }
263
174
  ```
264
175
 
265
- ### Parent Session Support
266
-
267
- For continuing authentication from another device:
268
-
269
- ```javascript
270
- // Desktop starts authentication
271
- const desktopResult = await phoneAuth.preparePhoneRequest({
272
- use_case: 'GetPhoneNumber'
273
- });
176
+ ## Authentication Strategies
274
177
 
275
- // Mobile continues with parent session
276
- const mobileResult = await phoneAuth.preparePhoneRequest({
277
- parent_session_id: desktopResult.session.session_id
278
- // use_case inherited from parent
279
- });
178
+ The SDK automatically selects the best strategy based on the device:
280
179
 
281
- // Complete authentication on mobile
282
- const credential = await phoneAuth.invokeSecurePrompt(mobileResult);
283
- ```
180
+ | Strategy | Platform | Description |
181
+ |----------|----------|-------------|
182
+ | `ts43` | Android Chrome 128+ | Native Digital Credentials API |
183
+ | `link` | iOS / Android | App Clip (iOS) or carrier app (Android) |
184
+ | `desktop` | Desktop browsers | QR code scanned by mobile |
284
185
 
285
- ## Authentication Strategies
186
+ ### Strategy-Specific Handling
286
187
 
287
- The SDK automatically selects the appropriate authentication strategy based on the device and browser:
288
-
289
- ### Desktop Strategy (QR Code)
290
- - **When**: Desktop browsers
291
- - **How**: Displays QR code for mobile scanning
292
- - **Default**: Shows built-in QR modal
293
- - **Custom**: Use `preventDefaultUI: true` to handle QR display yourself
188
+ ```javascript
189
+ const result = await client.invokeSecurePrompt(prepared);
294
190
 
295
- ### Link Strategy (App Clips/Deep Links)
296
- - **When**: Mobile browsers on iOS/Android
297
- - **How**: Opens native app or App Clip
298
- - **Default**: Opens app link immediately
299
- - **Custom**: Control when to open with `trigger()` in extended mode
191
+ switch (result.strategy) {
192
+ case 'ts43':
193
+ // Android: Credential returned directly
194
+ const credential = await result.credential;
195
+ break;
196
+
197
+ case 'link':
198
+ // iOS: Opens App Clip, polls for completion
199
+ // Android: Opens carrier's privileged app, polls for completion
200
+ const credential = await result.credential;
201
+ // Optionally cancel polling
202
+ result.cancel?.();
203
+ break;
204
+
205
+ case 'desktop':
206
+ // Desktop: Shows QR modal, polls for completion
207
+ const credential = await result.credential;
208
+ result.cancel?.();
209
+ break;
210
+ }
211
+ ```
300
212
 
301
- ### TS43 Strategy (Digital Credentials)
302
- - **When**: Chrome/Edge on Android with Digital Credentials API
303
- - **How**: Uses browser's native credential prompt
304
- - **Default**: Shows credential prompt immediately
305
- - **Custom**: Control timing with `trigger()` in extended mode
213
+ ## Framework Integration
306
214
 
307
- ## Type Guards for Safe Handling
215
+ ### React
308
216
 
309
- Use built-in type guards for type-safe result handling:
217
+ ```jsx
218
+ import { usePhoneAuth, USE_CASE } from '@glideidentity/web-client-sdk/react';
310
219
 
311
- ```typescript
312
- import {
313
- isExtendedResponse,
314
- isDesktopStrategy,
315
- isLinkStrategy,
316
- isTS43Strategy
317
- } from '@glideidentity/web-client-sdk';
220
+ function PhoneVerification() {
221
+ const { authenticate, isLoading, error, result } = usePhoneAuth({
222
+ endpoints: {
223
+ prepare: '/api/phone-auth/prepare',
224
+ process: '/api/phone-auth/process',
225
+ }
226
+ });
318
227
 
319
- const result = await phoneAuth.invokeSecurePrompt(prepareResponse, {
320
- executionMode: 'extended'
321
- });
228
+ const handleVerify = async () => {
229
+ try {
230
+ const result = await authenticate({
231
+ use_case: USE_CASE.VERIFY_PHONE_NUMBER,
232
+ phone_number: '+14155551234'
233
+ });
234
+ console.log('Verified:', result.verified);
235
+ } catch (err) {
236
+ console.error('Failed:', err);
237
+ }
238
+ };
322
239
 
323
- // Check if extended response
324
- if (isExtendedResponse(result)) {
325
- console.log('Strategy:', result.strategy);
326
-
327
- // Check specific strategies
328
- if (isDesktopStrategy(result)) {
329
- // TypeScript knows this is DesktopExtendedResponse
330
- console.log('QR data:', result.qr_code_data);
331
- } else if (isLinkStrategy(result)) {
332
- // TypeScript knows this is LinkExtendedResponse
333
- console.log('App URL:', result.data.app_url);
334
- } else if (isTS43Strategy(result)) {
335
- // TypeScript knows this is TS43ExtendedResponse
336
- await result.trigger();
337
- }
338
- } else {
339
- // Standard mode - got credential directly
340
- const verified = await phoneAuth.verifyPhoneNumber(result, session);
240
+ return (
241
+ <button onClick={handleVerify} disabled={isLoading}>
242
+ {isLoading ? 'Verifying...' : 'Verify Phone'}
243
+ </button>
244
+ );
341
245
  }
342
246
  ```
343
247
 
344
- ## Framework Examples
345
-
346
- ### Vue 3 Example
248
+ ### Vue
347
249
 
348
250
  ```vue
349
- <template>
350
- <div>
351
- <button @click="verifyPhone" :disabled="isLoading">
352
- Verify Phone
353
- </button>
354
-
355
- <div v-if="result">
356
- Phone: {{ result.phone_number }}
357
- </div>
358
- </div>
359
- </template>
360
-
361
251
  <script setup>
362
- import { ref } from 'vue';
363
- import { PhoneAuthClient } from '@glideidentity/web-client-sdk';
252
+ import { usePhoneAuth, USE_CASE } from '@glideidentity/web-client-sdk/vue';
364
253
 
365
- const phoneAuth = new PhoneAuthClient({
366
- maxPollingAttempts: 30
254
+ const { authenticate, isLoading, error, result } = usePhoneAuth({
255
+ endpoints: {
256
+ prepare: '/api/phone-auth/prepare',
257
+ process: '/api/phone-auth/process',
258
+ }
367
259
  });
368
260
 
369
- const isLoading = ref(false);
370
- const result = ref(null);
261
+ const handleVerify = async () => {
262
+ await authenticate({
263
+ use_case: USE_CASE.VERIFY_PHONE_NUMBER,
264
+ phone_number: '+14155551234'
265
+ });
266
+ };
267
+ </script>
371
268
 
372
- async function verifyPhone() {
373
- isLoading.value = true;
374
- try {
375
- const prepared = await phoneAuth.preparePhoneRequest({
376
- use_case: 'VerifyPhoneNumber',
269
+ <template>
270
+ <button @click="handleVerify" :disabled="isLoading">
271
+ {{ isLoading ? 'Verifying...' : 'Verify Phone' }}
272
+ </button>
273
+ </template>
274
+ ```
275
+
276
+ ### Vanilla JavaScript (Browser)
277
+
278
+ ```html
279
+ <script src="https://unpkg.com/@glideidentity/web-client-sdk/dist/browser/web-client-sdk.min.js"></script>
280
+ <script>
281
+ const { PhoneAuthClient, USE_CASE } = GlideWebClientSDK;
282
+
283
+ const client = new PhoneAuthClient({
284
+ endpoints: {
285
+ prepare: '/api/phone-auth/prepare',
286
+ process: '/api/phone-auth/process',
287
+ }
288
+ });
289
+
290
+ document.getElementById('verify-btn').onclick = async () => {
291
+ const result = await client.authenticate({
292
+ use_case: USE_CASE.VERIFY_PHONE_NUMBER,
377
293
  phone_number: '+14155551234'
378
294
  });
379
-
380
- const credential = await phoneAuth.invokeSecurePrompt(prepared);
381
- result.value = await phoneAuth.verifyPhoneNumber(
382
- credential,
383
- prepared.session
384
- );
385
- } catch (error) {
386
- console.error('Failed:', error);
387
- } finally {
388
- isLoading.value = false;
389
- }
390
- }
295
+ console.log('Verified:', result.verified);
296
+ };
391
297
  </script>
392
298
  ```
393
299
 
394
- ### Angular Example
300
+ ## Advanced Features
395
301
 
396
- ```typescript
397
- import { Component } from '@angular/core';
398
- import { PhoneAuthClient } from '@glideidentity/web-client-sdk';
399
-
400
- @Component({
401
- selector: 'app-phone-verify',
402
- template: `
403
- <button (click)="verify()" [disabled]="isLoading">
404
- Verify
405
- </button>
406
-
407
- <div *ngIf="result">
408
- Phone: {{ result.phone_number }}
409
- </div>
410
- `
411
- })
412
- export class PhoneVerifyComponent {
413
- phoneAuth = new PhoneAuthClient({
414
- // Optional configuration
415
- debug: false
416
- });
417
-
418
- isLoading = false;
419
- result: any = null;
420
-
421
- async verify() {
422
- this.isLoading = true;
423
- try {
424
- const prepared = await this.phoneAuth.preparePhoneRequest({
425
- use_case: 'VerifyPhoneNumber',
426
- phone_number: '+14155551234'
427
- });
428
-
429
- const credential = await this.phoneAuth.invokeSecurePrompt(prepared);
430
- this.result = await this.phoneAuth.verifyPhoneNumber(
431
- credential,
432
- prepared.session
433
- );
434
- } catch (error) {
435
- console.error('Failed:', error);
436
- } finally {
437
- this.isLoading = false;
302
+ ### Custom HTTP Headers
303
+
304
+ Add custom headers to all SDK requests:
305
+
306
+ ```javascript
307
+ const client = new PhoneAuthClient({
308
+ endpoints: { ... },
309
+ headers: {
310
+ common: {
311
+ 'X-Custom-Header': 'your-value'
438
312
  }
439
313
  }
440
- }
314
+ });
441
315
  ```
442
316
 
443
- ### Vanilla JavaScript
317
+ ### Custom Logger
444
318
 
445
- ```javascript
446
- import { PhoneAuthClient } from '@glideidentity/web-client-sdk';
319
+ Provide your own logger implementation:
447
320
 
321
+ ```javascript
448
322
  const client = new PhoneAuthClient({
449
- pollingInterval: 2000,
450
- maxPollingAttempts: 30,
451
- debug: false
323
+ endpoints: { ... },
324
+ logger: {
325
+ debug: (msg, data) => console.debug('[SDK]', msg, data),
326
+ info: (msg, data) => console.info('[SDK]', msg, data),
327
+ warn: (msg, data) => console.warn('[SDK]', msg, data),
328
+ error: (msg, data) => console.error('[SDK]', msg, data),
329
+ }
452
330
  });
331
+ ```
453
332
 
454
- // Get phone number
455
- async function getPhoneNumber() {
456
- try {
457
- const prepareResult = await client.preparePhoneRequest({
458
- use_case: 'GetPhoneNumber'
459
- });
460
-
461
- const credential = await client.invokeSecurePrompt(prepareResult);
462
-
463
- const result = await client.getPhoneNumber(
464
- credential,
465
- prepareResult.session
466
- );
467
-
468
- console.log('Phone:', result.phone_number);
469
- } catch (error) {
470
- console.error('Failed:', error);
471
- }
472
- }
333
+ ### Custom HTTP Client
473
334
 
474
- // Verify with extended mode
475
- async function verifyWithExtendedMode() {
476
- try {
477
- const prepareResult = await client.preparePhoneRequest({
478
- use_case: 'VerifyPhoneNumber',
479
- phone_number: '+14155551234'
480
- });
481
-
482
- const extendedResult = await client.invokeSecurePrompt(prepareResult, {
483
- executionMode: 'extended',
484
- preventDefaultUI: true
485
- });
486
-
487
- // Handle based on strategy
488
- if (extendedResult.strategy === 'desktop') {
489
- // Show custom QR
490
- document.getElementById('qr').src = extendedResult.qr_code_data.qr_code;
491
-
492
- // Start polling
493
- const credential = await extendedResult.start_polling();
494
- console.log('Verified!');
335
+ Bring your own HTTP client for full control:
336
+
337
+ ```javascript
338
+ const client = new PhoneAuthClient({
339
+ endpoints: { ... },
340
+ httpClient: {
341
+ post: async (url, body, options) => {
342
+ const response = await yourHttpLib.post(url, body, options);
343
+ return response.data;
344
+ },
345
+ get: async (url, options) => {
346
+ const response = await yourHttpLib.get(url, options);
347
+ return response.data;
495
348
  }
496
- } catch (error) {
497
- console.error('Failed:', error);
498
349
  }
499
- }
350
+ });
500
351
  ```
501
352
 
502
- ## Error Handling
353
+ ## Core Package
503
354
 
504
- The SDK provides detailed error information:
355
+ For advanced use cases, you can import just the types and validators without the full client:
505
356
 
506
- ```javascript
507
- try {
508
- const result = await phoneAuth.invokeSecurePrompt(prepareResponse);
509
- } catch (error) {
510
- console.log(error.code); // e.g., 'CARRIER_NOT_ELIGIBLE'
511
- console.log(error.message); // User-friendly error message
357
+ ```typescript
358
+ import {
359
+ // Types
360
+ type PrepareRequest,
361
+ type PrepareResponse,
362
+ type InvokeResult,
363
+ type SessionInfo,
512
364
 
513
- switch (error.code) {
514
- case 'CARRIER_NOT_ELIGIBLE':
515
- // Handle unsupported carrier
516
- break;
517
- case 'USER_DENIED':
518
- // User cancelled authentication
519
- break;
520
- case 'TIMEOUT':
521
- // Authentication timed out
522
- break;
523
- default:
524
- // Handle other errors
525
- }
526
- }
527
- ```
528
-
529
- ## Browser Support
365
+ // Constants
366
+ USE_CASE,
367
+ AUTHENTICATION_STRATEGY,
368
+ ERROR_CODES,
369
+
370
+ // Validators
371
+ validatePhoneNumber,
372
+ validatePlmn,
373
+
374
+ // Type Guards
375
+ isTS43Strategy,
376
+ isLinkStrategy,
377
+ isDesktopStrategy,
378
+ isAuthError,
379
+ } from '@glideidentity/web-client-sdk/core';
530
380
 
531
- ### Requirements
381
+ // Use validators
382
+ const { valid, error } = validatePhoneNumber('+14155551234');
532
383
 
533
- - Chrome 118+ or Edge 118+ (for TS43 strategy)
534
- - Digital Credentials API flag enabled (for TS43)
535
- - Any modern browser for Desktop/Link strategies
384
+ // Use type guards
385
+ if (isDesktopStrategy(result)) {
386
+ // TypeScript knows result has desktop-specific properties
387
+ }
388
+ ```
536
389
 
537
- ### Checking Support
390
+ ## Error Handling
538
391
 
539
392
  ```javascript
540
- // Check if current browser/device is supported
541
- const isSupported = phoneAuth.isSupported();
393
+ import { ERROR_CODES, isAuthError } from '@glideidentity/web-client-sdk';
542
394
 
543
- if (!isSupported) {
544
- console.log('Phone authentication not supported on this device');
395
+ try {
396
+ await client.authenticate({ ... });
397
+ } catch (error) {
398
+ if (isAuthError(error)) {
399
+ switch (error.code) {
400
+ case ERROR_CODES.USER_CANCELLED:
401
+ // User closed the modal or cancelled
402
+ break;
403
+ case ERROR_CODES.TIMEOUT:
404
+ // Authentication timed out
405
+ break;
406
+ case ERROR_CODES.NETWORK_ERROR:
407
+ // Network request failed
408
+ break;
409
+ default:
410
+ // Handle other errors
411
+ console.error(error.message);
412
+ }
413
+ }
545
414
  }
546
415
  ```
547
416
 
548
- ## API Reference
417
+ ## Type Reference
549
418
 
550
- ### Configuration Options
419
+ ### Use Cases
551
420
 
552
421
  ```typescript
553
- interface PhoneAuthConfig {
554
- endpoints?: {
555
- prepare?: string; // Custom prepare endpoint
556
- process?: string; // Custom process endpoint
557
- polling?: string; // Custom polling endpoint
558
- };
559
- pollingInterval?: number; // Polling interval in ms (default: 2000)
560
- maxPollingAttempts?: number; // Max polling attempts (default: 30 = 1 minute)
561
- timeout?: number; // API timeout in ms (default: 30000)
562
- debug?: boolean; // Enable debug logging (default: false)
563
- devtools?: {
564
- showMobileConsole?: boolean; // Show debug console on mobile (default: false)
565
- };
566
- }
422
+ type UseCase = 'GetPhoneNumber' | 'VerifyPhoneNumber';
423
+
424
+ // Or use the constant
425
+ USE_CASE.GET_PHONE_NUMBER // 'GetPhoneNumber'
426
+ USE_CASE.VERIFY_PHONE_NUMBER // 'VerifyPhoneNumber'
567
427
  ```
568
428
 
569
- ### Invoke Options
429
+ ### Prepare Request
570
430
 
571
431
  ```typescript
572
- interface InvokeOptions {
573
- // Execution mode
574
- executionMode?: 'standard' | 'extended'; // Default: 'standard'
575
- preventDefaultUI?: boolean; // Default: false
576
-
577
- // UI customization (when preventDefaultUI is false)
578
- modalOptions?: {
579
- className?: string;
580
- title?: string;
581
- description?: string;
582
- buttonText?: string;
583
- showCloseButton?: boolean;
584
- };
585
-
586
- // Callbacks
587
- callbacks?: {
588
- onOpen?: () => void;
589
- onClose?: () => void;
590
- onAuthStart?: () => void;
591
- onAuthComplete?: (result: any) => void;
592
- onError?: (error: Error) => void;
593
- };
432
+ interface PrepareRequest {
433
+ use_case: UseCase;
434
+ phone_number?: string; // Required for VerifyPhoneNumber
435
+ parent_session_id?: string; // For cross-device flows
594
436
  }
595
437
  ```
596
438
 
597
- ### Methods
439
+ ### Invoke Result
598
440
 
599
441
  ```typescript
600
- // Core methods (granular control)
601
- preparePhoneRequest(options: PrepareRequest): Promise<PrepareResponse>
602
- invokeSecurePrompt(response: PrepareResponse, options?: InvokeOptions): Promise<any>
603
- getPhoneNumber(credential: any, session: SessionInfo): Promise<GetPhoneNumberResponse>
604
- verifyPhoneNumber(credential: any, session: SessionInfo): Promise<VerifyPhoneNumberResponse>
605
-
606
- // High-level convenience methods (full flow)
607
- getPhoneNumberComplete(): Promise<GetPhoneNumberResponse>
608
- verifyPhoneNumberComplete(phoneNumber: string): Promise<VerifyPhoneNumberResponse>
609
-
610
- // Utility methods
611
- isSupported(): boolean
442
+ interface InvokeResult {
443
+ strategy: 'ts43' | 'link' | 'desktop';
444
+ session: SessionInfo;
445
+ credential: Promise<AuthCredential>;
446
+ cancel?: () => void; // Available for link and desktop
447
+ }
612
448
  ```
613
449
 
614
- ### Response Types
450
+ ### Responses
615
451
 
616
452
  ```typescript
617
- interface PrepareRequest {
618
- use_case: 'GetPhoneNumber' | 'VerifyPhoneNumber';
619
- phone_number?: string;
620
- parent_session_id?: string;
621
- }
622
-
623
- interface PrepareResponse {
624
- authentication_strategy: 'desktop' | 'link' | 'ts43';
625
- session: SessionInfo;
626
- data: any;
627
- }
628
-
629
453
  interface GetPhoneNumberResponse {
630
454
  phone_number: string;
631
- aud?: string;
632
455
  }
633
456
 
634
457
  interface VerifyPhoneNumberResponse {
635
458
  phone_number: string;
636
459
  verified: boolean;
637
- aud?: string;
638
460
  }
639
461
  ```
640
462
 
641
- ## Documentation
642
-
643
- For detailed documentation, see the [docs](./docs) folder:
644
-
645
- | Document | Description |
646
- |----------|-------------|
647
- | [Architecture](./docs/architecture.md) | SDK architecture and design principles |
648
- | [Phone Authentication](./docs/phone-auth.md) | Complete phone auth usage guide |
649
- | [Desktop Authentication](./docs/desktop-auth.md) | QR code authentication flow |
650
- | [Dual Platform QR](./docs/dual-platform-qr.md) | iOS/Android specific QR codes |
651
- | [Error Handling](./docs/error-handling.md) | Error codes and handling strategies |
652
- | [Trigger Pattern](./docs/trigger-pattern.md) | Consistent trigger API across strategies |
653
- | [Implementation Notes](./docs/implementation-notes.md) | Technical implementation details |
654
- | [Local Development](./docs/local-development.md) | Testing the SDK locally |
655
- | [TS43 Data Flow](./docs/TS43_DATA_FLOW.md) | Digital Credentials API details |
656
- | [Type Hierarchy](./docs/TYPE_HIERARCHY.md) | TypeScript type system |
657
- | [Naming Conventions](./docs/NAMING_CONVENTIONS.md) | API naming standards |
658
- | [Security Checklist](./docs/security-checklist.md) | NPM publishing security |
463
+ ## Browser Support
464
+
465
+ | Browser | Strategy | Requirements |
466
+ |---------|----------|--------------|
467
+ | Chrome Android 128+ | TS43 | Digital Credentials API |
468
+ | Safari iOS | Link | App Clips support |
469
+ | Chrome/Edge/Firefox Desktop | Desktop | Any modern version |
659
470
 
660
471
  ## Support
661
472
 
@@ -664,4 +475,4 @@ For detailed documentation, see the [docs](./docs) folder:
664
475
 
665
476
  ## License
666
477
 
667
- MIT
478
+ MIT