@noeos/verification-engine 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +11 -0
  4. package/README.md +7 -0
  5. package/dist/cjs/api/engine.js +271 -0
  6. package/dist/cjs/api/types.js +10 -0
  7. package/dist/cjs/chains/chain-builder.js +541 -0
  8. package/dist/cjs/chains/duplicate-detector.js +208 -0
  9. package/dist/cjs/chains/verify-chain.js +656 -0
  10. package/dist/cjs/contracts/generated.js +512 -0
  11. package/dist/cjs/contracts/schema-assets.js +6 -0
  12. package/dist/cjs/contracts/vector-assets.js +6 -0
  13. package/dist/cjs/domain/algorithm-id.js +5 -0
  14. package/dist/cjs/domain/byte-view.js +7 -0
  15. package/dist/cjs/domain/chain.js +3 -0
  16. package/dist/cjs/domain/diagnostic.js +6 -0
  17. package/dist/cjs/domain/digest.js +37 -0
  18. package/dist/cjs/domain/duplicate-policy.js +3 -0
  19. package/dist/cjs/domain/evidence.js +10 -0
  20. package/dist/cjs/domain/identifiers.js +52 -0
  21. package/dist/cjs/domain/json-value.js +3 -0
  22. package/dist/cjs/domain/limits.js +24 -0
  23. package/dist/cjs/domain/operation-result.js +19 -0
  24. package/dist/cjs/domain/position.js +16 -0
  25. package/dist/cjs/domain/protocol-version.js +5 -0
  26. package/dist/cjs/domain/rule.js +3 -0
  27. package/dist/cjs/domain/stream.js +3 -0
  28. package/dist/cjs/domain/version.js +16 -0
  29. package/dist/cjs/evidence/digest-evidence.js +22 -0
  30. package/dist/cjs/evidence/evidence-parser.js +288 -0
  31. package/dist/cjs/framing/frame-builders.js +124 -0
  32. package/dist/cjs/framing/frame-encoder.js +238 -0
  33. package/dist/cjs/framing/frame-parser.js +173 -0
  34. package/dist/cjs/framing/frame-types.js +3 -0
  35. package/dist/cjs/hashing/hash-adapter.js +90 -0
  36. package/dist/cjs/hashing/hash-frame.js +16 -0
  37. package/dist/cjs/index.js +16 -0
  38. package/dist/cjs/normalization/byte-sink.js +70 -0
  39. package/dist/cjs/normalization/jcs-profile.js +154 -0
  40. package/dist/cjs/normalization/normalize.js +56 -0
  41. package/dist/cjs/normalization/profile-registry.js +66 -0
  42. package/dist/cjs/normalization/profile.js +3 -0
  43. package/dist/cjs/normalization/raw-bytes-profile.js +27 -0
  44. package/dist/cjs/package.json +3 -0
  45. package/dist/cjs/profiles.js +9 -0
  46. package/dist/cjs/records/record-service.js +278 -0
  47. package/dist/cjs/rules/rule-set.js +211 -0
  48. package/dist/cjs/schemas.js +6 -0
  49. package/dist/cjs/validation/algorithm-validation.js +12 -0
  50. package/dist/cjs/validation/diagnostic-collector.js +159 -0
  51. package/dist/cjs/validation/digest-validation.js +48 -0
  52. package/dist/cjs/validation/identifier-validation.js +33 -0
  53. package/dist/cjs/validation/json-text-parser.js +297 -0
  54. package/dist/cjs/validation/json-value-validation.js +155 -0
  55. package/dist/cjs/validation/limit-validation.js +75 -0
  56. package/dist/cjs/validation/object-inspection.js +60 -0
  57. package/dist/cjs/validation/position-validation.js +13 -0
  58. package/dist/cjs/validation/result-helpers.js +9 -0
  59. package/dist/cjs/validation/utf8-validation.js +69 -0
  60. package/dist/cjs/validation/version-validation.js +31 -0
  61. package/dist/cjs/vectors.js +6 -0
  62. package/dist/esm/api/engine.js +266 -0
  63. package/dist/esm/api/types.js +4 -0
  64. package/dist/esm/chains/chain-builder.js +536 -0
  65. package/dist/esm/chains/duplicate-detector.js +204 -0
  66. package/dist/esm/chains/verify-chain.js +652 -0
  67. package/dist/esm/contracts/generated.js +509 -0
  68. package/dist/esm/contracts/schema-assets.js +2 -0
  69. package/dist/esm/contracts/vector-assets.js +2 -0
  70. package/dist/esm/domain/algorithm-id.js +2 -0
  71. package/dist/esm/domain/byte-view.js +4 -0
  72. package/dist/esm/domain/chain.js +2 -0
  73. package/dist/esm/domain/diagnostic.js +3 -0
  74. package/dist/esm/domain/digest.js +32 -0
  75. package/dist/esm/domain/duplicate-policy.js +2 -0
  76. package/dist/esm/domain/evidence.js +7 -0
  77. package/dist/esm/domain/identifiers.js +45 -0
  78. package/dist/esm/domain/json-value.js +2 -0
  79. package/dist/esm/domain/limits.js +21 -0
  80. package/dist/esm/domain/operation-result.js +15 -0
  81. package/dist/esm/domain/position.js +12 -0
  82. package/dist/esm/domain/protocol-version.js +2 -0
  83. package/dist/esm/domain/rule.js +2 -0
  84. package/dist/esm/domain/stream.js +2 -0
  85. package/dist/esm/domain/version.js +12 -0
  86. package/dist/esm/evidence/digest-evidence.js +19 -0
  87. package/dist/esm/evidence/evidence-parser.js +281 -0
  88. package/dist/esm/framing/frame-builders.js +114 -0
  89. package/dist/esm/framing/frame-encoder.js +234 -0
  90. package/dist/esm/framing/frame-parser.js +170 -0
  91. package/dist/esm/framing/frame-types.js +2 -0
  92. package/dist/esm/hashing/hash-adapter.js +84 -0
  93. package/dist/esm/hashing/hash-frame.js +12 -0
  94. package/dist/esm/index.js +5 -0
  95. package/dist/esm/normalization/byte-sink.js +66 -0
  96. package/dist/esm/normalization/jcs-profile.js +151 -0
  97. package/dist/esm/normalization/normalize.js +52 -0
  98. package/dist/esm/normalization/profile-registry.js +62 -0
  99. package/dist/esm/normalization/profile.js +2 -0
  100. package/dist/esm/normalization/raw-bytes-profile.js +24 -0
  101. package/dist/esm/profiles.js +6 -0
  102. package/dist/esm/records/record-service.js +270 -0
  103. package/dist/esm/rules/rule-set.js +206 -0
  104. package/dist/esm/schemas.js +2 -0
  105. package/dist/esm/validation/algorithm-validation.js +9 -0
  106. package/dist/esm/validation/diagnostic-collector.js +154 -0
  107. package/dist/esm/validation/digest-validation.js +43 -0
  108. package/dist/esm/validation/identifier-validation.js +27 -0
  109. package/dist/esm/validation/json-text-parser.js +294 -0
  110. package/dist/esm/validation/json-value-validation.js +152 -0
  111. package/dist/esm/validation/limit-validation.js +71 -0
  112. package/dist/esm/validation/object-inspection.js +54 -0
  113. package/dist/esm/validation/position-validation.js +10 -0
  114. package/dist/esm/validation/result-helpers.js +6 -0
  115. package/dist/esm/validation/utf8-validation.js +63 -0
  116. package/dist/esm/validation/version-validation.js +26 -0
  117. package/dist/esm/vectors.js +2 -0
  118. package/dist/types/api/engine.d.ts +8 -0
  119. package/dist/types/api/types.d.ts +124 -0
  120. package/dist/types/chains/chain-builder.d.ts +42 -0
  121. package/dist/types/chains/duplicate-detector.d.ts +18 -0
  122. package/dist/types/chains/verify-chain.d.ts +9 -0
  123. package/dist/types/contracts/generated.d.ts +442 -0
  124. package/dist/types/contracts/schema-assets.d.ts +2 -0
  125. package/dist/types/contracts/vector-assets.d.ts +2 -0
  126. package/dist/types/domain/algorithm-id.d.ts +4 -0
  127. package/dist/types/domain/byte-view.d.ts +1 -0
  128. package/dist/types/domain/chain.d.ts +43 -0
  129. package/dist/types/domain/diagnostic.d.ts +23 -0
  130. package/dist/types/domain/digest.d.ts +12 -0
  131. package/dist/types/domain/duplicate-policy.d.ts +26 -0
  132. package/dist/types/domain/evidence.d.ts +100 -0
  133. package/dist/types/domain/identifiers.d.ts +29 -0
  134. package/dist/types/domain/json-value.d.ts +6 -0
  135. package/dist/types/domain/limits.d.ts +13 -0
  136. package/dist/types/domain/operation-result.d.ts +12 -0
  137. package/dist/types/domain/position.d.ts +8 -0
  138. package/dist/types/domain/protocol-version.d.ts +2 -0
  139. package/dist/types/domain/rule.d.ts +34 -0
  140. package/dist/types/domain/stream.d.ts +5 -0
  141. package/dist/types/domain/version.d.ts +8 -0
  142. package/dist/types/evidence/digest-evidence.d.ts +4 -0
  143. package/dist/types/evidence/evidence-parser.d.ts +8 -0
  144. package/dist/types/framing/frame-builders.d.ts +40 -0
  145. package/dist/types/framing/frame-encoder.d.ts +6 -0
  146. package/dist/types/framing/frame-parser.d.ts +4 -0
  147. package/dist/types/framing/frame-types.d.ts +27 -0
  148. package/dist/types/hashing/hash-adapter.d.ts +12 -0
  149. package/dist/types/hashing/hash-frame.d.ts +6 -0
  150. package/dist/types/index.d.ts +8 -0
  151. package/dist/types/normalization/byte-sink.d.ts +19 -0
  152. package/dist/types/normalization/jcs-profile.d.ts +3 -0
  153. package/dist/types/normalization/normalize.d.ts +11 -0
  154. package/dist/types/normalization/profile-registry.d.ts +26 -0
  155. package/dist/types/normalization/profile.d.ts +22 -0
  156. package/dist/types/normalization/raw-bytes-profile.d.ts +2 -0
  157. package/dist/types/profiles.d.ts +8 -0
  158. package/dist/types/records/record-service.d.ts +38 -0
  159. package/dist/types/rules/rule-set.d.ts +13 -0
  160. package/dist/types/schemas.d.ts +2 -0
  161. package/dist/types/validation/algorithm-validation.d.ts +3 -0
  162. package/dist/types/validation/diagnostic-collector.d.ts +24 -0
  163. package/dist/types/validation/digest-validation.d.ts +6 -0
  164. package/dist/types/validation/identifier-validation.d.ts +6 -0
  165. package/dist/types/validation/json-text-parser.d.ts +4 -0
  166. package/dist/types/validation/json-value-validation.d.ts +4 -0
  167. package/dist/types/validation/limit-validation.d.ts +4 -0
  168. package/dist/types/validation/object-inspection.d.ts +11 -0
  169. package/dist/types/validation/position-validation.d.ts +3 -0
  170. package/dist/types/validation/result-helpers.d.ts +3 -0
  171. package/dist/types/validation/utf8-validation.d.ts +5 -0
  172. package/dist/types/validation/version-validation.d.ts +9 -0
  173. package/dist/types/vectors.d.ts +2 -0
  174. package/package.json +61 -0
  175. package/schemas/chain-summary.v1.schema.json +156 -0
  176. package/schemas/diagnostic.v1.schema.json +107 -0
  177. package/schemas/link-evidence.v1.schema.json +165 -0
  178. package/schemas/record-evidence.v1.schema.json +91 -0
  179. package/schemas/vector-set.v1.schema.json +52 -0
  180. package/vectors/evidence.json +26 -0
  181. package/vectors/framing.json +136 -0
  182. package/vectors/hashing.json +58 -0
  183. package/vectors/invalid.json +56 -0
  184. package/vectors/manifest.json +46 -0
@@ -0,0 +1,541 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ChainBuilder = exports.ChainLifecycleError = void 0;
5
+ const evidence_js_1 = require("../domain/evidence.js");
6
+ const operation_result_js_1 = require("../domain/operation-result.js");
7
+ const frame_builders_js_1 = require("../framing/frame-builders.js");
8
+ const hash_frame_js_1 = require("../hashing/hash-frame.js");
9
+ const record_service_js_1 = require("../records/record-service.js");
10
+ const rule_set_js_1 = require("../rules/rule-set.js");
11
+ const diagnostic_collector_js_1 = require("../validation/diagnostic-collector.js");
12
+ const algorithm_validation_js_1 = require("../validation/algorithm-validation.js");
13
+ const digest_validation_js_1 = require("../validation/digest-validation.js");
14
+ const identifier_validation_js_1 = require("../validation/identifier-validation.js");
15
+ const object_inspection_js_1 = require("../validation/object-inspection.js");
16
+ const position_validation_js_1 = require("../validation/position-validation.js");
17
+ const duplicate_detector_js_1 = require("./duplicate-detector.js");
18
+ class ChainLifecycleError extends Error {
19
+ code;
20
+ constructor(code) {
21
+ super(code);
22
+ this.code = code;
23
+ this.name = "ChainLifecycleError";
24
+ }
25
+ }
26
+ exports.ChainLifecycleError = ChainLifecycleError;
27
+ class ChainBuilder {
28
+ config;
29
+ rules;
30
+ options;
31
+ state = "active";
32
+ nextPosition = 0;
33
+ previous = Object.freeze({ kind: "none" });
34
+ firstDigest;
35
+ finalDigest;
36
+ diagnostics;
37
+ count = 0;
38
+ duplicates;
39
+ operationActive = false;
40
+ recordServiceOptions;
41
+ constructor(config, rules, options) {
42
+ this.config = config;
43
+ this.rules = rules;
44
+ this.options = options;
45
+ this.diagnostics = new diagnostic_collector_js_1.DiagnosticCollector(options.limits);
46
+ this.duplicates = (0, duplicate_detector_js_1.createDuplicateDetector)(config.duplicatePolicy, options.limits);
47
+ this.recordServiceOptions = Object.freeze({
48
+ limits: options.limits,
49
+ profiles: options.profiles,
50
+ rules,
51
+ });
52
+ }
53
+ static create(input, options) {
54
+ const config = validateChainConfig(input, options.limits);
55
+ if (!config.ok)
56
+ return config;
57
+ const rules = rule_set_js_1.RuleSet.create(config.value.rules, options.limits);
58
+ if (!rules.ok)
59
+ return rules;
60
+ return (0, operation_result_js_1.success)(new ChainBuilder(config.value, rules.value, options));
61
+ }
62
+ append(input) {
63
+ if (this.operationActive)
64
+ return (0, operation_result_js_1.failure)([createInternalDiagnostic("CONCURRENT_USE_FORBIDDEN")]);
65
+ return this.appendCore(input);
66
+ }
67
+ appendCore(input) {
68
+ this.requireActive();
69
+ const chainInput = validateChainRecordInput(input, this.config.algorithm, this.options.limits);
70
+ if (!chainInput.ok)
71
+ return chainInput;
72
+ const collector = new diagnostic_collector_js_1.DiagnosticCollector(this.options.limits);
73
+ if (chainInput.value.position !== this.nextPosition) {
74
+ collector.addCode("POSITION_MISMATCH", "link", { position: chainInput.value.position });
75
+ }
76
+ if (!samePrevious(chainInput.value.previous, this.previous, this.config.algorithm)) {
77
+ collector.addCode("PREVIOUS_LINK_MISMATCH", "link", { position: chainInput.value.position });
78
+ }
79
+ if (collector.hasErrors())
80
+ return (0, operation_result_js_1.failure)(collector.finish());
81
+ const record = (0, record_service_js_1.computeRecord)({
82
+ contextId: this.config.contextId,
83
+ recordId: chainInput.value.recordId,
84
+ payload: chainInput.value.payload,
85
+ profile: this.config.profile,
86
+ algorithm: this.config.algorithm,
87
+ }, this.recordServiceOptions);
88
+ if (!record.ok)
89
+ return record;
90
+ addAll(collector, record.diagnostics);
91
+ const previousDigest = chainInput.value.previous.kind === "digest"
92
+ ? (0, digest_validation_js_1.validateDigest)(chainInput.value.previous.value, this.config.algorithm)
93
+ : undefined;
94
+ if (previousDigest !== undefined && !previousDigest.ok)
95
+ return previousDigest;
96
+ const linkDigest = (0, hash_frame_js_1.hashTrustedFrame)(this.config.algorithm, (0, frame_builders_js_1.buildTrustedLinkFrame)({
97
+ algorithm: this.config.algorithm,
98
+ contextId: this.config.contextId,
99
+ sequenceId: this.config.sequenceId,
100
+ position: chainInput.value.position,
101
+ recordId: chainInput.value.recordId,
102
+ recordDigest: record.value.recordDigest,
103
+ ...(previousDigest === undefined ? {} : { previousLinkDigest: previousDigest.value }),
104
+ }, this.options.limits));
105
+ if (!linkDigest.ok)
106
+ return linkDigest;
107
+ const evidence = freezeLinkEvidence({
108
+ ...record.value.evidence,
109
+ $schema: evidence_js_1.LINK_EVIDENCE_SCHEMA,
110
+ sequenceId: this.config.sequenceId,
111
+ position: chainInput.value.position,
112
+ previous: chainInput.value.previous,
113
+ linkDigest: linkDigest.value.toHex(),
114
+ });
115
+ if (this.rules.hasRules()) {
116
+ addAll(collector, this.rules.evaluate(Object.freeze({
117
+ phase: "link",
118
+ link: evidence,
119
+ recordId: evidence.recordId,
120
+ position: evidence.position,
121
+ }), this.options.limits));
122
+ }
123
+ if (collector.hasErrors())
124
+ return (0, operation_result_js_1.failure)(collector.finish());
125
+ const observed = (0, duplicate_detector_js_1.observedLink)(evidence);
126
+ const duplicate = this.duplicates.inspect(observed);
127
+ if (!duplicate.ok) {
128
+ this.state = "failed";
129
+ return duplicate;
130
+ }
131
+ addAll(collector, duplicate.value);
132
+ if (collector.hasErrors())
133
+ return (0, operation_result_js_1.failure)(collector.finish());
134
+ try {
135
+ this.duplicates.commit(observed);
136
+ this.commit(evidence);
137
+ }
138
+ catch {
139
+ this.state = "failed";
140
+ return (0, operation_result_js_1.failure)([createInternalDiagnostic()]);
141
+ }
142
+ addAll(this.diagnostics, collector.finish());
143
+ return (0, operation_result_js_1.success)(evidence, collector.finish());
144
+ }
145
+ appendAll(input) {
146
+ if (this.operationActive)
147
+ return (0, operation_result_js_1.failure)([createInternalDiagnostic("CONCURRENT_USE_FORBIDDEN")]);
148
+ this.requireActive();
149
+ try {
150
+ for (const item of input) {
151
+ const result = this.append(item);
152
+ if (!result.ok)
153
+ return result;
154
+ }
155
+ }
156
+ catch {
157
+ this.state = "failed";
158
+ return (0, operation_result_js_1.failure)([createStreamDiagnostic("INPUT_STREAM_FAILED")]);
159
+ }
160
+ return this.finalize();
161
+ }
162
+ async appendStream(input, options = {}) {
163
+ if (this.operationActive)
164
+ return (0, operation_result_js_1.failure)([createInternalDiagnostic("CONCURRENT_USE_FORBIDDEN")]);
165
+ this.requireActive();
166
+ this.operationActive = true;
167
+ let iterator;
168
+ let terminal = false;
169
+ let closeIterator = false;
170
+ try {
171
+ if (isAborted(options.signal)) {
172
+ this.state = "aborted";
173
+ terminal = true;
174
+ return (0, operation_result_js_1.failure)([createStreamDiagnostic("OPERATION_ABORTED")]);
175
+ }
176
+ try {
177
+ iterator = input[Symbol.asyncIterator]();
178
+ }
179
+ catch {
180
+ this.state = "failed";
181
+ terminal = true;
182
+ return (0, operation_result_js_1.failure)([createStreamDiagnostic("INPUT_STREAM_FAILED")]);
183
+ }
184
+ for (;;) {
185
+ if (isAborted(options.signal)) {
186
+ this.state = "aborted";
187
+ terminal = true;
188
+ closeIterator = true;
189
+ return (0, operation_result_js_1.failure)([createStreamDiagnostic("OPERATION_ABORTED")]);
190
+ }
191
+ let next;
192
+ try {
193
+ next = await iterator.next();
194
+ }
195
+ catch {
196
+ this.state = "failed";
197
+ terminal = true;
198
+ closeIterator = true;
199
+ return (0, operation_result_js_1.failure)([createStreamDiagnostic("INPUT_STREAM_FAILED")]);
200
+ }
201
+ if (next.done === true) {
202
+ if (isAborted(options.signal)) {
203
+ this.state = "aborted";
204
+ terminal = true;
205
+ closeIterator = true;
206
+ return (0, operation_result_js_1.failure)([createStreamDiagnostic("OPERATION_ABORTED")]);
207
+ }
208
+ const finalized = this.finalize();
209
+ terminal = true;
210
+ return finalized;
211
+ }
212
+ const appended = this.appendCore(next.value);
213
+ if (!appended.ok) {
214
+ this.state = "failed";
215
+ terminal = true;
216
+ closeIterator = true;
217
+ return appended;
218
+ }
219
+ if (isAborted(options.signal)) {
220
+ this.state = "aborted";
221
+ terminal = true;
222
+ closeIterator = true;
223
+ return (0, operation_result_js_1.failure)([createStreamDiagnostic("OPERATION_ABORTED")]);
224
+ }
225
+ if (options.onEvidence !== undefined) {
226
+ try {
227
+ await options.onEvidence(appended.value);
228
+ }
229
+ catch {
230
+ this.state = "failed";
231
+ terminal = true;
232
+ closeIterator = true;
233
+ return (0, operation_result_js_1.failure)([createStreamDiagnostic("OUTPUT_SINK_FAILED")]);
234
+ }
235
+ }
236
+ }
237
+ }
238
+ finally {
239
+ if (iterator !== undefined && (closeIterator || !terminal)) {
240
+ try {
241
+ await iterator.return?.();
242
+ }
243
+ catch {
244
+ this.state = "failed";
245
+ }
246
+ }
247
+ this.operationActive = false;
248
+ }
249
+ }
250
+ snapshot() {
251
+ this.requireReadable();
252
+ return Object.freeze({
253
+ contextId: this.config.contextId,
254
+ sequenceId: this.config.sequenceId,
255
+ profile: Object.freeze({ ...this.config.profile }),
256
+ algorithm: this.config.algorithm,
257
+ nextPosition: this.nextPosition,
258
+ previous: freezePrevious(this.previous),
259
+ count: this.count,
260
+ });
261
+ }
262
+ finalize() {
263
+ this.requireActive();
264
+ if (this.count === 0 && !this.config.allowEmpty) {
265
+ return (0, operation_result_js_1.failure)([{ ...createInternalDiagnostic("EMPTY_CHAIN_FORBIDDEN"), phase: "chain" }]);
266
+ }
267
+ const collector = new diagnostic_collector_js_1.DiagnosticCollector(this.options.limits);
268
+ if (this.rules.hasRules()) {
269
+ addAll(collector, this.rules.evaluate(Object.freeze({ phase: "chain", chain: this.snapshot() }), this.options.limits));
270
+ }
271
+ if (collector.hasErrors())
272
+ return (0, operation_result_js_1.failure)(collector.finish());
273
+ addAll(this.diagnostics, collector.finish());
274
+ const evidence = this.summary("valid", "verified", "verified");
275
+ this.state = "finalized";
276
+ return (0, operation_result_js_1.success)(evidence, this.diagnostics.finish());
277
+ }
278
+ abort(reason) {
279
+ void reason;
280
+ if (this.state === "active")
281
+ this.state = "aborted";
282
+ }
283
+ commit(evidence) {
284
+ if (this.count === 0)
285
+ this.firstDigest = evidence.linkDigest;
286
+ this.finalDigest = evidence.linkDigest;
287
+ this.previous = Object.freeze({ kind: "digest", value: evidence.linkDigest });
288
+ this.nextPosition += 1;
289
+ this.count += 1;
290
+ }
291
+ summary(status, start, end) {
292
+ const diagnostics = this.diagnostics.finish();
293
+ const summary = diagnosticSummary(diagnostics);
294
+ const base = {
295
+ $schema: evidence_js_1.CHAIN_SUMMARY_EVIDENCE_SCHEMA,
296
+ protocolVersion: 1,
297
+ contextId: this.config.contextId,
298
+ sequenceId: this.config.sequenceId,
299
+ profile: Object.freeze({ ...this.config.profile }),
300
+ algorithm: this.config.algorithm,
301
+ count: this.count,
302
+ boundaries: Object.freeze({ start, end }),
303
+ status,
304
+ diagnostics: summary,
305
+ };
306
+ if (this.count === 0)
307
+ return Object.freeze(base);
308
+ if (this.firstDigest === undefined || this.finalDigest === undefined) {
309
+ throw new Error("chain summary invariant broken");
310
+ }
311
+ return Object.freeze({
312
+ ...base,
313
+ firstPosition: 0,
314
+ lastPosition: this.count - 1,
315
+ firstLinkDigest: this.firstDigest,
316
+ finalLinkDigest: this.finalDigest,
317
+ });
318
+ }
319
+ requireActive() {
320
+ if (this.state === "finalized")
321
+ throw new ChainLifecycleError("BUILDER_FINALIZED");
322
+ if (this.state === "failed" || this.state === "aborted")
323
+ throw new ChainLifecycleError("BUILDER_FAILED");
324
+ }
325
+ requireReadable() {
326
+ if (this.state === "failed" || this.state === "aborted")
327
+ throw new ChainLifecycleError("BUILDER_FAILED");
328
+ }
329
+ }
330
+ exports.ChainBuilder = ChainBuilder;
331
+ function validateChainConfig(value, limits) {
332
+ const entries = (0, object_inspection_js_1.inspectPlainObject)(value);
333
+ if (entries === undefined)
334
+ return invalidConfig(limits);
335
+ const fields = new Map(entries);
336
+ for (const key of fields.keys()) {
337
+ if (![
338
+ "contextId",
339
+ "sequenceId",
340
+ "profile",
341
+ "algorithm",
342
+ "duplicatePolicy",
343
+ "rules",
344
+ "allowEmpty",
345
+ ].includes(key))
346
+ return invalidConfig(limits);
347
+ }
348
+ if (!fields.has("contextId") ||
349
+ !fields.has("sequenceId") ||
350
+ !fields.has("profile") ||
351
+ !fields.has("algorithm")) {
352
+ return invalidConfig(limits);
353
+ }
354
+ const contextId = (0, identifier_validation_js_1.validateContextId)(fields.get("contextId"));
355
+ const sequenceId = (0, identifier_validation_js_1.validateSequenceId)(fields.get("sequenceId"));
356
+ const profile = (0, record_service_js_1.validateProfile)(fields.get("profile"), limits);
357
+ const algorithm = (0, algorithm_validation_js_1.validateAlgorithmId)(fields.get("algorithm"));
358
+ const duplicates = validateDuplicatePolicy(fields.get("duplicatePolicy"), limits);
359
+ const allowEmpty = fields.get("allowEmpty") ?? false;
360
+ if (!contextId.ok)
361
+ return contextId;
362
+ if (!sequenceId.ok)
363
+ return sequenceId;
364
+ if (!profile.ok)
365
+ return profile;
366
+ if (!algorithm.ok)
367
+ return algorithm;
368
+ if (!duplicates.ok || typeof allowEmpty !== "boolean")
369
+ return invalidConfig(limits);
370
+ return (0, operation_result_js_1.success)(Object.freeze({
371
+ contextId: contextId.value.value,
372
+ sequenceId: sequenceId.value.value,
373
+ profile: profile.value,
374
+ algorithm: algorithm.value,
375
+ duplicatePolicy: duplicates.value,
376
+ rules: fields.get("rules"),
377
+ allowEmpty,
378
+ }));
379
+ }
380
+ function validateDuplicatePolicy(value, limits) {
381
+ if (value === undefined)
382
+ return (0, operation_result_js_1.success)(Object.freeze({ kind: "none" }));
383
+ const entries = (0, object_inspection_js_1.inspectPlainObject)(value);
384
+ if (entries === undefined)
385
+ return invalidConfig(limits);
386
+ const fields = new Map(entries);
387
+ const kind = fields.get("kind");
388
+ if (kind === "none" && fields.size === 1)
389
+ return (0, operation_result_js_1.success)(Object.freeze({ kind }));
390
+ if (kind === "window" && fields.size === 2 && typeof fields.get("size") === "number") {
391
+ const size = fields.get("size");
392
+ if (typeof size !== "number" ||
393
+ !Number.isSafeInteger(size) ||
394
+ size < 1 ||
395
+ size > limits.maxFullRecords)
396
+ return invalidConfig(limits);
397
+ return (0, operation_result_js_1.success)(Object.freeze({ kind, size }));
398
+ }
399
+ if (kind === "full" && fields.size === 2 && typeof fields.get("maxRecords") === "number") {
400
+ const maxRecords = fields.get("maxRecords");
401
+ if (typeof maxRecords !== "number" ||
402
+ !Number.isSafeInteger(maxRecords) ||
403
+ maxRecords < 1 ||
404
+ maxRecords > limits.maxFullRecords)
405
+ return invalidConfig(limits);
406
+ return (0, operation_result_js_1.success)(Object.freeze({ kind, maxRecords }));
407
+ }
408
+ if (kind === "external" && fields.size === 2 && fields.has("index")) {
409
+ const index = fields.get("index");
410
+ const indexEntries = (0, object_inspection_js_1.inspectPlainObject)(index);
411
+ if (indexEntries === undefined) {
412
+ return invalidConfig(limits);
413
+ }
414
+ const indexFields = new Map(indexEntries);
415
+ const observe = indexFields.get("observe");
416
+ if (indexFields.size !== 1 || typeof observe !== "function")
417
+ return invalidConfig(limits);
418
+ return (0, operation_result_js_1.success)(Object.freeze({
419
+ kind,
420
+ index: Object.freeze({
421
+ observe(batch) {
422
+ return Reflect.apply(observe, undefined, [batch]);
423
+ },
424
+ }),
425
+ }));
426
+ }
427
+ return invalidConfig(limits);
428
+ }
429
+ function validateChainRecordInput(value, algorithm, limits) {
430
+ const entries = (0, object_inspection_js_1.inspectPlainObject)(value);
431
+ if (entries === undefined)
432
+ return invalidConfig(limits);
433
+ const fields = new Map(entries);
434
+ if (fields.size !== 4 ||
435
+ !fields.has("recordId") ||
436
+ !fields.has("payload") ||
437
+ !fields.has("position") ||
438
+ !fields.has("previous")) {
439
+ return invalidConfig(limits);
440
+ }
441
+ const recordId = (0, identifier_validation_js_1.validateRecordId)(fields.get("recordId"));
442
+ const position = (0, position_validation_js_1.validatePosition)(fields.get("position"));
443
+ const previous = validatePrevious(fields.get("previous"), algorithm, limits);
444
+ if (!recordId.ok)
445
+ return recordId;
446
+ if (!position.ok)
447
+ return position;
448
+ if (!previous.ok)
449
+ return previous;
450
+ return (0, operation_result_js_1.success)(Object.freeze({
451
+ recordId: recordId.value.value,
452
+ payload: fields.get("payload"),
453
+ position: position.value.value,
454
+ previous: previous.value,
455
+ }));
456
+ }
457
+ function validatePrevious(value, algorithm, limits) {
458
+ const entries = (0, object_inspection_js_1.inspectPlainObject)(value);
459
+ if (entries === undefined)
460
+ return invalidConfig(limits);
461
+ const fields = new Map(entries);
462
+ if (fields.get("kind") === "none" && fields.size === 1)
463
+ return (0, operation_result_js_1.success)(Object.freeze({ kind: "none" }));
464
+ if (fields.get("kind") === "digest" && fields.size === 2 && fields.has("value")) {
465
+ const digest = (0, digest_validation_js_1.validateDigest)(fields.get("value"), algorithm);
466
+ if (!digest.ok)
467
+ return digest;
468
+ return (0, operation_result_js_1.success)(Object.freeze({ kind: "digest", value: digest.value.toHex() }));
469
+ }
470
+ return invalidConfig(limits);
471
+ }
472
+ function samePrevious(left, right, algorithm) {
473
+ if (left.kind !== right.kind)
474
+ return false;
475
+ if (left.kind === "none" || right.kind === "none")
476
+ return true;
477
+ const expected = (0, digest_validation_js_1.validateDigest)(left.value, algorithm);
478
+ const actual = (0, digest_validation_js_1.validateDigest)(right.value, algorithm);
479
+ return expected.ok && actual.ok && (0, digest_validation_js_1.equalDigest)(expected.value, actual.value);
480
+ }
481
+ function freezePrevious(value) {
482
+ return value.kind === "none"
483
+ ? Object.freeze({ kind: "none" })
484
+ : Object.freeze({ kind: "digest", value: value.value });
485
+ }
486
+ function freezeLinkEvidence(value) {
487
+ return Object.freeze({
488
+ ...value,
489
+ profile: Object.freeze({ ...value.profile }),
490
+ previous: freezePrevious(value.previous),
491
+ });
492
+ }
493
+ function diagnosticSummary(diagnostics) {
494
+ let errors = 0;
495
+ let warnings = 0;
496
+ let info = 0;
497
+ for (const diagnostic of diagnostics) {
498
+ if (diagnostic.severity === "error")
499
+ errors += 1;
500
+ else if (diagnostic.severity === "warning")
501
+ warnings += 1;
502
+ else
503
+ info += 1;
504
+ }
505
+ return Object.freeze({
506
+ errors,
507
+ warnings,
508
+ info,
509
+ truncated: diagnostics.some(({ code }) => code === "DIAGNOSTIC_LIMIT_REACHED"),
510
+ });
511
+ }
512
+ function addAll(collector, diagnostics) {
513
+ for (const diagnostic of diagnostics)
514
+ collector.add(diagnostic);
515
+ }
516
+ function invalidConfig(limits) {
517
+ const collector = new diagnostic_collector_js_1.DiagnosticCollector(limits);
518
+ collector.addCode("INPUT_TYPE_INVALID", "input");
519
+ return (0, operation_result_js_1.failure)(collector.finish());
520
+ }
521
+ function createInternalDiagnostic(code = "INTERNAL_INVARIANT_BROKEN") {
522
+ return Object.freeze({
523
+ $schema: "urn:noeos:verification-engine:diagnostic:1",
524
+ code,
525
+ severity: "error",
526
+ phase: "chain",
527
+ messageKey: code.toLowerCase().replaceAll("_", "."),
528
+ });
529
+ }
530
+ function createStreamDiagnostic(code) {
531
+ return Object.freeze({
532
+ $schema: "urn:noeos:verification-engine:diagnostic:1",
533
+ code,
534
+ severity: code === "OPERATION_ABORTED" ? "info" : "error",
535
+ phase: "output",
536
+ messageKey: code.toLowerCase().replaceAll("_", "."),
537
+ });
538
+ }
539
+ function isAborted(signal) {
540
+ return signal?.aborted === true;
541
+ }