shogun-core 3.3.4 → 3.3.5

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.
@@ -1,224 +1,313 @@
1
1
  /**
2
- * SHIP-06: Ephemeral P2P Messaging Interface
2
+ * SHIP-06: Secure Vault Interface
3
3
  *
4
- * @title ISHIP_06 - Ephemeral P2P Messaging
5
- * @notice Interface for ephemeral peer-to-peer messaging via Gun Relay
6
- * @dev Can work standalone OR with ISHIP_00 for authenticated sessions
4
+ * @title ISHIP_06 - Secure Encrypted Vault
5
+ * @notice Interface for secure encrypted key-value storage on GunDB
6
+ * @dev This interface depends on ISHIP_00 for identity and encryption
7
7
  *
8
8
  * ## Abstract
9
9
  *
10
- * This standard defines an interface for ephemeral P2P messaging that allows:
11
- * - Relay-based connections via Gun network
12
- * - End-to-end encrypted messages (no storage)
13
- * - Broadcast and direct messaging
14
- * - Deterministic room discovery (SHA-256)
15
- * - Standalone mode (no authentication needed!)
10
+ * This standard defines an interface for secure vault storage that allows:
11
+ * - End-to-end encrypted key-value storage
12
+ * - Soft delete with recovery
13
+ * - Export/import for backup
14
+ * - Rich metadata support
15
+ * - Simple, secure, focused on storage only
16
16
  *
17
17
  * ## Dependencies
18
18
  *
19
- * - Gun: Relay-based P2P database
20
- * - Gun SEA: Cryptography (ECDH + AES-GCM)
21
- * - ISHIP_00 (OPTIONAL): For authenticated sessions
22
- *
23
- * ## Modes
24
- *
25
- * **Standalone**: new SHIP_06(gunPeers[], roomId)
26
- * **With Identity**: new SHIP_06(ISHIP_00, roomId)
19
+ * - ISHIP_00: Identity and authentication layer
20
+ * - GunDB: P2P storage
21
+ * - SEA: Cryptography (AES-256-GCM)
27
22
  *
28
23
  * ## Inspiration
29
24
  *
30
- * Based on Bugoff (https://github.com/draeder/bugoff)
31
- * Simplified for Gun relay instead of WebRTC
25
+ * Based on Gunsafe (https://github.com/draeder/gunsafe)
26
+ * Adapted for Shogun ecosystem with SHIP-00 integration
32
27
  */
33
- import type { SEAPair } from "./ISHIP_00";
28
+ import type { ISHIP_00 } from "./ISHIP_00";
29
+ /**
30
+ * @notice Vault record structure
31
+ */
32
+ export interface VaultRecord {
33
+ name: string;
34
+ data: any;
35
+ created: number;
36
+ updated: number;
37
+ deleted: boolean;
38
+ metadata?: RecordMetadata;
39
+ }
40
+ /**
41
+ * @notice Encrypted record (stored in GunDB)
42
+ */
43
+ export interface EncryptedRecord {
44
+ data: string;
45
+ created: string;
46
+ updated: string;
47
+ deleted: boolean;
48
+ metadata?: string;
49
+ }
50
+ /**
51
+ * @notice Record metadata
52
+ */
53
+ export interface RecordMetadata {
54
+ type?: string;
55
+ description?: string;
56
+ tags?: string[];
57
+ expiresAt?: number;
58
+ [key: string]: any;
59
+ }
60
+ /**
61
+ * @notice Vault operation result
62
+ */
63
+ export interface VaultResult {
64
+ success: boolean;
65
+ error?: string;
66
+ recordName?: string;
67
+ recordCount?: number;
68
+ }
69
+ /**
70
+ * @notice Vault statistics
71
+ */
72
+ export interface VaultStats {
73
+ totalRecords: number;
74
+ activeRecords: number;
75
+ deletedRecords: number;
76
+ totalSize: number;
77
+ created: number;
78
+ lastModified: number;
79
+ recordsByType?: Record<string, number>;
80
+ }
34
81
  /**
35
- * @notice Ephemeral message structure
82
+ * @notice Options for retrieving records
36
83
  */
37
- export interface EphemeralMessage {
38
- from: string;
39
- fromPubKey: string;
40
- content: string;
41
- timestamp: number;
42
- type: "broadcast" | "direct";
84
+ export interface GetOptions {
85
+ includeDeleted?: boolean;
86
+ decrypt?: boolean;
43
87
  }
44
88
  /**
45
- * @notice Encrypted message data (internal)
89
+ * @notice Options for listing records
46
90
  */
47
- export interface EncryptedMessageData {
48
- content: string;
49
- fromPubKey: string;
50
- timestamp: string;
51
- type: "broadcast" | "direct";
91
+ export interface ListOptions {
92
+ includeDeleted?: boolean;
93
+ filterByTag?: string;
94
+ filterByType?: string;
95
+ sortBy?: "name" | "created" | "updated";
96
+ sortDesc?: boolean;
52
97
  }
53
98
  /**
54
- * @notice Peer information
99
+ * @notice Options for importing vault
55
100
  */
56
- export interface PeerInfo {
57
- address: string;
58
- pubKey?: string;
59
- epub?: string;
60
- connectedAt: number;
101
+ export interface ImportOptions {
102
+ merge?: boolean;
103
+ overwrite?: boolean;
104
+ skipDeleted?: boolean;
61
105
  }
62
106
  /**
63
- * @title ISHIP_06 - Ephemeral P2P Messaging
64
- * @notice Main interface for ephemeral messaging system
65
- * @dev Can work standalone (array of peers) OR with ISHIP_00 identity
107
+ * @notice Options for exporting vault
108
+ */
109
+ export interface ExportOptions {
110
+ includeDeleted?: boolean;
111
+ pretty?: boolean;
112
+ filterByTag?: string;
113
+ filterByType?: string;
114
+ }
115
+ /**
116
+ * @title ISHIP_07 - Secure Vault
117
+ * @notice Main interface for secure encrypted vault
118
+ * @dev Depends on ISHIP_00 for all identity and encryption operations
66
119
  *
67
- * Constructor patterns:
120
+ * Constructor pattern:
68
121
  * ```typescript
69
- * // Standalone mode (no authentication)
70
- * class EphemeralMessaging implements ISHIP_06 {
71
- * constructor(
72
- * peers: string[], // Gun relay peers
73
- * roomId: string,
74
- * config?: { debug?: boolean }
75
- * ) {}
76
- * }
77
- *
78
- * // Identity mode (with SHIP-00)
79
- * class EphemeralMessaging implements ISHIP_06 {
80
- * constructor(
81
- * identity: ISHIP_00, // Authenticated identity
82
- * roomId: string,
83
- * config?: EphemeralConfig
84
- * ) {}
122
+ * class SecureVault implements ISHIP_07 {
123
+ * constructor(private identity: ISHIP_00) {}
85
124
  * }
86
125
  * ```
87
126
  */
88
127
  export interface ISHIP_06 {
89
128
  /**
90
- * @notice Connect to ephemeral swarm
91
- * @dev Joins WebTorrent swarm and establishes P2P connections
92
- *
93
- * Flow:
94
- * 1. Hash room ID with SHA-256 for swarm identifier
95
- * 2. Join WebTorrent swarm with hashed ID
96
- * 3. Listen for peer connections
97
- * 4. Exchange SEA public keys with peers
98
- * 5. Establish encrypted channels
99
- */
100
- connect(): Promise<void>;
101
- /**
102
- * @notice Disconnect from swarm
103
- * @dev Closes all P2P connections and leaves swarm
104
- */
105
- disconnect(): void;
106
- /**
107
- * @notice Check if connected to swarm
108
- * @return True if connected
129
+ * @notice Get the identity provider
130
+ * @dev Returns the ISHIP_00 instance used for identity operations
131
+ * @return Identity provider instance
109
132
  */
110
- isConnected(): boolean;
133
+ getIdentity(): ISHIP_00;
111
134
  /**
112
- * @notice Get swarm identifier (SHA-256 hash of room ID)
113
- * @return Hashed swarm identifier
135
+ * @notice Initialize vault
136
+ * @dev Sets up vault node structure in user's Gun space
137
+ *
138
+ * Prerequisites:
139
+ * - User must be authenticated (via ISHIP_00)
140
+ *
141
+ * Flow:
142
+ * 1. Verify user authentication
143
+ * 2. Create vault node structure
144
+ * 3. Initialize metadata
114
145
  */
115
- getSwarmId(): string;
146
+ initialize(): Promise<void>;
116
147
  /**
117
- * @notice Get own peer address in swarm
118
- * @return Peer address
148
+ * @notice Check if vault is initialized
149
+ * @return True if vault is initialized
119
150
  */
120
- getAddress(): string;
151
+ isInitialized(): boolean;
121
152
  /**
122
- * @notice Send broadcast message to all peers in swarm
123
- * @dev Message is encrypted with each peer's public key
124
- * @param message Plain text message content
153
+ * @notice Store encrypted record in vault
154
+ * @dev Encrypts data with SEA and stores in user's vault node
155
+ * @param name Record name/key (must be unique)
156
+ * @param data Data to encrypt and store (any type)
157
+ * @param metadata Optional metadata
158
+ * @return Operation result
125
159
  *
126
160
  * Prerequisites:
127
- * - Must be connected to swarm
128
- * - User must be authenticated (via ISHIP_00)
161
+ * - Vault must be initialized
162
+ * - User must be authenticated
129
163
  *
130
164
  * Flow:
131
- * 1. Get all connected peers
132
- * 2. For each peer:
133
- * a. Derive shared secret (ECDH)
134
- * b. Encrypt message
135
- * c. Send via WebRTC data channel
165
+ * 1. Validate record name
166
+ * 2. Encrypt data with SEA
167
+ * 3. Encrypt metadata if provided
168
+ * 4. Store in gun.user().get('vault').get('records').get(name)
169
+ * 5. Update vault metadata
136
170
  */
137
- sendBroadcast(message: string): Promise<void>;
171
+ put(name: string, data: any, metadata?: RecordMetadata): Promise<VaultResult>;
138
172
  /**
139
- * @notice Send direct message to specific peer
140
- * @dev Message encrypted only for target peer
141
- * @param peerAddress Target peer address
142
- * @param message Plain text message content
173
+ * @notice Retrieve and decrypt record from vault
174
+ * @dev Retrieves and decrypts record from user's vault node
175
+ * @param name Record name/key
176
+ * @param options Retrieval options
177
+ * @return Decrypted record or null if not found
143
178
  *
144
179
  * Prerequisites:
145
- * - Must be connected to swarm
146
- * - Target peer must be connected
147
- * - User must be authenticated (via ISHIP_00)
180
+ * - Vault must be initialized
181
+ * - User must be authenticated
148
182
  *
149
183
  * Flow:
150
- * 1. Get target peer's public key
151
- * 2. Derive shared secret (ECDH)
152
- * 3. Encrypt message
153
- * 4. Send via WebRTC data channel
184
+ * 1. Retrieve encrypted record from Gun
185
+ * 2. Decrypt data with SEA
186
+ * 3. Decrypt metadata if present
187
+ * 4. Return decrypted record
154
188
  */
155
- sendDirect(peerAddress: string, message: string): Promise<void>;
189
+ get(name: string, options?: GetOptions): Promise<VaultRecord | null>;
156
190
  /**
157
- * @notice Listen for decrypted messages
158
- * @dev Automatically decrypts received messages
159
- * @param callback Called for each received message
191
+ * @notice Delete record from vault (soft delete)
192
+ * @dev Marks record as deleted without removing data
193
+ * @param name Record name/key (optional - deletes all if omitted)
194
+ * @return Operation result
160
195
  *
161
- * Prerequisites:
162
- * - Must be connected to swarm
196
+ * Soft Delete:
197
+ * - Record data remains encrypted in Gun
198
+ * - Marked as deleted (deleted: true)
199
+ * - Can be recovered before compaction
200
+ * - Not returned by default in list/get
201
+ */
202
+ delete(name?: string): Promise<VaultResult>;
203
+ /**
204
+ * @notice List all record names in vault
205
+ * @dev Returns array of record names matching criteria
206
+ * @param options List options
207
+ * @return Array of record names
163
208
  *
164
- * Decryption flow:
165
- * 1. Receive encrypted message via WebRTC
166
- * 2. Retrieve sender's epub from message
167
- * 3. Derive shared secret (ECDH)
168
- * 4. Decrypt message content
169
- * 5. Call callback with decrypted message
209
+ * Flow:
210
+ * 1. Retrieve all records from vault node
211
+ * 2. Apply filters (deleted, tags, type)
212
+ * 3. Sort if requested
213
+ * 4. Return record names
170
214
  */
171
- onMessage(callback: (message: EphemeralMessage) => void): void;
215
+ list(options?: ListOptions): Promise<string[]>;
172
216
  /**
173
- * @notice Listen for encrypted messages (debugging)
174
- * @dev Raw encrypted messages before decryption
175
- * @param callback Called for each encrypted message
217
+ * @notice Check if record exists
218
+ * @param name Record name/key
219
+ * @return True if record exists (and not deleted)
176
220
  */
177
- onEncryptedMessage(callback: (address: string, data: any) => void): void;
221
+ exists(name: string): Promise<boolean>;
178
222
  /**
179
- * @notice Listen for peer join events
180
- * @dev Called when a new peer connects to swarm
181
- * @param callback Called with peer address
223
+ * @notice Update existing record
224
+ * @dev Updates record data and timestamp
225
+ * @param name Record name/key
226
+ * @param data New data
227
+ * @return Operation result
228
+ *
229
+ * Flow:
230
+ * 1. Check if record exists
231
+ * 2. Encrypt new data
232
+ * 3. Update record with new data
233
+ * 4. Update timestamp
182
234
  */
183
- onPeerSeen(callback: (address: string) => void): void;
235
+ update(name: string, data: any): Promise<VaultResult>;
184
236
  /**
185
- * @notice Listen for peer leave events
186
- * @dev Called when a peer disconnects from swarm
187
- * @param callback Called with peer address
237
+ * @notice Export entire vault (encrypted)
238
+ * @dev Exports all vault records as encrypted JSON string
239
+ * @param password Optional additional encryption password
240
+ * @param options Export options
241
+ * @return Encrypted vault backup as string
242
+ *
243
+ * Flow:
244
+ * 1. Retrieve all records
245
+ * 2. Optionally filter records
246
+ * 3. Serialize to JSON
247
+ * 4. Optionally encrypt with additional password
248
+ * 5. Return as base64 string
249
+ */
250
+ export(password?: string, options?: ExportOptions): Promise<string>;
251
+ /**
252
+ * @notice Import vault from backup
253
+ * @dev Imports and decrypts vault backup
254
+ * @param backupData Exported vault data
255
+ * @param password Optional decryption password
256
+ * @param options Import options
257
+ * @return Operation result
258
+ *
259
+ * Flow:
260
+ * 1. Decode base64 backup
261
+ * 2. Decrypt with password if provided
262
+ * 3. Parse JSON
263
+ * 4. For each record:
264
+ * - Check if exists (if merge mode)
265
+ * - Import or skip based on options
266
+ * 5. Update vault metadata
188
267
  */
189
- onPeerLeft(callback: (address: string) => void): void;
268
+ import(backupData: string, password?: string, options?: ImportOptions): Promise<VaultResult>;
190
269
  /**
191
- * @notice Get list of connected peers
192
- * @return Array of peer addresses
270
+ * @notice Get vault statistics
271
+ * @dev Returns statistics about vault contents
272
+ * @return Vault statistics
193
273
  */
194
- getPeers(): string[];
274
+ getStats(): Promise<VaultStats>;
195
275
  /**
196
- * @notice Get detailed peer information
197
- * @param address Peer address
198
- * @return Peer info or null if not found
276
+ * @notice Clear all records (soft delete all)
277
+ * @dev Marks all records as deleted
278
+ * @return Operation result
199
279
  */
200
- getPeerInfo(address: string): PeerInfo | null;
280
+ clear(): Promise<VaultResult>;
201
281
  /**
202
- * @notice Get current ephemeral SEA pair
203
- * @dev New pair generated per session for perfect forward secrecy
204
- * @return SEA key pair
282
+ * @notice Compact vault (remove deleted records permanently)
283
+ * @dev Permanently removes soft-deleted records
284
+ * @return Operation result
285
+ *
286
+ * ⚠️ WARNING:
287
+ * - This operation is irreversible
288
+ * - Deleted records cannot be recovered after compaction
205
289
  */
206
- getEphemeralPair(): Promise<SEAPair>;
290
+ compact(): Promise<VaultResult>;
207
291
  /**
208
- * @notice Manually set SEA pair (optional)
209
- * @dev By default, SHIP-06 generates ephemeral pair automatically
210
- * @param pair SEA key pair
292
+ * @notice Search records by content
293
+ * @dev Searches decrypted content (expensive operation)
294
+ * @param query Search query
295
+ * @return Array of matching record names
211
296
  */
212
- setEphemeralPair(pair: SEAPair): Promise<void>;
297
+ search(query: string): Promise<string[]>;
213
298
  }
214
299
  /**
215
- * @notice Ephemeral messaging configuration
300
+ * @notice Vault configuration
216
301
  */
217
- export interface EphemeralConfig {
302
+ export interface VaultConfig {
303
+ /**
304
+ * @notice Identity provider (SHIP-00 instance)
305
+ */
306
+ identity: ISHIP_00;
218
307
  /**
219
- * @notice Room identifier (will be hashed)
308
+ * @notice Vault node name in Gun (default: "vault")
220
309
  */
221
- roomId: string;
310
+ vaultNodeName?: string;
222
311
  /**
223
312
  * @notice Enable debug logging
224
313
  */
@@ -227,59 +316,60 @@ export interface EphemeralConfig {
227
316
  * @notice Operation timeout (ms)
228
317
  */
229
318
  timeout?: number;
319
+ /**
320
+ * @notice Enable automatic backup
321
+ */
322
+ autoBackup?: boolean;
323
+ /**
324
+ * @notice Backup interval (ms)
325
+ */
326
+ backupInterval?: number;
230
327
  }
231
328
  /**
232
- * @notice Event emitter interface for SHIP-06
329
+ * @notice Event emitter interface for SHIP-07
233
330
  */
234
- export interface ISHIP_06Events {
331
+ export interface ISHIP_07Events {
235
332
  /**
236
- * Emitted when connected to swarm
333
+ * Emitted when vault is initialized
237
334
  */
238
- connected: () => void;
335
+ initialized: () => void;
239
336
  /**
240
- * Emitted when disconnected from swarm
337
+ * Emitted when record is added
241
338
  */
242
- disconnected: () => void;
339
+ recordAdded: (name: string) => void;
243
340
  /**
244
- * Emitted when a peer joins
341
+ * Emitted when record is updated
245
342
  */
246
- peerSeen: (address: string) => void;
343
+ recordUpdated: (name: string) => void;
247
344
  /**
248
- * Emitted when a peer leaves
345
+ * Emitted when record is deleted
249
346
  */
250
- peerLeft: (address: string) => void;
347
+ recordDeleted: (name: string) => void;
251
348
  /**
252
- * Emitted when a message is received and decrypted
349
+ * Emitted when vault is exported
253
350
  */
254
- message: (message: EphemeralMessage) => void;
351
+ exported: (size: number) => void;
255
352
  /**
256
- * Emitted when an encrypted message is received (before decryption)
353
+ * Emitted when vault is imported
257
354
  */
258
- encryptedMessage: (address: string, data: any) => void;
355
+ imported: (recordCount: number) => void;
259
356
  /**
260
357
  * Emitted on error
261
358
  */
262
359
  error: (error: Error) => void;
263
360
  }
264
361
  /**
265
- * Example of how to implement ISHIP_06 with ISHIP_00 dependency
362
+ * Example of how to implement ISHIP_07 with ISHIP_00 dependency
266
363
  *
267
364
  * ```typescript
268
365
  * import { ISHIP_00 } from './ISHIP_00';
269
- * import { ISHIP_06, EphemeralMessage } from './ISHIP_06';
270
- * import Bugout from 'bugout';
271
- *
272
- * class EphemeralMessaging implements ISHIP_06 {
273
- * private bugout: any;
274
- * private ephemeralPair: SEAPair | null = null;
275
- * private peers: Map<string, PeerInfo> = new Map();
276
- * private messageCallbacks: ((msg: EphemeralMessage) => void)[] = [];
277
- *
278
- * constructor(
279
- * private identity: ISHIP_00,
280
- * private roomId: string,
281
- * private config?: EphemeralConfig
282
- * ) {
366
+ * import { ISHIP_07, VaultRecord, VaultResult } from './ISHIP_07';
367
+ *
368
+ * class SecureVault implements ISHIP_07 {
369
+ * private vaultNode: any;
370
+ * private initialized: boolean = false;
371
+ *
372
+ * constructor(private identity: ISHIP_00) {
283
373
  * if (!identity.isLoggedIn()) {
284
374
  * throw new Error('User must be authenticated via SHIP-00');
285
375
  * }
@@ -289,82 +379,144 @@ export interface ISHIP_06Events {
289
379
  * return this.identity;
290
380
  * }
291
381
  *
292
- * async connect(): Promise<void> {
293
- * // 1. Generate ephemeral SEA pair
294
- * const crypto = this.identity.shogun.db.crypto;
295
- * this.ephemeralPair = await crypto.pair();
296
- *
297
- * // 2. Hash room ID
298
- * const swarmId = await crypto.hashText(this.roomId);
299
- *
300
- * // 3. Create Bugout swarm
301
- * this.bugout = new Bugout(swarmId, {
302
- * iceServers: this.config?.iceServers
303
- * });
304
- *
305
- * // 4. Set SEA pair
306
- * await this.bugout.SEA(this.ephemeralPair);
382
+ * async initialize(): Promise<void> {
383
+ * // Get Gun user node
384
+ * const gun = this.identity.shogun.db.gun;
385
+ * this.vaultNode = gun.user().get('vault').get('records');
307
386
  *
308
- * // 5. Listen for events
309
- * this.bugout.on('seen', (address: string) => {
310
- * this.handlePeerSeen(address);
387
+ * // Initialize vault metadata
388
+ * await gun.user().get('vault').get('metadata').put({
389
+ * version: '1.0.0',
390
+ * created: Date.now().toString()
311
391
  * });
312
392
  *
313
- * this.bugout.on('decrypted', (address: string, pubkeys: any, message: string) => {
314
- * this.handleMessage(address, pubkeys, message);
315
- * });
393
+ * this.initialized = true;
316
394
  * }
317
395
  *
318
- * disconnect(): void {
319
- * if (this.bugout) {
320
- * this.bugout.destroy();
321
- * }
396
+ * isInitialized(): boolean {
397
+ * return this.initialized;
322
398
  * }
323
399
  *
324
- * async sendBroadcast(message: string): Promise<void> {
325
- * if (!this.bugout) {
326
- * throw new Error('Not connected to swarm');
400
+ * async put(name: string, data: any, metadata?: RecordMetadata): Promise<VaultResult> {
401
+ * if (!this.initialized) {
402
+ * return { success: false, error: 'Vault not initialized' };
327
403
  * }
328
404
  *
329
- * this.bugout.send(message);
405
+ * try {
406
+ * // Get SEA crypto
407
+ * const crypto = this.identity.shogun.db.crypto;
408
+ * const pair = this.identity.getKeyPair();
409
+ *
410
+ * if (!pair) {
411
+ * return { success: false, error: 'Cannot access key pair' };
412
+ * }
413
+ *
414
+ * // Encrypt data
415
+ * const encryptedData = await crypto.encrypt(
416
+ * JSON.stringify(data),
417
+ * pair.epriv
418
+ * );
419
+ *
420
+ * // Encrypt metadata if provided
421
+ * const encryptedMetadata = metadata
422
+ * ? await crypto.encrypt(JSON.stringify(metadata), pair.epriv)
423
+ * : undefined;
424
+ *
425
+ * // Store in vault
426
+ * const record = {
427
+ * data: encryptedData,
428
+ * created: Date.now().toString(),
429
+ * updated: Date.now().toString(),
430
+ * deleted: false,
431
+ * metadata: encryptedMetadata
432
+ * };
433
+ *
434
+ * await this.vaultNode.get(name).put(record);
435
+ *
436
+ * return { success: true, recordName: name };
437
+ * } catch (error: any) {
438
+ * return { success: false, error: error.message };
439
+ * }
330
440
  * }
331
441
  *
332
- * async sendDirect(peerAddress: string, message: string): Promise<void> {
333
- * if (!this.bugout) {
334
- * throw new Error('Not connected to swarm');
442
+ * async get(name: string, options?: GetOptions): Promise<VaultRecord | null> {
443
+ * if (!this.initialized) {
444
+ * return null;
335
445
  * }
336
446
  *
337
- * this.bugout.send(peerAddress, message);
447
+ * try {
448
+ * // Retrieve from vault
449
+ * const encryptedRecord = await this.vaultNode.get(name).then();
450
+ *
451
+ * if (!encryptedRecord || !encryptedRecord.data) {
452
+ * return null;
453
+ * }
454
+ *
455
+ * // Skip if deleted (unless includeDeleted)
456
+ * if (encryptedRecord.deleted && !options?.includeDeleted) {
457
+ * return null;
458
+ * }
459
+ *
460
+ * // Decrypt data
461
+ * const crypto = this.identity.shogun.db.crypto;
462
+ * const pair = this.identity.getKeyPair();
463
+ *
464
+ * if (!pair) {
465
+ * return null;
466
+ * }
467
+ *
468
+ * const decryptedData = await crypto.decrypt(
469
+ * encryptedRecord.data,
470
+ * pair.epriv
471
+ * );
472
+ *
473
+ * // Decrypt metadata if present
474
+ * const decryptedMetadata = encryptedRecord.metadata
475
+ * ? JSON.parse(await crypto.decrypt(encryptedRecord.metadata, pair.epriv))
476
+ * : undefined;
477
+ *
478
+ * return {
479
+ * name,
480
+ * data: JSON.parse(decryptedData),
481
+ * created: parseInt(encryptedRecord.created),
482
+ * updated: parseInt(encryptedRecord.updated),
483
+ * deleted: encryptedRecord.deleted,
484
+ * metadata: decryptedMetadata
485
+ * };
486
+ * } catch (error) {
487
+ * console.error('Error retrieving record:', error);
488
+ * return null;
489
+ * }
338
490
  * }
339
491
  *
340
- * onMessage(callback: (message: EphemeralMessage) => void): void {
341
- * this.messageCallbacks.push(callback);
492
+ * async delete(name?: string): Promise<VaultResult> {
493
+ * // Implementation here
494
+ * return { success: true };
342
495
  * }
343
496
  *
344
- * private handleMessage(address: string, pubkeys: any, content: string) {
345
- * const message: EphemeralMessage = {
346
- * from: address,
347
- * fromPubKey: pubkeys.pub,
348
- * content,
349
- * timestamp: Date.now(),
350
- * type: 'broadcast'
351
- * };
352
- *
353
- * this.messageCallbacks.forEach(cb => cb(message));
497
+ * async list(options?: ListOptions): Promise<string[]> {
498
+ * // Implementation here
499
+ * return [];
354
500
  * }
501
+ *
502
+ * // ... implement other methods
355
503
  * }
356
504
  *
357
505
  * // Usage
358
506
  * const identity = new SHIP_00(config);
359
507
  * await identity.login('alice', 'password123');
360
508
  *
361
- * const ephemeral = new EphemeralMessaging(identity, 'my-room');
362
- * await ephemeral.connect();
509
+ * const vault = new SecureVault(identity);
510
+ * await vault.initialize();
363
511
  *
364
- * ephemeral.onMessage((msg) => {
365
- * console.log(`${msg.from}: ${msg.content}`);
512
+ * // Store encrypted data
513
+ * await vault.put('my-password', 'super_secret', {
514
+ * type: 'password',
515
+ * description: 'GitHub password'
366
516
  * });
367
517
  *
368
- * await ephemeral.sendBroadcast('Hello everyone!');
518
+ * // Retrieve decrypted data
519
+ * const record = await vault.get('my-password');
520
+ * console.log('Password:', record?.data);
369
521
  * ```
370
522
  */