@originals/sdk 1.8.0 → 1.8.2

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 (145) hide show
  1. package/dist/utils/hash.js +1 -0
  2. package/package.json +6 -5
  3. package/src/adapters/FeeOracleMock.ts +9 -0
  4. package/src/adapters/index.ts +5 -0
  5. package/src/adapters/providers/OrdHttpProvider.ts +126 -0
  6. package/src/adapters/providers/OrdMockProvider.ts +101 -0
  7. package/src/adapters/types.ts +66 -0
  8. package/src/bitcoin/BitcoinManager.ts +329 -0
  9. package/src/bitcoin/BroadcastClient.ts +54 -0
  10. package/src/bitcoin/OrdinalsClient.ts +120 -0
  11. package/src/bitcoin/PSBTBuilder.ts +106 -0
  12. package/src/bitcoin/fee-calculation.ts +38 -0
  13. package/src/bitcoin/providers/OrdNodeProvider.ts +92 -0
  14. package/src/bitcoin/providers/OrdinalsProvider.ts +56 -0
  15. package/src/bitcoin/providers/types.ts +59 -0
  16. package/src/bitcoin/transactions/commit.ts +465 -0
  17. package/src/bitcoin/transactions/index.ts +13 -0
  18. package/src/bitcoin/transfer.ts +43 -0
  19. package/src/bitcoin/utxo-selection.ts +322 -0
  20. package/src/bitcoin/utxo.ts +113 -0
  21. package/src/cel/ExternalReferenceManager.ts +87 -0
  22. package/src/cel/OriginalsCel.ts +460 -0
  23. package/src/cel/algorithms/createEventLog.ts +68 -0
  24. package/src/cel/algorithms/deactivateEventLog.ts +109 -0
  25. package/src/cel/algorithms/index.ts +11 -0
  26. package/src/cel/algorithms/updateEventLog.ts +99 -0
  27. package/src/cel/algorithms/verifyEventLog.ts +306 -0
  28. package/src/cel/algorithms/witnessEvent.ts +87 -0
  29. package/src/cel/cli/create.ts +330 -0
  30. package/src/cel/cli/index.ts +383 -0
  31. package/src/cel/cli/inspect.ts +549 -0
  32. package/src/cel/cli/migrate.ts +473 -0
  33. package/src/cel/cli/verify.ts +249 -0
  34. package/src/cel/hash.ts +71 -0
  35. package/src/cel/index.ts +16 -0
  36. package/src/cel/layers/BtcoCelManager.ts +408 -0
  37. package/src/cel/layers/PeerCelManager.ts +371 -0
  38. package/src/cel/layers/WebVHCelManager.ts +361 -0
  39. package/src/cel/layers/index.ts +27 -0
  40. package/src/cel/serialization/cbor.ts +189 -0
  41. package/src/cel/serialization/index.ts +10 -0
  42. package/src/cel/serialization/json.ts +209 -0
  43. package/src/cel/types.ts +160 -0
  44. package/src/cel/witnesses/BitcoinWitness.ts +184 -0
  45. package/src/cel/witnesses/HttpWitness.ts +241 -0
  46. package/src/cel/witnesses/WitnessService.ts +51 -0
  47. package/src/cel/witnesses/index.ts +11 -0
  48. package/src/contexts/credentials-v1.json +237 -0
  49. package/src/contexts/credentials-v2-examples.json +5 -0
  50. package/src/contexts/credentials-v2.json +340 -0
  51. package/src/contexts/credentials.json +237 -0
  52. package/src/contexts/data-integrity-v2.json +81 -0
  53. package/src/contexts/dids.json +58 -0
  54. package/src/contexts/ed255192020.json +93 -0
  55. package/src/contexts/ordinals-plus.json +23 -0
  56. package/src/contexts/originals.json +22 -0
  57. package/src/core/OriginalsSDK.ts +420 -0
  58. package/src/crypto/Multikey.ts +194 -0
  59. package/src/crypto/Signer.ts +262 -0
  60. package/src/crypto/noble-init.ts +138 -0
  61. package/src/did/BtcoDidResolver.ts +231 -0
  62. package/src/did/DIDManager.ts +705 -0
  63. package/src/did/Ed25519Verifier.ts +68 -0
  64. package/src/did/KeyManager.ts +239 -0
  65. package/src/did/WebVHManager.ts +499 -0
  66. package/src/did/createBtcoDidDocument.ts +60 -0
  67. package/src/did/providers/OrdinalsClientProviderAdapter.ts +68 -0
  68. package/src/events/EventEmitter.ts +222 -0
  69. package/src/events/index.ts +19 -0
  70. package/src/events/types.ts +331 -0
  71. package/src/examples/basic-usage.ts +78 -0
  72. package/src/examples/create-module-original.ts +435 -0
  73. package/src/examples/full-lifecycle-flow.ts +514 -0
  74. package/src/examples/run.ts +60 -0
  75. package/src/index.ts +204 -0
  76. package/src/kinds/KindRegistry.ts +320 -0
  77. package/src/kinds/index.ts +74 -0
  78. package/src/kinds/types.ts +470 -0
  79. package/src/kinds/validators/AgentValidator.ts +257 -0
  80. package/src/kinds/validators/AppValidator.ts +211 -0
  81. package/src/kinds/validators/DatasetValidator.ts +242 -0
  82. package/src/kinds/validators/DocumentValidator.ts +311 -0
  83. package/src/kinds/validators/MediaValidator.ts +269 -0
  84. package/src/kinds/validators/ModuleValidator.ts +225 -0
  85. package/src/kinds/validators/base.ts +276 -0
  86. package/src/kinds/validators/index.ts +12 -0
  87. package/src/lifecycle/BatchOperations.ts +381 -0
  88. package/src/lifecycle/LifecycleManager.ts +2156 -0
  89. package/src/lifecycle/OriginalsAsset.ts +524 -0
  90. package/src/lifecycle/ProvenanceQuery.ts +280 -0
  91. package/src/lifecycle/ResourceVersioning.ts +163 -0
  92. package/src/migration/MigrationManager.ts +587 -0
  93. package/src/migration/audit/AuditLogger.ts +176 -0
  94. package/src/migration/checkpoint/CheckpointManager.ts +112 -0
  95. package/src/migration/checkpoint/CheckpointStorage.ts +101 -0
  96. package/src/migration/index.ts +33 -0
  97. package/src/migration/operations/BaseMigration.ts +126 -0
  98. package/src/migration/operations/PeerToBtcoMigration.ts +105 -0
  99. package/src/migration/operations/PeerToWebvhMigration.ts +62 -0
  100. package/src/migration/operations/WebvhToBtcoMigration.ts +105 -0
  101. package/src/migration/rollback/RollbackManager.ts +170 -0
  102. package/src/migration/state/StateMachine.ts +92 -0
  103. package/src/migration/state/StateTracker.ts +156 -0
  104. package/src/migration/types.ts +356 -0
  105. package/src/migration/validation/BitcoinValidator.ts +107 -0
  106. package/src/migration/validation/CredentialValidator.ts +62 -0
  107. package/src/migration/validation/DIDCompatibilityValidator.ts +151 -0
  108. package/src/migration/validation/LifecycleValidator.ts +64 -0
  109. package/src/migration/validation/StorageValidator.ts +79 -0
  110. package/src/migration/validation/ValidationPipeline.ts +213 -0
  111. package/src/resources/ResourceManager.ts +655 -0
  112. package/src/resources/index.ts +21 -0
  113. package/src/resources/types.ts +202 -0
  114. package/src/storage/LocalStorageAdapter.ts +64 -0
  115. package/src/storage/MemoryStorageAdapter.ts +29 -0
  116. package/src/storage/StorageAdapter.ts +25 -0
  117. package/src/storage/index.ts +3 -0
  118. package/src/types/bitcoin.ts +98 -0
  119. package/src/types/common.ts +92 -0
  120. package/src/types/credentials.ts +89 -0
  121. package/src/types/did.ts +31 -0
  122. package/src/types/external-shims.d.ts +53 -0
  123. package/src/types/index.ts +7 -0
  124. package/src/types/network.ts +178 -0
  125. package/src/utils/EventLogger.ts +298 -0
  126. package/src/utils/Logger.ts +324 -0
  127. package/src/utils/MetricsCollector.ts +358 -0
  128. package/src/utils/bitcoin-address.ts +132 -0
  129. package/src/utils/cbor.ts +31 -0
  130. package/src/utils/encoding.ts +135 -0
  131. package/src/utils/hash.ts +12 -0
  132. package/src/utils/retry.ts +46 -0
  133. package/src/utils/satoshi-validation.ts +196 -0
  134. package/src/utils/serialization.ts +102 -0
  135. package/src/utils/telemetry.ts +44 -0
  136. package/src/utils/validation.ts +123 -0
  137. package/src/vc/CredentialManager.ts +955 -0
  138. package/src/vc/Issuer.ts +105 -0
  139. package/src/vc/Verifier.ts +54 -0
  140. package/src/vc/cryptosuites/bbs.ts +253 -0
  141. package/src/vc/cryptosuites/bbsSimple.ts +21 -0
  142. package/src/vc/cryptosuites/eddsa.ts +99 -0
  143. package/src/vc/documentLoader.ts +81 -0
  144. package/src/vc/proofs/data-integrity.ts +33 -0
  145. package/src/vc/utils/jsonld.ts +18 -0
@@ -0,0 +1,460 @@
1
+ /**
2
+ * OriginalsCel - Unified SDK Entry Point for CEL Operations
3
+ *
4
+ * Provides a single, simplified interface for all Cryptographic Event Log
5
+ * operations across all layers (peer, webvh, btco).
6
+ *
7
+ * This class delegates to the appropriate layer manager based on
8
+ * the configured layer and the current state of the event log.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Create a peer-layer asset
13
+ * const cel = new OriginalsCel({
14
+ * layer: 'peer',
15
+ * signer: async (data) => createEdDsaProof(data, privateKey),
16
+ * });
17
+ *
18
+ * const log = await cel.create('My Asset', [
19
+ * { digestMultibase: 'uXYZ...', mediaType: 'image/png' }
20
+ * ]);
21
+ *
22
+ * // Update the asset
23
+ * const updated = await cel.update(log, { description: 'Updated' });
24
+ *
25
+ * // Verify the log
26
+ * const result = await cel.verify(updated);
27
+ *
28
+ * // Migrate to webvh layer
29
+ * const migrated = await cel.migrate(updated, 'webvh');
30
+ * ```
31
+ */
32
+
33
+ import type {
34
+ EventLog,
35
+ ExternalReference,
36
+ VerificationResult,
37
+ VerifyOptions,
38
+ AssetState
39
+ } from './types';
40
+ import { PeerCelManager, type PeerCelConfig, type CelSigner } from './layers/PeerCelManager';
41
+ import { WebVHCelManager, type WebVHCelConfig } from './layers/WebVHCelManager';
42
+ import { BtcoCelManager, type BtcoCelConfig } from './layers/BtcoCelManager';
43
+ import { verifyEventLog } from './algorithms/verifyEventLog';
44
+ import type { WitnessService } from './witnesses/WitnessService';
45
+ import type { BitcoinManager } from '../bitcoin/BitcoinManager';
46
+
47
+ /**
48
+ * Supported layer types
49
+ */
50
+ export type CelLayer = 'peer' | 'webvh' | 'btco';
51
+
52
+ // Re-export CelSigner for convenience
53
+ export type { CelSigner };
54
+
55
+ /**
56
+ * Configuration options for OriginalsCel
57
+ */
58
+ export interface OriginalsCelConfig {
59
+ /** Configuration for peer layer operations */
60
+ peer?: PeerCelConfig;
61
+
62
+ /** Configuration for webvh layer operations */
63
+ webvh?: {
64
+ /** The domain for the did:webvh DID (required for webvh operations) */
65
+ domain?: string;
66
+ /** Optional witness services for HTTP attestations */
67
+ witnesses?: WitnessService[];
68
+ } & WebVHCelConfig;
69
+
70
+ /** Configuration for btco layer operations */
71
+ btco?: {
72
+ /** BitcoinManager instance (required for btco operations) */
73
+ bitcoinManager?: BitcoinManager;
74
+ } & BtcoCelConfig;
75
+ }
76
+
77
+ /**
78
+ * Options for creating an OriginalsCel instance
79
+ */
80
+ export interface OriginalsCelOptions {
81
+ /** The target layer for operations */
82
+ layer: CelLayer;
83
+ /** Signer function that produces DataIntegrityProofs */
84
+ signer: CelSigner;
85
+ /** Optional layer-specific configuration */
86
+ config?: OriginalsCelConfig;
87
+ }
88
+
89
+ /**
90
+ * OriginalsCel - Unified SDK for Cryptographic Event Log operations
91
+ *
92
+ * Provides a consistent API for creating, updating, verifying, and migrating
93
+ * assets across all supported layers (peer, webvh, btco).
94
+ */
95
+ export class OriginalsCel {
96
+ private layer: CelLayer;
97
+ private signer: CelSigner;
98
+ private config: OriginalsCelConfig;
99
+
100
+ // Layer managers (created lazily)
101
+ private _peerManager?: PeerCelManager;
102
+ private _webvhManager?: WebVHCelManager;
103
+ private _btcoManager?: BtcoCelManager;
104
+
105
+ /**
106
+ * Creates a new OriginalsCel instance
107
+ *
108
+ * @param options - Configuration options
109
+ * @param options.layer - The target layer for operations (peer, webvh, btco)
110
+ * @param options.signer - Function that signs data and returns a DataIntegrityProof
111
+ * @param options.config - Optional layer-specific configuration
112
+ *
113
+ * @throws Error if signer is not a function
114
+ * @throws Error if layer is invalid
115
+ */
116
+ constructor(options: OriginalsCelOptions) {
117
+ if (typeof options.signer !== 'function') {
118
+ throw new Error('OriginalsCel requires a signer function');
119
+ }
120
+
121
+ const validLayers: CelLayer[] = ['peer', 'webvh', 'btco'];
122
+ if (!validLayers.includes(options.layer)) {
123
+ throw new Error(`Invalid layer: ${options.layer}. Must be one of: ${validLayers.join(', ')}`);
124
+ }
125
+
126
+ this.layer = options.layer;
127
+ this.signer = options.signer;
128
+ this.config = options.config || {};
129
+ }
130
+
131
+ /**
132
+ * Gets or creates the PeerCelManager instance
133
+ */
134
+ private get peerManager(): PeerCelManager {
135
+ if (!this._peerManager) {
136
+ this._peerManager = new PeerCelManager(this.signer, this.config.peer);
137
+ }
138
+ return this._peerManager;
139
+ }
140
+
141
+ /**
142
+ * Gets or creates the WebVHCelManager instance
143
+ *
144
+ * @throws Error if domain is not configured for webvh operations
145
+ */
146
+ private getWebVHManager(domain?: string): WebVHCelManager {
147
+ const webvhDomain = domain || this.config.webvh?.domain;
148
+
149
+ if (!webvhDomain) {
150
+ throw new Error('WebVH operations require a domain. Provide it in config.webvh.domain');
151
+ }
152
+
153
+ // Always create a new instance with the current domain to support different domains
154
+ return new WebVHCelManager(
155
+ this.signer,
156
+ webvhDomain,
157
+ this.config.webvh?.witnesses || [],
158
+ this.config.webvh
159
+ );
160
+ }
161
+
162
+ /**
163
+ * Gets or creates the BtcoCelManager instance
164
+ *
165
+ * @throws Error if BitcoinManager is not configured for btco operations
166
+ */
167
+ private get btcoManager(): BtcoCelManager {
168
+ if (!this._btcoManager) {
169
+ const bitcoinManager = this.config.btco?.bitcoinManager;
170
+
171
+ if (!bitcoinManager) {
172
+ throw new Error('BTCO operations require a BitcoinManager. Provide it in config.btco.bitcoinManager');
173
+ }
174
+
175
+ this._btcoManager = new BtcoCelManager(
176
+ this.signer,
177
+ bitcoinManager,
178
+ this.config.btco
179
+ );
180
+ }
181
+ return this._btcoManager;
182
+ }
183
+
184
+ /**
185
+ * Creates a new asset with a CEL event log
186
+ *
187
+ * This method creates an asset at the configured layer. Note that
188
+ * new assets can only be created at the peer layer - for other layers,
189
+ * create at peer first and then migrate.
190
+ *
191
+ * @param name - Human-readable name for the asset
192
+ * @param resources - External resources associated with the asset
193
+ * @returns Promise resolving to an EventLog with the create event
194
+ *
195
+ * @throws Error if signer produces invalid proof
196
+ * @throws Error if trying to create at non-peer layer
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * const log = await cel.create('My Asset', [
201
+ * createExternalReference(imageData, 'image/png')
202
+ * ]);
203
+ * ```
204
+ */
205
+ async create(name: string, resources: ExternalReference[]): Promise<EventLog> {
206
+ // Assets can only be created at the peer layer
207
+ // Other layers require migration from peer
208
+ if (this.layer !== 'peer') {
209
+ throw new Error(
210
+ `Cannot create assets at ${this.layer} layer directly. ` +
211
+ `Create at peer layer first, then use migrate() to move to ${this.layer}.`
212
+ );
213
+ }
214
+
215
+ return this.peerManager.create(name, resources);
216
+ }
217
+
218
+ /**
219
+ * Updates an existing event log by appending an update event
220
+ *
221
+ * The new event is cryptographically linked to the previous event
222
+ * via a hash chain (previousEvent field).
223
+ *
224
+ * @param log - The existing event log to update
225
+ * @param data - The update data (new metadata, resources, etc.)
226
+ * @returns Promise resolving to a new EventLog with the update event appended
227
+ *
228
+ * @throws Error if the log is empty or deactivated
229
+ * @throws Error if signer produces invalid proof
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * const updated = await cel.update(log, {
234
+ * description: 'Updated description',
235
+ * tags: ['art', 'digital']
236
+ * });
237
+ * ```
238
+ */
239
+ async update(log: EventLog, data: unknown): Promise<EventLog> {
240
+ // Determine the current layer of the log
241
+ const currentLayer = this.getCurrentLayer(log);
242
+
243
+ // Use the appropriate manager based on current layer
244
+ switch (currentLayer) {
245
+ case 'peer':
246
+ return this.peerManager.update(log, data);
247
+ case 'webvh': {
248
+ // For webvh, we need to use the webvh manager
249
+ // Get domain from the log if possible
250
+ const webvhDomain = this.extractDomainFromLog(log);
251
+ return this.getWebVHManager(webvhDomain).migrate(log).then(
252
+ // webvh manager doesn't have update, use peer manager's algorithm
253
+ () => this.peerManager.update(log, data)
254
+ );
255
+ }
256
+ case 'btco':
257
+ // For btco, updates use the same underlying algorithm
258
+ return this.peerManager.update(log, data);
259
+ default: {
260
+ // TypeScript exhaustiveness check
261
+ const _exhaustive: never = currentLayer;
262
+ throw new Error(`Unknown layer: ${String(_exhaustive)}`);
263
+ }
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Verifies all proofs and hash chain integrity in an event log
269
+ *
270
+ * This method verifies:
271
+ * - Each event has at least one proof
272
+ * - Each proof is structurally valid
273
+ * - The hash chain is intact (each event links to previous)
274
+ *
275
+ * @param log - The event log to verify
276
+ * @param options - Optional verification options
277
+ * @returns Promise resolving to VerificationResult with detailed status
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * const result = await cel.verify(log);
282
+ * if (result.verified) {
283
+ * console.log('Log is valid!');
284
+ * } else {
285
+ * console.error('Verification failed:', result.errors);
286
+ * }
287
+ * ```
288
+ */
289
+ async verify(log: EventLog, options?: VerifyOptions): Promise<VerificationResult> {
290
+ return verifyEventLog(log, options);
291
+ }
292
+
293
+ /**
294
+ * Migrates an event log to a target layer
295
+ *
296
+ * Migration adds an update event with migration data and (optionally)
297
+ * witness proofs. The valid migration paths are:
298
+ * - peer → webvh
299
+ * - webvh → btco
300
+ * - peer → btco (requires intermediate webvh migration)
301
+ *
302
+ * @param log - The event log to migrate
303
+ * @param targetLayer - The layer to migrate to
304
+ * @param options - Optional migration options (e.g., domain for webvh)
305
+ * @returns Promise resolving to the migrated EventLog
306
+ *
307
+ * @throws Error if migration path is invalid
308
+ * @throws Error if required config is missing for target layer
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * // Migrate peer to webvh
313
+ * const webvhLog = await cel.migrate(peerLog, 'webvh', {
314
+ * domain: 'example.com'
315
+ * });
316
+ *
317
+ * // Migrate webvh to btco
318
+ * const btcoLog = await cel.migrate(webvhLog, 'btco');
319
+ * ```
320
+ */
321
+ async migrate(
322
+ log: EventLog,
323
+ targetLayer: CelLayer,
324
+ options?: { domain?: string }
325
+ ): Promise<EventLog> {
326
+ const currentLayer = this.getCurrentLayer(log);
327
+
328
+ // Validate migration path
329
+ if (currentLayer === targetLayer) {
330
+ throw new Error(`Log is already at ${targetLayer} layer`);
331
+ }
332
+
333
+ if (currentLayer === 'btco') {
334
+ throw new Error('Cannot migrate from btco layer - it is the final layer');
335
+ }
336
+
337
+ // Perform migration based on current and target layers
338
+ switch (targetLayer) {
339
+ case 'peer':
340
+ throw new Error('Cannot migrate to peer layer - it is the initial layer');
341
+
342
+ case 'webvh': {
343
+ if (currentLayer !== 'peer') {
344
+ throw new Error(`Invalid migration: ${currentLayer} → webvh. Can only migrate peer → webvh.`);
345
+ }
346
+ const domain = options?.domain || this.config.webvh?.domain;
347
+ return this.getWebVHManager(domain).migrate(log);
348
+ }
349
+
350
+ case 'btco': {
351
+ if (currentLayer === 'peer') {
352
+ // Need to do two-step migration: peer → webvh → btco
353
+ throw new Error(
354
+ 'Cannot migrate directly from peer to btco. ' +
355
+ 'Migrate to webvh first, then to btco.'
356
+ );
357
+ }
358
+ if (currentLayer !== 'webvh') {
359
+ throw new Error(`Invalid migration: ${String(currentLayer)} → btco. Can only migrate webvh → btco.`);
360
+ }
361
+ return this.btcoManager.migrate(log);
362
+ }
363
+
364
+ default: {
365
+ // TypeScript exhaustiveness check
366
+ const _exhaustive: never = targetLayer;
367
+ throw new Error(`Unknown target layer: ${String(_exhaustive)}`);
368
+ }
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Derives the current asset state by replaying all events in the log
374
+ *
375
+ * @param log - The event log to derive state from
376
+ * @returns The current AssetState
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * const state = cel.getCurrentState(log);
381
+ * console.log(state.name); // Asset name
382
+ * console.log(state.layer); // Current layer
383
+ * console.log(state.deactivated); // Whether deactivated
384
+ * ```
385
+ */
386
+ getCurrentState(log: EventLog): AssetState {
387
+ // Determine current layer and use appropriate manager
388
+ const currentLayer = this.getCurrentLayer(log);
389
+
390
+ switch (currentLayer) {
391
+ case 'peer':
392
+ return this.peerManager.getCurrentState(log);
393
+ case 'webvh': {
394
+ // WebVH manager also handles state derivation correctly
395
+ const domain = this.extractDomainFromLog(log) || 'unknown.com';
396
+ return this.getWebVHManager(domain).getCurrentState(log);
397
+ }
398
+ case 'btco':
399
+ return this.btcoManager.getCurrentState(log);
400
+ default:
401
+ // Fallback to peer manager which handles all event types
402
+ return this.peerManager.getCurrentState(log);
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Determines the current layer of an event log by examining its events
408
+ *
409
+ * @param log - The event log to examine
410
+ * @returns The current layer of the log
411
+ */
412
+ private getCurrentLayer(log: EventLog): CelLayer {
413
+ if (!log || !log.events || log.events.length === 0) {
414
+ return 'peer'; // Default for empty logs
415
+ }
416
+
417
+ let currentLayer: CelLayer = 'peer';
418
+
419
+ for (const event of log.events) {
420
+ const eventData = event.data as Record<string, unknown>;
421
+
422
+ if (event.type === 'create') {
423
+ currentLayer = (eventData.layer as CelLayer) || 'peer';
424
+ } else if (event.type === 'update' && eventData.targetDid && eventData.layer) {
425
+ // This is a migration event
426
+ currentLayer = eventData.layer as CelLayer;
427
+ }
428
+ }
429
+
430
+ return currentLayer;
431
+ }
432
+
433
+ /**
434
+ * Extracts the domain from a webvh log's migration event
435
+ *
436
+ * @param log - The event log to examine
437
+ * @returns The domain if found, undefined otherwise
438
+ */
439
+ private extractDomainFromLog(log: EventLog): string | undefined {
440
+ if (!log || !log.events) {
441
+ return undefined;
442
+ }
443
+
444
+ for (const event of log.events) {
445
+ const eventData = event.data as Record<string, unknown>;
446
+ if (eventData.domain) {
447
+ return eventData.domain as string;
448
+ }
449
+ }
450
+
451
+ return undefined;
452
+ }
453
+
454
+ /**
455
+ * Gets the configured layer for this instance
456
+ */
457
+ get currentLayer(): CelLayer {
458
+ return this.layer;
459
+ }
460
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * createEventLog Algorithm
3
+ *
4
+ * Creates a new Cryptographic Event Log with an initial "create" event.
5
+ * The create event is the first event in a log and has no previousEvent reference.
6
+ *
7
+ * @see https://w3c-ccg.github.io/cel-spec/
8
+ */
9
+
10
+ import type { EventLog, LogEntry, CreateOptions, DataIntegrityProof } from '../types';
11
+
12
+ /**
13
+ * Creates a new event log with a single "create" event.
14
+ *
15
+ * This is the first step in creating a CEL-based provenance chain.
16
+ * The create event establishes the initial state of an asset.
17
+ *
18
+ * @param data - The initial data for the asset (e.g., name, resources, metadata)
19
+ * @param options - Signing options including signer function and verification method
20
+ * @returns A new EventLog containing a single create event
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const log = await createEventLog(
25
+ * { name: 'My Asset', resources: [...] },
26
+ * {
27
+ * signer: async (data) => createEdDsaProof(data, privateKey),
28
+ * verificationMethod: 'did:key:z6Mk...',
29
+ * proofPurpose: 'assertionMethod'
30
+ * }
31
+ * );
32
+ * ```
33
+ */
34
+ export async function createEventLog(
35
+ data: unknown,
36
+ options: CreateOptions
37
+ ): Promise<EventLog> {
38
+ const { signer, verificationMethod, proofPurpose = 'assertionMethod' } = options;
39
+
40
+ // Create the event structure without proof first
41
+ const eventBase = {
42
+ type: 'create' as const,
43
+ data,
44
+ // Note: First event has no previousEvent
45
+ };
46
+
47
+ // Generate proof using the provided signer
48
+ const proof: DataIntegrityProof = await signer(eventBase);
49
+
50
+ // Validate the proof has required fields
51
+ if (!proof.type || !proof.cryptosuite || !proof.proofValue) {
52
+ throw new Error('Invalid proof: missing required fields (type, cryptosuite, proofValue)');
53
+ }
54
+
55
+ // Construct the complete log entry
56
+ const entry: LogEntry = {
57
+ type: 'create',
58
+ data,
59
+ proof: [proof],
60
+ };
61
+
62
+ // Return the new event log
63
+ const eventLog: EventLog = {
64
+ events: [entry],
65
+ };
66
+
67
+ return eventLog;
68
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * deactivateEventLog Algorithm
3
+ *
4
+ * Seals an event log with a "deactivate" event. Once deactivated,
5
+ * no further events should be added to the log.
6
+ *
7
+ * @see https://w3c-ccg.github.io/cel-spec/
8
+ */
9
+
10
+ import type { EventLog, LogEntry, DeactivateOptions, DataIntegrityProof } from '../types';
11
+ import { computeDigestMultibase } from '../hash';
12
+
13
+ /**
14
+ * Serializes a LogEntry to a deterministic byte representation for hashing.
15
+ * Uses JSON with sorted keys for reproducibility.
16
+ *
17
+ * @param entry - The log entry to serialize
18
+ * @returns UTF-8 encoded bytes
19
+ */
20
+ function serializeEntry(entry: LogEntry): Uint8Array {
21
+ // Use JSON with sorted keys for deterministic serialization
22
+ const json = JSON.stringify(entry, Object.keys(entry).sort());
23
+ return new TextEncoder().encode(json);
24
+ }
25
+
26
+ /**
27
+ * Deactivates an event log by appending a final "deactivate" event.
28
+ *
29
+ * The deactivate event seals the log, indicating that no further
30
+ * events should be added. This is used to mark an asset as retired,
31
+ * revoked, or otherwise no longer active.
32
+ *
33
+ * @param log - The existing event log to deactivate
34
+ * @param reason - The reason for deactivation (e.g., "retired", "revoked", "superseded")
35
+ * @param options - Signing options including signer function and verification method
36
+ * @returns A new EventLog with the deactivate event appended (input is not mutated)
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const deactivatedLog = await deactivateEventLog(
41
+ * existingLog,
42
+ * 'Asset has been superseded by a new version',
43
+ * {
44
+ * signer: async (data) => createEdDsaProof(data, privateKey),
45
+ * verificationMethod: 'did:key:z6Mk...',
46
+ * proofPurpose: 'assertionMethod'
47
+ * }
48
+ * );
49
+ * ```
50
+ */
51
+ export async function deactivateEventLog(
52
+ log: EventLog,
53
+ reason: string,
54
+ options: DeactivateOptions
55
+ ): Promise<EventLog> {
56
+ const { signer, verificationMethod, proofPurpose = 'assertionMethod' } = options;
57
+
58
+ // Validate input log
59
+ if (!log.events || log.events.length === 0) {
60
+ throw new Error('Cannot deactivate an empty event log');
61
+ }
62
+
63
+ // Check if log is already deactivated
64
+ const lastEvent = log.events[log.events.length - 1];
65
+ if (lastEvent.type === 'deactivate') {
66
+ throw new Error('Event log is already deactivated');
67
+ }
68
+
69
+ // Compute the digestMultibase of the last event
70
+ const previousEvent = computeDigestMultibase(serializeEntry(lastEvent));
71
+
72
+ // Deactivation data includes the reason
73
+ const deactivationData = {
74
+ reason,
75
+ deactivatedAt: new Date().toISOString(),
76
+ };
77
+
78
+ // Create the event structure without proof first
79
+ const eventBase = {
80
+ type: 'deactivate' as const,
81
+ data: deactivationData,
82
+ previousEvent,
83
+ };
84
+
85
+ // Generate proof using the provided signer
86
+ const proof: DataIntegrityProof = await signer(eventBase);
87
+
88
+ // Validate the proof has required fields
89
+ if (!proof.type || !proof.cryptosuite || !proof.proofValue) {
90
+ throw new Error('Invalid proof: missing required fields (type, cryptosuite, proofValue)');
91
+ }
92
+
93
+ // Construct the complete log entry
94
+ const entry: LogEntry = {
95
+ type: 'deactivate',
96
+ data: deactivationData,
97
+ previousEvent,
98
+ proof: [proof],
99
+ };
100
+
101
+ // Return a new event log (immutable - does not mutate input)
102
+ const eventLog: EventLog = {
103
+ events: [...log.events, entry],
104
+ // Preserve previousLog reference if it exists
105
+ ...(log.previousLog ? { previousLog: log.previousLog } : {}),
106
+ };
107
+
108
+ return eventLog;
109
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CEL Algorithms
3
+ *
4
+ * Core algorithms for working with Cryptographic Event Logs.
5
+ */
6
+
7
+ export { createEventLog } from './createEventLog';
8
+ export { updateEventLog } from './updateEventLog';
9
+ export { deactivateEventLog } from './deactivateEventLog';
10
+ export { verifyEventLog } from './verifyEventLog';
11
+ export { witnessEvent } from './witnessEvent';