iframe.io 1.1.0 → 1.3.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 CHANGED
@@ -4,8 +4,10 @@ Easy and friendly API to connect and interact between content window and its con
4
4
 
5
5
  ## New Features & Improvements
6
6
 
7
- ### 🆕 Version 1.1.0 Updates
7
+ ### 🆕 Version 1.3.0 Updates
8
8
 
9
+ - **📋 Protocol Versioning**: Message format versioning for future-proof evolution
10
+ - **🔐 Session Key Rotation**: Opt-in session-derived keys for high-security applications
9
11
  - **🔒 Enhanced Security**: Origin validation, message sanitization, and payload size limits
10
12
  - **🔄 Auto-Reconnection**: Automatic reconnection with exponential backoff strategy
11
13
  - **💓 Heartbeat Monitoring**: Connection health monitoring with configurable intervals
@@ -78,6 +80,277 @@ iframeIO.on('hello', (data) => {
78
80
  })
79
81
  ```
80
82
 
83
+ ## Protocol Versioning
84
+
85
+ ### What is Protocol Versioning?
86
+
87
+ Every message sent includes a protocol version number (`v` field). This allows the library to evolve over time while maintaining backward compatibility. If a peer receives a message with an unsupported version, it can handle it gracefully.
88
+
89
+ ### Current Version
90
+
91
+ The current protocol version is **v1**.
92
+
93
+ ### How It Works
94
+
95
+ ```javascript
96
+ // All messages automatically include version
97
+ const messageData = {
98
+ v: 1, // Protocol version
99
+ _event: 'userAction',
100
+ payload: { action: 'click' },
101
+ timestamp: 1609459200000
102
+ }
103
+ ```
104
+
105
+ ### Version Checking
106
+
107
+ ```javascript
108
+ // Library automatically handles version checking
109
+ iframeIO.on('error', (error) => {
110
+ if (error.type === 'UNSUPPORTED_VERSION') {
111
+ console.log(`Peer using v${error.received}, we support v${error.supported}`)
112
+ // Handle gracefully - maybe show upgrade notice
113
+ }
114
+ })
115
+ ```
116
+
117
+ ### Get Version Information
118
+
119
+ ```javascript
120
+ const stats = iframeIO.getStats()
121
+ console.log(`Our version: v${stats.protocolVersion}`)
122
+ console.log(`Peer version: v${stats.peerProtocolVersion}`)
123
+ ```
124
+
125
+ ### Future-Proofing Benefits
126
+
127
+ 1. **Seamless Upgrades**: Deploy new versions without breaking old clients
128
+ 2. **Feature Detection**: Enable features based on peer capabilities
129
+ 3. **Debugging**: Identify which version caused issues
130
+ 4. **Graceful Degradation**: Fall back to older protocol when needed
131
+
132
+ ## Session Key Rotation (Opt-In)
133
+
134
+ ### When to Use Session Keys
135
+
136
+ Enable session key rotation for:
137
+ - ✅ **Long-lived connections** (> 1 hour)
138
+ - ✅ **High-security applications** (banking, healthcare)
139
+ - ✅ **Compliance requirements** (PCI-DSS, HIPAA, SOC 2)
140
+ - ✅ **Multiple concurrent iframe connections**
141
+ - ✅ **Applications handling sensitive data**
142
+
143
+ Don't enable for:
144
+ - ❌ Short-lived connections (< 30 minutes)
145
+ - ❌ Low-risk internal tools
146
+ - ❌ Same-origin communication
147
+ - ❌ Applications with minimal security requirements
148
+
149
+ ### Basic Configuration
150
+
151
+ ```javascript
152
+ const iframeIO = new IOF({
153
+ type: 'WINDOW',
154
+ cryptoAuth: {
155
+ secret: 'your-master-secret-key',
156
+ requireSigned: true,
157
+
158
+ // Enable session key rotation
159
+ enableSessionKeys: true,
160
+ sessionKeyRotationInterval: 3600000 // 1 hour (default)
161
+ }
162
+ })
163
+ ```
164
+
165
+ ### How It Works
166
+
167
+ 1. **Connection**: Normal ping/pong handshake
168
+ 2. **Key Exchange**: Peers exchange random session IDs
169
+ 3. **Key Derivation**: Both derive identical session key using HKDF
170
+ 4. **Secure Communication**: All signed messages use session key
171
+ 5. **Periodic Rotation**: New key derived every rotation interval
172
+ 6. **Graceful Transition**: Old key accepted during grace period
173
+
174
+ ```
175
+ Parent IFrame
176
+ | |
177
+ |---- ping -------------------->|
178
+ |<--- pong ----------------------|
179
+ | |
180
+ |-- __session_key_init -------->|
181
+ | (sessionId: abc123) |
182
+ | |
183
+ |<- __session_key_ack -----------|
184
+ | (sessionId: def456, keyId) |
185
+ | |
186
+ [Both derive: key = HKDF(master, abc123+def456, keyId)]
187
+ | |
188
+ |-- signed message (keyId) ---->|
189
+ |<- signed message (keyId) ------|
190
+ | |
191
+ [After rotation interval] |
192
+ |-- __session_key_rotate ------>|
193
+ | (newKeyId) |
194
+ | |
195
+ [Both derive new key] |
196
+ ```
197
+
198
+ ### Configuration Options
199
+
200
+ ```javascript
201
+ const iframeIO = new IOF({
202
+ type: 'WINDOW',
203
+ debug: true,
204
+ cryptoAuth: {
205
+ // Master secret (never transmitted)
206
+ secret: 'replace-with-shared-secret',
207
+
208
+ // Require all messages to be signed
209
+ requireSigned: true,
210
+
211
+ // Clock skew tolerance (2 minutes default)
212
+ maxSkewMs: 120000,
213
+
214
+ // Replay protection window (500 nonces default)
215
+ replayWindowSize: 500,
216
+
217
+ // SESSION KEY ROTATION (opt-in)
218
+ enableSessionKeys: true,
219
+
220
+ // Rotate every hour (adjust based on security needs)
221
+ // - High security: 15-30 minutes
222
+ // - Standard: 1 hour
223
+ // - Low risk: 2-4 hours
224
+ sessionKeyRotationInterval: 3600000
225
+ }
226
+ })
227
+ ```
228
+
229
+ ### Monitoring Session Keys
230
+
231
+ ```javascript
232
+ // Listen for session key events
233
+ iframeIO.on('session_key_established', (data) => {
234
+ console.log(`Session key established: ${data.keyId}`)
235
+ })
236
+
237
+ iframeIO.on('session_key_rotating', (data) => {
238
+ console.log(`Rotating to new key: ${data.keyId}`)
239
+ })
240
+
241
+ iframeIO.on('session_key_rotated', (data) => {
242
+ console.log(`Peer rotated to: ${data.keyId}`)
243
+ })
244
+
245
+ // Check current key status
246
+ const stats = iframeIO.getStats()
247
+ console.log(`Session key active: ${stats.sessionKeyActive}`)
248
+ console.log(`Current key ID: ${stats.sessionKeyId}`)
249
+ ```
250
+
251
+ ### Security Considerations
252
+
253
+ **✅ What Session Keys Provide:**
254
+ - Forward secrecy: Past sessions remain secure if master key leaks
255
+ - Session isolation: Each connection uses unique keys
256
+ - Automatic rotation: Limits exposure window
257
+ - Replay protection: Per-session nonce tracking
258
+
259
+ **⚠️ Important Security Notes:**
260
+
261
+ 1. **Not a Sandbox Boundary**: If attacker can execute JS in either peer, they can read keys
262
+ 2. **Master Secret Security**: Protect your master secret like a password
263
+ 3. **HTTPS Required**: Always use HTTPS for iframe communication
264
+ 4. **Origin Validation**: Session keys don't replace origin checking
265
+
266
+ ### Performance Impact
267
+
268
+ Session key rotation has minimal performance impact:
269
+ - **Key derivation**: ~5-10ms (uses WebCrypto HKDF)
270
+ - **Memory**: ~1KB per active key
271
+ - **Network**: 3 small handshake messages on connect
272
+ - **CPU**: Negligible during rotation (background process)
273
+
274
+ ### Example: Banking Application
275
+
276
+ ```javascript
277
+ // High-security banking app
278
+ const bankingIO = new IOF({
279
+ type: 'WINDOW',
280
+ debug: false,
281
+ cryptoAuth: {
282
+ secret: process.env.IFRAME_MASTER_SECRET,
283
+ requireSigned: true,
284
+ enableSessionKeys: true,
285
+ sessionKeyRotationInterval: 1800000 // 30 minutes
286
+ },
287
+ // Additional security
288
+ allowedIncomingEvents: [
289
+ 'transaction_request',
290
+ 'balance_query',
291
+ 'account_info'
292
+ ],
293
+ validateIncoming: (event, payload, origin) => {
294
+ // Validate payload structure
295
+ if (event === 'transaction_request') {
296
+ return payload &&
297
+ typeof payload.amount === 'number' &&
298
+ typeof payload.recipient === 'string'
299
+ }
300
+ return true
301
+ }
302
+ })
303
+
304
+ // Monitor security events
305
+ bankingIO.on('session_key_rotating', () => {
306
+ console.log('Security: Rotating session keys')
307
+ // Log to security audit trail
308
+ })
309
+
310
+ bankingIO.on('error', (error) => {
311
+ if (error.type === 'AUTH_FAILED') {
312
+ console.error('Security: Authentication failed')
313
+ // Trigger security alert
314
+ }
315
+ })
316
+ ```
317
+
318
+ ### Example: Healthcare Application (HIPAA Compliance)
319
+
320
+ ```javascript
321
+ // HIPAA-compliant healthcare app
322
+ const healthcareIO = new IOF({
323
+ type: 'IFRAME',
324
+ debug: false,
325
+ cryptoAuth: {
326
+ secret: process.env.PHI_MASTER_SECRET,
327
+ requireSigned: true,
328
+ enableSessionKeys: true,
329
+ sessionKeyRotationInterval: 3600000 // 1 hour
330
+ },
331
+ maxMessageSize: 512 * 1024, // 512KB limit for PHI
332
+ heartbeatInterval: 60000 // 1 minute health check
333
+ })
334
+
335
+ // Audit logging
336
+ healthcareIO.on('session_key_established', (data) => {
337
+ auditLog({
338
+ event: 'SESSION_KEY_ESTABLISHED',
339
+ keyId: data.keyId,
340
+ timestamp: new Date().toISOString(),
341
+ user: getCurrentUser()
342
+ })
343
+ })
344
+
345
+ healthcareIO.on('connect', () => {
346
+ // Send encrypted patient data
347
+ healthcareIO.emitSigned('patient_data', {
348
+ patientId: 'encrypted-id',
349
+ records: encryptedRecords
350
+ })
351
+ })
352
+ ```
353
+
81
354
  ## Enhanced Configuration Options
82
355
 
83
356
  ```javascript
@@ -89,7 +362,18 @@ const iframeIO = new IOF({
89
362
  maxMessageSize: 1024 * 1024, // Max message size in bytes (1MB)
90
363
  maxMessagesPerSecond: 100, // Rate limit (100 messages/second)
91
364
  autoReconnect: true, // Enable automatic reconnection
92
- messageQueueSize: 50 // Max queued messages when disconnected
365
+ messageQueueSize: 50, // Max queued messages when disconnected
366
+ allowedIncomingEvents: ['hello', 'response'], // Optional incoming event allowlist
367
+ validateIncoming: (event, payload, origin) => true, // Optional custom validator
368
+ cryptoAuth: {
369
+ secret: 'replace-with-shared-secret',
370
+ requireSigned: false,
371
+ maxSkewMs: 120000, // 2 minutes clock skew
372
+ replayWindowSize: 500,
373
+ // Session key rotation (opt-in)
374
+ enableSessionKeys: false, // Set to true for high-security apps
375
+ sessionKeyRotationInterval: 3600000 // 1 hour
376
+ }
93
377
  })
94
378
  ```
95
379
 
@@ -98,9 +382,9 @@ const iframeIO = new IOF({
98
382
  ### Send Messages with Acknowledgments
99
383
 
100
384
  ```javascript
101
- // Send message and wait for acknowledgment with timeout
385
+ // Send message and wait for response with timeout
102
386
  try {
103
- const response = await iframeIO.emitAsync('getData', { id: 123 }, 10000) // 10s timeout
387
+ const response = await iframeIO.emitAsync('getData', { id: 123 }, 10000)
104
388
  console.log('Response:', response)
105
389
  } catch (error) {
106
390
  console.error('Request failed:', error.message)
@@ -110,9 +394,9 @@ try {
110
394
  iframeIO.on('getData', async (data, ack) => {
111
395
  try {
112
396
  const result = await fetchData(data.id)
113
- ack(false, result) // Success: ack(error, ...response)
397
+ ack(false, result)
114
398
  } catch (error) {
115
- ack(error.message) // Error: ack(errorMessage)
399
+ ack(error.message)
116
400
  }
117
401
  })
118
402
  ```
@@ -122,15 +406,11 @@ iframeIO.on('getData', async (data, ack) => {
122
406
  ```javascript
123
407
  // Wait for connection with timeout
124
408
  try {
125
- await iframeIO.connectAsync(5000) // 5 second timeout
409
+ await iframeIO.connectAsync(5000)
126
410
  console.log('Connection established!')
127
411
  } catch (error) {
128
412
  console.error('Connection failed:', error.message)
129
413
  }
130
-
131
- // Wait for single event
132
- const userData = await iframeIO.onceAsync('userProfile')
133
- console.log('User data received:', userData)
134
414
  ```
135
415
 
136
416
  ## Enhanced Connection Management
@@ -165,7 +445,11 @@ console.log(stats)
165
445
  // queuedMessages: 0,
166
446
  // reconnectAttempts: 0,
167
447
  // activeListeners: 5,
168
- // messageRate: 2
448
+ // messageRate: 2,
449
+ // protocolVersion: 1,
450
+ // peerProtocolVersion: 1,
451
+ // sessionKeyActive: true,
452
+ // sessionKeyId: 'key-1609459200000-abc123'
169
453
  // }
170
454
  ```
171
455
 
@@ -175,9 +459,8 @@ console.log(stats)
175
459
 
176
460
  ```javascript
177
461
  // Strict origin checking
178
- iframeIO.listen('https://trusted-domain.com') // Only accept from this origin
462
+ iframeIO.listen('https://trusted-domain.com')
179
463
 
180
- // Error handling for invalid origins
181
464
  iframeIO.on('error', (error) => {
182
465
  if (error.type === 'INVALID_ORIGIN') {
183
466
  console.log(`Rejected message from ${error.received}`)
@@ -188,72 +471,28 @@ iframeIO.on('error', (error) => {
188
471
  ### Message Sanitization
189
472
 
190
473
  ```javascript
191
- // Automatic payload sanitization removes functions and undefined values
474
+ // Automatic payload sanitization
192
475
  iframeIO.emit('data', {
193
476
  text: 'Hello',
194
- func: () => {}, // Functions are automatically removed
195
- undef: undefined // Undefined values are automatically removed
477
+ func: () => {}, // Automatically removed
478
+ undef: undefined // Automatically removed
196
479
  })
197
480
  ```
198
481
 
199
- ### Rate Limiting
482
+ ### Cryptographic Message Authentication
200
483
 
201
484
  ```javascript
202
485
  const iframeIO = new IOF({
203
- maxMessagesPerSecond: 10 // Limit to 10 messages per second
204
- })
205
-
206
- iframeIO.on('error', (error) => {
207
- if (error.type === 'RATE_LIMIT_EXCEEDED') {
208
- console.log(`Rate limited: ${error.current}/${error.limit}`)
209
- }
210
- })
211
- ```
212
-
213
- ## Comprehensive Error Handling
214
-
215
- ```javascript
216
- iframeIO.on('error', (error) => {
217
- switch (error.type) {
218
- case 'INVALID_ORIGIN':
219
- console.error(`Invalid origin: expected ${error.expected}, got ${error.received}`)
220
- break
221
- case 'ORIGIN_MISMATCH':
222
- console.error(`Origin mismatch: expected ${error.expected}, got ${error.received}`)
223
- break
224
- case 'RATE_LIMIT_EXCEEDED':
225
- console.warn(`Rate limit exceeded: ${error.current}/${error.limit} messages/second`)
226
- break
227
- case 'MESSAGE_HANDLING_ERROR':
228
- console.error(`Error handling event ${error.event}: ${error.error}`)
229
- break
230
- case 'EMIT_ERROR':
231
- console.error(`Error sending event ${error.event}: ${error.error}`)
232
- break
233
- case 'LISTENER_ERROR':
234
- console.error(`Error in listener for ${error.event}: ${error.error}`)
235
- break
236
- case 'NO_CONNECTION':
237
- console.error(`Attempted to send ${error.event} without connection`)
238
- break
239
- default:
240
- console.error('Unknown error:', error)
486
+ type: 'WINDOW',
487
+ cryptoAuth: {
488
+ secret: 'replace-with-shared-secret',
489
+ requireSigned: true
241
490
  }
242
491
  })
243
- ```
244
-
245
- ## Message Queuing
246
492
 
247
- ```javascript
248
- // Messages are automatically queued when disconnected
249
- iframeIO.emit('important-data', { data: 'This will be queued if disconnected' })
250
-
251
- // Clear queue manually if needed
252
- iframeIO.clearQueue()
253
-
254
- // Check queue status
255
- const stats = iframeIO.getStats()
256
- console.log(`${stats.queuedMessages} messages queued`)
493
+ // Send signed messages
494
+ await iframeIO.emitSigned('hello', { msg: 'signed' })
495
+ const reply = await iframeIO.emitAsyncSigned('getData', { id: 123 }, 5000)
257
496
  ```
258
497
 
259
498
  ## API Reference
@@ -261,24 +500,26 @@ console.log(`${stats.queuedMessages} messages queued`)
261
500
  ### New Methods
262
501
 
263
502
  #### Async Methods
264
- - **`emitAsync(event, payload?, timeout?)`** - Send message and wait for response (Promise)
265
- - **`connectAsync(timeout?)`** - Wait for connection with timeout (Promise)
266
- - **`onceAsync(event)`** - Wait for single event (Promise)
503
+ - **`emitAsync(event, payload?, timeout?)`** - Send message and wait for response
504
+ - **`emitAsyncSigned(event, payload?, timeout?)`** - Send signed message and wait for response
505
+ - **`connectAsync(timeout?)`** - Wait for connection with timeout
506
+ - **`onceAsync(event)`** - Wait for single event
267
507
 
268
508
  #### Utility Methods
269
- - **`getStats()`** - Get connection statistics
509
+ - **`getStats()`** - Get connection statistics (includes version and session key info)
270
510
  - **`clearQueue()`** - Clear queued messages
271
511
 
272
512
  ### Connection Methods
273
513
 
274
- - **`initiate(contentWindow, iframeOrigin)`** - Establish connection (WINDOW peer only)
275
- - **`listen(hostOrigin?)`** - Listen for connection (IFRAME peer only)
514
+ - **`initiate(contentWindow, iframeOrigin)`** - Establish connection (WINDOW peer)
515
+ - **`listen(hostOrigin?)`** - Listen for connection (IFRAME peer)
276
516
  - **`disconnect(callback?)`** - Disconnect and cleanup
277
517
  - **`isConnected()`** - Check connection status
278
518
 
279
519
  ### Messaging Methods
280
520
 
281
521
  - **`emit(event, payload?, callback?)`** - Send message
522
+ - **`emitSigned(event, payload?, callback?)`** - Send signed message
282
523
  - **`on(event, listener)`** - Add event listener
283
524
  - **`once(event, listener)`** - Add one-time event listener
284
525
  - **`off(event, listener?)`** - Remove event listener(s)
@@ -292,6 +533,11 @@ console.log(`${stats.queuedMessages} messages queued`)
292
533
  - **`reconnecting`** - Reconnection attempt started
293
534
  - **`reconnection_failed`** - All reconnection attempts failed
294
535
 
536
+ #### Session Key Events (when enabled)
537
+ - **`session_key_established`** - Session key derived and active
538
+ - **`session_key_rotating`** - New key being generated
539
+ - **`session_key_rotated`** - Peer rotated to new key
540
+
295
541
  #### Error Events
296
542
  - **`error`** - Various error conditions with detailed error objects
297
543
 
@@ -300,33 +546,24 @@ console.log(`${stats.queuedMessages} messages queued`)
300
546
  Full TypeScript support with comprehensive type definitions:
301
547
 
302
548
  ```typescript
303
- import IOF, { Options, Listener, AckFunction } from 'iframe.io'
549
+ import IOF, { Options, Listener, AckFunction, SessionKeyInfo } from 'iframe.io'
304
550
 
305
551
  const options: Options = {
306
552
  type: 'WINDOW',
307
553
  debug: true,
308
- heartbeatInterval: 30000,
309
- maxMessageSize: 512 * 1024
554
+ cryptoAuth: {
555
+ secret: 'my-secret',
556
+ enableSessionKeys: true,
557
+ sessionKeyRotationInterval: 1800000
558
+ }
310
559
  }
311
560
 
312
561
  const iframeIO = new IOF(options)
313
562
 
314
- // Typed event listeners
315
- iframeIO.on('userAction', (data: { action: string; userId: number }) => {
316
- console.log(`User ${data.userId} performed ${data.action}`)
563
+ // Session key events are typed
564
+ iframeIO.on('session_key_established', (data: { keyId: string }) => {
565
+ console.log(`Key established: ${data.keyId}`)
317
566
  })
318
-
319
- // Typed async responses
320
- interface ApiResponse {
321
- success: boolean
322
- data: any[]
323
- }
324
-
325
- const response = await iframeIO.emitAsync<{ query: string }, ApiResponse>(
326
- 'search',
327
- { query: 'hello' },
328
- 5000 // 5 second timeout
329
- )
330
567
  ```
331
568
 
332
569
  ## Error Types Reference
@@ -335,11 +572,16 @@ const response = await iframeIO.emitAsync<{ query: string }, ApiResponse>(
335
572
  |------------|-------------|
336
573
  | `INVALID_ORIGIN` | Message from unexpected origin |
337
574
  | `ORIGIN_MISMATCH` | Origin changed during session |
575
+ | `UNSUPPORTED_VERSION` | Peer using unsupported protocol version |
338
576
  | `MESSAGE_HANDLING_ERROR` | Error processing incoming message |
339
577
  | `EMIT_ERROR` | Error sending message |
340
578
  | `LISTENER_ERROR` | Error in event listener |
579
+ | `DISALLOWED_EVENT` | Event rejected by allowlist |
580
+ | `INVALID_MESSAGE` | Message rejected by validator |
581
+ | `AUTH_FAILED` | Cryptographic authentication failed |
582
+ | `AUTH_ERROR` | Crypto verification errored |
341
583
  | `RATE_LIMIT_EXCEEDED` | Too many messages sent |
342
- | `NO_CONNECTION` | Attempted to send without connection |
584
+ | `NO_CONNECTION` | Attempted send without connection |
343
585
 
344
586
  ## Browser Compatibility
345
587
 
@@ -348,37 +590,70 @@ const response = await iframeIO.emitAsync<{ query: string }, ApiResponse>(
348
590
  - Safari 12+
349
591
  - Edge 79+
350
592
 
593
+ WebCrypto API required for session key rotation feature.
594
+
351
595
  ## Migration Guide
352
596
 
353
- ### From v1.0.x to v1.1.0
597
+ ### From v1.2.x to v1.3.0
354
598
 
355
599
  All existing code continues to work without changes. New features are additive:
356
600
 
357
601
  ```javascript
358
602
  // Old way (still works)
359
- iframeIO.emit('getData', { id: 123 }, (error, result) => {
360
- if (error) {
361
- console.error('Error:', error)
362
- } else {
363
- console.log('Result:', result)
603
+ const iframeIO = new IOF({
604
+ type: 'WINDOW',
605
+ cryptoAuth: {
606
+ secret: 'my-secret'
364
607
  }
365
608
  })
366
609
 
367
- // New async way
368
- try {
369
- const result = await iframeIO.emitAsync('getData', { id: 123 })
370
- console.log('Result:', result)
371
- } catch (error) {
372
- console.error('Error:', error.message)
373
- }
610
+ // New way with session keys (opt-in)
611
+ const iframeIO = new IOF({
612
+ type: 'WINDOW',
613
+ cryptoAuth: {
614
+ secret: 'my-secret',
615
+ enableSessionKeys: true // Enable for high-security apps
616
+ }
617
+ })
618
+
619
+ // Protocol version is automatic - no code changes needed
374
620
  ```
375
621
 
376
622
  ## Performance Considerations
377
623
 
378
- - **Message Size**: Keep messages under the configured `maxMessageSize` (default 1MB)
379
- - **Rate Limiting**: Respect the `maxMessagesPerSecond` limit (default 100/sec)
624
+ - **Message Size**: Keep under `maxMessageSize` (default 1MB)
625
+ - **Rate Limiting**: Respect `maxMessagesPerSecond` (default 100/sec)
380
626
  - **Queue Size**: Monitor queued messages to avoid memory issues
381
- - **Heartbeat**: Adjust `heartbeatInterval` based on your reliability needs
627
+ - **Heartbeat**: Adjust `heartbeatInterval` based on needs
628
+ - **Session Keys**: Minimal overhead (~5-10ms derivation, ~1KB memory)
629
+
630
+ ## Best Practices
631
+
632
+ ### Security
633
+
634
+ 1. **Always use HTTPS** for production deployments
635
+ 2. **Validate origins** strictly in both peers
636
+ 3. **Enable session keys** for applications handling sensitive data
637
+ 4. **Use allowedIncomingEvents** to limit attack surface
638
+ 5. **Implement custom validation** for critical payloads
639
+ 6. **Monitor error events** for security incidents
640
+ 7. **Rotate master secrets** periodically (outside of session rotation)
641
+
642
+ ### Performance
643
+
644
+ 1. **Batch related messages** when possible
645
+ 2. **Use appropriate queue sizes** for your use case
646
+ 3. **Monitor connection stats** regularly
647
+ 4. **Adjust heartbeat intervals** based on reliability needs
648
+ 5. **Set reasonable rotation intervals** (1 hour is good default)
649
+
650
+ ### Reliability
651
+
652
+ 1. **Handle all error types** appropriately
653
+ 2. **Implement retry logic** at application level for critical operations
654
+ 3. **Use `emitAsync`** for operations requiring acknowledgment
655
+ 4. **Monitor reconnection events** and alert on failures
656
+ 5. **Test disconnection scenarios** thoroughly
382
657
 
383
658
  ## License
384
659
 
@@ -393,3 +668,25 @@ Contributions are welcome! Please read our contributing guidelines and submit pu
393
668
  - Create an issue on GitHub for bug reports
394
669
  - Check existing issues for common problems
395
670
  - Review the documentation for usage examples
671
+
672
+ ## Changelog
673
+
674
+ ### v1.3.0
675
+ - Added protocol versioning for future-proof evolution
676
+ - Added optional session key rotation for high-security applications
677
+ - Enhanced connection statistics with version and key information
678
+ - Improved error handling for version mismatches
679
+ - Added comprehensive documentation and examples
680
+
681
+ ### v1.2.0
682
+ - Enhanced security features (origin validation, sanitization, rate limiting)
683
+ - Auto-reconnection with exponential backoff
684
+ - Heartbeat monitoring
685
+ - Message queuing
686
+ - Modern async/await APIs
687
+ - Comprehensive error handling
688
+
689
+ ### v1.1.0
690
+ - Initial release
691
+ - Basic iframe communication
692
+ - Event-based API