@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,238 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.encodeFrame = encodeFrame;
5
+ exports.encodeTrustedFrame = encodeTrustedFrame;
6
+ const node_util_1 = require("node:util");
7
+ const operation_result_js_1 = require("../domain/operation-result.js");
8
+ const diagnostic_collector_js_1 = require("../validation/diagnostic-collector.js");
9
+ const utf8_validation_js_1 = require("../validation/utf8-validation.js");
10
+ const object_inspection_js_1 = require("../validation/object-inspection.js");
11
+ const byte_sink_js_1 = require("../normalization/byte-sink.js");
12
+ const MAGIC = "NOEOSVE1";
13
+ const PROTOCOL_VERSION = 1;
14
+ const KIND_CODES = Object.freeze({
15
+ content: 0x01,
16
+ record: 0x02,
17
+ link: 0x03,
18
+ evidence: 0x04,
19
+ });
20
+ const MAGIC_BYTES = new TextEncoder().encode(MAGIC);
21
+ const UTF8_ENCODER = new TextEncoder();
22
+ const SHA256_BYTES = UTF8_ENCODER.encode("sha-256");
23
+ const SHA384_BYTES = UTF8_ENCODER.encode("sha-384");
24
+ const SHA512_BYTES = UTF8_ENCODER.encode("sha-512");
25
+ const RAW_PROFILE_BYTES = UTF8_ENCODER.encode("dev.noeos.raw-bytes");
26
+ const JCS_PROFILE_BYTES = UTF8_ENCODER.encode("dev.noeos.jcs");
27
+ const PROFILE_VERSION_BYTES = UTF8_ENCODER.encode("1.0.0");
28
+ function encodeFrame(input, limits) {
29
+ const frameInput = validateFrameInput(input);
30
+ if (!frameInput.ok)
31
+ return frameFailure(frameInput.code, limits);
32
+ const kindCode = KIND_CODES[frameInput.value.kind];
33
+ if (frameInput.value.fields.length > 0xffff)
34
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
35
+ const encodedFields = [];
36
+ let previousTag = 0;
37
+ for (const field of frameInput.value.fields) {
38
+ if (!Number.isSafeInteger(field.tag) || field.tag < 1 || field.tag > 0xffff) {
39
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
40
+ }
41
+ if (field.tag === previousTag)
42
+ return frameFailure("FRAME_FIELD_DUPLICATE", limits);
43
+ if (field.tag < previousTag)
44
+ return frameFailure("FRAME_FIELD_ORDER_INVALID", limits);
45
+ previousTag = field.tag;
46
+ const encoded = encodeField(field, limits);
47
+ if (!encoded.ok)
48
+ return encoded;
49
+ encodedFields.push(encoded.value);
50
+ }
51
+ const sink = new byte_sink_js_1.ByteArraySink(limits.maxPayloadBytes);
52
+ try {
53
+ sink.write(new TextEncoder().encode(MAGIC));
54
+ sink.write(Uint8Array.of(kindCode, 0, PROTOCOL_VERSION));
55
+ sink.write(uint16Bytes(encodedFields.length));
56
+ for (const field of encodedFields) {
57
+ sink.write(uint16Bytes(field.tag));
58
+ sink.write(Uint8Array.of(field.typeCode));
59
+ sink.write(uint64Bytes(field.value.length));
60
+ sink.write(field.value);
61
+ }
62
+ return { ok: true, value: sink.toBytes(), diagnostics: Object.freeze([]) };
63
+ }
64
+ catch {
65
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
66
+ }
67
+ }
68
+ /** Internal fast path. Callers must have completed positive validation. */
69
+ function encodeTrustedFrame(input, limits) {
70
+ const kindCode = KIND_CODES[input.kind];
71
+ const encodedFields = [];
72
+ let total = MAGIC_BYTES.length + 3 + 2;
73
+ try {
74
+ for (const field of input.fields) {
75
+ const encoded = encodeTrustedField(field, limits);
76
+ total += 2 + 1 + 8 + encoded.length;
77
+ encodedFields.push(encoded);
78
+ }
79
+ if (input.fields.length > 0xffff || total > limits.maxPayloadBytes) {
80
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
81
+ }
82
+ const output = new Uint8Array(total);
83
+ let offset = 0;
84
+ output.set(MAGIC_BYTES, offset);
85
+ offset += MAGIC_BYTES.length;
86
+ output[offset++] = kindCode;
87
+ output[offset++] = 0;
88
+ output[offset++] = PROTOCOL_VERSION;
89
+ output[offset++] = (encodedFields.length >>> 8) & 0xff;
90
+ output[offset++] = encodedFields.length & 0xff;
91
+ for (const field of encodedFields) {
92
+ output[offset++] = (field.tag >>> 8) & 0xff;
93
+ output[offset++] = field.tag & 0xff;
94
+ output[offset++] = field.typeCode;
95
+ writeUint64(output, offset, field.length);
96
+ offset += 8;
97
+ if (field.value instanceof Uint8Array) {
98
+ output.set(field.value, offset);
99
+ offset += field.length;
100
+ }
101
+ else {
102
+ writeUint64(output, offset, field.value);
103
+ offset += 8;
104
+ }
105
+ }
106
+ return (0, operation_result_js_1.success)(output);
107
+ }
108
+ catch {
109
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
110
+ }
111
+ }
112
+ function validateFrameInput(input) {
113
+ if (!(0, object_inspection_js_1.isPlainObject)(input) || !isFrameKind(input["kind"]))
114
+ return { ok: false, code: "FRAME_KIND_UNKNOWN" };
115
+ if (!Array.isArray(input["fields"]) || node_util_1.types.isProxy(input["fields"]))
116
+ return { ok: false, code: "FRAME_LENGTH_INVALID" };
117
+ const fields = [];
118
+ for (const field of input["fields"]) {
119
+ const validated = validateFrameField(field);
120
+ if (validated === undefined)
121
+ return { ok: false, code: "FRAME_FIELD_TYPE_INVALID" };
122
+ fields.push(validated);
123
+ }
124
+ return { ok: true, value: { kind: input["kind"], fields } };
125
+ }
126
+ function validateFrameField(input) {
127
+ if (!(0, object_inspection_js_1.isPlainObject)(input))
128
+ return undefined;
129
+ const entries = (0, object_inspection_js_1.inspectPlainObject)(input);
130
+ if (entries === undefined)
131
+ return undefined;
132
+ const properties = new Map(entries);
133
+ const tag = properties.get("tag");
134
+ const type = properties.get("type");
135
+ if (typeof tag !== "number" || typeof type !== "string")
136
+ return undefined;
137
+ if (type === "bytes") {
138
+ const value = properties.get("value");
139
+ if (node_util_1.types.isProxy(value) || !(value instanceof Uint8Array))
140
+ return undefined;
141
+ return { tag, type, value };
142
+ }
143
+ if (type === "utf8") {
144
+ const value = properties.get("value");
145
+ if (typeof value !== "string")
146
+ return undefined;
147
+ return { tag, type, value };
148
+ }
149
+ if (type === "uint64") {
150
+ const value = properties.get("value");
151
+ if (typeof value !== "number")
152
+ return undefined;
153
+ return { tag, type, value };
154
+ }
155
+ if (type === "none" && !properties.has("value"))
156
+ return { tag, type };
157
+ return undefined;
158
+ }
159
+ function isFrameKind(value) {
160
+ return value === "content" || value === "record" || value === "link" || value === "evidence";
161
+ }
162
+ function encodeField(field, limits) {
163
+ if (field.type === "bytes") {
164
+ return successField(field.tag, 0x01, field.value);
165
+ }
166
+ if (field.type === "utf8") {
167
+ const encoded = (0, utf8_validation_js_1.encodeUtf8)(field.value, limits.maxPayloadBytes);
168
+ if (!encoded.ok)
169
+ return encoded;
170
+ return successField(field.tag, 0x02, encoded.value);
171
+ }
172
+ if (field.type === "uint64") {
173
+ if (!Number.isSafeInteger(field.value) || field.value < 0)
174
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
175
+ return successField(field.tag, 0x03, uint64Bytes(field.value));
176
+ }
177
+ return successField(field.tag, 0x04, new Uint8Array(0));
178
+ }
179
+ function encodeTrustedField(field, limits) {
180
+ if (field.type === "bytes") {
181
+ return { tag: field.tag, typeCode: 0x01, value: field.value, length: field.value.length };
182
+ }
183
+ if (field.type === "utf8") {
184
+ const value = trustedUtf8(field.value);
185
+ if (value.length > limits.maxPayloadBytes)
186
+ throw new RangeError("frame field too large");
187
+ return { tag: field.tag, typeCode: 0x02, value, length: value.length };
188
+ }
189
+ if (field.type === "uint64")
190
+ return { tag: field.tag, typeCode: 0x03, value: field.value, length: 8 };
191
+ return { tag: field.tag, typeCode: 0x04, value: 0, length: 0 };
192
+ }
193
+ function trustedUtf8(value) {
194
+ if (value === "sha-256")
195
+ return SHA256_BYTES;
196
+ if (value === "sha-384")
197
+ return SHA384_BYTES;
198
+ if (value === "sha-512")
199
+ return SHA512_BYTES;
200
+ if (value === "dev.noeos.raw-bytes")
201
+ return RAW_PROFILE_BYTES;
202
+ if (value === "dev.noeos.jcs")
203
+ return JCS_PROFILE_BYTES;
204
+ if (value === "1.0.0")
205
+ return PROFILE_VERSION_BYTES;
206
+ return UTF8_ENCODER.encode(value);
207
+ }
208
+ function successField(tag, typeCode, value) {
209
+ return {
210
+ ok: true,
211
+ value: Object.freeze({ tag, typeCode, value: Uint8Array.from(value) }),
212
+ diagnostics: Object.freeze([]),
213
+ };
214
+ }
215
+ function uint16Bytes(value) {
216
+ return Uint8Array.of((value >>> 8) & 0xff, value & 0xff);
217
+ }
218
+ function uint64Bytes(value) {
219
+ const output = new Uint8Array(8);
220
+ let remaining = BigInt(value);
221
+ for (let index = 7; index >= 0; index -= 1) {
222
+ output[index] = Number(remaining & 0xffn);
223
+ remaining >>= 8n;
224
+ }
225
+ return output;
226
+ }
227
+ function writeUint64(output, offset, value) {
228
+ let remaining = BigInt(value);
229
+ for (let index = offset + 7; index >= offset; index -= 1) {
230
+ output[index] = Number(remaining & 0xffn);
231
+ remaining >>= 8n;
232
+ }
233
+ }
234
+ function frameFailure(code, limits) {
235
+ const collector = new diagnostic_collector_js_1.DiagnosticCollector(limits);
236
+ collector.addCode(code, "input");
237
+ return (0, operation_result_js_1.failure)(collector.finish());
238
+ }
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.parseFrame = parseFrame;
5
+ const node_util_1 = require("node:util");
6
+ const operation_result_js_1 = require("../domain/operation-result.js");
7
+ const diagnostic_collector_js_1 = require("../validation/diagnostic-collector.js");
8
+ const utf8_validation_js_1 = require("../validation/utf8-validation.js");
9
+ const MAGIC = "NOEOSVE1";
10
+ const HEADER_LENGTH = 13;
11
+ const KIND_NAMES = Object.freeze({
12
+ 1: "content",
13
+ 2: "record",
14
+ 3: "link",
15
+ 4: "evidence",
16
+ });
17
+ const TYPE_NAMES = Object.freeze({
18
+ 1: "bytes",
19
+ 2: "utf8",
20
+ 3: "uint64",
21
+ 4: "none",
22
+ });
23
+ function parseFrame(input, limits) {
24
+ if (node_util_1.types.isProxy(input) || !(input instanceof Uint8Array))
25
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
26
+ if (input.length > limits.maxPayloadBytes)
27
+ return frameFailure("INPUT_LIMIT_EXCEEDED", limits);
28
+ if (input.length < HEADER_LENGTH)
29
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
30
+ const view = new DataView(input.buffer, input.byteOffset, input.byteLength);
31
+ for (let index = 0; index < MAGIC.length; index += 1) {
32
+ if (view.getUint8(index) !== MAGIC.charCodeAt(index))
33
+ return frameFailure("FRAME_MAGIC_INVALID", limits);
34
+ }
35
+ const kind = KIND_NAMES[view.getUint8(8)];
36
+ if (kind === undefined)
37
+ return frameFailure("FRAME_KIND_UNKNOWN", limits);
38
+ if (view.getUint8(9) !== 0 || view.getUint8(10) !== 1)
39
+ return frameFailure("FRAME_VERSION_UNSUPPORTED", limits);
40
+ const fieldCount = view.getUint16(11);
41
+ let offset = HEADER_LENGTH;
42
+ let previousTag = 0;
43
+ const fields = [];
44
+ for (let index = 0; index < fieldCount; index += 1) {
45
+ if (offset + 11 > input.length)
46
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
47
+ const tag = view.getUint16(offset);
48
+ offset += 2;
49
+ const expected = expectedField(kind, tag);
50
+ if (tag === 0 || expected === undefined)
51
+ return frameFailure("FRAME_FIELD_UNKNOWN", limits);
52
+ if (tag === previousTag)
53
+ return frameFailure("FRAME_FIELD_DUPLICATE", limits);
54
+ if (tag < previousTag)
55
+ return frameFailure("FRAME_FIELD_ORDER_INVALID", limits);
56
+ previousTag = tag;
57
+ const typeCode = view.getUint8(offset);
58
+ offset += 1;
59
+ const type = TYPE_NAMES[typeCode];
60
+ if (type === undefined)
61
+ return frameFailure("FRAME_FIELD_TYPE_INVALID", limits);
62
+ const length = readUint64(view, offset);
63
+ if (length === undefined)
64
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
65
+ offset += 8;
66
+ if (length > input.length - offset)
67
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
68
+ if (!expected.types.includes(type))
69
+ return frameFailure("FRAME_FIELD_TYPE_INVALID", limits);
70
+ const value = readValue(tag, type, input.subarray(offset, offset + length), limits);
71
+ if (!value.ok)
72
+ return value;
73
+ fields.push(value.value);
74
+ offset += length;
75
+ }
76
+ if (offset !== input.length)
77
+ return frameFailure("FRAME_TRAILING_DATA", limits);
78
+ const expectedFields = expectedFieldsFor(kind);
79
+ if (fields.length !== expectedFields.length) {
80
+ return frameFailure("FRAME_FIELD_MISSING", limits);
81
+ }
82
+ return {
83
+ ok: true,
84
+ value: Object.freeze({ kind, protocolVersion: 1, fields: Object.freeze(fields) }),
85
+ diagnostics: Object.freeze([]),
86
+ };
87
+ }
88
+ function expectedFieldsFor(kind) {
89
+ const text = ["utf8"];
90
+ const bytes = ["bytes"];
91
+ const uint64 = ["uint64"];
92
+ if (kind === "content")
93
+ return [
94
+ { tag: 1, types: text },
95
+ { tag: 2, types: text },
96
+ { tag: 3, types: text },
97
+ { tag: 4, types: bytes },
98
+ ];
99
+ if (kind === "record")
100
+ return [
101
+ { tag: 1, types: text },
102
+ { tag: 2, types: text },
103
+ { tag: 3, types: text },
104
+ { tag: 4, types: text },
105
+ { tag: 5, types: text },
106
+ { tag: 6, types: uint64 },
107
+ { tag: 7, types: bytes },
108
+ ];
109
+ if (kind === "link")
110
+ return [
111
+ { tag: 1, types: text },
112
+ { tag: 2, types: text },
113
+ { tag: 3, types: text },
114
+ { tag: 4, types: uint64 },
115
+ { tag: 5, types: text },
116
+ { tag: 6, types: bytes },
117
+ { tag: 7, types: ["none", "bytes"] },
118
+ ];
119
+ return [
120
+ { tag: 1, types: text },
121
+ { tag: 2, types: text },
122
+ { tag: 3, types: bytes },
123
+ ];
124
+ }
125
+ function expectedField(kind, tag) {
126
+ return expectedFieldsFor(kind).find((field) => field.tag === tag);
127
+ }
128
+ function readValue(tag, type, value, limits) {
129
+ if (type === "none") {
130
+ if (value.length !== 0)
131
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
132
+ return { ok: true, value: { tag, type: "none" }, diagnostics: Object.freeze([]) };
133
+ }
134
+ if (type === "bytes")
135
+ return {
136
+ ok: true,
137
+ value: { tag, type: "bytes", value: Uint8Array.from(value) },
138
+ diagnostics: Object.freeze([]),
139
+ };
140
+ if (type === "utf8") {
141
+ const decoded = (0, utf8_validation_js_1.decodeUtf8)(value);
142
+ if (!decoded.ok)
143
+ return frameFailure("UTF8_INVALID", limits);
144
+ return {
145
+ ok: true,
146
+ value: { tag, type: "utf8", value: decoded.value },
147
+ diagnostics: Object.freeze([]),
148
+ };
149
+ }
150
+ if (value.length !== 8)
151
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
152
+ const number = readUint64(new DataView(value.buffer, value.byteOffset, value.byteLength), 0);
153
+ if (number === undefined)
154
+ return frameFailure("FRAME_LENGTH_INVALID", limits);
155
+ return {
156
+ ok: true,
157
+ value: { tag, type: "uint64", value: number },
158
+ diagnostics: Object.freeze([]),
159
+ };
160
+ }
161
+ function readUint64(view, offset) {
162
+ let value = 0n;
163
+ for (let index = 0; index < 8; index += 1)
164
+ value = (value << 8n) | BigInt(view.getUint8(offset + index));
165
+ if (value > BigInt(Number.MAX_SAFE_INTEGER))
166
+ return undefined;
167
+ return Number(value);
168
+ }
169
+ function frameFailure(code, limits) {
170
+ const collector = new diagnostic_collector_js_1.DiagnosticCollector(limits);
171
+ collector.addCode(code, "input");
172
+ return (0, operation_result_js_1.failure)(collector.finish());
173
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.createHashSink = createHashSink;
5
+ exports.hashBytes = hashBytes;
6
+ exports.hashValidatedBytes = hashValidatedBytes;
7
+ exports.hashChunks = hashChunks;
8
+ const node_crypto_1 = require("node:crypto");
9
+ const node_assert_1 = require("node:assert");
10
+ const node_util_1 = require("node:util");
11
+ const operation_result_js_1 = require("../domain/operation-result.js");
12
+ const diagnostic_collector_js_1 = require("../validation/diagnostic-collector.js");
13
+ const digest_validation_js_1 = require("../validation/digest-validation.js");
14
+ const algorithm_validation_js_1 = require("../validation/algorithm-validation.js");
15
+ const digest_js_1 = require("../domain/digest.js");
16
+ const NODE_ALGORITHMS = Object.freeze({
17
+ "sha-256": "sha256",
18
+ "sha-384": "sha384",
19
+ "sha-512": "sha512",
20
+ });
21
+ function createHashSink(algorithm, limits) {
22
+ void limits;
23
+ const validated = (0, algorithm_validation_js_1.validateAlgorithmId)(algorithm);
24
+ if (!validated.ok)
25
+ return validated;
26
+ return (0, operation_result_js_1.success)(new NodeHashSink(validated.value));
27
+ }
28
+ function hashBytes(algorithm, input, limits) {
29
+ const sinkResult = createHashSink(algorithm, limits);
30
+ if (!sinkResult.ok)
31
+ return sinkResult;
32
+ if (node_util_1.types.isProxy(input) || !(input instanceof Uint8Array))
33
+ return hashFailure("INPUT_TYPE_INVALID", limits);
34
+ if (input.length > limits.maxPayloadBytes)
35
+ return hashFailure("INPUT_LIMIT_EXCEEDED", limits);
36
+ sinkResult.value.update(input);
37
+ return (0, operation_result_js_1.success)(sinkResult.value.digest());
38
+ }
39
+ function hashValidatedBytes(algorithm, input) {
40
+ const sink = new NodeHashSink(algorithm);
41
+ sink.update(input);
42
+ return (0, operation_result_js_1.success)(sink.digest());
43
+ }
44
+ function hashChunks(algorithm, chunks, limits) {
45
+ const sinkResult = createHashSink(algorithm, limits);
46
+ if (!sinkResult.ok)
47
+ return sinkResult;
48
+ let total = 0;
49
+ try {
50
+ for (const chunk of chunks) {
51
+ if (node_util_1.types.isProxy(chunk) || !(chunk instanceof Uint8Array))
52
+ return hashFailure("INPUT_TYPE_INVALID", limits);
53
+ if (chunk.length > limits.maxPayloadBytes - total)
54
+ return hashFailure("INPUT_LIMIT_EXCEEDED", limits);
55
+ total += chunk.length;
56
+ sinkResult.value.update(chunk);
57
+ }
58
+ return (0, operation_result_js_1.success)(sinkResult.value.digest());
59
+ }
60
+ catch {
61
+ return hashFailure("NORMALIZATION_FAILED", limits);
62
+ }
63
+ }
64
+ class NodeHashSink {
65
+ algorithm;
66
+ hash;
67
+ finalized = false;
68
+ constructor(algorithm) {
69
+ this.algorithm = algorithm;
70
+ this.hash = (0, node_crypto_1.createHash)(NODE_ALGORITHMS[algorithm]);
71
+ }
72
+ update(value) {
73
+ if (this.finalized)
74
+ throw new Error("hash already finalized");
75
+ this.hash.update(value);
76
+ }
77
+ digest() {
78
+ if (this.finalized)
79
+ throw new Error("hash already finalized");
80
+ this.finalized = true;
81
+ const bytes = this.hash.digest();
82
+ node_assert_1.strict.equal(bytes.length, (0, digest_validation_js_1.digestLength)(this.algorithm), "unexpected digest length");
83
+ return digest_js_1.Digest.fromValidated(this.algorithm, bytes);
84
+ }
85
+ }
86
+ function hashFailure(code, limits) {
87
+ const collector = new diagnostic_collector_js_1.DiagnosticCollector(limits);
88
+ collector.addCode(code, "input");
89
+ return (0, operation_result_js_1.failure)(collector.finish());
90
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.hashFrame = hashFrame;
5
+ exports.hashTrustedFrame = hashTrustedFrame;
6
+ const hash_adapter_js_1 = require("./hash-adapter.js");
7
+ function hashFrame(algorithm, frame, limits) {
8
+ if (!frame.ok)
9
+ return frame;
10
+ return (0, hash_adapter_js_1.hashBytes)(algorithm, frame.value, limits);
11
+ }
12
+ function hashTrustedFrame(algorithm, frame) {
13
+ if (!frame.ok)
14
+ return frame;
15
+ return (0, hash_adapter_js_1.hashValidatedBytes)(algorithm, frame.value);
16
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.RECORD_EVIDENCE_SCHEMA = exports.LINK_EVIDENCE_SCHEMA = exports.DIAGNOSTIC_SCHEMA = exports.CHAIN_SUMMARY_EVIDENCE_SCHEMA = exports.BUILTIN_PROFILES = exports.EngineConfigurationError = exports.createEngine = exports.DIAGNOSTIC_CODES = void 0;
5
+ var generated_js_1 = require("./contracts/generated.js");
6
+ Object.defineProperty(exports, "DIAGNOSTIC_CODES", { enumerable: true, get: function () { return generated_js_1.DIAGNOSTIC_CODES; } });
7
+ var engine_js_1 = require("./api/engine.js");
8
+ Object.defineProperty(exports, "createEngine", { enumerable: true, get: function () { return engine_js_1.createEngine; } });
9
+ Object.defineProperty(exports, "EngineConfigurationError", { enumerable: true, get: function () { return engine_js_1.EngineConfigurationError; } });
10
+ var profiles_js_1 = require("./profiles.js");
11
+ Object.defineProperty(exports, "BUILTIN_PROFILES", { enumerable: true, get: function () { return profiles_js_1.BUILTIN_PROFILES; } });
12
+ var types_js_1 = require("./api/types.js");
13
+ Object.defineProperty(exports, "CHAIN_SUMMARY_EVIDENCE_SCHEMA", { enumerable: true, get: function () { return types_js_1.CHAIN_SUMMARY_EVIDENCE_SCHEMA; } });
14
+ Object.defineProperty(exports, "DIAGNOSTIC_SCHEMA", { enumerable: true, get: function () { return types_js_1.DIAGNOSTIC_SCHEMA; } });
15
+ Object.defineProperty(exports, "LINK_EVIDENCE_SCHEMA", { enumerable: true, get: function () { return types_js_1.LINK_EVIDENCE_SCHEMA; } });
16
+ Object.defineProperty(exports, "RECORD_EVIDENCE_SCHEMA", { enumerable: true, get: function () { return types_js_1.RECORD_EVIDENCE_SCHEMA; } });
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ByteArraySink = void 0;
5
+ const byte_view_js_1 = require("../domain/byte-view.js");
6
+ const UTF8_ENCODER = new TextEncoder();
7
+ class ByteArraySink {
8
+ maximum;
9
+ buffer = new Uint8Array(0);
10
+ written = 0;
11
+ constructor(maximum, initialCapacity = 0) {
12
+ this.maximum = maximum;
13
+ if (!Number.isSafeInteger(initialCapacity) || initialCapacity < 0) {
14
+ throw new RangeError("invalid initial sink capacity");
15
+ }
16
+ const capacity = Math.min(maximum, Math.max(0, initialCapacity));
17
+ if (capacity > 0)
18
+ this.buffer = new Uint8Array(capacity);
19
+ }
20
+ get byteLength() {
21
+ return this.written;
22
+ }
23
+ write(value) {
24
+ this.ensureCapacity(value.length);
25
+ this.buffer.set(value, this.written);
26
+ this.written += value.length;
27
+ }
28
+ writeByte(value) {
29
+ if (!Number.isInteger(value) || value < 0 || value > 0xff)
30
+ throw new RangeError("byte value out of range");
31
+ this.ensureCapacity(1);
32
+ this.buffer[this.written++] = value;
33
+ }
34
+ writeAscii(value) {
35
+ this.ensureCapacity(value.length);
36
+ for (let index = 0; index < value.length; index += 1) {
37
+ const code = value.charCodeAt(index);
38
+ if (code > 0x7f)
39
+ throw new RangeError("non-ASCII value");
40
+ this.buffer[this.written++] = code;
41
+ }
42
+ }
43
+ writeText(value) {
44
+ this.write(UTF8_ENCODER.encode(value));
45
+ }
46
+ toBytes() {
47
+ return (0, byte_view_js_1.copyBytes)(this.buffer.subarray(0, this.written));
48
+ }
49
+ /** Internal ownership transfer; the returned view is never exposed to callers. */
50
+ takeBytes() {
51
+ const bytes = this.buffer.subarray(0, this.written);
52
+ this.buffer = new Uint8Array(0);
53
+ this.written = 0;
54
+ return bytes;
55
+ }
56
+ ensureCapacity(additional) {
57
+ if (additional > this.maximum - this.written)
58
+ throw new RangeError("byte sink limit exceeded");
59
+ const required = this.written + additional;
60
+ if (required <= this.buffer.length)
61
+ return;
62
+ let capacity = Math.max(256, this.buffer.length);
63
+ while (capacity < required)
64
+ capacity = Math.min(this.maximum, capacity * 2);
65
+ const expanded = new Uint8Array(capacity);
66
+ expanded.set(this.buffer.subarray(0, this.written));
67
+ this.buffer = expanded;
68
+ }
69
+ }
70
+ exports.ByteArraySink = ByteArraySink;