@sparkvault/sdk 1.0.0
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.
- package/README.md +720 -0
- package/dist/auto-init.d.ts +51 -0
- package/dist/config.d.ts +25 -0
- package/dist/errors.d.ts +30 -0
- package/dist/http.d.ts +48 -0
- package/dist/identity/api.d.ts +101 -0
- package/dist/identity/container.d.ts +49 -0
- package/dist/identity/handlers/index.d.ts +9 -0
- package/dist/identity/handlers/passkey-handler.d.ts +52 -0
- package/dist/identity/handlers/sparklink-handler.d.ts +43 -0
- package/dist/identity/handlers/totp-handler.d.ts +52 -0
- package/dist/identity/index.d.ts +69 -0
- package/dist/identity/inline-container.d.ts +60 -0
- package/dist/identity/methods.d.ts +23 -0
- package/dist/identity/modal.d.ts +74 -0
- package/dist/identity/renderer.d.ts +97 -0
- package/dist/identity/state.d.ts +95 -0
- package/dist/identity/styles.d.ts +22 -0
- package/dist/identity/types.d.ts +183 -0
- package/dist/identity/utils/cooldown-timer.d.ts +73 -0
- package/dist/identity/utils/index.d.ts +5 -0
- package/dist/identity/utils.d.ts +27 -0
- package/dist/identity/views/base.d.ts +62 -0
- package/dist/identity/views/error.d.ts +25 -0
- package/dist/identity/views/icons.d.ts +34 -0
- package/dist/identity/views/identity-input.d.ts +48 -0
- package/dist/identity/views/index.d.ts +14 -0
- package/dist/identity/views/loading.d.ts +15 -0
- package/dist/identity/views/method-select.d.ts +29 -0
- package/dist/identity/views/passkey-prompt.d.ts +22 -0
- package/dist/identity/views/passkey.d.ts +38 -0
- package/dist/identity/views/sparklink-waiting.d.ts +33 -0
- package/dist/identity/views/totp-verify.d.ts +58 -0
- package/dist/index.d.ts +658 -0
- package/dist/logger.d.ts +45 -0
- package/dist/rng/index.d.ts +54 -0
- package/dist/rng/types.d.ts +26 -0
- package/dist/sparks/index.d.ts +37 -0
- package/dist/sparks/types.d.ts +56 -0
- package/dist/sparkvault.cjs.js +6152 -0
- package/dist/sparkvault.cjs.js.map +1 -0
- package/dist/sparkvault.esm.js +6137 -0
- package/dist/sparkvault.esm.js.map +1 -0
- package/dist/sparkvault.js +2 -0
- package/dist/sparkvault.js.map +1 -0
- package/dist/utils/base64url.d.ts +49 -0
- package/dist/utils/retry.d.ts +32 -0
- package/dist/vaults/index.d.ts +83 -0
- package/dist/vaults/types.d.ts +120 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,720 @@
|
|
|
1
|
+
# SparkVault JavaScript SDK
|
|
2
|
+
|
|
3
|
+
A unified JavaScript SDK for SparkVault services: Identity verification, encrypted Sparks, secure Vaults, and cryptographic RNG.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@sparkvault/sdk)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Table of Contents
|
|
9
|
+
|
|
10
|
+
- [Installation](#installation)
|
|
11
|
+
- [Quick Start](#quick-start)
|
|
12
|
+
- [Architecture](#architecture)
|
|
13
|
+
- [Modules](#modules)
|
|
14
|
+
- [Identity](#identity)
|
|
15
|
+
- [Sparks](#sparks)
|
|
16
|
+
- [Vaults](#vaults)
|
|
17
|
+
- [RNG](#rng)
|
|
18
|
+
- [Configuration](#configuration)
|
|
19
|
+
- [Error Handling](#error-handling)
|
|
20
|
+
- [TypeScript](#typescript)
|
|
21
|
+
- [Security](#security)
|
|
22
|
+
- [Development](#development)
|
|
23
|
+
- [License](#license)
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
### CDN (Browser)
|
|
28
|
+
|
|
29
|
+
Include the SDK directly in your HTML. This is the recommended approach for most web applications.
|
|
30
|
+
|
|
31
|
+
#### Zero-Config Auto-Init (Recommended)
|
|
32
|
+
|
|
33
|
+
The simplest way to add SparkVault authentication to your site:
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<script
|
|
37
|
+
async
|
|
38
|
+
src="https://cdn.sparkvault.com/sdk/v1/sparkvault.js"
|
|
39
|
+
data-account-id="acc_your_account"
|
|
40
|
+
data-attach-selector=".js-sparkvault-auth"
|
|
41
|
+
data-success-url="https://example.com/auth/verify-token"
|
|
42
|
+
data-debug="true"
|
|
43
|
+
></script>
|
|
44
|
+
|
|
45
|
+
<button class="js-sparkvault-auth">Login with SparkVault</button>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
That's it! The SDK automatically:
|
|
49
|
+
- Initializes with your account ID
|
|
50
|
+
- Attaches click handlers to matching elements
|
|
51
|
+
- Opens the verification modal on click
|
|
52
|
+
- POSTs the result to your success URL
|
|
53
|
+
|
|
54
|
+
#### Auto-Init Data Attributes
|
|
55
|
+
|
|
56
|
+
| Attribute | Description |
|
|
57
|
+
|-----------|-------------|
|
|
58
|
+
| `data-account-id` | Your SparkVault account ID (required for auto-init) |
|
|
59
|
+
| `data-attach-selector` | CSS selector for elements to attach click handlers |
|
|
60
|
+
| `data-success-url` | URL to POST `{ token, identity, identityType }` on success |
|
|
61
|
+
| `data-success-function` | Global function name to call on success (e.g., `"handleAuth"` or `"MyApp.auth.onSuccess"`) |
|
|
62
|
+
| `data-error-url` | URL to redirect to on error (appends `?error=message`) |
|
|
63
|
+
| `data-error-function` | Global function name to call on error |
|
|
64
|
+
| `data-debug` | Set to `"true"` for verbose console logging |
|
|
65
|
+
|
|
66
|
+
#### Success Handling
|
|
67
|
+
|
|
68
|
+
When verification succeeds, the SDK can call a function and/or POST to a URL:
|
|
69
|
+
|
|
70
|
+
```html
|
|
71
|
+
<!-- Call a function -->
|
|
72
|
+
<script>
|
|
73
|
+
function handleSparkVaultAuth(result) {
|
|
74
|
+
console.log('Verified:', result.identity);
|
|
75
|
+
console.log('Token:', result.token);
|
|
76
|
+
// Your logic here...
|
|
77
|
+
}
|
|
78
|
+
</script>
|
|
79
|
+
<script
|
|
80
|
+
src="https://cdn.sparkvault.com/sdk/v1/sparkvault.js"
|
|
81
|
+
data-account-id="acc_your_account"
|
|
82
|
+
data-attach-selector=".login-btn"
|
|
83
|
+
data-success-function="handleSparkVaultAuth"
|
|
84
|
+
></script>
|
|
85
|
+
|
|
86
|
+
<!-- POST to your backend -->
|
|
87
|
+
<script
|
|
88
|
+
src="https://cdn.sparkvault.com/sdk/v1/sparkvault.js"
|
|
89
|
+
data-account-id="acc_your_account"
|
|
90
|
+
data-attach-selector=".login-btn"
|
|
91
|
+
data-success-url="/auth/verify-sparkvault-token"
|
|
92
|
+
></script>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
When POSTing to `data-success-url`, the SDK sends:
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"token": "eyJ...",
|
|
99
|
+
"identity": "user@example.com",
|
|
100
|
+
"identityType": "email"
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Your backend can respond with:
|
|
105
|
+
```json
|
|
106
|
+
{ "redirectUrl": "/dashboard" } // SDK redirects to this URL
|
|
107
|
+
{ "reload": true } // SDK reloads the page
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### Manual Initialization
|
|
111
|
+
|
|
112
|
+
For more control, initialize the SDK manually:
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<script src="https://cdn.sparkvault.com/sdk/v1/sparkvault.js"></script>
|
|
116
|
+
<script>
|
|
117
|
+
const sv = SparkVault.init({
|
|
118
|
+
accountId: 'acc_your_account'
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Trigger verification popup manually
|
|
122
|
+
document.getElementById('login-btn').addEventListener('click', async () => {
|
|
123
|
+
const result = await sv.identity.pop();
|
|
124
|
+
// Handle result...
|
|
125
|
+
});
|
|
126
|
+
</script>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Available CDN Files
|
|
130
|
+
|
|
131
|
+
| File | Description |
|
|
132
|
+
|------|-------------|
|
|
133
|
+
| `sparkvault.js` | Minified UMD bundle (recommended) |
|
|
134
|
+
| `sparkvault.esm.js` | ES module bundle |
|
|
135
|
+
| `sparkvault.cjs.js` | CommonJS bundle |
|
|
136
|
+
|
|
137
|
+
### npm
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npm install @sparkvault/sdk
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
// ES Modules
|
|
145
|
+
import { SparkVault } from '@sparkvault/sdk';
|
|
146
|
+
|
|
147
|
+
// CommonJS
|
|
148
|
+
const { SparkVault } = require('@sparkvault/sdk');
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Quick Start
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
// Initialize the SDK
|
|
155
|
+
const sv = SparkVault.init({
|
|
156
|
+
accountId: 'acc_your_account'
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Identity - Open verification popup
|
|
160
|
+
const result = await sv.identity.pop({
|
|
161
|
+
email: 'user@example.com'
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// The token is a single-use verification proof - send it to YOUR backend
|
|
165
|
+
await fetch('/api/auth/login', {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
headers: { 'Content-Type': 'application/json' },
|
|
168
|
+
body: JSON.stringify({ token: result.token })
|
|
169
|
+
});
|
|
170
|
+
// Your backend verifies the token, then creates YOUR session
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Architecture
|
|
174
|
+
|
|
175
|
+
The SparkVault SDK follows a Stripe.js-like architecture:
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
179
|
+
│ Your Application │
|
|
180
|
+
├─────────────────────────────────────────────────────────────┤
|
|
181
|
+
│ SparkVault SDK │
|
|
182
|
+
│ ┌─────────────┬─────────────┬─────────────┬─────────────┐ │
|
|
183
|
+
│ │ Identity │ Sparks │ Vaults │ RNG │ │
|
|
184
|
+
│ │ Module │ Module │ Module │ Module │ │
|
|
185
|
+
│ └─────────────┴─────────────┴─────────────┴─────────────┘ │
|
|
186
|
+
│ │ │
|
|
187
|
+
│ HTTP Client │
|
|
188
|
+
├─────────────────────────────────────────────────────────────┤
|
|
189
|
+
│ api.sparkvault.com │
|
|
190
|
+
└─────────────────────────────────────────────────────────────┘
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Identity Popup Flow
|
|
194
|
+
|
|
195
|
+
The Identity module uses a secure popup window for authentication:
|
|
196
|
+
|
|
197
|
+
1. **SDK opens popup** → `api.sparkvault.com/apps/identity/{account_id}/embed`
|
|
198
|
+
2. **User authenticates** → Passkey, TOTP, Magic Link, or Social OAuth
|
|
199
|
+
3. **Popup posts result** → `postMessage` with signed JWT token
|
|
200
|
+
4. **SDK validates origin** → Ensures message is from SparkVault
|
|
201
|
+
5. **Promise resolves** → Returns verified user info and token
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
|
|
205
|
+
│ Your App │ │ SDK Popup │ │ SparkVault │
|
|
206
|
+
│ │ │ │ │ Identity │
|
|
207
|
+
├──────────────┤ ├──────────────────┤ ├──────────────┤
|
|
208
|
+
│ sv.identity │────>│ Opens popup │ │ │
|
|
209
|
+
│ .pop() │ │ window │────>│ /embed page │
|
|
210
|
+
│ │ │ │ │ │
|
|
211
|
+
│ │ │ User selects │ │ Auth methods │
|
|
212
|
+
│ │ │ auth method │<────│ displayed │
|
|
213
|
+
│ │ │ │ │ │
|
|
214
|
+
│ │ │ User completes │────>│ Verify │
|
|
215
|
+
│ │ │ authentication │ │ credentials │
|
|
216
|
+
│ │ │ │ │ │
|
|
217
|
+
│ Promise │<────│ postMessage │<────│ Sign JWT │
|
|
218
|
+
│ resolves │ │ with token │ │ token │
|
|
219
|
+
└──────────────┘ └──────────────────┘ └──────────────┘
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Modules
|
|
223
|
+
|
|
224
|
+
### Identity
|
|
225
|
+
|
|
226
|
+
Verify user identity through passkey, TOTP, magic link, or social authentication.
|
|
227
|
+
|
|
228
|
+
The SDK provides two methods:
|
|
229
|
+
- **`pop()`** — Opens a modal popup (most common)
|
|
230
|
+
- **`render()`** — Embeds UI inline in your page
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
// Open popup modal
|
|
234
|
+
const result = await sv.identity.pop();
|
|
235
|
+
|
|
236
|
+
// With options
|
|
237
|
+
const result = await sv.identity.pop({
|
|
238
|
+
email: 'user@example.com', // Pre-fill email
|
|
239
|
+
methods: ['passkey', 'totp_email', 'magic_link'], // Filter methods
|
|
240
|
+
theme: 'dark', // 'light', 'dark', or 'auto' (system preference)
|
|
241
|
+
backdropBlur: true, // Enable backdrop blur effect (default: true)
|
|
242
|
+
locale: 'en', // UI language
|
|
243
|
+
onSuccess: (result) => {}, // Success callback
|
|
244
|
+
onCancel: () => {}, // User cancelled
|
|
245
|
+
onError: (error) => {} // Error callback
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Result structure
|
|
249
|
+
console.log(result.token); // Signed JWT
|
|
250
|
+
console.log(result.identity); // Verified identity (email or phone)
|
|
251
|
+
console.log(result.identityType); // 'email' or 'phone'
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### Inline Rendering
|
|
255
|
+
|
|
256
|
+
For cases where you want to embed the authentication UI directly in your page instead of a popup modal, use `render()`:
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
// Render inline in a container element
|
|
260
|
+
const result = await sv.identity.render({
|
|
261
|
+
target: document.getElementById('auth-container'),
|
|
262
|
+
email: 'user@example.com'
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Embed in your own dialog without SparkVault header/footer
|
|
266
|
+
const result = await sv.identity.render({
|
|
267
|
+
target: dialogContentElement,
|
|
268
|
+
showHeader: false,
|
|
269
|
+
showFooter: false
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Minimal - just the auth flow, no chrome
|
|
273
|
+
const result = await sv.identity.render({
|
|
274
|
+
target: myElement,
|
|
275
|
+
showHeader: false,
|
|
276
|
+
showCloseButton: false,
|
|
277
|
+
showFooter: false
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
| Option | Type | Default | Description |
|
|
282
|
+
|--------|------|---------|-------------|
|
|
283
|
+
| `target` | `HTMLElement` | **required** | Element to render the auth UI into |
|
|
284
|
+
| `showHeader` | `boolean` | `true` | Show header with branding |
|
|
285
|
+
| `showCloseButton` | `boolean` | `true` | Show close button in header |
|
|
286
|
+
| `showFooter` | `boolean` | `true` | Show "Secured by SparkVault" footer |
|
|
287
|
+
|
|
288
|
+
All other options from `pop()` are also supported (`email`, `phone`, `onSuccess`, etc.).
|
|
289
|
+
|
|
290
|
+
#### Supported Authentication Methods
|
|
291
|
+
|
|
292
|
+
| Method | Description |
|
|
293
|
+
|--------|-------------|
|
|
294
|
+
| `passkey` | WebAuthn/FIDO2 passkey authentication |
|
|
295
|
+
| `totp_email` | Time-based OTP sent via email |
|
|
296
|
+
| `totp_sms` | Time-based OTP sent via SMS |
|
|
297
|
+
| `magic_link` | One-click email verification link |
|
|
298
|
+
| `google` | Google OAuth |
|
|
299
|
+
| `apple` | Apple Sign In |
|
|
300
|
+
| `microsoft` | Microsoft OAuth |
|
|
301
|
+
| `github` | GitHub OAuth |
|
|
302
|
+
|
|
303
|
+
#### Appearance Options
|
|
304
|
+
|
|
305
|
+
The Identity popup supports theming and visual effects:
|
|
306
|
+
|
|
307
|
+
```javascript
|
|
308
|
+
// Dark mode
|
|
309
|
+
await sv.identity.pop({
|
|
310
|
+
theme: 'dark'
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// Light mode
|
|
314
|
+
await sv.identity.pop({
|
|
315
|
+
theme: 'light'
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// Auto (follows system preference)
|
|
319
|
+
await sv.identity.pop({
|
|
320
|
+
theme: 'auto'
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// Disable backdrop blur (enabled by default)
|
|
324
|
+
await sv.identity.pop({
|
|
325
|
+
backdropBlur: false
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// Combine options
|
|
329
|
+
await sv.identity.pop({
|
|
330
|
+
email: 'user@example.com',
|
|
331
|
+
theme: 'dark',
|
|
332
|
+
backdropBlur: true
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
| Option | Type | Default | Description |
|
|
337
|
+
|--------|------|---------|-------------|
|
|
338
|
+
| `theme` | `'light' \| 'dark' \| 'auto'` | Tenant default | UI color theme. `'auto'` follows system preference. |
|
|
339
|
+
| `backdropBlur` | `boolean` | `true` | Apply blur effect to the page behind the popup. |
|
|
340
|
+
|
|
341
|
+
#### Token Verification
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
// Verify a token (validates expiration and issuer)
|
|
345
|
+
const claims = await sv.identity.verifyToken(token);
|
|
346
|
+
console.log(claims.identity); // Verified email or phone
|
|
347
|
+
console.log(claims.identity_type); // 'email' or 'phone'
|
|
348
|
+
console.log(claims.method); // Auth method used
|
|
349
|
+
console.log(claims.verified_at); // Verification timestamp
|
|
350
|
+
console.log(claims.exp); // Expiration timestamp
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Sparks
|
|
354
|
+
|
|
355
|
+
Create and read ephemeral encrypted secrets that burn on read.
|
|
356
|
+
|
|
357
|
+
```javascript
|
|
358
|
+
// Create a spark
|
|
359
|
+
const spark = await sv.sparks.create({
|
|
360
|
+
payload: 'secret data', // String or binary data
|
|
361
|
+
ttl: 3600, // Time-to-live in seconds (default: 3600)
|
|
362
|
+
maxReads: 1, // Max reads before burn (default: 1)
|
|
363
|
+
password: 'optional-password' // Optional password protection
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
console.log(spark.id); // Spark ID
|
|
367
|
+
console.log(spark.url); // Direct shareable URL
|
|
368
|
+
console.log(spark.expiresAt); // Expiration timestamp
|
|
369
|
+
console.log(spark.maxReads); // Remaining reads
|
|
370
|
+
|
|
371
|
+
// Read a spark (burns it)
|
|
372
|
+
const data = await sv.sparks.read(sparkId);
|
|
373
|
+
// or
|
|
374
|
+
const data = await sv.sparks.read(sparkId, 'password');
|
|
375
|
+
|
|
376
|
+
console.log(data.payload); // Decrypted payload
|
|
377
|
+
console.log(data.burned); // true if this was the last read
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Vaults
|
|
381
|
+
|
|
382
|
+
Create and manage encrypted vaults with persistent storage for files (Ingots).
|
|
383
|
+
|
|
384
|
+
```javascript
|
|
385
|
+
// Create a vault
|
|
386
|
+
const vault = await sv.vaults.create({
|
|
387
|
+
name: 'My Vault'
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
console.log(vault.id); // Vault ID
|
|
391
|
+
console.log(vault.name); // Vault name
|
|
392
|
+
console.log(vault.vmk); // Vault Master Key (24 chars) - SAVE THIS!
|
|
393
|
+
console.log(vault.createdAt); // Creation timestamp
|
|
394
|
+
|
|
395
|
+
// List vaults
|
|
396
|
+
const vaults = await sv.vaults.list();
|
|
397
|
+
|
|
398
|
+
// Unseal a vault (required before accessing ingots)
|
|
399
|
+
const unsealed = await sv.vaults.unseal(vaultId, vmk);
|
|
400
|
+
console.log(unsealed.vatToken); // Vault Access Token
|
|
401
|
+
console.log(unsealed.expiresAt); // Token expiration
|
|
402
|
+
|
|
403
|
+
// Upload a file (ingot)
|
|
404
|
+
const ingot = await sv.vaults.uploadIngot(unsealed, {
|
|
405
|
+
file: fileObject, // File or Blob
|
|
406
|
+
name: 'document.pdf' // Display name
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
console.log(ingot.id); // Ingot ID
|
|
410
|
+
console.log(ingot.name); // File name
|
|
411
|
+
console.log(ingot.size); // File size in bytes
|
|
412
|
+
console.log(ingot.mimeType); // MIME type
|
|
413
|
+
|
|
414
|
+
// List ingots
|
|
415
|
+
const ingots = await sv.vaults.listIngots(unsealed);
|
|
416
|
+
|
|
417
|
+
// Download an ingot
|
|
418
|
+
const blob = await sv.vaults.downloadIngot(unsealed, ingotId);
|
|
419
|
+
|
|
420
|
+
// Delete an ingot
|
|
421
|
+
await sv.vaults.deleteIngot(unsealed, ingotId);
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### RNG
|
|
425
|
+
|
|
426
|
+
Generate cryptographically secure random numbers using hybrid entropy (KMS + local).
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
// Generate random bytes
|
|
430
|
+
const result = await sv.rng.generate({
|
|
431
|
+
bytes: 32, // 1-1024 bytes
|
|
432
|
+
format: 'hex' // Output format
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
console.log(result.value); // Random value in requested format
|
|
436
|
+
console.log(result.bytes); // Number of bytes generated
|
|
437
|
+
console.log(result.format); // Format used
|
|
438
|
+
|
|
439
|
+
// Available formats
|
|
440
|
+
// 'hex' - Hexadecimal string
|
|
441
|
+
// 'base64' - Base64 encoded
|
|
442
|
+
// 'base64url' - URL-safe Base64
|
|
443
|
+
// 'bytes' - Raw Uint8Array
|
|
444
|
+
// 'alphanumeric' - Alphanumeric string
|
|
445
|
+
// 'numeric' - Numeric string
|
|
446
|
+
// 'uuid' - UUID v4 format
|
|
447
|
+
// 'password' - Password-safe characters
|
|
448
|
+
|
|
449
|
+
// Convenience methods
|
|
450
|
+
const uuid = await sv.rng.uuid(); // UUID v4
|
|
451
|
+
const password = await sv.rng.password(16); // 16-char password
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## Configuration
|
|
455
|
+
|
|
456
|
+
```javascript
|
|
457
|
+
const sv = SparkVault.init({
|
|
458
|
+
// Required
|
|
459
|
+
accountId: 'acc_your_account', // Your SparkVault account ID
|
|
460
|
+
|
|
461
|
+
// Optional
|
|
462
|
+
locale: 'en', // Default UI locale
|
|
463
|
+
timeout: 30000, // Request timeout in ms (default: 30000)
|
|
464
|
+
preloadConfig: true // Preload Identity config on init (default: true)
|
|
465
|
+
});
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Configuration Options
|
|
469
|
+
|
|
470
|
+
| Option | Type | Default | Description |
|
|
471
|
+
|--------|------|---------|-------------|
|
|
472
|
+
| `accountId` | `string` | **required** | Your SparkVault account ID (starts with `acc_`) |
|
|
473
|
+
| `locale` | `string` | `'en'` | Default UI locale for the Identity modal |
|
|
474
|
+
| `timeout` | `number` | `30000` | Request timeout in milliseconds |
|
|
475
|
+
| `preloadConfig` | `boolean` | `true` | Preload Identity configuration on SDK init |
|
|
476
|
+
|
|
477
|
+
### Config Preloading
|
|
478
|
+
|
|
479
|
+
By default, the SDK preloads your Identity configuration in the background when `SparkVault.init()` is called. This means when the user clicks your "Sign In" button and you call `pop()`, the modal opens **instantly** without a loading spinner.
|
|
480
|
+
|
|
481
|
+
```javascript
|
|
482
|
+
// Default behavior (preloadConfig: true)
|
|
483
|
+
// Config is fetched immediately when SDK initializes
|
|
484
|
+
const sv = SparkVault.init({ accountId: 'acc_xxx' });
|
|
485
|
+
|
|
486
|
+
// Later, when user clicks "Sign In"...
|
|
487
|
+
await sv.identity.pop(); // Opens instantly - config already loaded!
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
If you want to defer config loading until `pop()` is called (the legacy behavior), disable preloading:
|
|
491
|
+
|
|
492
|
+
```javascript
|
|
493
|
+
// Disable preloading - config loads when pop() is called
|
|
494
|
+
const sv = SparkVault.init({
|
|
495
|
+
accountId: 'acc_xxx',
|
|
496
|
+
preloadConfig: false
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
// Config loads on-demand with a brief loading spinner
|
|
500
|
+
await sv.identity.pop();
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Environments
|
|
504
|
+
|
|
505
|
+
| Environment | API Base URL | Use Case |
|
|
506
|
+
|-------------|--------------|----------|
|
|
507
|
+
| `production` | `https://api.sparkvault.com` | Live applications |
|
|
508
|
+
| `sandbox` | `https://sandbox.api.sparkvault.com` | Testing and development |
|
|
509
|
+
|
|
510
|
+
## Error Handling
|
|
511
|
+
|
|
512
|
+
The SDK provides typed errors for different failure scenarios:
|
|
513
|
+
|
|
514
|
+
```javascript
|
|
515
|
+
import {
|
|
516
|
+
SparkVaultError, // Base error class
|
|
517
|
+
ValidationError, // Invalid input (400)
|
|
518
|
+
AuthenticationError, // Not authenticated (401)
|
|
519
|
+
AuthorizationError, // Not authorized (403)
|
|
520
|
+
NetworkError, // Network failure
|
|
521
|
+
TimeoutError, // Request timeout
|
|
522
|
+
PopupBlockedError, // Popup was blocked
|
|
523
|
+
UserCancelledError // User closed popup
|
|
524
|
+
} from '@sparkvault/sdk';
|
|
525
|
+
|
|
526
|
+
try {
|
|
527
|
+
await sv.identity.pop();
|
|
528
|
+
} catch (error) {
|
|
529
|
+
if (error instanceof PopupBlockedError) {
|
|
530
|
+
alert('Please allow popups for this site');
|
|
531
|
+
} else if (error instanceof UserCancelledError) {
|
|
532
|
+
console.log('User cancelled verification');
|
|
533
|
+
} else if (error instanceof ValidationError) {
|
|
534
|
+
console.error('Validation failed:', error.message);
|
|
535
|
+
console.error('Details:', error.details);
|
|
536
|
+
} else if (error instanceof AuthenticationError) {
|
|
537
|
+
console.error('Authentication failed:', error.message);
|
|
538
|
+
} else if (error instanceof NetworkError) {
|
|
539
|
+
console.error('Network error:', error.message);
|
|
540
|
+
} else if (error instanceof TimeoutError) {
|
|
541
|
+
console.error('Request timed out');
|
|
542
|
+
} else {
|
|
543
|
+
console.error('Unknown error:', error);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Error Properties
|
|
549
|
+
|
|
550
|
+
All errors extend `SparkVaultError` and include:
|
|
551
|
+
|
|
552
|
+
```typescript
|
|
553
|
+
interface SparkVaultError extends Error {
|
|
554
|
+
message: string; // Human-readable message
|
|
555
|
+
code: string; // Error code (e.g., 'validation_error')
|
|
556
|
+
statusCode?: number; // HTTP status code if applicable
|
|
557
|
+
details?: Record<string, any>; // Additional error details
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
## TypeScript
|
|
562
|
+
|
|
563
|
+
The SDK is written in TypeScript and includes full type definitions:
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
import {
|
|
567
|
+
SparkVault,
|
|
568
|
+
SparkVaultConfig,
|
|
569
|
+
VerifyOptions,
|
|
570
|
+
RenderOptions,
|
|
571
|
+
VerifyResult,
|
|
572
|
+
TokenClaims,
|
|
573
|
+
AuthMethod,
|
|
574
|
+
CreateSparkOptions,
|
|
575
|
+
Spark,
|
|
576
|
+
SparkPayload,
|
|
577
|
+
CreateVaultOptions,
|
|
578
|
+
Vault,
|
|
579
|
+
UnsealedVault,
|
|
580
|
+
Ingot,
|
|
581
|
+
UploadIngotOptions,
|
|
582
|
+
GenerateOptions,
|
|
583
|
+
RandomResult,
|
|
584
|
+
RNGFormat
|
|
585
|
+
} from '@sparkvault/sdk';
|
|
586
|
+
|
|
587
|
+
// All methods are fully typed
|
|
588
|
+
const sv = SparkVault.init({
|
|
589
|
+
accountId: 'acc_test'
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// TypeScript knows the return types
|
|
593
|
+
const result: VerifyResult = await sv.identity.pop();
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
## Security
|
|
597
|
+
|
|
598
|
+
### Token Security
|
|
599
|
+
|
|
600
|
+
- All tokens are Ed25519-signed JWTs
|
|
601
|
+
- Tokens are validated for expiration and issuer
|
|
602
|
+
- Tokens are short-lived (1 hour default) and scoped to your account
|
|
603
|
+
- **Tokens are single-use verification proofs** — not session tokens
|
|
604
|
+
|
|
605
|
+
### Session Management
|
|
606
|
+
|
|
607
|
+
SparkVault Identity follows the same pattern as "Login with Google" and other major IdPs:
|
|
608
|
+
|
|
609
|
+
1. **SparkVault verifies identity** → Returns signed ID token
|
|
610
|
+
2. **Your backend validates the token** → Checks signature via JWKS
|
|
611
|
+
3. **Your backend creates YOUR session** → Cookie, JWT, database session
|
|
612
|
+
4. **Token is discarded** → Your session takes over
|
|
613
|
+
|
|
614
|
+
There are no refresh tokens by design. Your application owns the user relationship and decides session lifetime, storage, and re-verification policy. This is the industry standard approach used by Google, Okta, Auth0, and all major identity providers.
|
|
615
|
+
|
|
616
|
+
### Popup Security
|
|
617
|
+
|
|
618
|
+
- Origin validation prevents cross-origin attacks
|
|
619
|
+
- `postMessage` is used securely with origin checking
|
|
620
|
+
- Popups are isolated from your main window context
|
|
621
|
+
|
|
622
|
+
### API Security
|
|
623
|
+
|
|
624
|
+
- All requests use HTTPS
|
|
625
|
+
- The SDK only requires your account ID (no secrets in client-side code)
|
|
626
|
+
|
|
627
|
+
### Best Practices
|
|
628
|
+
|
|
629
|
+
1. **Validate tokens server-side** - Don't trust client-side token validation alone
|
|
630
|
+
2. **Use HTTPS** - Always serve your application over HTTPS
|
|
631
|
+
3. **Keep VMKs secure** - Vault Master Keys should be stored securely by users
|
|
632
|
+
|
|
633
|
+
## Development
|
|
634
|
+
|
|
635
|
+
### Setup
|
|
636
|
+
|
|
637
|
+
```bash
|
|
638
|
+
git clone https://github.com/Spark-Vault/sdk-js.git
|
|
639
|
+
cd sdk-js
|
|
640
|
+
npm install
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### Scripts
|
|
644
|
+
|
|
645
|
+
```bash
|
|
646
|
+
npm run build # Build all bundles
|
|
647
|
+
npm run build:watch # Build with watch mode
|
|
648
|
+
npm run typecheck # Run TypeScript type checking
|
|
649
|
+
npm run lint # Run ESLint
|
|
650
|
+
npm run test # Run tests
|
|
651
|
+
npm run test:watch # Run tests in watch mode
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
### Project Structure
|
|
655
|
+
|
|
656
|
+
```
|
|
657
|
+
sdk-js/
|
|
658
|
+
├── src/
|
|
659
|
+
│ ├── index.ts # Main entry point
|
|
660
|
+
│ ├── config.ts # Configuration management
|
|
661
|
+
│ ├── http.ts # HTTP client
|
|
662
|
+
│ ├── errors.ts # Error types
|
|
663
|
+
│ ├── identity/ # Identity module
|
|
664
|
+
│ │ ├── index.ts
|
|
665
|
+
│ │ ├── modal.ts # Popup manager
|
|
666
|
+
│ │ └── types.ts
|
|
667
|
+
│ ├── sparks/ # Sparks module
|
|
668
|
+
│ │ ├── index.ts
|
|
669
|
+
│ │ └── types.ts
|
|
670
|
+
│ ├── vaults/ # Vaults module
|
|
671
|
+
│ │ ├── index.ts
|
|
672
|
+
│ │ └── types.ts
|
|
673
|
+
│ └── rng/ # RNG module
|
|
674
|
+
│ ├── index.ts
|
|
675
|
+
│ └── types.ts
|
|
676
|
+
├── dist/ # Built bundles
|
|
677
|
+
├── tests/ # Test files
|
|
678
|
+
├── .github/workflows/ # CI/CD workflows
|
|
679
|
+
├── rollup.config.js # Rollup bundler config
|
|
680
|
+
├── tsconfig.json # TypeScript config
|
|
681
|
+
└── package.json
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
### CI/CD
|
|
685
|
+
|
|
686
|
+
The SDK uses GitHub Actions for automated testing and deployment:
|
|
687
|
+
|
|
688
|
+
- **On PR**: Runs build, lint, typecheck, and tests
|
|
689
|
+
- **On push to main**: Deploys to CDN (`cdn.sparkvault.com`)
|
|
690
|
+
- **On release commit**: Publishes to npm
|
|
691
|
+
|
|
692
|
+
Required secrets for deployment:
|
|
693
|
+
- `CLOUDFLARE_API_TOKEN` - Cloudflare API token with R2 access
|
|
694
|
+
- `CLOUDFLARE_ACCOUNT_ID` - Cloudflare account ID
|
|
695
|
+
- `NPM_TOKEN` - npm publish token (for releases)
|
|
696
|
+
|
|
697
|
+
## Browser Support
|
|
698
|
+
|
|
699
|
+
- Chrome 80+
|
|
700
|
+
- Firefox 75+
|
|
701
|
+
- Safari 13.1+
|
|
702
|
+
- Edge 80+
|
|
703
|
+
|
|
704
|
+
The SDK requires:
|
|
705
|
+
- `fetch` API
|
|
706
|
+
- `Promise`
|
|
707
|
+
- `window.open` (for Identity popup)
|
|
708
|
+
- `postMessage` (for popup communication)
|
|
709
|
+
|
|
710
|
+
## License
|
|
711
|
+
|
|
712
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
713
|
+
|
|
714
|
+
## Links
|
|
715
|
+
|
|
716
|
+
- [SparkVault Documentation](https://sparkvault.com/api/docs)
|
|
717
|
+
- [SDK API Reference](https://sparkvault.com/api/docs/sdk)
|
|
718
|
+
- [GitHub Repository](https://github.com/Spark-Vault/sdk-js)
|
|
719
|
+
- [npm Package](https://www.npmjs.com/package/@sparkvault/sdk)
|
|
720
|
+
- [Report Issues](https://github.com/Spark-Vault/sdk-js/issues)
|