@originals/sdk 1.5.0 → 1.6.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.
Files changed (105) hide show
  1. package/dist/adapters/FeeOracleMock.js +2 -2
  2. package/dist/bitcoin/OrdinalsClient.d.ts +1 -1
  3. package/dist/bitcoin/OrdinalsClient.js +10 -8
  4. package/dist/bitcoin/PSBTBuilder.js +1 -1
  5. package/dist/bitcoin/utxo-selection.js +2 -2
  6. package/dist/cel/ExternalReferenceManager.d.ts +57 -0
  7. package/dist/cel/ExternalReferenceManager.js +73 -0
  8. package/dist/cel/OriginalsCel.d.ts +245 -0
  9. package/dist/cel/OriginalsCel.js +349 -0
  10. package/dist/cel/algorithms/createEventLog.d.ts +32 -0
  11. package/dist/cel/algorithms/createEventLog.js +56 -0
  12. package/dist/cel/algorithms/deactivateEventLog.d.ts +35 -0
  13. package/dist/cel/algorithms/deactivateEventLog.js +91 -0
  14. package/dist/cel/algorithms/index.d.ts +10 -0
  15. package/dist/cel/algorithms/index.js +10 -0
  16. package/dist/cel/algorithms/updateEventLog.d.ts +34 -0
  17. package/dist/cel/algorithms/updateEventLog.js +82 -0
  18. package/dist/cel/algorithms/verifyEventLog.d.ts +45 -0
  19. package/dist/cel/algorithms/verifyEventLog.js +255 -0
  20. package/dist/cel/algorithms/witnessEvent.d.ts +29 -0
  21. package/dist/cel/algorithms/witnessEvent.js +75 -0
  22. package/dist/cel/cli/create.d.ts +36 -0
  23. package/dist/cel/cli/create.js +282 -0
  24. package/dist/cel/cli/index.d.ts +11 -0
  25. package/dist/cel/cli/index.js +351 -0
  26. package/dist/cel/cli/inspect.d.ts +30 -0
  27. package/dist/cel/cli/inspect.js +475 -0
  28. package/dist/cel/cli/migrate.d.ts +41 -0
  29. package/dist/cel/cli/migrate.js +405 -0
  30. package/dist/cel/cli/verify.d.ts +31 -0
  31. package/dist/cel/cli/verify.js +205 -0
  32. package/dist/cel/hash.d.ts +46 -0
  33. package/dist/cel/hash.js +66 -0
  34. package/dist/cel/index.d.ts +15 -0
  35. package/dist/cel/index.js +15 -0
  36. package/dist/cel/layers/BtcoCelManager.d.ts +121 -0
  37. package/dist/cel/layers/BtcoCelManager.js +329 -0
  38. package/dist/cel/layers/PeerCelManager.d.ts +151 -0
  39. package/dist/cel/layers/PeerCelManager.js +299 -0
  40. package/dist/cel/layers/WebVHCelManager.d.ts +122 -0
  41. package/dist/cel/layers/WebVHCelManager.js +291 -0
  42. package/dist/cel/layers/index.d.ts +13 -0
  43. package/dist/cel/layers/index.js +16 -0
  44. package/dist/cel/serialization/cbor.d.ts +42 -0
  45. package/dist/cel/serialization/cbor.js +163 -0
  46. package/dist/cel/serialization/index.d.ts +9 -0
  47. package/dist/cel/serialization/index.js +9 -0
  48. package/dist/cel/serialization/json.d.ts +41 -0
  49. package/dist/cel/serialization/json.js +180 -0
  50. package/dist/cel/types.d.ts +149 -0
  51. package/dist/cel/types.js +7 -0
  52. package/dist/cel/witnesses/BitcoinWitness.d.ts +83 -0
  53. package/dist/cel/witnesses/BitcoinWitness.js +116 -0
  54. package/dist/cel/witnesses/HttpWitness.d.ts +79 -0
  55. package/dist/cel/witnesses/HttpWitness.js +163 -0
  56. package/dist/cel/witnesses/WitnessService.d.ts +49 -0
  57. package/dist/cel/witnesses/WitnessService.js +10 -0
  58. package/dist/cel/witnesses/index.d.ts +10 -0
  59. package/dist/cel/witnesses/index.js +7 -0
  60. package/dist/core/OriginalsSDK.js +5 -1
  61. package/dist/crypto/Signer.js +14 -6
  62. package/dist/crypto/noble-init.js +20 -1
  63. package/dist/did/BtcoDidResolver.d.ts +2 -2
  64. package/dist/did/BtcoDidResolver.js +12 -8
  65. package/dist/did/DIDManager.js +6 -4
  66. package/dist/did/KeyManager.d.ts +1 -1
  67. package/dist/did/KeyManager.js +7 -4
  68. package/dist/did/WebVHManager.js +1 -1
  69. package/dist/did/createBtcoDidDocument.js +2 -1
  70. package/dist/events/types.d.ts +4 -1
  71. package/dist/examples/create-module-original.js +1 -1
  72. package/dist/examples/full-lifecycle-flow.js +2 -2
  73. package/dist/index.d.ts +13 -0
  74. package/dist/index.js +12 -0
  75. package/dist/kinds/KindRegistry.js +59 -29
  76. package/dist/lifecycle/BatchOperations.d.ts +5 -3
  77. package/dist/lifecycle/BatchOperations.js +11 -5
  78. package/dist/lifecycle/LifecycleManager.d.ts +1 -1
  79. package/dist/lifecycle/LifecycleManager.js +42 -33
  80. package/dist/lifecycle/OriginalsAsset.js +2 -2
  81. package/dist/migration/MigrationManager.js +67 -3
  82. package/dist/storage/LocalStorageAdapter.js +4 -1
  83. package/dist/storage/MemoryStorageAdapter.js +7 -7
  84. package/dist/types/network.js +6 -3
  85. package/dist/utils/Logger.d.ts +6 -6
  86. package/dist/utils/Logger.js +5 -3
  87. package/dist/utils/MetricsCollector.js +1 -1
  88. package/dist/utils/bitcoin-address.js +4 -2
  89. package/dist/utils/cbor.js +16 -3
  90. package/dist/utils/encoding.d.ts +4 -4
  91. package/dist/utils/encoding.js +7 -6
  92. package/dist/utils/hash.js +6 -1
  93. package/dist/utils/serialization.d.ts +2 -2
  94. package/dist/utils/serialization.js +7 -5
  95. package/dist/utils/telemetry.js +6 -2
  96. package/dist/utils/validation.js +8 -4
  97. package/dist/vc/CredentialManager.d.ts +8 -8
  98. package/dist/vc/CredentialManager.js +46 -33
  99. package/dist/vc/Issuer.d.ts +2 -2
  100. package/dist/vc/Issuer.js +5 -1
  101. package/dist/vc/Verifier.d.ts +2 -2
  102. package/dist/vc/Verifier.js +12 -6
  103. package/dist/vc/documentLoader.d.ts +5 -3
  104. package/dist/vc/documentLoader.js +5 -4
  105. package/package.json +4 -1
@@ -0,0 +1,82 @@
1
+ /**
2
+ * updateEventLog Algorithm
3
+ *
4
+ * Appends an update event to an existing Cryptographic Event Log.
5
+ * Each update event references the previous event via a hash chain.
6
+ *
7
+ * @see https://w3c-ccg.github.io/cel-spec/
8
+ */
9
+ import { computeDigestMultibase } from '../hash';
10
+ /**
11
+ * Serializes a LogEntry to a deterministic byte representation for hashing.
12
+ * Uses JSON with sorted keys for reproducibility.
13
+ *
14
+ * @param entry - The log entry to serialize
15
+ * @returns UTF-8 encoded bytes
16
+ */
17
+ function serializeEntry(entry) {
18
+ // Use JSON with sorted keys for deterministic serialization
19
+ const json = JSON.stringify(entry, Object.keys(entry).sort());
20
+ return new TextEncoder().encode(json);
21
+ }
22
+ /**
23
+ * Updates an event log by appending a new "update" event.
24
+ *
25
+ * The new event is cryptographically linked to the previous event
26
+ * via a hash of the last event (previousEvent field).
27
+ *
28
+ * @param log - The existing event log to update
29
+ * @param data - The update data (e.g., modified metadata, new resources)
30
+ * @param options - Signing options including signer function and verification method
31
+ * @returns A new EventLog with the update event appended (input is not mutated)
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const updatedLog = await updateEventLog(
36
+ * existingLog,
37
+ * { name: 'Updated Asset Name', version: 2 },
38
+ * {
39
+ * signer: async (data) => createEdDsaProof(data, privateKey),
40
+ * verificationMethod: 'did:key:z6Mk...',
41
+ * proofPurpose: 'assertionMethod'
42
+ * }
43
+ * );
44
+ * ```
45
+ */
46
+ export async function updateEventLog(log, data, options) {
47
+ const { signer, verificationMethod, proofPurpose = 'assertionMethod' } = options;
48
+ // Validate input log
49
+ if (!log.events || log.events.length === 0) {
50
+ throw new Error('Cannot update an empty event log');
51
+ }
52
+ // Get the last event to compute the hash chain link
53
+ const lastEvent = log.events[log.events.length - 1];
54
+ // Compute the digestMultibase of the last event
55
+ const previousEvent = computeDigestMultibase(serializeEntry(lastEvent));
56
+ // Create the event structure without proof first
57
+ const eventBase = {
58
+ type: 'update',
59
+ data,
60
+ previousEvent,
61
+ };
62
+ // Generate proof using the provided signer
63
+ const proof = await signer(eventBase);
64
+ // Validate the proof has required fields
65
+ if (!proof.type || !proof.cryptosuite || !proof.proofValue) {
66
+ throw new Error('Invalid proof: missing required fields (type, cryptosuite, proofValue)');
67
+ }
68
+ // Construct the complete log entry
69
+ const entry = {
70
+ type: 'update',
71
+ data,
72
+ previousEvent,
73
+ proof: [proof],
74
+ };
75
+ // Return a new event log (immutable - does not mutate input)
76
+ const eventLog = {
77
+ events: [...log.events, entry],
78
+ // Preserve previousLog reference if it exists
79
+ ...(log.previousLog ? { previousLog: log.previousLog } : {}),
80
+ };
81
+ return eventLog;
82
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * verifyEventLog Algorithm
3
+ *
4
+ * Verifies all proofs and hash chain integrity in a Cryptographic Event Log.
5
+ * Returns detailed per-event verification status.
6
+ *
7
+ * @see https://w3c-ccg.github.io/cel-spec/
8
+ */
9
+ import type { EventLog, VerifyOptions, VerificationResult } from '../types';
10
+ /**
11
+ * Verifies all proofs and hash chain integrity in an event log.
12
+ *
13
+ * This algorithm verifies:
14
+ * - Each event has at least one proof
15
+ * - Each proof is structurally valid (type, cryptosuite, proofValue, verificationMethod, proofPurpose)
16
+ * - Proofs use valid cryptosuite (eddsa-jcs-2022 or eddsa-rdfc-2022)
17
+ * - The first event has no previousEvent field
18
+ * - Each subsequent event's previousEvent matches the digestMultibase of the prior event
19
+ *
20
+ * For full cryptographic verification, provide a custom verifier function
21
+ * in the options that can resolve the public key from the verificationMethod.
22
+ *
23
+ * @param log - The event log to verify
24
+ * @param options - Optional verification options including custom verifier
25
+ * @returns VerificationResult with detailed per-event status including chainValid
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Basic structural and chain verification
30
+ * const result = await verifyEventLog(eventLog);
31
+ * if (result.verified) {
32
+ * console.log('All proofs are valid and hash chain is intact');
33
+ * }
34
+ *
35
+ * // With custom cryptographic verifier
36
+ * const result = await verifyEventLog(eventLog, {
37
+ * verifier: async (proof, data) => {
38
+ * // Resolve public key and verify signature
39
+ * const publicKey = await resolvePublicKey(proof.verificationMethod);
40
+ * return verifyEdDsaSignature(data, proof.proofValue, publicKey);
41
+ * }
42
+ * });
43
+ * ```
44
+ */
45
+ export declare function verifyEventLog(log: EventLog, options?: VerifyOptions): Promise<VerificationResult>;
@@ -0,0 +1,255 @@
1
+ /**
2
+ * verifyEventLog Algorithm
3
+ *
4
+ * Verifies all proofs and hash chain integrity in a Cryptographic Event Log.
5
+ * Returns detailed per-event verification status.
6
+ *
7
+ * @see https://w3c-ccg.github.io/cel-spec/
8
+ */
9
+ import { computeDigestMultibase } from '../hash';
10
+ /**
11
+ * Serializes data to JCS (JSON Canonicalization Scheme) format.
12
+ * Uses JSON with sorted keys for deterministic serialization.
13
+ *
14
+ * @param data - The data to serialize
15
+ * @returns UTF-8 encoded bytes
16
+ */
17
+ function serializeToJcs(data) {
18
+ // JCS uses JSON with lexicographically sorted keys
19
+ const json = JSON.stringify(data, (_, value) => {
20
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
21
+ return Object.keys(value).sort().reduce((sorted, key) => {
22
+ sorted[key] = value[key];
23
+ return sorted;
24
+ }, {});
25
+ }
26
+ return value;
27
+ });
28
+ return new TextEncoder().encode(json);
29
+ }
30
+ /**
31
+ * Serializes a LogEntry to a deterministic byte representation for hashing.
32
+ * Uses JSON with sorted keys for reproducibility.
33
+ * This must match the serialization used in createEventLog/updateEventLog.
34
+ *
35
+ * @param entry - The log entry to serialize
36
+ * @returns UTF-8 encoded bytes
37
+ */
38
+ function serializeEntry(entry) {
39
+ // Use JSON with sorted keys for deterministic serialization
40
+ const json = JSON.stringify(entry, Object.keys(entry).sort());
41
+ return new TextEncoder().encode(json);
42
+ }
43
+ /**
44
+ * Default proof verifier using eddsa-jcs-2022 cryptosuite.
45
+ *
46
+ * This is a basic implementation that validates proof structure.
47
+ * For full cryptographic verification, a custom verifier should be provided
48
+ * that has access to the public key from the verificationMethod.
49
+ *
50
+ * @param proof - The proof to verify
51
+ * @param data - The data that was signed
52
+ * @returns True if proof structure is valid
53
+ */
54
+ async function defaultVerifier(proof, data) {
55
+ // Validate proof has required fields
56
+ if (!proof.type || proof.type !== 'DataIntegrityProof') {
57
+ return false;
58
+ }
59
+ if (!proof.cryptosuite) {
60
+ return false;
61
+ }
62
+ if (!proof.proofValue || typeof proof.proofValue !== 'string' || proof.proofValue.length === 0) {
63
+ return false;
64
+ }
65
+ if (!proof.verificationMethod || typeof proof.verificationMethod !== 'string') {
66
+ return false;
67
+ }
68
+ if (!proof.proofPurpose || typeof proof.proofPurpose !== 'string') {
69
+ return false;
70
+ }
71
+ // Check for valid cryptosuite
72
+ const validCryptosuites = ['eddsa-jcs-2022', 'eddsa-rdfc-2022'];
73
+ if (!validCryptosuites.includes(proof.cryptosuite)) {
74
+ return false;
75
+ }
76
+ // Validate proofValue is properly formatted (multibase encoded)
77
+ // Most proofValues start with 'z' (base58btc) or 'u' (base64url)
78
+ if (!proof.proofValue.startsWith('z') && !proof.proofValue.startsWith('u')) {
79
+ return false;
80
+ }
81
+ return true;
82
+ }
83
+ /**
84
+ * Verifies the hash chain for a single event.
85
+ *
86
+ * @param event - The current event to verify
87
+ * @param index - The index of the event in the log
88
+ * @param previousEvent - The previous event in the log (undefined for first event)
89
+ * @returns Object with chainValid boolean and any errors
90
+ */
91
+ function verifyChain(event, index, previousEvent) {
92
+ const errors = [];
93
+ if (index === 0) {
94
+ // First event must NOT have previousEvent
95
+ if (event.previousEvent !== undefined) {
96
+ errors.push(`Event ${index}: First event must not have previousEvent field`);
97
+ return { chainValid: false, errors };
98
+ }
99
+ }
100
+ else {
101
+ // Subsequent events must have previousEvent that matches hash of prior event
102
+ if (event.previousEvent === undefined) {
103
+ errors.push(`Event ${index}: Missing previousEvent reference`);
104
+ return { chainValid: false, errors };
105
+ }
106
+ if (!previousEvent) {
107
+ errors.push(`Event ${index}: Cannot verify chain - previous event not provided`);
108
+ return { chainValid: false, errors };
109
+ }
110
+ // Compute the expected hash of the previous event
111
+ const expectedHash = computeDigestMultibase(serializeEntry(previousEvent));
112
+ if (event.previousEvent !== expectedHash) {
113
+ errors.push(`Event ${index}: Hash chain broken - previousEvent does not match hash of prior event`);
114
+ return { chainValid: false, errors };
115
+ }
116
+ }
117
+ return { chainValid: true, errors: [] };
118
+ }
119
+ /**
120
+ * Verifies a single event's proofs.
121
+ *
122
+ * @param event - The event to verify
123
+ * @param index - The index of the event in the log
124
+ * @param verifier - The proof verification function
125
+ * @param previousEvent - The previous event in the log (undefined for first event)
126
+ * @returns EventVerification result
127
+ */
128
+ async function verifyEvent(event, index, verifier, previousEvent) {
129
+ const errors = [];
130
+ // Verify hash chain
131
+ const chainResult = verifyChain(event, index, previousEvent);
132
+ const chainValid = chainResult.chainValid;
133
+ errors.push(...chainResult.errors);
134
+ // Check that event has proofs
135
+ if (!event.proof || !Array.isArray(event.proof) || event.proof.length === 0) {
136
+ errors.push(`Event ${index}: No proofs found`);
137
+ return {
138
+ index,
139
+ type: event.type,
140
+ proofValid: false,
141
+ chainValid,
142
+ errors,
143
+ };
144
+ }
145
+ // Verify each proof
146
+ let allProofsValid = true;
147
+ const eventData = {
148
+ type: event.type,
149
+ data: event.data,
150
+ ...(event.previousEvent ? { previousEvent: event.previousEvent } : {}),
151
+ };
152
+ for (let proofIndex = 0; proofIndex < event.proof.length; proofIndex++) {
153
+ const proof = event.proof[proofIndex];
154
+ try {
155
+ const isValid = await verifier(proof, eventData);
156
+ if (!isValid) {
157
+ allProofsValid = false;
158
+ errors.push(`Event ${index}, Proof ${proofIndex}: Verification failed`);
159
+ }
160
+ }
161
+ catch (error) {
162
+ allProofsValid = false;
163
+ const message = error instanceof Error ? error.message : 'Unknown error';
164
+ errors.push(`Event ${index}, Proof ${proofIndex}: ${message}`);
165
+ }
166
+ }
167
+ return {
168
+ index,
169
+ type: event.type,
170
+ proofValid: allProofsValid,
171
+ chainValid,
172
+ errors,
173
+ };
174
+ }
175
+ /**
176
+ * Verifies all proofs and hash chain integrity in an event log.
177
+ *
178
+ * This algorithm verifies:
179
+ * - Each event has at least one proof
180
+ * - Each proof is structurally valid (type, cryptosuite, proofValue, verificationMethod, proofPurpose)
181
+ * - Proofs use valid cryptosuite (eddsa-jcs-2022 or eddsa-rdfc-2022)
182
+ * - The first event has no previousEvent field
183
+ * - Each subsequent event's previousEvent matches the digestMultibase of the prior event
184
+ *
185
+ * For full cryptographic verification, provide a custom verifier function
186
+ * in the options that can resolve the public key from the verificationMethod.
187
+ *
188
+ * @param log - The event log to verify
189
+ * @param options - Optional verification options including custom verifier
190
+ * @returns VerificationResult with detailed per-event status including chainValid
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * // Basic structural and chain verification
195
+ * const result = await verifyEventLog(eventLog);
196
+ * if (result.verified) {
197
+ * console.log('All proofs are valid and hash chain is intact');
198
+ * }
199
+ *
200
+ * // With custom cryptographic verifier
201
+ * const result = await verifyEventLog(eventLog, {
202
+ * verifier: async (proof, data) => {
203
+ * // Resolve public key and verify signature
204
+ * const publicKey = await resolvePublicKey(proof.verificationMethod);
205
+ * return verifyEdDsaSignature(data, proof.proofValue, publicKey);
206
+ * }
207
+ * });
208
+ * ```
209
+ */
210
+ export async function verifyEventLog(log, options) {
211
+ const errors = [];
212
+ const eventVerifications = [];
213
+ // Use custom verifier if provided, otherwise use default
214
+ const verifier = options?.verifier ?? defaultVerifier;
215
+ // Validate log structure
216
+ if (!log || !log.events) {
217
+ return {
218
+ verified: false,
219
+ errors: ['Invalid event log: missing events array'],
220
+ events: [],
221
+ };
222
+ }
223
+ if (!Array.isArray(log.events)) {
224
+ return {
225
+ verified: false,
226
+ errors: ['Invalid event log: events is not an array'],
227
+ events: [],
228
+ };
229
+ }
230
+ if (log.events.length === 0) {
231
+ return {
232
+ verified: false,
233
+ errors: ['Invalid event log: empty events array'],
234
+ events: [],
235
+ };
236
+ }
237
+ // Verify each event's proofs and hash chain
238
+ for (let i = 0; i < log.events.length; i++) {
239
+ const event = log.events[i];
240
+ const previousEvent = i > 0 ? log.events[i - 1] : undefined;
241
+ const eventResult = await verifyEvent(event, i, verifier, previousEvent);
242
+ eventVerifications.push(eventResult);
243
+ if (!eventResult.proofValid || !eventResult.chainValid) {
244
+ errors.push(...eventResult.errors);
245
+ }
246
+ }
247
+ // Determine overall verification status (both proofs AND chain must be valid)
248
+ const allProofsValid = eventVerifications.every(ev => ev.proofValid);
249
+ const allChainsValid = eventVerifications.every(ev => ev.chainValid);
250
+ return {
251
+ verified: allProofsValid && allChainsValid,
252
+ errors,
253
+ events: eventVerifications,
254
+ };
255
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * witnessEvent Algorithm
3
+ *
4
+ * Adds a witness proof to an existing log entry. The witness proof is
5
+ * appended to the event's proof array, preserving the original controller proof.
6
+ *
7
+ * @see https://w3c-ccg.github.io/cel-spec/
8
+ */
9
+ import type { LogEntry } from '../types';
10
+ import type { WitnessService } from '../witnesses/WitnessService';
11
+ /**
12
+ * Adds a witness proof to an event by calling a witness service.
13
+ *
14
+ * The witness service attests to the event's digest and returns a proof
15
+ * that is appended to the event's proof array. This does not replace
16
+ * the original controller proof - it adds an additional attestation.
17
+ *
18
+ * @param event - The log entry to witness
19
+ * @param witness - The witness service to use for attestation
20
+ * @returns A new LogEntry with the witness proof appended to the proof array
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const httpWitness = new HttpWitness('https://witness.example.com');
25
+ * const witnessedEvent = await witnessEvent(myEvent, httpWitness);
26
+ * // witnessedEvent.proof now has 2 proofs: original + witness
27
+ * ```
28
+ */
29
+ export declare function witnessEvent(event: LogEntry, witness: WitnessService): Promise<LogEntry>;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * witnessEvent Algorithm
3
+ *
4
+ * Adds a witness proof to an existing log entry. The witness proof is
5
+ * appended to the event's proof array, preserving the original controller proof.
6
+ *
7
+ * @see https://w3c-ccg.github.io/cel-spec/
8
+ */
9
+ import { computeDigestMultibase } from '../hash';
10
+ /**
11
+ * Serializes a log entry to bytes for hashing.
12
+ * Uses deterministic JSON serialization with sorted keys.
13
+ */
14
+ function serializeEntry(entry) {
15
+ // Create a canonical representation with sorted keys
16
+ const canonical = JSON.stringify(entry, (key, value) => {
17
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
18
+ return Object.keys(value)
19
+ .sort()
20
+ .reduce((sorted, k) => {
21
+ sorted[k] = value[k];
22
+ return sorted;
23
+ }, {});
24
+ }
25
+ return value;
26
+ });
27
+ return new TextEncoder().encode(canonical);
28
+ }
29
+ /**
30
+ * Adds a witness proof to an event by calling a witness service.
31
+ *
32
+ * The witness service attests to the event's digest and returns a proof
33
+ * that is appended to the event's proof array. This does not replace
34
+ * the original controller proof - it adds an additional attestation.
35
+ *
36
+ * @param event - The log entry to witness
37
+ * @param witness - The witness service to use for attestation
38
+ * @returns A new LogEntry with the witness proof appended to the proof array
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const httpWitness = new HttpWitness('https://witness.example.com');
43
+ * const witnessedEvent = await witnessEvent(myEvent, httpWitness);
44
+ * // witnessedEvent.proof now has 2 proofs: original + witness
45
+ * ```
46
+ */
47
+ export async function witnessEvent(event, witness) {
48
+ // Validate inputs
49
+ if (!event) {
50
+ throw new Error('Event is required');
51
+ }
52
+ if (!event.proof || event.proof.length === 0) {
53
+ throw new Error('Event must have at least one proof (controller proof)');
54
+ }
55
+ if (!witness) {
56
+ throw new Error('Witness service is required');
57
+ }
58
+ // Compute digest of the event
59
+ const eventBytes = serializeEntry(event);
60
+ const digestMultibase = computeDigestMultibase(eventBytes);
61
+ // Get witness proof
62
+ const witnessProof = await witness.witness(digestMultibase);
63
+ // Validate witness proof has required fields
64
+ if (!witnessProof.type || !witnessProof.cryptosuite || !witnessProof.proofValue) {
65
+ throw new Error('Invalid witness proof: missing required fields (type, cryptosuite, proofValue)');
66
+ }
67
+ if (!witnessProof.witnessedAt) {
68
+ throw new Error('Invalid witness proof: missing witnessedAt timestamp');
69
+ }
70
+ // Return new event with witness proof appended (immutable - don't modify input)
71
+ return {
72
+ ...event,
73
+ proof: [...event.proof, witnessProof],
74
+ };
75
+ }
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI Create Command
4
+ *
5
+ * Creates a new CEL asset with an initial event.
6
+ * Generates Ed25519 key pair if --key not provided.
7
+ *
8
+ * Usage: originals-cel create --name <name> --file <path> [options]
9
+ */
10
+ /**
11
+ * Flags parsed from command line arguments
12
+ */
13
+ export interface CreateFlags {
14
+ name?: string;
15
+ file?: string;
16
+ key?: string;
17
+ output?: string;
18
+ format?: string;
19
+ help?: boolean;
20
+ h?: boolean;
21
+ }
22
+ /**
23
+ * Result of the create command
24
+ */
25
+ export interface CreateResult {
26
+ success: boolean;
27
+ message: string;
28
+ log?: unknown;
29
+ keyGenerated?: boolean;
30
+ privateKey?: string;
31
+ publicKey?: string;
32
+ }
33
+ /**
34
+ * Execute the create command
35
+ */
36
+ export declare function createCommand(flags: CreateFlags): Promise<CreateResult>;