@disclosureos/schema 2.0.0-beta.4 → 2.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +19 -0
- package/dist/experimental/v2/index.d.ts +572 -101
- package/dist/experimental/v2/index.js +1309 -638
- package/dist/experimental/v2/index.js.map +1 -1
- package/package.json +10 -6
- package/schema/experimental/claim-review-evaluation-0.1.0.schema.json +52 -0
- package/schema/experimental/claim-review-receipt-0.1.0.schema.json +99 -0
- package/schema/experimental/mcap-source-mapping-0.1.0.schema.json +303 -0
- package/schema/experimental/video-frame-source-mapping-0.1.0.schema.json +165 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseExperimentalClaimHistory, compareUtcInstants, parseContextClaimHistory, parseObservationContext, parseExperimentalObservation,
|
|
1
|
+
import { OBSERVATION_CLAIM_HISTORY_SCHEMA_ID, CASE_CLAIM_HISTORY_V02_SCHEMA_ID, parseExperimentalClaimHistory, parseObservationClaimHistory, compareUtcInstants, parseContextClaimHistory, parseObservationContext, parseExperimentalObservation, caseProvenances, parseCaseRecordV02, caseSnapshotKey, parseCaseClaimHistoryV02, parseCaseLinks, parseCaseRecord, parseResearchEntities, parseArchivalEntities, parseMaterialEntities, parseLaboratoryEntities, parseCaseClaimHistory, contextAssertions, parseResearchClaimHistory, researchEntityAssertions, parseArchivalClaimHistory, parseLaboratoryClaimHistory, parseVocabularyBindings, parseVocabularyCatalog, VOCABULARY_CATALOG_SCHEMA_ID, archivalArtifactReferences, researchEntityContextReferences, CASE_CLAIM_HISTORY_SCHEMA_ID, LABORATORY_CLAIM_HISTORY_SCHEMA_ID, ARCHIVAL_CLAIM_HISTORY_SCHEMA_ID, RESEARCH_CLAIM_HISTORY_SCHEMA_ID, CONTEXT_CLAIM_HISTORY_SCHEMA_ID, EXPERIMENTAL_CLAIM_HISTORY_SCHEMA_ID } from '@disclosureos/records/experimental/v2';
|
|
2
2
|
export { VOCABULARY_BINDINGS_SCHEMA_ID, VOCABULARY_CATALOG_SCHEMA_ID, VOCABULARY_TERM_REFERENCE_SCHEMA_ID, VocabularyBindingSchema, VocabularyBindingsSchema, VocabularyCatalogSchema, VocabularyCatalogTermSchema, VocabularyTermReferenceSchema, parseVocabularyBindings, parseVocabularyCatalog, vocabularyBindingsJsonSchema, vocabularyCatalogJsonSchema, vocabularyTermReferenceJsonSchema } from '@disclosureos/records/experimental/v2';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { parseAcquisitionContext } from '@disclosureos/instruments/experimental/v2';
|
|
@@ -22,10 +22,26 @@ function inventories(observation, claims) {
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
async function evaluateAssessmentDocumentation(input, options = {}) {
|
|
25
|
-
|
|
25
|
+
return evaluateParsedDocumentation(parseExperimentalClaimHistory(input), options, ASSESSMENT_DOCUMENTATION_PROFILE);
|
|
26
|
+
}
|
|
27
|
+
var OBSERVATION_CLAIM_DOCUMENTATION_PROFILE = Object.freeze({
|
|
28
|
+
id: "urn:disclosureos:experimental:profile:assessment-documentation",
|
|
29
|
+
version: "0.2.0",
|
|
30
|
+
scope: "documentary_only"
|
|
31
|
+
});
|
|
32
|
+
async function evaluateObservationClaimDocumentation(input, options = {}) {
|
|
33
|
+
const parsed = parseObservationClaimHistory(input);
|
|
34
|
+
const result = await evaluateParsedDocumentation(parsed, options, OBSERVATION_CLAIM_DOCUMENTATION_PROFILE);
|
|
35
|
+
return {
|
|
36
|
+
...result,
|
|
37
|
+
processingChronology: "not_checked",
|
|
38
|
+
unknownProcessingTimes: parsed.success ? parsed.data.observation.processing.filter((p) => typeof p.performedAt !== "string").map((p) => ({ processRef: `process:${p.id}`, performedAt: p.performedAt })) : []
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async function evaluateParsedDocumentation(parsed, options, profile) {
|
|
26
42
|
const result = {
|
|
27
43
|
success: false,
|
|
28
|
-
profile
|
|
44
|
+
profile,
|
|
29
45
|
contract: parsed.contract,
|
|
30
46
|
checks: { ...parsed.checks, profile: "not_checked" },
|
|
31
47
|
scientific: "not_checked",
|
|
@@ -37,71 +53,71 @@ async function evaluateAssessmentDocumentation(input, options = {}) {
|
|
|
37
53
|
if (!parsed.success) return result;
|
|
38
54
|
const observation = parsed.data.observation;
|
|
39
55
|
const inv = inventories(observation, parsed.data.claims);
|
|
40
|
-
const assets2 = new Map([...options.assets ?? []].map(([
|
|
56
|
+
const assets2 = new Map([...options.assets ?? []].map(([ref18, bytes6]) => [ref18, Uint8Array.from(bytes6)]));
|
|
41
57
|
const hashes = /* @__PURE__ */ new Map();
|
|
42
|
-
function
|
|
43
|
-
const cached = hashes.get(
|
|
58
|
+
function hash8(ref18) {
|
|
59
|
+
const cached = hashes.get(ref18);
|
|
44
60
|
if (cached) return cached;
|
|
45
|
-
const
|
|
61
|
+
const bytes6 = assets2.get(ref18);
|
|
46
62
|
const pending = (async () => {
|
|
47
|
-
if (!
|
|
63
|
+
if (!bytes6) return void 0;
|
|
48
64
|
try {
|
|
49
|
-
const
|
|
50
|
-
return [...new Uint8Array(
|
|
65
|
+
const digest12 = await globalThis.crypto.subtle.digest("SHA-256", bytes6);
|
|
66
|
+
return [...new Uint8Array(digest12)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
51
67
|
} catch {
|
|
52
68
|
return void 0;
|
|
53
69
|
}
|
|
54
70
|
})();
|
|
55
|
-
hashes.set(
|
|
71
|
+
hashes.set(ref18, pending);
|
|
56
72
|
return pending;
|
|
57
73
|
}
|
|
58
|
-
function dependencies(
|
|
59
|
-
const claim = inv.claims.get(
|
|
74
|
+
function dependencies(ref18) {
|
|
75
|
+
const claim = inv.claims.get(ref18)?.value;
|
|
60
76
|
if (claim) return claim.kind === "source_assertion" ? [claim.provenance.sourceRef] : claim.inputRefs;
|
|
61
|
-
const measurement = inv.measurements.get(
|
|
77
|
+
const measurement = inv.measurements.get(ref18)?.value;
|
|
62
78
|
if (measurement) return measurement.sourceRefs;
|
|
63
|
-
const assertion = inv.assertions.get(
|
|
79
|
+
const assertion = inv.assertions.get(ref18)?.value;
|
|
64
80
|
if (assertion) return [assertion.provenance.sourceRef];
|
|
65
|
-
const product = inv.products.get(
|
|
81
|
+
const product = inv.products.get(ref18)?.value;
|
|
66
82
|
if (product) return product.kind === "raw" ? product.sourceRefs : [product.generatedBy];
|
|
67
|
-
return inv.processes.get(
|
|
83
|
+
return inv.processes.get(ref18)?.value.inputRefs ?? [];
|
|
68
84
|
}
|
|
69
85
|
function closure(roots) {
|
|
70
86
|
const seen = /* @__PURE__ */ new Set();
|
|
71
87
|
const queue = [...roots];
|
|
72
88
|
for (let i = 0; i < queue.length; i++) {
|
|
73
|
-
const
|
|
74
|
-
if (seen.has(
|
|
75
|
-
seen.add(
|
|
76
|
-
queue.push(...dependencies(
|
|
89
|
+
const ref18 = queue[i];
|
|
90
|
+
if (seen.has(ref18)) continue;
|
|
91
|
+
seen.add(ref18);
|
|
92
|
+
queue.push(...dependencies(ref18));
|
|
77
93
|
}
|
|
78
94
|
return seen;
|
|
79
95
|
}
|
|
80
96
|
for (const claimRef of parsed.currentClaimRefs) {
|
|
81
|
-
let checkMethod2 = function(
|
|
82
|
-
const method2 = inv.methods.get(
|
|
97
|
+
let checkMethod2 = function(ref18) {
|
|
98
|
+
const method2 = inv.methods.get(ref18);
|
|
83
99
|
if (method2 && !method2.value.description) issue("PROFILE.METHOD_CONTEXT", `${method2.pointer}/description`, "The referenced method needs a declared description; correctness is not verified.");
|
|
84
100
|
};
|
|
85
101
|
const entry = inv.claims.get(claimRef);
|
|
86
102
|
const claim = entry.value;
|
|
87
103
|
if (claim.kind !== "assessment") continue;
|
|
88
104
|
const report = { claimRef, status: "not_checked", inputRefs: [...claim.inputRefs], sourceRefs: [], productRefs: [], measurementRefs: [], assets: [], issues: [] };
|
|
89
|
-
const issue = (code, pointer6,
|
|
105
|
+
const issue = (code, pointer6, message2, stage = "profile", severity = "error") => report.issues.push({ code, pointer: pointer6, message: message2, stage, severity });
|
|
90
106
|
if (claim.status === "unassessed") {
|
|
91
107
|
issue("PROFILE.UNASSESSED", `${entry.pointer}/status`, "No evaluator assessment has been made.", "profile", "warning");
|
|
92
108
|
result.assessments.push(report);
|
|
93
109
|
continue;
|
|
94
110
|
}
|
|
95
111
|
const support = closure(claim.inputRefs);
|
|
96
|
-
report.sourceRefs = [...support].filter((
|
|
97
|
-
report.productRefs = [...support].filter((
|
|
98
|
-
report.measurementRefs = [...support].filter((
|
|
112
|
+
report.sourceRefs = [...support].filter((ref18) => inv.sources.has(ref18));
|
|
113
|
+
report.productRefs = [...support].filter((ref18) => inv.products.has(ref18));
|
|
114
|
+
report.measurementRefs = [...support].filter((ref18) => inv.measurements.has(ref18));
|
|
99
115
|
const requiredAssets = new Set(report.productRefs);
|
|
100
116
|
const located = /* @__PURE__ */ new Set();
|
|
101
117
|
checkMethod2(claim.methodRef);
|
|
102
|
-
for (const
|
|
103
|
-
const statement = inv.claims.get(
|
|
104
|
-
const assertion = inv.assertions.get(
|
|
118
|
+
for (const ref18 of support) {
|
|
119
|
+
const statement = inv.claims.get(ref18);
|
|
120
|
+
const assertion = inv.assertions.get(ref18);
|
|
105
121
|
const provenance = statement?.value.kind === "source_assertion" ? statement.value.provenance : assertion?.value.provenance;
|
|
106
122
|
const path2 = statement?.pointer ?? assertion?.pointer;
|
|
107
123
|
if (provenance && path2) {
|
|
@@ -109,28 +125,28 @@ async function evaluateAssessmentDocumentation(input, options = {}) {
|
|
|
109
125
|
if (!provenance.locator) issue("PROFILE.LOCATOR_REQUIRED", `${path2}/provenance/locator`, "A supporting statement or value assertion requires a source passage locator.");
|
|
110
126
|
else located.add(provenance.sourceRef);
|
|
111
127
|
}
|
|
112
|
-
const process = inv.processes.get(
|
|
128
|
+
const process = inv.processes.get(ref18)?.value;
|
|
113
129
|
if (process) checkMethod2(process.methodRef);
|
|
114
|
-
const measurement = inv.measurements.get(
|
|
130
|
+
const measurement = inv.measurements.get(ref18)?.value;
|
|
115
131
|
if (measurement?.selection) checkMethod2(measurement.selection.methodRef);
|
|
116
132
|
if (statement?.value.kind === "assessment" && statement.value.status === "assessed") checkMethod2(statement.value.methodRef);
|
|
117
133
|
}
|
|
118
|
-
for (const
|
|
119
|
-
const source = inv.sources.get(
|
|
134
|
+
for (const ref18 of report.sourceRefs) {
|
|
135
|
+
const source = inv.sources.get(ref18);
|
|
120
136
|
if (source.value.kind === "instrument_data") continue;
|
|
121
|
-
requiredAssets.add(
|
|
122
|
-
if (!located.has(
|
|
137
|
+
requiredAssets.add(ref18);
|
|
138
|
+
if (!located.has(ref18)) issue("PROFILE.LOCATOR_REQUIRED", source.pointer, "A directly cited documentary source needs a passage locator through an assertion.");
|
|
123
139
|
}
|
|
124
140
|
if (!claim.inputRefs.length || !requiredAssets.size) issue("PROFILE.INPUTS_REQUIRED", `${entry.pointer}/inputRefs`, "Assessment requires traceable source content or data products; descriptors alone are insufficient.");
|
|
125
141
|
if (claim.outcome === "confirmed") {
|
|
126
142
|
const measurementSubject = claim.subject.kind === "measurement" ? `measurement:${claim.subject.measurementId}` : void 0;
|
|
127
|
-
const relevant = report.measurementRefs.filter((
|
|
143
|
+
const relevant = report.measurementRefs.filter((ref18) => !measurementSubject || ref18 === measurementSubject);
|
|
128
144
|
if (!relevant.length) issue("PROFILE.MEASUREMENT_REQUIRED", `${entry.pointer}/inputRefs`, "A confirmed declaration requires a measurement input matching its subject.");
|
|
129
145
|
if (observation.eventTime.state !== "known" && observation.eventTime.state !== "approximate") issue("PROFILE.EVENT_TIME", "/observation/eventTime", "Instrument documentation requires a supplied event time; an archival unknown remains valid outside this profile.");
|
|
130
|
-
for (const
|
|
131
|
-
const measurement = inv.measurements.get(
|
|
146
|
+
for (const ref18 of relevant) {
|
|
147
|
+
const measurement = inv.measurements.get(ref18);
|
|
132
148
|
if (measurement.value.value.uncertainty.kind === "unknown") issue("PROFILE.MEASUREMENT_UNCERTAINTY", `${measurement.pointer}/value/uncertainty`, "Measurement uncertainty has not been characterized in the record.");
|
|
133
|
-
const lineage = closure([
|
|
149
|
+
const lineage = closure([ref18]);
|
|
134
150
|
if (![...lineage].some((item) => {
|
|
135
151
|
const raw = inv.products.get(item)?.value;
|
|
136
152
|
return raw?.kind === "raw" && raw.sourceRefs.some((source) => inv.sources.get(source)?.value.kind === "instrument_data");
|
|
@@ -147,34 +163,34 @@ async function evaluateAssessmentDocumentation(input, options = {}) {
|
|
|
147
163
|
if (measurement.value.value.uncertainty.kind !== "unknown") for (const source of measurement.value.value.uncertainty.sourceRefs) requiredAssets.add(source);
|
|
148
164
|
}
|
|
149
165
|
}
|
|
150
|
-
for (const
|
|
151
|
-
const asset = inv.sources.get(
|
|
166
|
+
for (const ref18 of requiredAssets) {
|
|
167
|
+
const asset = inv.sources.get(ref18) ?? inv.products.get(ref18);
|
|
152
168
|
if (!asset) continue;
|
|
153
|
-
const
|
|
154
|
-
const check = { ref:
|
|
155
|
-
if (
|
|
169
|
+
const digest12 = asset.value.digest?.value;
|
|
170
|
+
const check = { ref: ref18, status: "not_checked" };
|
|
171
|
+
if (digest12) check.expectedSha256 = digest12;
|
|
156
172
|
report.assets.push(check);
|
|
157
|
-
if (!
|
|
173
|
+
if (!digest12) {
|
|
158
174
|
issue("PROFILE.DIGEST_REQUIRED", `${asset.pointer}/digest`, "Supporting content requires a pinned SHA-256 digest.");
|
|
159
175
|
continue;
|
|
160
176
|
}
|
|
161
|
-
const
|
|
162
|
-
if (!
|
|
163
|
-
issue("EXTERNAL.ASSET_UNAVAILABLE", asset.pointer, `No local bytes supplied for ${
|
|
177
|
+
const bytes6 = assets2.get(ref18);
|
|
178
|
+
if (!bytes6) {
|
|
179
|
+
issue("EXTERNAL.ASSET_UNAVAILABLE", asset.pointer, `No local bytes supplied for ${ref18}; a URI or digest alone is not verification.`, "external", "warning");
|
|
164
180
|
continue;
|
|
165
181
|
}
|
|
166
|
-
if (!
|
|
182
|
+
if (!bytes6.length) {
|
|
167
183
|
check.status = "failed";
|
|
168
184
|
issue("EXTERNAL.EMPTY_ASSET", asset.pointer, "Empty content cannot support this assessment.", "external");
|
|
169
185
|
continue;
|
|
170
186
|
}
|
|
171
|
-
const actual = await
|
|
187
|
+
const actual = await hash8(ref18);
|
|
172
188
|
if (!actual) {
|
|
173
189
|
issue("EXTERNAL.HASH_UNAVAILABLE", asset.pointer, "SHA-256 verification is unavailable in this runtime.", "external", "warning");
|
|
174
190
|
continue;
|
|
175
191
|
}
|
|
176
192
|
check.actualSha256 = actual;
|
|
177
|
-
check.status = actual ===
|
|
193
|
+
check.status = actual === digest12 ? "passed" : "failed";
|
|
178
194
|
if (check.status === "failed") issue("EXTERNAL.DIGEST_MISMATCH", `${asset.pointer}/digest`, "Supplied bytes do not match the pinned SHA-256 digest.", "external");
|
|
179
195
|
}
|
|
180
196
|
report.status = report.issues.some((item) => item.severity === "error") ? "failed" : report.assets.some((asset) => asset.status === "not_checked") ? "not_checked" : "passed";
|
|
@@ -238,7 +254,7 @@ async function evaluateAcquisitionBindings(historyInput, contextInput, bindingsI
|
|
|
238
254
|
}
|
|
239
255
|
const bindingData = bindingParse.data;
|
|
240
256
|
const observation = history.data.observation;
|
|
241
|
-
const issue = (code, path2,
|
|
257
|
+
const issue = (code, path2, message2, stage = "semantic", severity = "error") => result.issues.push({ code, stage, severity, pointer: path2, message: message2 });
|
|
242
258
|
for (const [field2, expected] of [["historyId", history.data.id], ["observationId", observation.id], ["contextId", context.data.id]]) {
|
|
243
259
|
if (bindingData[field2] !== expected) issue("BINDING.DOCUMENT_ID", `/bindings/${field2}`, "Binding document identifies a different input document.");
|
|
244
260
|
}
|
|
@@ -279,11 +295,11 @@ async function evaluateAcquisitionBindings(historyInput, contextInput, bindingsI
|
|
|
279
295
|
}
|
|
280
296
|
if (product.digest && product.digest.value !== target.artifact.digest.value) issue("BINDING.DIGEST_MISMATCH", path2, "The linked product declarations pin different SHA-256 digests.");
|
|
281
297
|
if (product.format !== target.artifact.mediaType) issue("BINDING.FORMAT_MISMATCH", path2, "Declared product format and context media type must match exactly; no format conversion is inferred.");
|
|
282
|
-
const producingSources = product.sourceRefs.filter((
|
|
298
|
+
const producingSources = product.sourceRefs.filter((ref18) => sources.get(ref18)?.kind === "instrument_data");
|
|
283
299
|
if (!producingSources.length) issue("BINDING.SOURCE_KIND", `${path2}/observationProductRef`, "Raw product does not declare an instrument-data source.");
|
|
284
300
|
const acquisition = acquisitions.get(target.acquisitionRef);
|
|
285
|
-
for (const
|
|
286
|
-
const instrument = sourceBindings.get(
|
|
301
|
+
for (const ref18 of producingSources) {
|
|
302
|
+
const instrument = sourceBindings.get(ref18);
|
|
287
303
|
if (instrument && instrument !== acquisition.instrumentRef) issue("BINDING.SOURCE_IDENTITY", path2, "A producing source is mapped to a different instrument than the product acquisition.");
|
|
288
304
|
}
|
|
289
305
|
}
|
|
@@ -292,13 +308,13 @@ async function evaluateAcquisitionBindings(historyInput, contextInput, bindingsI
|
|
|
292
308
|
return result;
|
|
293
309
|
}
|
|
294
310
|
result.checks.semantic = "passed";
|
|
295
|
-
const required = [...products].filter(([, entry]) => entry.value.kind === "raw" && entry.value.sourceRefs.some((
|
|
296
|
-
for (const [
|
|
311
|
+
const required = [...products].filter(([, entry]) => entry.value.kind === "raw" && entry.value.sourceRefs.some((ref18) => sources.get(ref18)?.kind === "instrument_data"));
|
|
312
|
+
for (const [ref18, entry] of required) if (!observationBindings.has(ref18)) issue("BINDING.PRODUCT_REQUIRED", entry.pointer, "Instrument raw product needs an explicit acquisition-product binding.", "profile");
|
|
297
313
|
if (!required.length) issue("BINDING.NO_INSTRUMENT_PRODUCTS", "/history/observation/products", "No instrument raw products are present to evaluate.", "profile", "warning");
|
|
298
314
|
const artifacts = /* @__PURE__ */ new Map();
|
|
299
|
-
const register = (
|
|
300
|
-
artifacts.set(
|
|
301
|
-
if (!report.assetRefs.includes(
|
|
315
|
+
const register = (ref18, artifact2, path2, report) => {
|
|
316
|
+
artifacts.set(ref18, { artifact: artifact2, pointer: path2 });
|
|
317
|
+
if (!report.assetRefs.includes(ref18)) report.assetRefs.push(ref18);
|
|
302
318
|
};
|
|
303
319
|
for (const [i, binding] of bindingData.products.entries()) {
|
|
304
320
|
const product = products.get(binding.observationProductRef);
|
|
@@ -306,10 +322,10 @@ async function evaluateAcquisitionBindings(historyInput, contextInput, bindingsI
|
|
|
306
322
|
const acquisition = acquisitions.get(target.value.acquisitionRef);
|
|
307
323
|
const resolution = resolutions.get(target.value.acquisitionRef);
|
|
308
324
|
const report = { ...binding, acquisitionRef: target.value.acquisitionRef, instrumentRef: acquisition.instrumentRef, assetRefs: [], status: "not_checked", issues: [] };
|
|
309
|
-
const fail = (code, path2,
|
|
325
|
+
const fail = (code, path2, message2) => report.issues.push({ code, stage: "profile", severity: "error", pointer: path2, message: message2 });
|
|
310
326
|
if (!product.value.digest) fail("BINDING.DIGEST_REQUIRED", `${product.pointer}/digest`, "Observation product must pin the same bytes as its context product.");
|
|
311
327
|
if (product.value.kind === "raw") {
|
|
312
|
-
for (const
|
|
328
|
+
for (const ref18 of product.value.sourceRefs) if (sources.get(ref18)?.kind === "instrument_data" && !sourceBindings.has(ref18)) {
|
|
313
329
|
fail("BINDING.SOURCE_REQUIRED", `/bindings/products/${i}`, "Each declared producing instrument source needs an explicit instrument binding.");
|
|
314
330
|
}
|
|
315
331
|
}
|
|
@@ -319,31 +335,31 @@ async function evaluateAcquisitionBindings(historyInput, contextInput, bindingsI
|
|
|
319
335
|
const manifest = manifests.get(acquisition.manifest.ref);
|
|
320
336
|
register(acquisition.manifest.ref, manifest.value.artifact, `${manifest.pointer}/artifact`, report);
|
|
321
337
|
}
|
|
322
|
-
for (const
|
|
323
|
-
const calibration = calibrations.get(
|
|
324
|
-
if (calibration.value.report.state === "known") register(`${
|
|
325
|
-
if (calibration.value.review.state === "reviewed") register(`${
|
|
338
|
+
for (const ref18 of resolution.calibrationRefs) {
|
|
339
|
+
const calibration = calibrations.get(ref18);
|
|
340
|
+
if (calibration.value.report.state === "known") register(`${ref18}/report`, calibration.value.report.artifact, `${calibration.pointer}/report/artifact`, report);
|
|
341
|
+
if (calibration.value.review.state === "reviewed") register(`${ref18}/review`, calibration.value.review.report, `${calibration.pointer}/review/report`, report);
|
|
326
342
|
}
|
|
327
343
|
result.bindings.push(report);
|
|
328
344
|
}
|
|
329
|
-
const assets2 = new Map([...options.assets ?? []].map(([
|
|
330
|
-
for (const [
|
|
331
|
-
const check = { ref:
|
|
345
|
+
const assets2 = new Map([...options.assets ?? []].map(([ref18, bytes6]) => [ref18, Uint8Array.from(bytes6)]));
|
|
346
|
+
for (const [ref18, entry] of artifacts) {
|
|
347
|
+
const check = { ref: ref18, status: "not_checked", pointer: entry.pointer, expectedSha256: entry.artifact.digest.value, expectedByteLength: entry.artifact.byteLength };
|
|
332
348
|
result.assets.push(check);
|
|
333
|
-
const
|
|
334
|
-
if (!
|
|
335
|
-
issue("EXTERNAL.ASSET_UNAVAILABLE", entry.pointer, `No complete local bytes supplied for ${
|
|
349
|
+
const bytes6 = assets2.get(ref18);
|
|
350
|
+
if (!bytes6) {
|
|
351
|
+
issue("EXTERNAL.ASSET_UNAVAILABLE", entry.pointer, `No complete local bytes supplied for ${ref18}.`, "external", "warning");
|
|
336
352
|
continue;
|
|
337
353
|
}
|
|
338
|
-
check.actualByteLength =
|
|
339
|
-
if (!
|
|
354
|
+
check.actualByteLength = bytes6.byteLength;
|
|
355
|
+
if (!bytes6.byteLength || bytes6.byteLength !== entry.artifact.byteLength) {
|
|
340
356
|
check.status = "failed";
|
|
341
|
-
issue(!
|
|
357
|
+
issue(!bytes6.byteLength ? "EXTERNAL.EMPTY_ASSET" : "EXTERNAL.SIZE_MISMATCH", entry.pointer, "Supplied nonempty bytes must match the declared byte length.", "external");
|
|
342
358
|
continue;
|
|
343
359
|
}
|
|
344
360
|
try {
|
|
345
|
-
const
|
|
346
|
-
check.actualSha256 = [...new Uint8Array(
|
|
361
|
+
const digest12 = await globalThis.crypto.subtle.digest("SHA-256", bytes6);
|
|
362
|
+
check.actualSha256 = [...new Uint8Array(digest12)].map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
347
363
|
check.status = check.actualSha256 === entry.artifact.digest.value ? "passed" : "failed";
|
|
348
364
|
if (check.status === "failed") issue("EXTERNAL.DIGEST_MISMATCH", entry.pointer, "Supplied bytes do not match the pinned SHA-256 digest.", "external");
|
|
349
365
|
} catch {
|
|
@@ -352,7 +368,7 @@ async function evaluateAcquisitionBindings(historyInput, contextInput, bindingsI
|
|
|
352
368
|
}
|
|
353
369
|
const assetChecks = new Map(result.assets.map((check) => [check.ref, check]));
|
|
354
370
|
for (const report of result.bindings) {
|
|
355
|
-
const statuses = report.assetRefs.map((
|
|
371
|
+
const statuses = report.assetRefs.map((ref18) => assetChecks.get(ref18).status);
|
|
356
372
|
report.status = report.issues.length || statuses.includes("failed") ? "failed" : statuses.includes("not_checked") ? "not_checked" : "passed";
|
|
357
373
|
result.issues.push(...report.issues);
|
|
358
374
|
}
|
|
@@ -438,12 +454,12 @@ async function evaluateMeasurementBindings(historyInput, contextInput, acquisiti
|
|
|
438
454
|
clockUncertainty: "not_checked",
|
|
439
455
|
artifactContents: "not_checked"
|
|
440
456
|
};
|
|
441
|
-
const issue = (code, path2,
|
|
457
|
+
const issue = (code, path2, message2, stage = "semantic") => result.issues.push({
|
|
442
458
|
code,
|
|
443
459
|
stage,
|
|
444
460
|
severity: "error",
|
|
445
461
|
pointer: path2,
|
|
446
|
-
message
|
|
462
|
+
message: message2
|
|
447
463
|
});
|
|
448
464
|
for (const [parsed, prefix] of [
|
|
449
465
|
[h, "/history"],
|
|
@@ -505,16 +521,16 @@ async function evaluateMeasurementBindings(historyInput, contextInput, acquisiti
|
|
|
505
521
|
const queue = [...refs], seen2 = /* @__PURE__ */ new Set(), raw = /* @__PURE__ */ new Set();
|
|
506
522
|
let instrument = false;
|
|
507
523
|
while (queue.length) {
|
|
508
|
-
const
|
|
509
|
-
if (seen2.has(
|
|
510
|
-
seen2.add(
|
|
511
|
-
const source = sources.get(
|
|
524
|
+
const ref18 = queue.pop();
|
|
525
|
+
if (seen2.has(ref18)) continue;
|
|
526
|
+
seen2.add(ref18);
|
|
527
|
+
const source = sources.get(ref18);
|
|
512
528
|
if (source?.kind === "instrument_data") instrument = true;
|
|
513
|
-
const assertion = assertions.get(
|
|
529
|
+
const assertion = assertions.get(ref18);
|
|
514
530
|
if (assertion) queue.push(assertion.provenance.sourceRef);
|
|
515
|
-
const product = products.get(
|
|
531
|
+
const product = products.get(ref18);
|
|
516
532
|
if (product?.kind === "raw") {
|
|
517
|
-
raw.add(
|
|
533
|
+
raw.add(ref18);
|
|
518
534
|
queue.push(...product.sourceRefs);
|
|
519
535
|
} else if (product?.kind === "derived")
|
|
520
536
|
queue.push(...processes.get(product.generatedBy).inputRefs);
|
|
@@ -548,7 +564,7 @@ async function evaluateMeasurementBindings(historyInput, contextInput, acquisiti
|
|
|
548
564
|
"Bound raw product must occur in primary measurement lineage; uncertainty and unused assertions do not supply support."
|
|
549
565
|
);
|
|
550
566
|
const instrumentRaw = [...support.raw].filter(
|
|
551
|
-
(
|
|
567
|
+
(ref18) => products.get(ref18)?.kind === "raw" && lineage([ref18]).instrument
|
|
552
568
|
);
|
|
553
569
|
if (instrumentRaw.length > 1)
|
|
554
570
|
issue(
|
|
@@ -571,8 +587,8 @@ async function evaluateMeasurementBindings(historyInput, contextInput, acquisiti
|
|
|
571
587
|
);
|
|
572
588
|
continue;
|
|
573
589
|
}
|
|
574
|
-
const
|
|
575
|
-
const manifest =
|
|
590
|
+
const pin5 = acquisition2.manifest;
|
|
591
|
+
const manifest = pin5.state === "pinned" ? c.data.manifests.find((p) => `manifest:${p.id}` === pin5.ref) : void 0;
|
|
576
592
|
const channel = manifest?.channels.find((p) => p.id === binding.channelId);
|
|
577
593
|
if (!channel || !acquisition2.channels.some((p) => p.channelId === binding.channelId))
|
|
578
594
|
issue(
|
|
@@ -637,14 +653,14 @@ async function evaluateMeasurementBindings(historyInput, contextInput, acquisiti
|
|
|
637
653
|
);
|
|
638
654
|
}
|
|
639
655
|
let applicable = 0;
|
|
640
|
-
for (const [
|
|
656
|
+
for (const [ref18, measurement] of measurements)
|
|
641
657
|
if (lineage(measurement.sourceRefs).instrument) {
|
|
642
658
|
applicable++;
|
|
643
|
-
if (!seen.has(
|
|
659
|
+
if (!seen.has(ref18))
|
|
644
660
|
issue(
|
|
645
661
|
"MEASUREMENT.REQUIRED",
|
|
646
662
|
"/measurements/measurements",
|
|
647
|
-
`Instrument-supported ${
|
|
663
|
+
`Instrument-supported ${ref18} needs an explicit channel and capture-time mapping.`,
|
|
648
664
|
"profile"
|
|
649
665
|
);
|
|
650
666
|
}
|
|
@@ -759,7 +775,7 @@ function instrumentResearchReviewJsonSchema() {
|
|
|
759
775
|
}
|
|
760
776
|
var pointer3 = (path2) => path2.map((p) => `/${String(p).replace(/~/g, "~0").replace(/\//g, "~1")}`).join("");
|
|
761
777
|
var snapshot = (assets2) => new Map(
|
|
762
|
-
[...assets2 ?? []].map(([
|
|
778
|
+
[...assets2 ?? []].map(([ref18, bytes6]) => [ref18, Uint8Array.from(bytes6)])
|
|
763
779
|
);
|
|
764
780
|
async function evaluateInstrumentResearchPrerequisites(historyInput, contextInput, acquisitionBindingsInput, measurementBindingsInput, reviewInput, options = {}) {
|
|
765
781
|
const h = parseExperimentalClaimHistory(historyInput), c = parseAcquisitionContext(contextInput), a = AcquisitionBindingsSchema.safeParse(acquisitionBindingsInput), m = MeasurementBindingsSchema.safeParse(measurementBindingsInput), r = InstrumentResearchReviewSchema.safeParse(reviewInput);
|
|
@@ -786,7 +802,7 @@ async function evaluateInstrumentResearchPrerequisites(historyInput, contextInpu
|
|
|
786
802
|
timingModel: "not_checked",
|
|
787
803
|
reviewerAuthenticity: "not_checked"
|
|
788
804
|
};
|
|
789
|
-
const issue = (code, path2,
|
|
805
|
+
const issue = (code, path2, message2, stage = "profile", severity = "error") => result.issues.push({ code, stage, severity, pointer: path2, message: message2 });
|
|
790
806
|
for (const [parsed, prefix] of [
|
|
791
807
|
[h, "/history"],
|
|
792
808
|
[c, "/context"]
|
|
@@ -831,7 +847,7 @@ async function evaluateInstrumentResearchPrerequisites(historyInput, contextInpu
|
|
|
831
847
|
"semantic"
|
|
832
848
|
);
|
|
833
849
|
const artifacts = /* @__PURE__ */ new Map();
|
|
834
|
-
const inspectReview = (value,
|
|
850
|
+
const inspectReview = (value, ref18, path2, notBefore) => {
|
|
835
851
|
if (value.state !== "reviewed") {
|
|
836
852
|
issue(
|
|
837
853
|
"RESEARCH.REVIEW_REQUIRED",
|
|
@@ -860,7 +876,7 @@ async function evaluateInstrumentResearchPrerequisites(historyInput, contextInpu
|
|
|
860
876
|
`${path2}/outcome`,
|
|
861
877
|
"Rejected or inconclusive review cannot satisfy the prerequisites."
|
|
862
878
|
);
|
|
863
|
-
artifacts.set(
|
|
879
|
+
artifacts.set(ref18, { value: value.report, path: `${path2}/report` });
|
|
864
880
|
};
|
|
865
881
|
const seen = /* @__PURE__ */ new Set();
|
|
866
882
|
for (const [i, entry] of r.data.measurements.entries()) {
|
|
@@ -1045,27 +1061,27 @@ async function evaluateInstrumentResearchPrerequisites(historyInput, contextInpu
|
|
|
1045
1061
|
})),
|
|
1046
1062
|
...measurements.issues
|
|
1047
1063
|
);
|
|
1048
|
-
for (const [
|
|
1064
|
+
for (const [ref18, { value, path: path2 }] of artifacts) {
|
|
1049
1065
|
const check = {
|
|
1050
|
-
ref:
|
|
1066
|
+
ref: ref18,
|
|
1051
1067
|
status: "not_checked",
|
|
1052
1068
|
expectedSha256: value.digest.value,
|
|
1053
1069
|
expectedByteLength: value.byteLength
|
|
1054
1070
|
};
|
|
1055
1071
|
result.reviewAssets.push(check);
|
|
1056
|
-
const
|
|
1057
|
-
if (!
|
|
1072
|
+
const bytes6 = reviewAssets.get(ref18);
|
|
1073
|
+
if (!bytes6) {
|
|
1058
1074
|
issue(
|
|
1059
1075
|
"RESEARCH.REPORT_UNAVAILABLE",
|
|
1060
1076
|
path2,
|
|
1061
|
-
`No local bytes supplied for ${
|
|
1077
|
+
`No local bytes supplied for ${ref18}.`,
|
|
1062
1078
|
"external",
|
|
1063
1079
|
"warning"
|
|
1064
1080
|
);
|
|
1065
1081
|
continue;
|
|
1066
1082
|
}
|
|
1067
|
-
check.actualByteLength =
|
|
1068
|
-
if (
|
|
1083
|
+
check.actualByteLength = bytes6.byteLength;
|
|
1084
|
+
if (bytes6.byteLength !== value.byteLength) {
|
|
1069
1085
|
check.status = "failed";
|
|
1070
1086
|
issue(
|
|
1071
1087
|
"RESEARCH.REPORT_SIZE",
|
|
@@ -1076,8 +1092,8 @@ async function evaluateInstrumentResearchPrerequisites(historyInput, contextInpu
|
|
|
1076
1092
|
continue;
|
|
1077
1093
|
}
|
|
1078
1094
|
try {
|
|
1079
|
-
const
|
|
1080
|
-
check.actualSha256 = [...new Uint8Array(
|
|
1095
|
+
const hash8 = await globalThis.crypto.subtle.digest("SHA-256", bytes6);
|
|
1096
|
+
check.actualSha256 = [...new Uint8Array(hash8)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1081
1097
|
check.status = check.actualSha256 === value.digest.value ? "passed" : "failed";
|
|
1082
1098
|
if (check.status === "failed")
|
|
1083
1099
|
issue(
|
|
@@ -1181,7 +1197,7 @@ async function evaluateReproductionPacket(input, options = {}) {
|
|
|
1181
1197
|
environmentExecution: "not_checked",
|
|
1182
1198
|
scientificEligibility: "not_checked"
|
|
1183
1199
|
};
|
|
1184
|
-
const issue = (code, pointer6,
|
|
1200
|
+
const issue = (code, pointer6, message2) => result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
1185
1201
|
if (!parsed.success) {
|
|
1186
1202
|
result.checks.structural = "failed";
|
|
1187
1203
|
for (const i of parsed.error.issues)
|
|
@@ -1202,13 +1218,13 @@ async function evaluateReproductionPacket(input, options = {}) {
|
|
|
1202
1218
|
inventory.add(file.id);
|
|
1203
1219
|
}
|
|
1204
1220
|
const used = /* @__PURE__ */ new Set();
|
|
1205
|
-
const requireRef = (
|
|
1206
|
-
used.add(
|
|
1207
|
-
if (!inventory.has(
|
|
1221
|
+
const requireRef = (ref18, path2) => {
|
|
1222
|
+
used.add(ref18);
|
|
1223
|
+
if (!inventory.has(ref18))
|
|
1208
1224
|
issue("PACKET.REFERENCE", path2, "File reference is not inventoried.");
|
|
1209
1225
|
};
|
|
1210
|
-
for (const [name,
|
|
1211
|
-
requireRef(
|
|
1226
|
+
for (const [name, ref18] of Object.entries(packet.documents))
|
|
1227
|
+
requireRef(ref18, `/documents/${name}`);
|
|
1212
1228
|
for (const [namespace, entries] of Object.entries(packet.assets)) {
|
|
1213
1229
|
const seen = /* @__PURE__ */ new Set();
|
|
1214
1230
|
for (const [i, entry] of entries.entries()) {
|
|
@@ -1239,12 +1255,12 @@ async function evaluateReproductionPacket(input, options = {}) {
|
|
|
1239
1255
|
`/method/implementations/${i}/environmentRef`
|
|
1240
1256
|
);
|
|
1241
1257
|
}
|
|
1242
|
-
for (const
|
|
1243
|
-
if (!used.has(
|
|
1258
|
+
for (const ref18 of inventory)
|
|
1259
|
+
if (!used.has(ref18))
|
|
1244
1260
|
issue(
|
|
1245
1261
|
"PACKET.UNUSED_FILE",
|
|
1246
1262
|
"/files",
|
|
1247
|
-
`Unreferenced file ${
|
|
1263
|
+
`Unreferenced file ${ref18}; inventory must describe the evaluated packet.`
|
|
1248
1264
|
);
|
|
1249
1265
|
if (result.issues.length) {
|
|
1250
1266
|
result.checks.semantic = "failed";
|
|
@@ -1252,9 +1268,9 @@ async function evaluateReproductionPacket(input, options = {}) {
|
|
|
1252
1268
|
}
|
|
1253
1269
|
result.checks.semantic = "passed";
|
|
1254
1270
|
const files = new Map(
|
|
1255
|
-
[...options.files ?? []].map(([
|
|
1256
|
-
|
|
1257
|
-
Uint8Array.from(
|
|
1271
|
+
[...options.files ?? []].map(([id26, bytes6]) => [
|
|
1272
|
+
id26,
|
|
1273
|
+
Uint8Array.from(bytes6)
|
|
1258
1274
|
])
|
|
1259
1275
|
);
|
|
1260
1276
|
for (const [i, file] of packet.files.entries()) {
|
|
@@ -1265,8 +1281,8 @@ async function evaluateReproductionPacket(input, options = {}) {
|
|
|
1265
1281
|
expectedByteLength: file.byteLength
|
|
1266
1282
|
};
|
|
1267
1283
|
result.files.push(check);
|
|
1268
|
-
const
|
|
1269
|
-
if (!
|
|
1284
|
+
const bytes6 = files.get(file.id);
|
|
1285
|
+
if (!bytes6) {
|
|
1270
1286
|
issue(
|
|
1271
1287
|
"PACKET.MISSING_FILE",
|
|
1272
1288
|
`/files/${i}`,
|
|
@@ -1274,8 +1290,8 @@ async function evaluateReproductionPacket(input, options = {}) {
|
|
|
1274
1290
|
);
|
|
1275
1291
|
continue;
|
|
1276
1292
|
}
|
|
1277
|
-
check.actualByteLength =
|
|
1278
|
-
if (
|
|
1293
|
+
check.actualByteLength = bytes6.byteLength;
|
|
1294
|
+
if (bytes6.byteLength !== file.byteLength) {
|
|
1279
1295
|
check.status = "failed";
|
|
1280
1296
|
issue(
|
|
1281
1297
|
"PACKET.SIZE",
|
|
@@ -1285,8 +1301,8 @@ async function evaluateReproductionPacket(input, options = {}) {
|
|
|
1285
1301
|
continue;
|
|
1286
1302
|
}
|
|
1287
1303
|
try {
|
|
1288
|
-
const
|
|
1289
|
-
check.actualSha256 = [...new Uint8Array(
|
|
1304
|
+
const digest12 = await globalThis.crypto.subtle.digest("SHA-256", bytes6);
|
|
1305
|
+
check.actualSha256 = [...new Uint8Array(digest12)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1290
1306
|
check.status = check.actualSha256 === file.sha256 ? "passed" : "failed";
|
|
1291
1307
|
if (check.status === "failed")
|
|
1292
1308
|
issue(
|
|
@@ -1309,13 +1325,13 @@ async function evaluateReproductionPacket(input, options = {}) {
|
|
|
1309
1325
|
}
|
|
1310
1326
|
if (result.files.some((f) => f.status === "not_checked")) return result;
|
|
1311
1327
|
const documents = {};
|
|
1312
|
-
for (const [name,
|
|
1328
|
+
for (const [name, ref18] of Object.entries(packet.documents))
|
|
1313
1329
|
try {
|
|
1314
|
-
const
|
|
1330
|
+
const bytes6 = files.get(ref18);
|
|
1315
1331
|
const decoded = new TextDecoder("utf-8", {
|
|
1316
1332
|
fatal: true,
|
|
1317
1333
|
ignoreBOM: true
|
|
1318
|
-
}).decode(
|
|
1334
|
+
}).decode(bytes6);
|
|
1319
1335
|
documents[name] = JSON.parse(decoded);
|
|
1320
1336
|
} catch {
|
|
1321
1337
|
issue(
|
|
@@ -1431,8 +1447,8 @@ function datasetReleaseJsonSchema() {
|
|
|
1431
1447
|
};
|
|
1432
1448
|
}
|
|
1433
1449
|
var pointer4 = (path2) => path2.map((p) => `/${String(p).replace(/~/g, "~0").replace(/\//g, "~1")}`).join("");
|
|
1434
|
-
var decode = (
|
|
1435
|
-
new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
|
|
1450
|
+
var decode = (bytes6) => JSON.parse(
|
|
1451
|
+
new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes6)
|
|
1436
1452
|
);
|
|
1437
1453
|
async function evaluateDatasetRelease(input, options = {}) {
|
|
1438
1454
|
const parsed = DatasetReleaseSchema.safeParse(input);
|
|
@@ -1453,7 +1469,7 @@ async function evaluateDatasetRelease(input, options = {}) {
|
|
|
1453
1469
|
authorization: "not_checked",
|
|
1454
1470
|
crossInstrumentIdentity: "not_checked"
|
|
1455
1471
|
};
|
|
1456
|
-
const issue = (code, path2,
|
|
1472
|
+
const issue = (code, path2, message2, stage = "semantic") => result.issues.push({ code, pointer: path2, message: message2, stage });
|
|
1457
1473
|
if (!parsed.success) {
|
|
1458
1474
|
result.checks.structural = "failed";
|
|
1459
1475
|
for (const i of parsed.error.issues)
|
|
@@ -1516,11 +1532,11 @@ async function evaluateDatasetRelease(input, options = {}) {
|
|
|
1516
1532
|
return result;
|
|
1517
1533
|
}
|
|
1518
1534
|
const packets = new Map(
|
|
1519
|
-
[...options.packets ?? []].map(([
|
|
1520
|
-
|
|
1535
|
+
[...options.packets ?? []].map(([id26, p]) => [
|
|
1536
|
+
id26,
|
|
1521
1537
|
{
|
|
1522
1538
|
manifest: Uint8Array.from(p.manifest),
|
|
1523
|
-
files: new Map([...p.files].map(([
|
|
1539
|
+
files: new Map([...p.files].map(([id27, b]) => [id27, Uint8Array.from(b)]))
|
|
1524
1540
|
}
|
|
1525
1541
|
])
|
|
1526
1542
|
);
|
|
@@ -1689,8 +1705,8 @@ async function evaluateDatasetRelease(input, options = {}) {
|
|
|
1689
1705
|
continue;
|
|
1690
1706
|
}
|
|
1691
1707
|
member.classification = acquisition.classification;
|
|
1692
|
-
const
|
|
1693
|
-
const assigned = canonicalSessions.get(
|
|
1708
|
+
const canonical2 = `${context.id}/${m.acquisitionRef}`;
|
|
1709
|
+
const assigned = canonicalSessions.get(canonical2);
|
|
1694
1710
|
if (assigned && assigned !== s.id) {
|
|
1695
1711
|
member.status = "failed";
|
|
1696
1712
|
issue(
|
|
@@ -1700,7 +1716,7 @@ async function evaluateDatasetRelease(input, options = {}) {
|
|
|
1700
1716
|
);
|
|
1701
1717
|
continue;
|
|
1702
1718
|
}
|
|
1703
|
-
canonicalSessions.set(
|
|
1719
|
+
canonicalSessions.set(canonical2, s.id);
|
|
1704
1720
|
const t = acquisition.time;
|
|
1705
1721
|
if (t.state === "unknown" || s.time.state === "unknown") continue;
|
|
1706
1722
|
const start = t.kind === "instant" ? t.value : t.start, end = t.kind === "instant" ? t.value : t.end;
|
|
@@ -1828,7 +1844,7 @@ async function evaluateSourceIntake(input, options = {}) {
|
|
|
1828
1844
|
artifactContents: "not_checked",
|
|
1829
1845
|
authorization: "not_checked"
|
|
1830
1846
|
};
|
|
1831
|
-
const issue = (code, stage, path2,
|
|
1847
|
+
const issue = (code, stage, path2, message2) => result.issues.push({ code, stage, pointer: path2, message: message2 });
|
|
1832
1848
|
if (!parsed.success) {
|
|
1833
1849
|
result.checks.structural = "failed";
|
|
1834
1850
|
for (const i of parsed.error.issues)
|
|
@@ -1911,7 +1927,7 @@ async function evaluateSourceIntake(input, options = {}) {
|
|
|
1911
1927
|
}
|
|
1912
1928
|
result.checks.semantic = "passed";
|
|
1913
1929
|
const files = new Map(
|
|
1914
|
-
[...options.files ?? []].map(([
|
|
1930
|
+
[...options.files ?? []].map(([id26, b]) => [id26, Uint8Array.from(b)])
|
|
1915
1931
|
);
|
|
1916
1932
|
for (const [i, a] of data.artifacts.entries()) {
|
|
1917
1933
|
const path2 = `/artifacts/${i}`, check = {
|
|
@@ -1921,8 +1937,8 @@ async function evaluateSourceIntake(input, options = {}) {
|
|
|
1921
1937
|
expectedByteLength: a.byteLength
|
|
1922
1938
|
};
|
|
1923
1939
|
result.files.push(check);
|
|
1924
|
-
const
|
|
1925
|
-
if (!
|
|
1940
|
+
const bytes6 = files.get(a.id);
|
|
1941
|
+
if (!bytes6) {
|
|
1926
1942
|
issue(
|
|
1927
1943
|
"INTAKE.FILE_UNAVAILABLE",
|
|
1928
1944
|
"external",
|
|
@@ -1931,8 +1947,8 @@ async function evaluateSourceIntake(input, options = {}) {
|
|
|
1931
1947
|
);
|
|
1932
1948
|
continue;
|
|
1933
1949
|
}
|
|
1934
|
-
check.actualByteLength =
|
|
1935
|
-
if (
|
|
1950
|
+
check.actualByteLength = bytes6.length;
|
|
1951
|
+
if (bytes6.length !== a.byteLength) {
|
|
1936
1952
|
check.status = "failed";
|
|
1937
1953
|
issue(
|
|
1938
1954
|
"INTAKE.SIZE",
|
|
@@ -1945,7 +1961,7 @@ async function evaluateSourceIntake(input, options = {}) {
|
|
|
1945
1961
|
try {
|
|
1946
1962
|
check.actualSha256 = [
|
|
1947
1963
|
...new Uint8Array(
|
|
1948
|
-
await globalThis.crypto.subtle.digest("SHA-256",
|
|
1964
|
+
await globalThis.crypto.subtle.digest("SHA-256", bytes6)
|
|
1949
1965
|
)
|
|
1950
1966
|
].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1951
1967
|
check.status = check.actualSha256 === a.sha256 ? "passed" : "failed";
|
|
@@ -2081,16 +2097,16 @@ async function evaluateDocumentationCompletion(input, options = {}) {
|
|
|
2081
2097
|
const assessed = claim.status === "assessed", confirmed = assessed && claim.outcome === "confirmed";
|
|
2082
2098
|
const subjectRef = claim.subject.kind === "measurement" ? `measurement:${claim.subject.measurementId}` : void 0;
|
|
2083
2099
|
const relevant = report.measurementRefs.filter(
|
|
2084
|
-
(
|
|
2100
|
+
(ref18) => !subjectRef || ref18 === subjectRef
|
|
2085
2101
|
);
|
|
2086
2102
|
const requirements = [];
|
|
2087
2103
|
for (const definition of DOCUMENTATION_REQUIREMENTS) {
|
|
2088
|
-
const
|
|
2104
|
+
const id26 = definition.id;
|
|
2089
2105
|
const issues = report.issues.filter(
|
|
2090
|
-
(i) => codes[
|
|
2106
|
+
(i) => codes[id26].includes(i.code)
|
|
2091
2107
|
);
|
|
2092
2108
|
const row = {
|
|
2093
|
-
id:
|
|
2109
|
+
id: id26,
|
|
2094
2110
|
label: definition.label,
|
|
2095
2111
|
importance: "required",
|
|
2096
2112
|
applicability: "applicable",
|
|
@@ -2099,7 +2115,7 @@ async function evaluateDocumentationCompletion(input, options = {}) {
|
|
|
2099
2115
|
actions: issues.map(action),
|
|
2100
2116
|
blockedBy: []
|
|
2101
2117
|
};
|
|
2102
|
-
if (
|
|
2118
|
+
if (id26 === "assessment") {
|
|
2103
2119
|
if (!assessed) {
|
|
2104
2120
|
row.status = "missing";
|
|
2105
2121
|
row.reason = "No attributed evaluator assessment has been recorded; unassessed remains a valid state.";
|
|
@@ -2109,7 +2125,7 @@ async function evaluateDocumentationCompletion(input, options = {}) {
|
|
|
2109
2125
|
"documentary_support",
|
|
2110
2126
|
"content_digests",
|
|
2111
2127
|
"content_integrity"
|
|
2112
|
-
].includes(
|
|
2128
|
+
].includes(id26);
|
|
2113
2129
|
if (!assessed) {
|
|
2114
2130
|
row.blockedBy = ["assessment"];
|
|
2115
2131
|
row.status = "not_checked";
|
|
@@ -2123,19 +2139,19 @@ async function evaluateDocumentationCompletion(input, options = {}) {
|
|
|
2123
2139
|
"measurement_uncertainty",
|
|
2124
2140
|
"raw_product_lineage",
|
|
2125
2141
|
"reference_frames"
|
|
2126
|
-
].includes(
|
|
2142
|
+
].includes(id26) && !relevant.length) {
|
|
2127
2143
|
row.blockedBy = ["measurement"];
|
|
2128
2144
|
row.status = "not_checked";
|
|
2129
2145
|
row.reason = "A measurement matching the subject is required before this check can run.";
|
|
2130
|
-
} else if (
|
|
2146
|
+
} else if (id26 === "reference_frames" && !relevant.some((ref18) => measurements.get(ref18)?.frameRef)) {
|
|
2131
2147
|
row.status = "not_applicable";
|
|
2132
2148
|
row.applicability = "not_applicable";
|
|
2133
2149
|
row.reason = "No relevant measurement declares a frame reference; this does not establish that a frame is scientifically unnecessary.";
|
|
2134
|
-
} else if (["content_digests", "content_integrity"].includes(
|
|
2150
|
+
} else if (["content_digests", "content_integrity"].includes(id26) && !report.assets.length) {
|
|
2135
2151
|
row.blockedBy = ["documentary_support"];
|
|
2136
2152
|
row.status = "not_checked";
|
|
2137
2153
|
row.reason = "Traceable supporting content is required before pins and local bytes can be checked.";
|
|
2138
|
-
} else if (
|
|
2154
|
+
} else if (id26 === "content_integrity") {
|
|
2139
2155
|
if (report.assets.some((a) => a.status === "failed")) {
|
|
2140
2156
|
row.status = "failed";
|
|
2141
2157
|
row.reason = "Supplied content is empty or differs from its pinned digest.";
|
|
@@ -2310,7 +2326,7 @@ async function evaluateInstrumentResearchCompletion(historyInput, contextInput,
|
|
|
2310
2326
|
blockedBy: [],
|
|
2311
2327
|
actions: []
|
|
2312
2328
|
}));
|
|
2313
|
-
const item = (
|
|
2329
|
+
const item = (id26) => requirements.find((r) => r.id === id26);
|
|
2314
2330
|
const inputs = item("input_consistency");
|
|
2315
2331
|
inputs.actions = actions.filter(
|
|
2316
2332
|
(i) => i.stage === "structural" || i.stage === "semantic"
|
|
@@ -2350,14 +2366,14 @@ async function evaluateInstrumentResearchCompletion(historyInput, contextInput,
|
|
|
2350
2366
|
} else {
|
|
2351
2367
|
reviewed.blockedBy = ["input_consistency", "review_scope"];
|
|
2352
2368
|
}
|
|
2353
|
-
for (const [
|
|
2369
|
+
for (const [id26, nested] of [
|
|
2354
2370
|
["assessment_documentation", validation.documentation],
|
|
2355
2371
|
["measurement_acquisition", validation.measurements]
|
|
2356
2372
|
]) {
|
|
2357
|
-
const row = item(
|
|
2373
|
+
const row = item(id26);
|
|
2358
2374
|
row.actions = nested ? nested.issues.map(
|
|
2359
2375
|
(i) => action2(
|
|
2360
|
-
|
|
2376
|
+
id26 === "assessment_documentation" ? { ...i, pointer: "/documentation" + i.pointer } : i
|
|
2361
2377
|
)
|
|
2362
2378
|
) : [];
|
|
2363
2379
|
if (!nested) {
|
|
@@ -2453,15 +2469,15 @@ function serialize(value) {
|
|
|
2453
2469
|
}
|
|
2454
2470
|
return JSON.stringify(value);
|
|
2455
2471
|
}
|
|
2456
|
-
async function digest(
|
|
2457
|
-
const buffer = Uint8Array.from(
|
|
2472
|
+
async function digest(bytes6) {
|
|
2473
|
+
const buffer = Uint8Array.from(bytes6);
|
|
2458
2474
|
return [
|
|
2459
2475
|
...new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", buffer))
|
|
2460
2476
|
].map((v) => v.toString(16).padStart(2, "0")).join("");
|
|
2461
2477
|
}
|
|
2462
|
-
function decode2(
|
|
2478
|
+
function decode2(bytes6) {
|
|
2463
2479
|
return JSON.parse(
|
|
2464
|
-
new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
|
|
2480
|
+
new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes6)
|
|
2465
2481
|
);
|
|
2466
2482
|
}
|
|
2467
2483
|
async function evaluateResearchEvaluation(input, options = {}) {
|
|
@@ -2486,7 +2502,7 @@ async function evaluateResearchEvaluation(input, options = {}) {
|
|
|
2486
2502
|
vocabularyMembership: "not_checked",
|
|
2487
2503
|
scientificEligibility: "not_checked"
|
|
2488
2504
|
};
|
|
2489
|
-
const issue = (code, pointer6,
|
|
2505
|
+
const issue = (code, pointer6, message2) => result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
2490
2506
|
if (!parsed.success) {
|
|
2491
2507
|
result.checks.structural = "failed";
|
|
2492
2508
|
for (const i of parsed.error.issues)
|
|
@@ -2529,15 +2545,15 @@ async function evaluateResearchEvaluation(input, options = {}) {
|
|
|
2529
2545
|
result.checks.semantic = "passed";
|
|
2530
2546
|
const packetBytes = options.packetBytes ? Uint8Array.from(options.packetBytes) : void 0;
|
|
2531
2547
|
const files = new Map(
|
|
2532
|
-
[...options.files ?? []].map(([
|
|
2533
|
-
|
|
2534
|
-
Uint8Array.from(
|
|
2548
|
+
[...options.files ?? []].map(([ref18, bytes6]) => [
|
|
2549
|
+
ref18,
|
|
2550
|
+
Uint8Array.from(bytes6)
|
|
2535
2551
|
])
|
|
2536
2552
|
);
|
|
2537
2553
|
const dependencyFiles = new Map(
|
|
2538
|
-
[...options.dependencyFiles ?? []].map(([
|
|
2539
|
-
|
|
2540
|
-
Uint8Array.from(
|
|
2554
|
+
[...options.dependencyFiles ?? []].map(([ref18, bytes6]) => [
|
|
2555
|
+
ref18,
|
|
2556
|
+
Uint8Array.from(bytes6)
|
|
2541
2557
|
])
|
|
2542
2558
|
);
|
|
2543
2559
|
const checks = [
|
|
@@ -2638,9 +2654,9 @@ async function evaluateResearchEvaluation(input, options = {}) {
|
|
|
2638
2654
|
);
|
|
2639
2655
|
result.checks.external = "passed";
|
|
2640
2656
|
const documents = Object.fromEntries(
|
|
2641
|
-
Object.entries(packet.data.documents).map(([name,
|
|
2657
|
+
Object.entries(packet.data.documents).map(([name, ref18]) => [
|
|
2642
2658
|
name,
|
|
2643
|
-
decode2(files.get(
|
|
2659
|
+
decode2(files.get(ref18))
|
|
2644
2660
|
])
|
|
2645
2661
|
);
|
|
2646
2662
|
const maps = Object.fromEntries(
|
|
@@ -2837,12 +2853,12 @@ async function evaluateReleasedDocuments(historyInput, selectionInput, options =
|
|
|
2837
2853
|
}
|
|
2838
2854
|
if (!validation.success) return result;
|
|
2839
2855
|
const chosen = selection.data, history = validation.data;
|
|
2840
|
-
const problem = (code, pointer6,
|
|
2856
|
+
const problem = (code, pointer6, message2) => result.issues.push({
|
|
2841
2857
|
code,
|
|
2842
2858
|
stage: "semantic",
|
|
2843
2859
|
severity: "error",
|
|
2844
2860
|
pointer: pointer6,
|
|
2845
|
-
message,
|
|
2861
|
+
message: message2,
|
|
2846
2862
|
nextAction: "Resolve the selection against the exact history and source inventory."
|
|
2847
2863
|
});
|
|
2848
2864
|
if (chosen.historyId !== history.id)
|
|
@@ -2878,7 +2894,7 @@ async function evaluateReleasedDocuments(historyInput, selectionInput, options =
|
|
|
2878
2894
|
return result;
|
|
2879
2895
|
}
|
|
2880
2896
|
const assets2 = new Map(
|
|
2881
|
-
[...options.assets ?? []].map(([
|
|
2897
|
+
[...options.assets ?? []].map(([ref18, b]) => [ref18, Uint8Array.from(b)])
|
|
2882
2898
|
);
|
|
2883
2899
|
const current = new Set(validation.currentClaimRefs);
|
|
2884
2900
|
for (const [i, d] of chosen.documents.entries()) {
|
|
@@ -2899,17 +2915,17 @@ async function evaluateReleasedDocuments(historyInput, selectionInput, options =
|
|
|
2899
2915
|
asset: { status: "not_checked" }
|
|
2900
2916
|
};
|
|
2901
2917
|
result.documents.push(row);
|
|
2902
|
-
const requirement = (
|
|
2903
|
-
const pass = (
|
|
2904
|
-
const r = requirement(
|
|
2918
|
+
const requirement = (id26) => row.requirements.find((r) => r.id === id26);
|
|
2919
|
+
const pass = (id26, reason) => {
|
|
2920
|
+
const r = requirement(id26);
|
|
2905
2921
|
r.status = "satisfied";
|
|
2906
2922
|
r.reason = reason;
|
|
2907
2923
|
};
|
|
2908
|
-
const gap = (
|
|
2909
|
-
const r = requirement(
|
|
2924
|
+
const gap = (id26, status, code, pointer6, message2, nextAction, stage = "profile", severity = "error") => {
|
|
2925
|
+
const r = requirement(id26);
|
|
2910
2926
|
r.status = status;
|
|
2911
|
-
r.reason =
|
|
2912
|
-
const issue = { code, pointer: pointer6, message, nextAction, stage, severity };
|
|
2927
|
+
r.reason = message2;
|
|
2928
|
+
const issue = { code, pointer: pointer6, message: message2, nextAction, stage, severity };
|
|
2913
2929
|
r.issues.push(issue);
|
|
2914
2930
|
result.issues.push(issue);
|
|
2915
2931
|
};
|
|
@@ -2965,8 +2981,8 @@ async function evaluateReleasedDocuments(historyInput, selectionInput, options =
|
|
|
2965
2981
|
r.blockedBy = ["content_digest"];
|
|
2966
2982
|
r.reason = "A declared source digest is required before byte comparison.";
|
|
2967
2983
|
} else {
|
|
2968
|
-
const
|
|
2969
|
-
if (!
|
|
2984
|
+
const bytes6 = assets2.get(d.sourceRef);
|
|
2985
|
+
if (!bytes6)
|
|
2970
2986
|
gap(
|
|
2971
2987
|
"content_integrity",
|
|
2972
2988
|
"missing",
|
|
@@ -2978,8 +2994,8 @@ async function evaluateReleasedDocuments(historyInput, selectionInput, options =
|
|
|
2978
2994
|
"warning"
|
|
2979
2995
|
);
|
|
2980
2996
|
else {
|
|
2981
|
-
row.asset.byteLength =
|
|
2982
|
-
if (!
|
|
2997
|
+
row.asset.byteLength = bytes6.length;
|
|
2998
|
+
if (!bytes6.length) {
|
|
2983
2999
|
row.asset.status = "failed";
|
|
2984
3000
|
gap(
|
|
2985
3001
|
"content_integrity",
|
|
@@ -2992,11 +3008,11 @@ async function evaluateReleasedDocuments(historyInput, selectionInput, options =
|
|
|
2992
3008
|
);
|
|
2993
3009
|
} else
|
|
2994
3010
|
try {
|
|
2995
|
-
const
|
|
3011
|
+
const hash8 = await globalThis.crypto.subtle.digest(
|
|
2996
3012
|
"SHA-256",
|
|
2997
|
-
|
|
3013
|
+
bytes6
|
|
2998
3014
|
);
|
|
2999
|
-
row.asset.actualSha256 = [...new Uint8Array(
|
|
3015
|
+
row.asset.actualSha256 = [...new Uint8Array(hash8)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3000
3016
|
if (row.asset.actualSha256 === source.digest.value) {
|
|
3001
3017
|
row.asset.status = "passed";
|
|
3002
3018
|
pass(
|
|
@@ -3051,11 +3067,11 @@ async function evaluateReleasedDocuments(historyInput, selectionInput, options =
|
|
|
3051
3067
|
];
|
|
3052
3068
|
row.extractionRefs = extractions.map((e) => e.ref);
|
|
3053
3069
|
if (!extractions.length) {
|
|
3054
|
-
for (const
|
|
3070
|
+
for (const id26 of [
|
|
3055
3071
|
"extraction_traceability",
|
|
3056
3072
|
"source_attribution"
|
|
3057
3073
|
]) {
|
|
3058
|
-
const r = requirement(
|
|
3074
|
+
const r = requirement(id26);
|
|
3059
3075
|
r.status = "not_applicable";
|
|
3060
3076
|
r.reason = "No current source statements or value assertions directly cite this selected document.";
|
|
3061
3077
|
}
|
|
@@ -3100,18 +3116,18 @@ async function evaluateReleasedDocuments(historyInput, selectionInput, options =
|
|
|
3100
3116
|
);
|
|
3101
3117
|
}
|
|
3102
3118
|
}
|
|
3103
|
-
for (const [
|
|
3119
|
+
for (const [id26, value, field2] of [
|
|
3104
3120
|
["source_title", source.title, "title"],
|
|
3105
3121
|
["source_uri", source.uri, "uri"]
|
|
3106
3122
|
]) {
|
|
3107
3123
|
if (value)
|
|
3108
3124
|
pass(
|
|
3109
|
-
|
|
3125
|
+
id26,
|
|
3110
3126
|
"The source supplies this citation aid; correctness and availability are unchecked."
|
|
3111
3127
|
);
|
|
3112
3128
|
else
|
|
3113
3129
|
gap(
|
|
3114
|
-
|
|
3130
|
+
id26,
|
|
3115
3131
|
"missing",
|
|
3116
3132
|
"DOCUMENT." + field2.toUpperCase() + "_RECOMMENDED",
|
|
3117
3133
|
path2 + "/" + field2,
|
|
@@ -3258,12 +3274,12 @@ async function evaluateHistoricalTestimony(historyInput, selectionInput, options
|
|
|
3258
3274
|
}
|
|
3259
3275
|
if (!validation.success) return result;
|
|
3260
3276
|
const chosen = selection.data, history = validation.data;
|
|
3261
|
-
const problem = (code, pointer6,
|
|
3277
|
+
const problem = (code, pointer6, message2) => result.issues.push({
|
|
3262
3278
|
code,
|
|
3263
3279
|
stage: "semantic",
|
|
3264
3280
|
severity: "error",
|
|
3265
3281
|
pointer: pointer6,
|
|
3266
|
-
message,
|
|
3282
|
+
message: message2,
|
|
3267
3283
|
nextAction: "Resolve the selection against the exact history and source inventory."
|
|
3268
3284
|
});
|
|
3269
3285
|
if (chosen.historyId !== history.id)
|
|
@@ -3299,7 +3315,7 @@ async function evaluateHistoricalTestimony(historyInput, selectionInput, options
|
|
|
3299
3315
|
return result;
|
|
3300
3316
|
}
|
|
3301
3317
|
const assets2 = new Map(
|
|
3302
|
-
[...options.assets ?? []].map(([
|
|
3318
|
+
[...options.assets ?? []].map(([ref18, b]) => [ref18, Uint8Array.from(b)])
|
|
3303
3319
|
);
|
|
3304
3320
|
const current = new Set(validation.currentClaimRefs);
|
|
3305
3321
|
for (const [i, d] of chosen.accounts.entries()) {
|
|
@@ -3320,17 +3336,17 @@ async function evaluateHistoricalTestimony(historyInput, selectionInput, options
|
|
|
3320
3336
|
asset: { status: "not_checked" }
|
|
3321
3337
|
};
|
|
3322
3338
|
result.accounts.push(row);
|
|
3323
|
-
const requirement = (
|
|
3324
|
-
const pass = (
|
|
3325
|
-
const r = requirement(
|
|
3339
|
+
const requirement = (id26) => row.requirements.find((r) => r.id === id26);
|
|
3340
|
+
const pass = (id26, reason) => {
|
|
3341
|
+
const r = requirement(id26);
|
|
3326
3342
|
r.status = "satisfied";
|
|
3327
3343
|
r.reason = reason;
|
|
3328
3344
|
};
|
|
3329
|
-
const gap = (
|
|
3330
|
-
const r = requirement(
|
|
3345
|
+
const gap = (id26, status, code, pointer6, message2, nextAction, stage = "profile", severity = "error") => {
|
|
3346
|
+
const r = requirement(id26);
|
|
3331
3347
|
r.status = status;
|
|
3332
|
-
r.reason =
|
|
3333
|
-
const issue = { code, pointer: pointer6, message, nextAction, stage, severity };
|
|
3348
|
+
r.reason = message2;
|
|
3349
|
+
const issue = { code, pointer: pointer6, message: message2, nextAction, stage, severity };
|
|
3334
3350
|
r.issues.push(issue);
|
|
3335
3351
|
result.issues.push(issue);
|
|
3336
3352
|
};
|
|
@@ -3386,8 +3402,8 @@ async function evaluateHistoricalTestimony(historyInput, selectionInput, options
|
|
|
3386
3402
|
r.blockedBy = ["content_digest"];
|
|
3387
3403
|
r.reason = "A declared source digest is required before byte comparison.";
|
|
3388
3404
|
} else {
|
|
3389
|
-
const
|
|
3390
|
-
if (!
|
|
3405
|
+
const bytes6 = assets2.get(d.sourceRef);
|
|
3406
|
+
if (!bytes6)
|
|
3391
3407
|
gap(
|
|
3392
3408
|
"content_integrity",
|
|
3393
3409
|
"missing",
|
|
@@ -3399,8 +3415,8 @@ async function evaluateHistoricalTestimony(historyInput, selectionInput, options
|
|
|
3399
3415
|
"warning"
|
|
3400
3416
|
);
|
|
3401
3417
|
else {
|
|
3402
|
-
row.asset.byteLength =
|
|
3403
|
-
if (!
|
|
3418
|
+
row.asset.byteLength = bytes6.length;
|
|
3419
|
+
if (!bytes6.length) {
|
|
3404
3420
|
row.asset.status = "failed";
|
|
3405
3421
|
gap(
|
|
3406
3422
|
"content_integrity",
|
|
@@ -3413,11 +3429,11 @@ async function evaluateHistoricalTestimony(historyInput, selectionInput, options
|
|
|
3413
3429
|
);
|
|
3414
3430
|
} else
|
|
3415
3431
|
try {
|
|
3416
|
-
const
|
|
3432
|
+
const hash8 = await globalThis.crypto.subtle.digest(
|
|
3417
3433
|
"SHA-256",
|
|
3418
|
-
|
|
3434
|
+
bytes6
|
|
3419
3435
|
);
|
|
3420
|
-
row.asset.actualSha256 = [...new Uint8Array(
|
|
3436
|
+
row.asset.actualSha256 = [...new Uint8Array(hash8)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3421
3437
|
if (row.asset.actualSha256 === source.digest.value) {
|
|
3422
3438
|
row.asset.status = "passed";
|
|
3423
3439
|
pass(
|
|
@@ -3472,8 +3488,8 @@ async function evaluateHistoricalTestimony(historyInput, selectionInput, options
|
|
|
3472
3488
|
];
|
|
3473
3489
|
row.extractionRefs = extractions.map((e) => e.ref);
|
|
3474
3490
|
if (!extractions.length) {
|
|
3475
|
-
for (const
|
|
3476
|
-
const r = requirement(
|
|
3491
|
+
for (const id26 of ["extraction_traceability"]) {
|
|
3492
|
+
const r = requirement(id26);
|
|
3477
3493
|
r.status = "not_applicable";
|
|
3478
3494
|
r.reason = "No current source statements or value assertions directly cite this selected account.";
|
|
3479
3495
|
}
|
|
@@ -3512,18 +3528,18 @@ async function evaluateHistoricalTestimony(historyInput, selectionInput, options
|
|
|
3512
3528
|
);
|
|
3513
3529
|
}
|
|
3514
3530
|
}
|
|
3515
|
-
for (const [
|
|
3531
|
+
for (const [id26, value, field2] of [
|
|
3516
3532
|
["source_title", source.title, "title"],
|
|
3517
3533
|
["source_uri", source.uri, "uri"]
|
|
3518
3534
|
]) {
|
|
3519
3535
|
if (value)
|
|
3520
3536
|
pass(
|
|
3521
|
-
|
|
3537
|
+
id26,
|
|
3522
3538
|
"The source supplies this citation aid; correctness and availability are unchecked."
|
|
3523
3539
|
);
|
|
3524
3540
|
else
|
|
3525
3541
|
gap(
|
|
3526
|
-
|
|
3542
|
+
id26,
|
|
3527
3543
|
"missing",
|
|
3528
3544
|
"TESTIMONY." + field2.toUpperCase() + "_RECOMMENDED",
|
|
3529
3545
|
path2 + "/" + field2,
|
|
@@ -3711,12 +3727,12 @@ async function evaluatePhysicalSamples(historyInput, selectionInput, options = {
|
|
|
3711
3727
|
}
|
|
3712
3728
|
if (!validation.success) return result;
|
|
3713
3729
|
const selection = parsed.data, history = validation.data;
|
|
3714
|
-
const problem = (code, pointer6,
|
|
3730
|
+
const problem = (code, pointer6, message2) => result.issues.push({
|
|
3715
3731
|
code,
|
|
3716
3732
|
stage: "semantic",
|
|
3717
3733
|
severity: "error",
|
|
3718
3734
|
pointer: pointer6,
|
|
3719
|
-
message,
|
|
3735
|
+
message: message2,
|
|
3720
3736
|
nextAction: "Resolve the selection against the exact history and source inventory; do not invent references."
|
|
3721
3737
|
});
|
|
3722
3738
|
if (selection.historyId !== history.id)
|
|
@@ -3744,12 +3760,12 @@ async function evaluatePhysicalSamples(historyInput, selectionInput, options = {
|
|
|
3744
3760
|
"Sample ID is selected more than once."
|
|
3745
3761
|
);
|
|
3746
3762
|
sampleIds.add(s.id);
|
|
3747
|
-
for (const
|
|
3748
|
-
if (!sources.has(
|
|
3763
|
+
for (const ref18 of references(s))
|
|
3764
|
+
if (!sources.has(ref18))
|
|
3749
3765
|
problem(
|
|
3750
3766
|
"SAMPLE.SOURCE_REF",
|
|
3751
3767
|
path2,
|
|
3752
|
-
`Cited record ${
|
|
3768
|
+
`Cited record ${ref18} is absent from this history.`
|
|
3753
3769
|
);
|
|
3754
3770
|
if (s.custody.state === "documented") {
|
|
3755
3771
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -3769,7 +3785,7 @@ async function evaluatePhysicalSamples(historyInput, selectionInput, options = {
|
|
|
3769
3785
|
return result;
|
|
3770
3786
|
}
|
|
3771
3787
|
const assets2 = new Map(
|
|
3772
|
-
[...options.assets ?? []].map(([
|
|
3788
|
+
[...options.assets ?? []].map(([ref18, b]) => [ref18, Uint8Array.from(b)])
|
|
3773
3789
|
);
|
|
3774
3790
|
for (const [i, s] of selection.samples.entries()) {
|
|
3775
3791
|
const path2 = `/selection/samples/${i}`;
|
|
@@ -3786,17 +3802,17 @@ async function evaluatePhysicalSamples(historyInput, selectionInput, options = {
|
|
|
3786
3802
|
records: []
|
|
3787
3803
|
};
|
|
3788
3804
|
result.samples.push(row);
|
|
3789
|
-
const requirement = (
|
|
3790
|
-
const pass = (
|
|
3791
|
-
const r = requirement(
|
|
3805
|
+
const requirement = (id26) => row.requirements.find((r) => r.id === id26);
|
|
3806
|
+
const pass = (id26, reason) => {
|
|
3807
|
+
const r = requirement(id26);
|
|
3792
3808
|
r.status = "satisfied";
|
|
3793
3809
|
r.reason = reason;
|
|
3794
3810
|
};
|
|
3795
|
-
const gap = (
|
|
3796
|
-
const r = requirement(
|
|
3811
|
+
const gap = (id26, status, code, pointer6, message2, nextAction, stage = "profile", severity = "error") => {
|
|
3812
|
+
const r = requirement(id26);
|
|
3797
3813
|
r.status = status;
|
|
3798
|
-
r.reason =
|
|
3799
|
-
const issue = { code, pointer: pointer6, message, nextAction, stage, severity };
|
|
3814
|
+
r.reason = message2;
|
|
3815
|
+
const issue = { code, pointer: pointer6, message: message2, nextAction, stage, severity };
|
|
3800
3816
|
r.issues.push(issue);
|
|
3801
3817
|
result.issues.push(issue);
|
|
3802
3818
|
};
|
|
@@ -3925,9 +3941,9 @@ async function evaluatePhysicalSamples(historyInput, selectionInput, options = {
|
|
|
3925
3941
|
r.blockedBy = ["collection_record", "current_custodian"];
|
|
3926
3942
|
r.reason = "No collection, handoff or current-custody records are cited.";
|
|
3927
3943
|
} else {
|
|
3928
|
-
for (const
|
|
3929
|
-
const source = sources.get(
|
|
3930
|
-
sourceRef:
|
|
3944
|
+
for (const ref18 of refs) {
|
|
3945
|
+
const source = sources.get(ref18), check = {
|
|
3946
|
+
sourceRef: ref18,
|
|
3931
3947
|
status: "not_checked"
|
|
3932
3948
|
};
|
|
3933
3949
|
row.records.push(check);
|
|
@@ -3946,8 +3962,8 @@ async function evaluatePhysicalSamples(historyInput, selectionInput, options = {
|
|
|
3946
3962
|
continue;
|
|
3947
3963
|
}
|
|
3948
3964
|
check.expectedSha256 = source.digest.value;
|
|
3949
|
-
const
|
|
3950
|
-
if (!
|
|
3965
|
+
const bytes6 = assets2.get(ref18);
|
|
3966
|
+
if (!bytes6) {
|
|
3951
3967
|
gap(
|
|
3952
3968
|
"record_integrity",
|
|
3953
3969
|
"missing",
|
|
@@ -3960,8 +3976,8 @@ async function evaluatePhysicalSamples(historyInput, selectionInput, options = {
|
|
|
3960
3976
|
);
|
|
3961
3977
|
continue;
|
|
3962
3978
|
}
|
|
3963
|
-
check.byteLength =
|
|
3964
|
-
if (!
|
|
3979
|
+
check.byteLength = bytes6.length;
|
|
3980
|
+
if (!bytes6.length) {
|
|
3965
3981
|
check.status = "failed";
|
|
3966
3982
|
gap(
|
|
3967
3983
|
"record_integrity",
|
|
@@ -3975,8 +3991,8 @@ async function evaluatePhysicalSamples(historyInput, selectionInput, options = {
|
|
|
3975
3991
|
continue;
|
|
3976
3992
|
}
|
|
3977
3993
|
try {
|
|
3978
|
-
const
|
|
3979
|
-
check.actualSha256 = [...new Uint8Array(
|
|
3994
|
+
const hash8 = await globalThis.crypto.subtle.digest("SHA-256", bytes6);
|
|
3995
|
+
check.actualSha256 = [...new Uint8Array(hash8)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
3980
3996
|
if (check.actualSha256 === source.digest.value)
|
|
3981
3997
|
check.status = "passed";
|
|
3982
3998
|
else {
|
|
@@ -4107,10 +4123,10 @@ function serialize2(value) {
|
|
|
4107
4123
|
}
|
|
4108
4124
|
return JSON.stringify(value);
|
|
4109
4125
|
}
|
|
4110
|
-
async function digest2(
|
|
4126
|
+
async function digest2(bytes6) {
|
|
4111
4127
|
return [
|
|
4112
4128
|
...new Uint8Array(
|
|
4113
|
-
await globalThis.crypto.subtle.digest("SHA-256", Uint8Array.from(
|
|
4129
|
+
await globalThis.crypto.subtle.digest("SHA-256", Uint8Array.from(bytes6))
|
|
4114
4130
|
)
|
|
4115
4131
|
].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
4116
4132
|
}
|
|
@@ -4137,7 +4153,7 @@ async function evaluateProfileEvaluation(input, options = {}) {
|
|
|
4137
4153
|
implementationExecution: "not_attested",
|
|
4138
4154
|
environmentExecution: "not_attested"
|
|
4139
4155
|
};
|
|
4140
|
-
const issue = (code, pointer6,
|
|
4156
|
+
const issue = (code, pointer6, message2) => result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
4141
4157
|
if (!parsed.success) {
|
|
4142
4158
|
result.checks.structural = "failed";
|
|
4143
4159
|
for (const i of parsed.error.issues)
|
|
@@ -4201,15 +4217,15 @@ async function evaluateProfileEvaluation(input, options = {}) {
|
|
|
4201
4217
|
const historyBytes = options.historyBytes ? Uint8Array.from(options.historyBytes) : void 0;
|
|
4202
4218
|
const selectionBytes = options.selectionBytes ? Uint8Array.from(options.selectionBytes) : void 0;
|
|
4203
4219
|
const assetFiles = new Map(
|
|
4204
|
-
[...options.assetFiles ?? []].map(([
|
|
4205
|
-
|
|
4206
|
-
Uint8Array.from(
|
|
4220
|
+
[...options.assetFiles ?? []].map(([ref18, bytes6]) => [
|
|
4221
|
+
ref18,
|
|
4222
|
+
Uint8Array.from(bytes6)
|
|
4207
4223
|
])
|
|
4208
4224
|
);
|
|
4209
4225
|
const files = new Map(
|
|
4210
|
-
[...options.dependencyFiles ?? []].map(([
|
|
4211
|
-
|
|
4212
|
-
Uint8Array.from(
|
|
4226
|
+
[...options.dependencyFiles ?? []].map(([ref18, bytes6]) => [
|
|
4227
|
+
ref18,
|
|
4228
|
+
Uint8Array.from(bytes6)
|
|
4213
4229
|
])
|
|
4214
4230
|
);
|
|
4215
4231
|
const inputs = [
|
|
@@ -4288,13 +4304,13 @@ async function evaluateProfileEvaluation(input, options = {}) {
|
|
|
4288
4304
|
}
|
|
4289
4305
|
result.checks.external = "passed";
|
|
4290
4306
|
const documents = {};
|
|
4291
|
-
for (const [name,
|
|
4307
|
+
for (const [name, bytes6] of [
|
|
4292
4308
|
["history", historyBytes],
|
|
4293
4309
|
["selection", selectionBytes]
|
|
4294
4310
|
]) {
|
|
4295
4311
|
try {
|
|
4296
4312
|
documents[name] = JSON.parse(
|
|
4297
|
-
new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
|
|
4313
|
+
new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes6)
|
|
4298
4314
|
);
|
|
4299
4315
|
} catch {
|
|
4300
4316
|
result.checks.semantic = "failed";
|
|
@@ -4616,12 +4632,12 @@ async function evaluateContextClaimHistory(input, options) {
|
|
|
4616
4632
|
}));
|
|
4617
4633
|
const snapshots = [];
|
|
4618
4634
|
const contexts = /* @__PURE__ */ new Map();
|
|
4619
|
-
const problem = (code, pointer6,
|
|
4620
|
-
async function load(
|
|
4621
|
-
const supplied = options.documents.get(
|
|
4622
|
-
const
|
|
4623
|
-
if (!
|
|
4624
|
-
snapshots.push({ ...
|
|
4635
|
+
const problem = (code, pointer6, message2, stage = "semantic") => issues.push({ code, pointer: pointer6, message: message2, stage });
|
|
4636
|
+
async function load(ref18, pointer6) {
|
|
4637
|
+
const supplied = options.documents.get(ref18.sha256);
|
|
4638
|
+
const bytes6 = supplied ? Uint8Array.from(supplied) : void 0;
|
|
4639
|
+
if (!bytes6) {
|
|
4640
|
+
snapshots.push({ ...ref18, status: "unavailable" });
|
|
4625
4641
|
problem(
|
|
4626
4642
|
"SNAPSHOT.UNAVAILABLE",
|
|
4627
4643
|
pointer6,
|
|
@@ -4632,10 +4648,10 @@ async function evaluateContextClaimHistory(input, options) {
|
|
|
4632
4648
|
}
|
|
4633
4649
|
if ([
|
|
4634
4650
|
...new Uint8Array(
|
|
4635
|
-
await globalThis.crypto.subtle.digest("SHA-256",
|
|
4651
|
+
await globalThis.crypto.subtle.digest("SHA-256", bytes6)
|
|
4636
4652
|
)
|
|
4637
|
-
].map((b) => b.toString(16).padStart(2, "0")).join("") !==
|
|
4638
|
-
snapshots.push({ ...
|
|
4653
|
+
].map((b) => b.toString(16).padStart(2, "0")).join("") !== ref18.sha256) {
|
|
4654
|
+
snapshots.push({ ...ref18, status: "failed" });
|
|
4639
4655
|
problem(
|
|
4640
4656
|
"SNAPSHOT.DIGEST",
|
|
4641
4657
|
pointer6,
|
|
@@ -4647,10 +4663,10 @@ async function evaluateContextClaimHistory(input, options) {
|
|
|
4647
4663
|
let value;
|
|
4648
4664
|
try {
|
|
4649
4665
|
value = JSON.parse(
|
|
4650
|
-
new TextDecoder("utf-8", { fatal: true }).decode(
|
|
4666
|
+
new TextDecoder("utf-8", { fatal: true }).decode(bytes6)
|
|
4651
4667
|
);
|
|
4652
4668
|
} catch {
|
|
4653
|
-
snapshots.push({ ...
|
|
4669
|
+
snapshots.push({ ...ref18, status: "failed" });
|
|
4654
4670
|
problem(
|
|
4655
4671
|
"SNAPSHOT.JSON",
|
|
4656
4672
|
pointer6,
|
|
@@ -4659,8 +4675,8 @@ async function evaluateContextClaimHistory(input, options) {
|
|
|
4659
4675
|
);
|
|
4660
4676
|
return;
|
|
4661
4677
|
}
|
|
4662
|
-
snapshots.push({ ...
|
|
4663
|
-
if (!value || typeof value !== "object" || value.id !==
|
|
4678
|
+
snapshots.push({ ...ref18, status: "passed" });
|
|
4679
|
+
if (!value || typeof value !== "object" || value.id !== ref18.documentId) {
|
|
4664
4680
|
problem(
|
|
4665
4681
|
"SNAPSHOT.IDENTITY",
|
|
4666
4682
|
pointer6,
|
|
@@ -4721,8 +4737,8 @@ async function evaluateContextClaimHistory(input, options) {
|
|
|
4721
4737
|
const value = assertion.content.value;
|
|
4722
4738
|
if (value === void 0) continue;
|
|
4723
4739
|
if (field2 === "productRefs") {
|
|
4724
|
-
for (const
|
|
4725
|
-
if (!sources.has(
|
|
4740
|
+
for (const ref18 of value)
|
|
4741
|
+
if (!sources.has(ref18))
|
|
4726
4742
|
problem(
|
|
4727
4743
|
"REF.LOCAL_RESOLUTION",
|
|
4728
4744
|
ep,
|
|
@@ -4730,8 +4746,8 @@ async function evaluateContextClaimHistory(input, options) {
|
|
|
4730
4746
|
);
|
|
4731
4747
|
}
|
|
4732
4748
|
if (field2 === "acquisitionIds") {
|
|
4733
|
-
for (const
|
|
4734
|
-
if (!acquisitionIds?.has(
|
|
4749
|
+
for (const id26 of value)
|
|
4750
|
+
if (!acquisitionIds?.has(id26))
|
|
4735
4751
|
problem(
|
|
4736
4752
|
"REF.ACQUISITION",
|
|
4737
4753
|
ep,
|
|
@@ -4873,9 +4889,9 @@ async function evaluateContextClaimHistory(input, options) {
|
|
|
4873
4889
|
"Assessment input must select an existing assertion on its named field."
|
|
4874
4890
|
);
|
|
4875
4891
|
};
|
|
4876
|
-
for (const [i,
|
|
4892
|
+
for (const [i, ref18] of history.data.contextRefs.entries()) {
|
|
4877
4893
|
const p = `/contextRefs/${i}`;
|
|
4878
|
-
const value = await load(
|
|
4894
|
+
const value = await load(ref18, p);
|
|
4879
4895
|
if (value === void 0) continue;
|
|
4880
4896
|
const parsed = parseObservationContext(value);
|
|
4881
4897
|
if (!parsed.success) {
|
|
@@ -4901,14 +4917,14 @@ async function evaluateContextClaimHistory(input, options) {
|
|
|
4901
4917
|
continue;
|
|
4902
4918
|
}
|
|
4903
4919
|
await checkContext(context, observation.data, p);
|
|
4904
|
-
contexts.set(
|
|
4920
|
+
contexts.set(ref18.sha256, context);
|
|
4905
4921
|
}
|
|
4906
4922
|
for (const [i, claim] of history.data.claims.entries()) {
|
|
4907
4923
|
if (claim.subject.kind === "context")
|
|
4908
4924
|
resolve2(claim.subject.reference, `/claims/${i}/subject`);
|
|
4909
4925
|
if (claim.kind === "assessment")
|
|
4910
|
-
for (const [j,
|
|
4911
|
-
resolve2(
|
|
4926
|
+
for (const [j, ref18] of (claim.contextInputRefs ?? []).entries())
|
|
4927
|
+
resolve2(ref18, `/claims/${i}/contextInputRefs/${j}`, ref18.assertionId);
|
|
4912
4928
|
}
|
|
4913
4929
|
}
|
|
4914
4930
|
const external = snapshots.some((s) => s.status === "failed") ? "failed" : snapshots.some((s) => s.status === "unavailable") || !snapshots.length ? "not_checked" : "passed";
|
|
@@ -4947,8 +4963,8 @@ async function checkLaboratoryDependencies(entities, observation, historyId, poi
|
|
|
4947
4963
|
for (const [i, e] of entities.entities.entries()) {
|
|
4948
4964
|
const p = `${pointer6}/entities/${i}`;
|
|
4949
4965
|
if (e.kind === "material" && e.selectionRef) {
|
|
4950
|
-
const
|
|
4951
|
-
const raw = await load(
|
|
4966
|
+
const ref18 = e.selectionRef;
|
|
4967
|
+
const raw = await load(ref18.document, `${p}/selectionRef/document`);
|
|
4952
4968
|
if (raw === void 0) continue;
|
|
4953
4969
|
const parsed = PhysicalSampleSelectionSchema.safeParse(raw);
|
|
4954
4970
|
if (!parsed.success) {
|
|
@@ -4992,7 +5008,7 @@ async function checkLaboratoryDependencies(entities, observation, historyId, poi
|
|
|
4992
5008
|
"Selection record is absent from the scoped observation inventory."
|
|
4993
5009
|
);
|
|
4994
5010
|
}
|
|
4995
|
-
const sample = selection.samples.find((s) => s.id ===
|
|
5011
|
+
const sample = selection.samples.find((s) => s.id === ref18.sampleId);
|
|
4996
5012
|
if (!sample)
|
|
4997
5013
|
problem(
|
|
4998
5014
|
"MATERIAL.SELECTION_SAMPLE",
|
|
@@ -5012,15 +5028,15 @@ async function checkLaboratoryDependencies(entities, observation, historyId, poi
|
|
|
5012
5028
|
"Known specimen lineage differs from the selected specimen declaration."
|
|
5013
5029
|
);
|
|
5014
5030
|
}
|
|
5015
|
-
selections.set(
|
|
5031
|
+
selections.set(ref18.document.sha256, selection);
|
|
5016
5032
|
}
|
|
5017
5033
|
if (e.kind !== "laboratory_analysis" && e.kind !== "laboratory_result")
|
|
5018
5034
|
continue;
|
|
5019
5035
|
for (const a of e.fields.reportArtifacts ?? [])
|
|
5020
5036
|
if ("value" in a.content)
|
|
5021
|
-
for (const
|
|
5022
|
-
const source = sources.get(
|
|
5023
|
-
if (!source?.digest || source.digest.value !==
|
|
5037
|
+
for (const ref18 of a.content.value) {
|
|
5038
|
+
const source = sources.get(ref18.sourceRef);
|
|
5039
|
+
if (!source?.digest || source.digest.value !== ref18.digest.value)
|
|
5024
5040
|
problem(
|
|
5025
5041
|
"LAB.REPORT_IDENTITY",
|
|
5026
5042
|
p,
|
|
@@ -5061,11 +5077,11 @@ async function checkLaboratoryDependencies(entities, observation, historyId, poi
|
|
|
5061
5077
|
}
|
|
5062
5078
|
for (const [i, e] of entities.entities.entries()) {
|
|
5063
5079
|
if (e.kind !== "material_custody_action" || !e.transferRef) continue;
|
|
5064
|
-
const p = `${pointer6}/entities/${i}/transferRef`,
|
|
5065
|
-
const sample = selections.get(
|
|
5080
|
+
const p = `${pointer6}/entities/${i}/transferRef`, ref18 = e.transferRef;
|
|
5081
|
+
const sample = selections.get(ref18.document.sha256)?.samples.find((s) => s.id === ref18.sampleId);
|
|
5066
5082
|
if (!sample) continue;
|
|
5067
5083
|
const transfers = sample.custody.state === "documented" ? sample.custody.transfers : [];
|
|
5068
|
-
const index3 = transfers.findIndex((t) => t.id ===
|
|
5084
|
+
const index3 = transfers.findIndex((t) => t.id === ref18.transferId), transfer = transfers[index3];
|
|
5069
5085
|
if (!transfer) {
|
|
5070
5086
|
problem(
|
|
5071
5087
|
"MATERIAL.SELECTION_TRANSFER",
|
|
@@ -5094,7 +5110,7 @@ async function checkLaboratoryDependencies(entities, observation, historyId, poi
|
|
|
5094
5110
|
const prior = entities.entities.find(
|
|
5095
5111
|
(p2) => p2.kind === "material_custody_action" && p2.id === predecessorId
|
|
5096
5112
|
);
|
|
5097
|
-
if (prior?.kind === "material_custody_action" && prior.transferRef?.document.sha256 ===
|
|
5113
|
+
if (prior?.kind === "material_custody_action" && prior.transferRef?.document.sha256 === ref18.document.sha256 && transfers[index3 - 1]?.id !== prior.transferRef.transferId)
|
|
5098
5114
|
problem(
|
|
5099
5115
|
"MATERIAL.TRANSFER_ORDER",
|
|
5100
5116
|
p,
|
|
@@ -5125,12 +5141,12 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5125
5141
|
const snapshots = [];
|
|
5126
5142
|
const contexts = /* @__PURE__ */ new Map();
|
|
5127
5143
|
const entityDocuments = /* @__PURE__ */ new Map();
|
|
5128
|
-
const problem = (code, pointer6,
|
|
5129
|
-
async function load(
|
|
5130
|
-
const supplied = options.documents.get(
|
|
5131
|
-
const
|
|
5132
|
-
if (!
|
|
5133
|
-
snapshots.push({ ...
|
|
5144
|
+
const problem = (code, pointer6, message2, stage = "semantic") => issues.push({ code, pointer: pointer6, message: message2, stage });
|
|
5145
|
+
async function load(ref18, pointer6) {
|
|
5146
|
+
const supplied = options.documents.get(ref18.sha256);
|
|
5147
|
+
const bytes6 = supplied ? Uint8Array.from(supplied) : void 0;
|
|
5148
|
+
if (!bytes6) {
|
|
5149
|
+
snapshots.push({ ...ref18, status: "unavailable" });
|
|
5134
5150
|
problem(
|
|
5135
5151
|
"SNAPSHOT.UNAVAILABLE",
|
|
5136
5152
|
pointer6,
|
|
@@ -5141,10 +5157,10 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5141
5157
|
}
|
|
5142
5158
|
if ([
|
|
5143
5159
|
...new Uint8Array(
|
|
5144
|
-
await globalThis.crypto.subtle.digest("SHA-256",
|
|
5160
|
+
await globalThis.crypto.subtle.digest("SHA-256", bytes6)
|
|
5145
5161
|
)
|
|
5146
|
-
].map((b) => b.toString(16).padStart(2, "0")).join("") !==
|
|
5147
|
-
snapshots.push({ ...
|
|
5162
|
+
].map((b) => b.toString(16).padStart(2, "0")).join("") !== ref18.sha256) {
|
|
5163
|
+
snapshots.push({ ...ref18, status: "failed" });
|
|
5148
5164
|
problem(
|
|
5149
5165
|
"SNAPSHOT.DIGEST",
|
|
5150
5166
|
pointer6,
|
|
@@ -5156,10 +5172,10 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5156
5172
|
let value;
|
|
5157
5173
|
try {
|
|
5158
5174
|
value = JSON.parse(
|
|
5159
|
-
new TextDecoder("utf-8", { fatal: true }).decode(
|
|
5175
|
+
new TextDecoder("utf-8", { fatal: true }).decode(bytes6)
|
|
5160
5176
|
);
|
|
5161
5177
|
} catch {
|
|
5162
|
-
snapshots.push({ ...
|
|
5178
|
+
snapshots.push({ ...ref18, status: "failed" });
|
|
5163
5179
|
problem(
|
|
5164
5180
|
"SNAPSHOT.JSON",
|
|
5165
5181
|
pointer6,
|
|
@@ -5168,8 +5184,8 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5168
5184
|
);
|
|
5169
5185
|
return;
|
|
5170
5186
|
}
|
|
5171
|
-
snapshots.push({ ...
|
|
5172
|
-
if (!value || typeof value !== "object" || value.id !==
|
|
5187
|
+
snapshots.push({ ...ref18, status: "passed" });
|
|
5188
|
+
if (!value || typeof value !== "object" || value.id !== ref18.documentId) {
|
|
5173
5189
|
problem(
|
|
5174
5190
|
"SNAPSHOT.IDENTITY",
|
|
5175
5191
|
pointer6,
|
|
@@ -5230,8 +5246,8 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5230
5246
|
const value = assertion.content.value;
|
|
5231
5247
|
if (value === void 0) continue;
|
|
5232
5248
|
if (field2 === "productRefs") {
|
|
5233
|
-
for (const
|
|
5234
|
-
if (!sources.has(
|
|
5249
|
+
for (const ref18 of value)
|
|
5250
|
+
if (!sources.has(ref18))
|
|
5235
5251
|
problem(
|
|
5236
5252
|
"REF.LOCAL_RESOLUTION",
|
|
5237
5253
|
ep,
|
|
@@ -5239,8 +5255,8 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5239
5255
|
);
|
|
5240
5256
|
}
|
|
5241
5257
|
if (field2 === "acquisitionIds") {
|
|
5242
|
-
for (const
|
|
5243
|
-
if (!acquisitionIds?.has(
|
|
5258
|
+
for (const id26 of value)
|
|
5259
|
+
if (!acquisitionIds?.has(id26))
|
|
5244
5260
|
problem(
|
|
5245
5261
|
"REF.ACQUISITION",
|
|
5246
5262
|
ep,
|
|
@@ -5438,9 +5454,9 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5438
5454
|
"Citation exceeds the edition's explicitly declared page count."
|
|
5439
5455
|
);
|
|
5440
5456
|
};
|
|
5441
|
-
for (const [i,
|
|
5457
|
+
for (const [i, ref18] of history.data.contextRefs.entries()) {
|
|
5442
5458
|
const p = `/contextRefs/${i}`;
|
|
5443
|
-
const value = await load(
|
|
5459
|
+
const value = await load(ref18, p);
|
|
5444
5460
|
if (value === void 0) continue;
|
|
5445
5461
|
const parsed = parseObservationContext(value);
|
|
5446
5462
|
if (!parsed.success) {
|
|
@@ -5466,11 +5482,11 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5466
5482
|
continue;
|
|
5467
5483
|
}
|
|
5468
5484
|
await checkContext(context, observation.data, p);
|
|
5469
|
-
contexts.set(
|
|
5485
|
+
contexts.set(ref18.sha256, context);
|
|
5470
5486
|
}
|
|
5471
|
-
for (const [i,
|
|
5487
|
+
for (const [i, ref18] of history.data.entityRefs.entries()) {
|
|
5472
5488
|
const p = `/entityRefs/${i}`;
|
|
5473
|
-
const value = await load(
|
|
5489
|
+
const value = await load(ref18, p);
|
|
5474
5490
|
if (value === void 0) continue;
|
|
5475
5491
|
const parsed = mode === "laboratory" ? parseLaboratoryEntities(value) : archival ? parseArchivalEntities(value) : parseResearchEntities(value);
|
|
5476
5492
|
if (!parsed.success) {
|
|
@@ -5537,9 +5553,9 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5537
5553
|
);
|
|
5538
5554
|
}
|
|
5539
5555
|
if (archival) {
|
|
5540
|
-
for (const
|
|
5541
|
-
const source = sources.get(
|
|
5542
|
-
if (!source?.digest || source.digest.value !==
|
|
5556
|
+
for (const ref19 of "artifact" in entity ? archivalArtifactReferences(entity) : []) {
|
|
5557
|
+
const source = sources.get(ref19.sourceRef);
|
|
5558
|
+
if (!source?.digest || source.digest.value !== ref19.digest.value)
|
|
5543
5559
|
problem(
|
|
5544
5560
|
"ARCHIVE.ARTIFACT_IDENTITY",
|
|
5545
5561
|
ep,
|
|
@@ -5571,7 +5587,7 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5571
5587
|
load,
|
|
5572
5588
|
problem
|
|
5573
5589
|
);
|
|
5574
|
-
entityDocuments.set(
|
|
5590
|
+
entityDocuments.set(ref18.sha256, entities);
|
|
5575
5591
|
}
|
|
5576
5592
|
for (const [i, claim] of history.data.claims.entries()) {
|
|
5577
5593
|
if (archival) {
|
|
@@ -5587,17 +5603,17 @@ async function evaluateEntityHistory(input, options, mode) {
|
|
|
5587
5603
|
if (claim.subject.kind === "entity")
|
|
5588
5604
|
resolveEntity2(claim.subject.reference, `/claims/${i}/subject`);
|
|
5589
5605
|
if (claim.kind === "assessment")
|
|
5590
|
-
for (const [j,
|
|
5606
|
+
for (const [j, ref18] of (claim.entityInputRefs ?? []).entries())
|
|
5591
5607
|
resolveEntity2(
|
|
5592
|
-
|
|
5608
|
+
ref18,
|
|
5593
5609
|
`/claims/${i}/entityInputRefs/${j}`,
|
|
5594
|
-
|
|
5610
|
+
ref18.assertionId
|
|
5595
5611
|
);
|
|
5596
5612
|
if (claim.subject.kind === "context")
|
|
5597
5613
|
resolve2(claim.subject.reference, `/claims/${i}/subject`);
|
|
5598
5614
|
if (claim.kind === "assessment")
|
|
5599
|
-
for (const [j,
|
|
5600
|
-
resolve2(
|
|
5615
|
+
for (const [j, ref18] of (claim.contextInputRefs ?? []).entries())
|
|
5616
|
+
resolve2(ref18, `/claims/${i}/contextInputRefs/${j}`, ref18.assertionId);
|
|
5601
5617
|
}
|
|
5602
5618
|
}
|
|
5603
5619
|
const external = snapshots.some((s) => s.status === "failed") ? "failed" : snapshots.some((s) => s.status === "unavailable") || !snapshots.length ? "not_checked" : "passed";
|
|
@@ -5639,7 +5655,10 @@ async function evaluateLaboratoryClaimHistory(input, options) {
|
|
|
5639
5655
|
};
|
|
5640
5656
|
}
|
|
5641
5657
|
async function evaluateCaseRecord(input, options) {
|
|
5642
|
-
|
|
5658
|
+
return evaluateCaseRecordWithParser(input, options, parseCaseRecord);
|
|
5659
|
+
}
|
|
5660
|
+
async function evaluateCaseRecordWithParser(input, options, parse) {
|
|
5661
|
+
const parsed = parse(input);
|
|
5643
5662
|
const result = {
|
|
5644
5663
|
success: false,
|
|
5645
5664
|
issues: [...parsed.issues],
|
|
@@ -5657,20 +5676,20 @@ async function evaluateCaseRecord(input, options) {
|
|
|
5657
5676
|
const data = parsed.data;
|
|
5658
5677
|
const supplied = new Map(
|
|
5659
5678
|
data.observationRefs.map((r) => {
|
|
5660
|
-
const
|
|
5661
|
-
return [r.sha256,
|
|
5679
|
+
const bytes6 = options.documents.get(r.sha256);
|
|
5680
|
+
return [r.sha256, bytes6 ? Uint8Array.from(bytes6) : void 0];
|
|
5662
5681
|
})
|
|
5663
5682
|
);
|
|
5664
5683
|
const observations = /* @__PURE__ */ new Map();
|
|
5665
|
-
const problem = (code, pointer6,
|
|
5666
|
-
for (const [i,
|
|
5667
|
-
const p = `/observationRefs/${i}`,
|
|
5684
|
+
const problem = (code, pointer6, message2) => result.issues.push({ code, stage: "external", pointer: pointer6, message: message2 });
|
|
5685
|
+
for (const [i, ref18] of data.observationRefs.entries()) {
|
|
5686
|
+
const p = `/observationRefs/${i}`, bytes6 = supplied.get(ref18.sha256);
|
|
5668
5687
|
const snapshot3 = {
|
|
5669
|
-
...
|
|
5688
|
+
...ref18,
|
|
5670
5689
|
status: "failed"
|
|
5671
5690
|
};
|
|
5672
5691
|
result.snapshots.push(snapshot3);
|
|
5673
|
-
if (!
|
|
5692
|
+
if (!bytes6) {
|
|
5674
5693
|
snapshot3.status = "unavailable";
|
|
5675
5694
|
problem(
|
|
5676
5695
|
"SNAPSHOT.UNAVAILABLE",
|
|
@@ -5679,10 +5698,10 @@ async function evaluateCaseRecord(input, options) {
|
|
|
5679
5698
|
);
|
|
5680
5699
|
continue;
|
|
5681
5700
|
}
|
|
5682
|
-
const
|
|
5683
|
-
new Uint8Array(await crypto.subtle.digest("SHA-256",
|
|
5701
|
+
const hash8 = Array.from(
|
|
5702
|
+
new Uint8Array(await crypto.subtle.digest("SHA-256", bytes6))
|
|
5684
5703
|
).map((n) => n.toString(16).padStart(2, "0")).join("");
|
|
5685
|
-
if (
|
|
5704
|
+
if (hash8 !== ref18.sha256) {
|
|
5686
5705
|
problem(
|
|
5687
5706
|
"SNAPSHOT.DIGEST",
|
|
5688
5707
|
p,
|
|
@@ -5692,13 +5711,13 @@ async function evaluateCaseRecord(input, options) {
|
|
|
5692
5711
|
}
|
|
5693
5712
|
let raw;
|
|
5694
5713
|
try {
|
|
5695
|
-
raw = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(
|
|
5714
|
+
raw = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes6));
|
|
5696
5715
|
} catch {
|
|
5697
5716
|
problem("SNAPSHOT.JSON", p, "Snapshot is not valid UTF-8 JSON.");
|
|
5698
5717
|
continue;
|
|
5699
5718
|
}
|
|
5700
5719
|
const observation = parseExperimentalObservation(raw);
|
|
5701
|
-
if (!observation.success) {
|
|
5720
|
+
if (!observation.success || ref18.schemaId !== `urn:disclosureos:experimental:observation:${observation.data.schemaVersion}`) {
|
|
5702
5721
|
problem(
|
|
5703
5722
|
"SNAPSHOT.CONTRACT",
|
|
5704
5723
|
p,
|
|
@@ -5706,7 +5725,7 @@ async function evaluateCaseRecord(input, options) {
|
|
|
5706
5725
|
);
|
|
5707
5726
|
continue;
|
|
5708
5727
|
}
|
|
5709
|
-
if (observation.data.id !==
|
|
5728
|
+
if (observation.data.id !== ref18.documentId) {
|
|
5710
5729
|
problem(
|
|
5711
5730
|
"SNAPSHOT.IDENTITY",
|
|
5712
5731
|
p,
|
|
@@ -5714,14 +5733,14 @@ async function evaluateCaseRecord(input, options) {
|
|
|
5714
5733
|
);
|
|
5715
5734
|
continue;
|
|
5716
5735
|
}
|
|
5717
|
-
observations.set(
|
|
5736
|
+
observations.set(ref18.documentId, observation.data);
|
|
5718
5737
|
snapshot3.status = "passed";
|
|
5719
5738
|
}
|
|
5720
5739
|
for (const { pointer: pointer6, provenance: p } of caseProvenances(data)) {
|
|
5721
5740
|
const observation = observations.get(p.observationId);
|
|
5722
5741
|
if (!observation) continue;
|
|
5723
|
-
const [kind,
|
|
5724
|
-
const artifact2 = (kind === "source" ? observation.sources : observation.products).find((s) => s.id ===
|
|
5742
|
+
const [kind, id26] = p.sourceRef.split(":");
|
|
5743
|
+
const artifact2 = (kind === "source" ? observation.sources : observation.products).find((s) => s.id === id26);
|
|
5725
5744
|
if (!artifact2)
|
|
5726
5745
|
problem(
|
|
5727
5746
|
"CASE.SOURCE_SCOPE",
|
|
@@ -5755,8 +5774,14 @@ async function evaluateCaseRecord(input, options) {
|
|
|
5755
5774
|
result.declaredChronology = result.success ? "acyclic" : "incomplete";
|
|
5756
5775
|
return result;
|
|
5757
5776
|
}
|
|
5777
|
+
function evaluateCaseRecordV02(input, options) {
|
|
5778
|
+
return evaluateCaseRecordWithParser(input, options, parseCaseRecordV02);
|
|
5779
|
+
}
|
|
5758
5780
|
async function evaluateCaseClaimHistory(input, options) {
|
|
5759
|
-
|
|
5781
|
+
return evaluateCaseHistoryWithParsers(input, options, parseCaseClaimHistory, parseCaseRecord, evaluateCaseRecord);
|
|
5782
|
+
}
|
|
5783
|
+
async function evaluateCaseHistoryWithParsers(input, options, parseHistory, parseCase, evaluateCase) {
|
|
5784
|
+
const history = parseHistory(input);
|
|
5760
5785
|
const result = {
|
|
5761
5786
|
success: false,
|
|
5762
5787
|
issues: [...history.issues],
|
|
@@ -5771,35 +5796,35 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5771
5796
|
};
|
|
5772
5797
|
if (!history.success) return result;
|
|
5773
5798
|
const data = history.data, copies = /* @__PURE__ */ new Map();
|
|
5774
|
-
const
|
|
5775
|
-
if (!copies.has(
|
|
5776
|
-
const value = options.documents.get(
|
|
5777
|
-
if (value) copies.set(
|
|
5799
|
+
const copy2 = (hash8) => {
|
|
5800
|
+
if (!copies.has(hash8)) {
|
|
5801
|
+
const value = options.documents.get(hash8);
|
|
5802
|
+
if (value) copies.set(hash8, Uint8Array.from(value));
|
|
5778
5803
|
}
|
|
5779
5804
|
};
|
|
5780
|
-
for (const
|
|
5781
|
-
for (const
|
|
5805
|
+
for (const ref18 of data.caseRefs) copy2(ref18.sha256);
|
|
5806
|
+
for (const ref18 of data.caseRefs) {
|
|
5782
5807
|
try {
|
|
5783
|
-
const
|
|
5784
|
-
if (!
|
|
5785
|
-
const peek =
|
|
5786
|
-
JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(
|
|
5808
|
+
const bytes6 = copies.get(ref18.sha256);
|
|
5809
|
+
if (!bytes6) continue;
|
|
5810
|
+
const peek = parseCase(
|
|
5811
|
+
JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes6))
|
|
5787
5812
|
);
|
|
5788
5813
|
if (peek.success)
|
|
5789
|
-
peek.data.observationRefs.forEach((r) =>
|
|
5814
|
+
peek.data.observationRefs.forEach((r) => copy2(r.sha256));
|
|
5790
5815
|
} catch {
|
|
5791
5816
|
}
|
|
5792
5817
|
}
|
|
5793
|
-
const problem = (code, pointer6,
|
|
5818
|
+
const problem = (code, pointer6, message2) => result.issues.push({ code, stage: "external", pointer: pointer6, message: message2 });
|
|
5794
5819
|
const snapshots = /* @__PURE__ */ new Map();
|
|
5795
|
-
async function load(
|
|
5820
|
+
async function load(ref18, p) {
|
|
5796
5821
|
const item = {
|
|
5797
|
-
...
|
|
5822
|
+
...ref18,
|
|
5798
5823
|
status: "failed"
|
|
5799
5824
|
};
|
|
5800
|
-
snapshots.set(caseSnapshotKey(
|
|
5801
|
-
const
|
|
5802
|
-
if (!
|
|
5825
|
+
snapshots.set(caseSnapshotKey(ref18), item);
|
|
5826
|
+
const bytes6 = copies.get(ref18.sha256);
|
|
5827
|
+
if (!bytes6) {
|
|
5803
5828
|
item.status = "unavailable";
|
|
5804
5829
|
problem(
|
|
5805
5830
|
"SNAPSHOT.UNAVAILABLE",
|
|
@@ -5808,10 +5833,10 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5808
5833
|
);
|
|
5809
5834
|
return;
|
|
5810
5835
|
}
|
|
5811
|
-
const
|
|
5812
|
-
new Uint8Array(await crypto.subtle.digest("SHA-256",
|
|
5836
|
+
const digest12 = Array.from(
|
|
5837
|
+
new Uint8Array(await crypto.subtle.digest("SHA-256", bytes6))
|
|
5813
5838
|
).map((n) => n.toString(16).padStart(2, "0")).join("");
|
|
5814
|
-
if (
|
|
5839
|
+
if (digest12 !== ref18.sha256) {
|
|
5815
5840
|
problem(
|
|
5816
5841
|
"SNAPSHOT.DIGEST",
|
|
5817
5842
|
p,
|
|
@@ -5821,18 +5846,18 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5821
5846
|
}
|
|
5822
5847
|
try {
|
|
5823
5848
|
return JSON.parse(
|
|
5824
|
-
new TextDecoder("utf-8", { fatal: true }).decode(
|
|
5849
|
+
new TextDecoder("utf-8", { fatal: true }).decode(bytes6)
|
|
5825
5850
|
);
|
|
5826
5851
|
} catch {
|
|
5827
5852
|
problem("SNAPSHOT.JSON", p, "Snapshot is not valid UTF-8 JSON.");
|
|
5828
5853
|
}
|
|
5829
5854
|
}
|
|
5830
5855
|
const cases = /* @__PURE__ */ new Map(), observations = /* @__PURE__ */ new Map();
|
|
5831
|
-
for (const [i,
|
|
5832
|
-
const p = `/caseRefs/${i}`, raw = await load(
|
|
5856
|
+
for (const [i, ref18] of data.caseRefs.entries()) {
|
|
5857
|
+
const p = `/caseRefs/${i}`, raw = await load(ref18, p);
|
|
5833
5858
|
if (raw === void 0) continue;
|
|
5834
|
-
const parsed =
|
|
5835
|
-
if (!parsed.success) {
|
|
5859
|
+
const parsed = parseCase(raw);
|
|
5860
|
+
if (!parsed.success || ref18.schemaId !== `urn:disclosureos:experimental:case-record:${parsed.data.schemaVersion}`) {
|
|
5836
5861
|
problem(
|
|
5837
5862
|
"SNAPSHOT.CONTRACT",
|
|
5838
5863
|
p,
|
|
@@ -5840,13 +5865,13 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5840
5865
|
);
|
|
5841
5866
|
continue;
|
|
5842
5867
|
}
|
|
5843
|
-
if (parsed.data.id !==
|
|
5868
|
+
if (parsed.data.id !== ref18.documentId) {
|
|
5844
5869
|
problem("SNAPSHOT.IDENTITY", p, "Case ID differs from its reference.");
|
|
5845
5870
|
continue;
|
|
5846
5871
|
}
|
|
5847
|
-
snapshots.get(caseSnapshotKey(
|
|
5848
|
-
cases.set(caseSnapshotKey(
|
|
5849
|
-
const checked = await
|
|
5872
|
+
snapshots.get(caseSnapshotKey(ref18)).status = "passed";
|
|
5873
|
+
cases.set(caseSnapshotKey(ref18), parsed.data);
|
|
5874
|
+
const checked = await evaluateCase(parsed.data, {
|
|
5850
5875
|
documents: copies
|
|
5851
5876
|
});
|
|
5852
5877
|
result.issues.push(
|
|
@@ -5873,10 +5898,10 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5873
5898
|
function observation(r, p) {
|
|
5874
5899
|
const owner = cases.get(caseSnapshotKey(r.case));
|
|
5875
5900
|
if (!owner) return;
|
|
5876
|
-
const
|
|
5901
|
+
const ref18 = owner.observationRefs.find(
|
|
5877
5902
|
(s) => s.documentId === r.observationId
|
|
5878
5903
|
);
|
|
5879
|
-
if (!
|
|
5904
|
+
if (!ref18) {
|
|
5880
5905
|
problem(
|
|
5881
5906
|
"CASE.OBSERVATION_SCOPE",
|
|
5882
5907
|
p,
|
|
@@ -5884,8 +5909,8 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5884
5909
|
);
|
|
5885
5910
|
return;
|
|
5886
5911
|
}
|
|
5887
|
-
const value = observations.get(caseSnapshotKey(
|
|
5888
|
-
return value ? { value, ref:
|
|
5912
|
+
const value = observations.get(caseSnapshotKey(ref18));
|
|
5913
|
+
return value ? { value, ref: ref18 } : void 0;
|
|
5889
5914
|
}
|
|
5890
5915
|
function entity(document, target, p) {
|
|
5891
5916
|
const owner = cases.get(caseSnapshotKey(document));
|
|
@@ -5929,8 +5954,8 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5929
5954
|
if (c.kind === "source_assertion") {
|
|
5930
5955
|
const owner = observation(c.provenance, `${p}/provenance`);
|
|
5931
5956
|
if (!owner) continue;
|
|
5932
|
-
const [kind,
|
|
5933
|
-
const artifact2 = (kind === "source" ? owner.value.sources : owner.value.products).find((a) => a.id ===
|
|
5957
|
+
const [kind, id26] = c.provenance.sourceRef.split(":");
|
|
5958
|
+
const artifact2 = (kind === "source" ? owner.value.sources : owner.value.products).find((a) => a.id === id26);
|
|
5934
5959
|
if (!artifact2)
|
|
5935
5960
|
problem(
|
|
5936
5961
|
"CASE.SOURCE_SCOPE",
|
|
@@ -5960,9 +5985,9 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5960
5985
|
for (const [j, r] of (c.observationInputRefs ?? []).entries()) {
|
|
5961
5986
|
const q = `${p}/observationInputRefs/${j}`, o = observation(r, q)?.value;
|
|
5962
5987
|
if (!o) continue;
|
|
5963
|
-
const [kind,
|
|
5988
|
+
const [kind, id26] = r.ref.split(":");
|
|
5964
5989
|
const rows = kind === "source" ? o.sources : kind === "product" ? o.products : kind === "assertion" ? o.assertions : o.measurements;
|
|
5965
|
-
if (!rows.some((e) => e.id ===
|
|
5990
|
+
if (!rows.some((e) => e.id === id26))
|
|
5966
5991
|
problem(
|
|
5967
5992
|
"CASE.INPUT_RESOLUTION",
|
|
5968
5993
|
q,
|
|
@@ -5994,6 +6019,14 @@ async function evaluateCaseClaimHistory(input, options) {
|
|
|
5994
6019
|
result.snapshots = [...snapshots.values()];
|
|
5995
6020
|
return result;
|
|
5996
6021
|
}
|
|
6022
|
+
function evaluateCaseClaimHistoryV02(input, options) {
|
|
6023
|
+
const parse = (value) => {
|
|
6024
|
+
const old = parseCaseRecord(value);
|
|
6025
|
+
return old.success ? old : parseCaseRecordV02(value);
|
|
6026
|
+
};
|
|
6027
|
+
const evaluate = (value, opts) => parseCaseRecord(value).success ? evaluateCaseRecord(value, opts) : evaluateCaseRecordV02(value, opts);
|
|
6028
|
+
return evaluateCaseHistoryWithParsers(input, options, parseCaseClaimHistoryV02, parse, evaluate);
|
|
6029
|
+
}
|
|
5997
6030
|
async function evaluateCaseLinks(input, options) {
|
|
5998
6031
|
const parsed = parseCaseLinks(input);
|
|
5999
6032
|
const result = {
|
|
@@ -6011,40 +6044,40 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6011
6044
|
};
|
|
6012
6045
|
if (!parsed.success) return result;
|
|
6013
6046
|
const data = parsed.data, copies = /* @__PURE__ */ new Map();
|
|
6014
|
-
const
|
|
6015
|
-
if (!copies.has(
|
|
6016
|
-
const
|
|
6017
|
-
if (
|
|
6047
|
+
const copy2 = (hash8) => {
|
|
6048
|
+
if (!copies.has(hash8)) {
|
|
6049
|
+
const bytes6 = options.documents.get(hash8);
|
|
6050
|
+
if (bytes6) copies.set(hash8, Uint8Array.from(bytes6));
|
|
6018
6051
|
}
|
|
6019
6052
|
};
|
|
6020
|
-
|
|
6053
|
+
copy2(data.caseRef.sha256);
|
|
6021
6054
|
data.links.forEach(
|
|
6022
|
-
(l) =>
|
|
6055
|
+
(l) => copy2(l.kind === "intake" ? l.document.sha256 : l.reference.document.sha256)
|
|
6023
6056
|
);
|
|
6024
6057
|
try {
|
|
6025
|
-
const
|
|
6026
|
-
if (
|
|
6058
|
+
const bytes6 = copies.get(data.caseRef.sha256);
|
|
6059
|
+
if (bytes6) {
|
|
6027
6060
|
const peek = parseCaseRecord(
|
|
6028
|
-
JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(
|
|
6061
|
+
JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes6))
|
|
6029
6062
|
);
|
|
6030
6063
|
if (peek.success)
|
|
6031
|
-
peek.data.observationRefs.forEach((r) =>
|
|
6064
|
+
peek.data.observationRefs.forEach((r) => copy2(r.sha256));
|
|
6032
6065
|
}
|
|
6033
6066
|
} catch {
|
|
6034
6067
|
}
|
|
6035
|
-
const problem = (code, pointer6,
|
|
6068
|
+
const problem = (code, pointer6, message2) => result.issues.push({ code, stage: "external", pointer: pointer6, message: message2 });
|
|
6036
6069
|
const snapshots = /* @__PURE__ */ new Map();
|
|
6037
6070
|
const loaded = /* @__PURE__ */ new Map();
|
|
6038
|
-
async function load(
|
|
6039
|
-
const key3 = caseSnapshotKey(
|
|
6071
|
+
async function load(ref18, p) {
|
|
6072
|
+
const key3 = caseSnapshotKey(ref18);
|
|
6040
6073
|
if (loaded.has(key3)) return loaded.get(key3);
|
|
6041
6074
|
const snapshot3 = {
|
|
6042
|
-
...
|
|
6075
|
+
...ref18,
|
|
6043
6076
|
status: "failed"
|
|
6044
6077
|
};
|
|
6045
6078
|
snapshots.set(key3, snapshot3);
|
|
6046
|
-
const
|
|
6047
|
-
if (!
|
|
6079
|
+
const bytes6 = copies.get(ref18.sha256);
|
|
6080
|
+
if (!bytes6) {
|
|
6048
6081
|
snapshot3.status = "unavailable";
|
|
6049
6082
|
problem(
|
|
6050
6083
|
"SNAPSHOT.UNAVAILABLE",
|
|
@@ -6053,10 +6086,10 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6053
6086
|
);
|
|
6054
6087
|
return;
|
|
6055
6088
|
}
|
|
6056
|
-
const
|
|
6057
|
-
new Uint8Array(await crypto.subtle.digest("SHA-256",
|
|
6089
|
+
const digest12 = Array.from(
|
|
6090
|
+
new Uint8Array(await crypto.subtle.digest("SHA-256", bytes6))
|
|
6058
6091
|
).map((n) => n.toString(16).padStart(2, "0")).join("");
|
|
6059
|
-
if (
|
|
6092
|
+
if (digest12 !== ref18.sha256) {
|
|
6060
6093
|
problem(
|
|
6061
6094
|
"SNAPSHOT.DIGEST",
|
|
6062
6095
|
p,
|
|
@@ -6066,12 +6099,12 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6066
6099
|
}
|
|
6067
6100
|
let raw;
|
|
6068
6101
|
try {
|
|
6069
|
-
raw = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(
|
|
6102
|
+
raw = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes6));
|
|
6070
6103
|
} catch {
|
|
6071
6104
|
problem("SNAPSHOT.JSON", p, "Snapshot is not valid UTF-8 JSON.");
|
|
6072
6105
|
return;
|
|
6073
6106
|
}
|
|
6074
|
-
if (!raw || typeof raw !== "object" || !("id" in raw) || raw.id !==
|
|
6107
|
+
if (!raw || typeof raw !== "object" || !("id" in raw) || raw.id !== ref18.documentId) {
|
|
6075
6108
|
problem(
|
|
6076
6109
|
"SNAPSHOT.IDENTITY",
|
|
6077
6110
|
p,
|
|
@@ -6141,8 +6174,8 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6141
6174
|
"Basis provenance is outside the case snapshot."
|
|
6142
6175
|
);
|
|
6143
6176
|
else if (sourceOwner) {
|
|
6144
|
-
const [kind,
|
|
6145
|
-
const source = (kind === "source" ? sourceOwner.sources : sourceOwner.products).find((s) => s.id ===
|
|
6177
|
+
const [kind, id26] = prov.sourceRef.split(":");
|
|
6178
|
+
const source = (kind === "source" ? sourceOwner.sources : sourceOwner.products).find((s) => s.id === id26);
|
|
6146
6179
|
if (!source)
|
|
6147
6180
|
problem(
|
|
6148
6181
|
"CASE.SOURCE_SCOPE",
|
|
@@ -6156,7 +6189,7 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6156
6189
|
"Declared source digests differ."
|
|
6157
6190
|
);
|
|
6158
6191
|
}
|
|
6159
|
-
const
|
|
6192
|
+
const ref18 = l.kind === "intake" ? l.document : l.reference.document, raw = await load(ref18, p);
|
|
6160
6193
|
if (raw === void 0) continue;
|
|
6161
6194
|
if (l.kind === "intake") {
|
|
6162
6195
|
const intake = SourceIntakeSchema.safeParse(raw);
|
|
@@ -6176,7 +6209,7 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6176
6209
|
);
|
|
6177
6210
|
continue;
|
|
6178
6211
|
}
|
|
6179
|
-
snapshots.get(caseSnapshotKey(
|
|
6212
|
+
snapshots.get(caseSnapshotKey(ref18)).status = "passed";
|
|
6180
6213
|
for (const [j, a] of (l.artifactLinks ?? []).entries()) {
|
|
6181
6214
|
const q = `${p}/artifactLinks/${j}`, artifact2 = intake.data.artifacts.find(
|
|
6182
6215
|
(item) => item.id === a.artifactId
|
|
@@ -6190,8 +6223,8 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6190
6223
|
continue;
|
|
6191
6224
|
}
|
|
6192
6225
|
if (!observation) continue;
|
|
6193
|
-
const [kind,
|
|
6194
|
-
const inventory = (kind === "source" ? observation.sources : observation.products).find((item) => item.id ===
|
|
6226
|
+
const [kind, id26] = a.observationRef.split(":");
|
|
6227
|
+
const inventory = (kind === "source" ? observation.sources : observation.products).find((item) => item.id === id26);
|
|
6195
6228
|
if (!inventory)
|
|
6196
6229
|
problem(
|
|
6197
6230
|
"CASE.INPUT_RESOLUTION",
|
|
@@ -6213,7 +6246,7 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6213
6246
|
}
|
|
6214
6247
|
continue;
|
|
6215
6248
|
}
|
|
6216
|
-
const supplement = l.kind === "context" ? parseObservationContext(raw) :
|
|
6249
|
+
const supplement = l.kind === "context" ? parseObservationContext(raw) : ref18.schemaId === "urn:disclosureos:experimental:research-entities:0.1.0" ? parseResearchEntities(raw) : ref18.schemaId === "urn:disclosureos:experimental:research-entities:0.2.0" ? parseArchivalEntities(raw) : ref18.schemaId === "urn:disclosureos:experimental:research-entities:0.3.0" ? parseMaterialEntities(raw) : parseLaboratoryEntities(raw);
|
|
6217
6250
|
if (!supplement.success) {
|
|
6218
6251
|
problem(
|
|
6219
6252
|
"SNAPSHOT.CONTRACT",
|
|
@@ -6222,7 +6255,7 @@ async function evaluateCaseLinks(input, options) {
|
|
|
6222
6255
|
);
|
|
6223
6256
|
continue;
|
|
6224
6257
|
}
|
|
6225
|
-
snapshots.get(caseSnapshotKey(
|
|
6258
|
+
snapshots.get(caseSnapshotKey(ref18)).status = "passed";
|
|
6226
6259
|
result.supplements.push({
|
|
6227
6260
|
linkId: l.id,
|
|
6228
6261
|
uncheckedRefs: [...supplement.uncheckedRefs],
|
|
@@ -6374,17 +6407,17 @@ function parseCasePresentation(input) {
|
|
|
6374
6407
|
return { success: true, data: d };
|
|
6375
6408
|
}
|
|
6376
6409
|
var approvalSchema = z.strictObject({ presentationSha256: sha256, policyVersion: short });
|
|
6377
|
-
async function digest3(
|
|
6378
|
-
return Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256", Uint8Array.from(
|
|
6410
|
+
async function digest3(bytes6) {
|
|
6411
|
+
return Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes6)))).map((n) => n.toString(16).padStart(2, "0")).join("");
|
|
6379
6412
|
}
|
|
6380
|
-
var decode3 = (
|
|
6413
|
+
var decode3 = (bytes6) => JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes6));
|
|
6381
6414
|
async function buildPublicCase(presentationBytes, options) {
|
|
6382
6415
|
const approved = approvalSchema.safeParse(options.approval);
|
|
6383
6416
|
if (!approved.success) return { success: false, code: "APPROVAL_REQUIRED" };
|
|
6384
|
-
const
|
|
6417
|
+
const bytes6 = Uint8Array.from(presentationBytes);
|
|
6385
6418
|
let parsed;
|
|
6386
6419
|
try {
|
|
6387
|
-
parsed = parseCasePresentation(decode3(
|
|
6420
|
+
parsed = parseCasePresentation(decode3(bytes6));
|
|
6388
6421
|
} catch {
|
|
6389
6422
|
return { success: false, code: "INVALID_PRESENTATION" };
|
|
6390
6423
|
}
|
|
@@ -6393,21 +6426,21 @@ async function buildPublicCase(presentationBytes, options) {
|
|
|
6393
6426
|
if (d.status === "draft" || d.status === "withdrawn")
|
|
6394
6427
|
return { success: false, code: "NOT_PUBLISHED" };
|
|
6395
6428
|
const copies = /* @__PURE__ */ new Map();
|
|
6396
|
-
const
|
|
6397
|
-
const b = options.documents.get(
|
|
6398
|
-
if (b && !copies.has(
|
|
6429
|
+
const copy2 = (hash8) => {
|
|
6430
|
+
const b = options.documents.get(hash8);
|
|
6431
|
+
if (b && !copies.has(hash8)) copies.set(hash8, Uint8Array.from(b));
|
|
6399
6432
|
};
|
|
6400
6433
|
const refs = [
|
|
6401
6434
|
d.caseRef,
|
|
6402
6435
|
...d.linksRef ? [d.linksRef] : [],
|
|
6403
6436
|
...d.findings.map((f) => f.historyRef)
|
|
6404
6437
|
];
|
|
6405
|
-
refs.forEach((r) =>
|
|
6438
|
+
refs.forEach((r) => copy2(r.sha256));
|
|
6406
6439
|
try {
|
|
6407
6440
|
const c = copies.get(d.caseRef.sha256);
|
|
6408
6441
|
if (c) {
|
|
6409
6442
|
const p = parseCaseRecord(decode3(c));
|
|
6410
|
-
if (p.success) p.data.observationRefs.forEach((r) =>
|
|
6443
|
+
if (p.success) p.data.observationRefs.forEach((r) => copy2(r.sha256));
|
|
6411
6444
|
}
|
|
6412
6445
|
for (const f of d.findings) {
|
|
6413
6446
|
const b = copies.get(f.historyRef.sha256);
|
|
@@ -6415,11 +6448,11 @@ async function buildPublicCase(presentationBytes, options) {
|
|
|
6415
6448
|
const h = parseCaseClaimHistory(decode3(b));
|
|
6416
6449
|
if (h.success)
|
|
6417
6450
|
for (const r of h.data.caseRefs) {
|
|
6418
|
-
|
|
6451
|
+
copy2(r.sha256);
|
|
6419
6452
|
const cb = copies.get(r.sha256);
|
|
6420
6453
|
if (cb) {
|
|
6421
6454
|
const p = parseCaseRecord(decode3(cb));
|
|
6422
|
-
if (p.success) p.data.observationRefs.forEach((o) =>
|
|
6455
|
+
if (p.success) p.data.observationRefs.forEach((o) => copy2(o.sha256));
|
|
6423
6456
|
}
|
|
6424
6457
|
}
|
|
6425
6458
|
}
|
|
@@ -6429,20 +6462,20 @@ async function buildPublicCase(presentationBytes, options) {
|
|
|
6429
6462
|
const links = parseCaseLinks(decode3(b));
|
|
6430
6463
|
if (links.success)
|
|
6431
6464
|
links.data.links.forEach(
|
|
6432
|
-
(l) =>
|
|
6465
|
+
(l) => copy2(l.kind === "intake" ? l.document.sha256 : l.reference.document.sha256)
|
|
6433
6466
|
);
|
|
6434
6467
|
}
|
|
6435
6468
|
}
|
|
6436
6469
|
} catch {
|
|
6437
6470
|
return { success: false, code: "INVALID_REFERENCES" };
|
|
6438
6471
|
}
|
|
6439
|
-
if (await digest3(
|
|
6472
|
+
if (await digest3(bytes6) !== approved.data.presentationSha256)
|
|
6440
6473
|
return { success: false, code: "APPROVAL_REQUIRED" };
|
|
6441
|
-
const load = async (
|
|
6442
|
-
const b = copies.get(
|
|
6443
|
-
if (!b || await digest3(b) !==
|
|
6474
|
+
const load = async (ref18) => {
|
|
6475
|
+
const b = copies.get(ref18.sha256);
|
|
6476
|
+
if (!b || await digest3(b) !== ref18.sha256) throw new Error("reference");
|
|
6444
6477
|
const raw = decode3(b);
|
|
6445
|
-
if (!raw || typeof raw !== "object" || !("id" in raw) || raw.id !==
|
|
6478
|
+
if (!raw || typeof raw !== "object" || !("id" in raw) || raw.id !== ref18.documentId)
|
|
6446
6479
|
throw new Error("reference");
|
|
6447
6480
|
return raw;
|
|
6448
6481
|
};
|
|
@@ -6458,10 +6491,10 @@ async function buildPublicCase(presentationBytes, options) {
|
|
|
6458
6491
|
return [r.documentId, p.data];
|
|
6459
6492
|
})
|
|
6460
6493
|
);
|
|
6461
|
-
const artifact2 = (observationId,
|
|
6494
|
+
const artifact2 = (observationId, ref18) => {
|
|
6462
6495
|
const o = observations.get(observationId);
|
|
6463
|
-
const [kind,
|
|
6464
|
-
return (kind === "source" ? o?.sources : o?.products)?.find((a) => a.id ===
|
|
6496
|
+
const [kind, id26] = ref18.split(":");
|
|
6497
|
+
return (kind === "source" ? o?.sources : o?.products)?.find((a) => a.id === id26);
|
|
6465
6498
|
};
|
|
6466
6499
|
const linkedIds = /* @__PURE__ */ new Set();
|
|
6467
6500
|
if (d.linksRef) {
|
|
@@ -6470,7 +6503,7 @@ async function buildPublicCase(presentationBytes, options) {
|
|
|
6470
6503
|
return invalid5();
|
|
6471
6504
|
const result = await evaluateCaseLinks(links.data, { documents: copies });
|
|
6472
6505
|
if (!result.success) return invalid5();
|
|
6473
|
-
result.resolvedLinkIds.forEach((
|
|
6506
|
+
result.resolvedLinkIds.forEach((id26) => linkedIds.add(id26));
|
|
6474
6507
|
}
|
|
6475
6508
|
for (const c of d.citations) {
|
|
6476
6509
|
if (c.target.kind === "artifact" && !artifact2(c.target.observationId, c.target.ref))
|
|
@@ -6738,23 +6771,23 @@ async function buildPublicContextCase(input, options) {
|
|
|
6738
6771
|
return { success: false, code: "INVALID_PRESENTATION" };
|
|
6739
6772
|
const d = parsed.data, selection = d.context;
|
|
6740
6773
|
const copies = /* @__PURE__ */ new Map();
|
|
6741
|
-
const
|
|
6742
|
-
const b = options.documents.get(
|
|
6743
|
-
if (b && !copies.has(
|
|
6744
|
-
copies.set(
|
|
6774
|
+
const copy2 = (ref18) => {
|
|
6775
|
+
const b = options.documents.get(ref18.sha256);
|
|
6776
|
+
if (b && !copies.has(ref18.sha256))
|
|
6777
|
+
copies.set(ref18.sha256, Uint8Array.from(b));
|
|
6745
6778
|
};
|
|
6746
|
-
[selection.document, selection.history, d.presentation.caseRef].forEach(
|
|
6779
|
+
[selection.document, selection.history, d.presentation.caseRef].forEach(copy2);
|
|
6747
6780
|
try {
|
|
6748
6781
|
const h = parseContextClaimHistory(
|
|
6749
6782
|
decode4(copies.get(selection.history.sha256))
|
|
6750
6783
|
);
|
|
6751
6784
|
if (!h.success) return invalid();
|
|
6752
6785
|
for (const r of h.data.contextRefs) {
|
|
6753
|
-
|
|
6786
|
+
copy2(r);
|
|
6754
6787
|
const c = parseObservationContext(decode4(copies.get(r.sha256)));
|
|
6755
6788
|
if (!c.success) return invalid();
|
|
6756
|
-
|
|
6757
|
-
if (c.data.acquisitionRef)
|
|
6789
|
+
copy2(c.data.observationRef);
|
|
6790
|
+
if (c.data.acquisitionRef) copy2(c.data.acquisitionRef);
|
|
6758
6791
|
}
|
|
6759
6792
|
const baseDocuments = /* @__PURE__ */ new Map();
|
|
6760
6793
|
const pending = [
|
|
@@ -6787,11 +6820,11 @@ async function buildPublicContextCase(input, options) {
|
|
|
6787
6820
|
}
|
|
6788
6821
|
});
|
|
6789
6822
|
if (!base2.success) return base2;
|
|
6790
|
-
const load = async (
|
|
6791
|
-
const b = copies.get(
|
|
6792
|
-
if (!b || await digest4(b) !==
|
|
6823
|
+
const load = async (ref18) => {
|
|
6824
|
+
const b = copies.get(ref18.sha256);
|
|
6825
|
+
if (!b || await digest4(b) !== ref18.sha256) throw new Error("reference");
|
|
6793
6826
|
const v = decode4(b);
|
|
6794
|
-
if (v.id !==
|
|
6827
|
+
if (v.id !== ref18.documentId) throw new Error("reference");
|
|
6795
6828
|
return v;
|
|
6796
6829
|
};
|
|
6797
6830
|
const context = parseObservationContext(await load(selection.document));
|
|
@@ -6814,11 +6847,11 @@ async function buildPublicContextCase(input, options) {
|
|
|
6814
6847
|
return invalid();
|
|
6815
6848
|
const citeRefs = (ids, required) => {
|
|
6816
6849
|
const selected2 = ids.map(
|
|
6817
|
-
(
|
|
6850
|
+
(id26) => d.presentation.citations.find((c) => c.id === id26).target
|
|
6818
6851
|
);
|
|
6819
6852
|
if (required.some(
|
|
6820
|
-
(
|
|
6821
|
-
(t) => t.kind === "artifact" && t.observationId === observation.id && t.ref ===
|
|
6853
|
+
(ref18) => !selected2.some(
|
|
6854
|
+
(t) => t.kind === "artifact" && t.observationId === observation.id && t.ref === ref18
|
|
6822
6855
|
)
|
|
6823
6856
|
))
|
|
6824
6857
|
throw new Error("citation");
|
|
@@ -7175,11 +7208,11 @@ async function buildPublicTestimonyCase(input, options) {
|
|
|
7175
7208
|
const observationId = entities.data.observationRef.documentId;
|
|
7176
7209
|
const cite = (ids, refs) => {
|
|
7177
7210
|
const targets = ids.map(
|
|
7178
|
-
(
|
|
7211
|
+
(id26) => d.presentation.citations.find((c) => c.id === id26).target
|
|
7179
7212
|
);
|
|
7180
7213
|
if (refs.some(
|
|
7181
|
-
(
|
|
7182
|
-
(t) => t.kind === "artifact" && t.observationId === observationId && t.ref ===
|
|
7214
|
+
(ref18) => !targets.some(
|
|
7215
|
+
(t) => t.kind === "artifact" && t.observationId === observationId && t.ref === ref18
|
|
7183
7216
|
)
|
|
7184
7217
|
))
|
|
7185
7218
|
throw Error("citation");
|
|
@@ -7639,11 +7672,11 @@ async function buildPublicArchivalCase(input, options) {
|
|
|
7639
7672
|
const observationId = entities.data.observationRef.documentId;
|
|
7640
7673
|
const cite = (ids, refs) => {
|
|
7641
7674
|
const targets = ids.map(
|
|
7642
|
-
(
|
|
7675
|
+
(id26) => d.presentation.citations.find((c2) => c2.id === id26).target
|
|
7643
7676
|
);
|
|
7644
7677
|
if (refs.some(
|
|
7645
|
-
(
|
|
7646
|
-
(t) => t.kind === "artifact" && t.observationId === observationId && t.ref ===
|
|
7678
|
+
(ref18) => !targets.some(
|
|
7679
|
+
(t) => t.kind === "artifact" && t.observationId === observationId && t.ref === ref18
|
|
7647
7680
|
)
|
|
7648
7681
|
))
|
|
7649
7682
|
throw Error("citation");
|
|
@@ -7824,8 +7857,8 @@ async function buildPublicArchivalCase(input, options) {
|
|
|
7824
7857
|
ordered.push(...ready);
|
|
7825
7858
|
pending = pending.filter((a) => !ready.includes(a));
|
|
7826
7859
|
}
|
|
7827
|
-
const sourceCitationId = e.citationIds.find((
|
|
7828
|
-
const t = d.presentation.citations.find((c2) => c2.id ===
|
|
7860
|
+
const sourceCitationId = e.citationIds.find((id26) => {
|
|
7861
|
+
const t = d.presentation.citations.find((c2) => c2.id === id26).target;
|
|
7829
7862
|
return t.kind === "artifact" && t.observationId === observationId && t.ref === edition.artifact.sourceRef;
|
|
7830
7863
|
});
|
|
7831
7864
|
publicEditions.push({
|
|
@@ -7960,7 +7993,7 @@ async function buildPublicArchivalCaseOutputs(input, options) {
|
|
|
7960
7993
|
action2.citationIds
|
|
7961
7994
|
);
|
|
7962
7995
|
}
|
|
7963
|
-
const editionLabel = (
|
|
7996
|
+
const editionLabel = (id26) => a.editions.find((e) => e.id === id26).label;
|
|
7964
7997
|
for (const p of a.passages)
|
|
7965
7998
|
add3(
|
|
7966
7999
|
`${editionLabel(p.editionId)}, page ${p.page}`,
|
|
@@ -8153,11 +8186,11 @@ async function buildPublicMaterialCase(input, options) {
|
|
|
8153
8186
|
const observation = history.data.observation;
|
|
8154
8187
|
const cite = (ids, refs2) => {
|
|
8155
8188
|
const targets = ids.map(
|
|
8156
|
-
(
|
|
8189
|
+
(id26) => d.presentation.citations.find((c2) => c2.id === id26).target
|
|
8157
8190
|
);
|
|
8158
8191
|
if (refs2.some(
|
|
8159
|
-
(
|
|
8160
|
-
(t) => t.kind === "artifact" && t.observationId === observation.id && t.ref ===
|
|
8192
|
+
(ref18) => !targets.some(
|
|
8193
|
+
(t) => t.kind === "artifact" && t.observationId === observation.id && t.ref === ref18
|
|
8161
8194
|
)
|
|
8162
8195
|
))
|
|
8163
8196
|
throw Error("citation");
|
|
@@ -8476,7 +8509,7 @@ async function buildPublicMaterialCaseOutputs(input, options) {
|
|
|
8476
8509
|
);
|
|
8477
8510
|
search.push(title, ...body);
|
|
8478
8511
|
};
|
|
8479
|
-
const specimen = (
|
|
8512
|
+
const specimen = (id26) => m.specimens.find((x) => x.id === id26).label;
|
|
8480
8513
|
for (const t of m.traces)
|
|
8481
8514
|
add3(
|
|
8482
8515
|
t.label,
|
|
@@ -8550,7 +8583,7 @@ async function buildPublicMaterialCaseOutputs(input, options) {
|
|
|
8550
8583
|
m.review.summary,
|
|
8551
8584
|
`${m.review.reviewerLabel} \xB7 ${m.review.outcome} \xB7 ${m.review.revision}`,
|
|
8552
8585
|
m.review.method,
|
|
8553
|
-
`Reviewed results: ${m.review.resultIds.map((
|
|
8586
|
+
`Reviewed results: ${m.review.resultIds.map((id26) => m.results.find((x) => x.id === id26).label).join(", ")}`
|
|
8554
8587
|
],
|
|
8555
8588
|
m.review.citationIds
|
|
8556
8589
|
);
|
|
@@ -8572,8 +8605,8 @@ var safe = (value) => {
|
|
|
8572
8605
|
if (!integer(value)) throw new Error("Unsafe integer arithmetic");
|
|
8573
8606
|
return value;
|
|
8574
8607
|
};
|
|
8575
|
-
function readSourceCsv(
|
|
8576
|
-
const
|
|
8608
|
+
function readSourceCsv(bytes6) {
|
|
8609
|
+
const text21 = new TextDecoder("utf-8", { fatal: true }).decode(bytes6);
|
|
8577
8610
|
const rows = [];
|
|
8578
8611
|
let row = [], cell = "", quoted = false, closed = false;
|
|
8579
8612
|
const field2 = () => {
|
|
@@ -8586,11 +8619,11 @@ function readSourceCsv(bytes5) {
|
|
|
8586
8619
|
rows.push(row);
|
|
8587
8620
|
row = [];
|
|
8588
8621
|
};
|
|
8589
|
-
for (let i = 0; i <
|
|
8590
|
-
const c =
|
|
8622
|
+
for (let i = 0; i < text21.length; i++) {
|
|
8623
|
+
const c = text21[i];
|
|
8591
8624
|
if (quoted) {
|
|
8592
8625
|
if (c === '"') {
|
|
8593
|
-
if (
|
|
8626
|
+
if (text21[i + 1] === '"') {
|
|
8594
8627
|
cell += '"';
|
|
8595
8628
|
i++;
|
|
8596
8629
|
} else {
|
|
@@ -8600,7 +8633,7 @@ function readSourceCsv(bytes5) {
|
|
|
8600
8633
|
} else cell += c;
|
|
8601
8634
|
} else if (c === ",") field2();
|
|
8602
8635
|
else if (c === "\n" || c === "\r") {
|
|
8603
|
-
if (c === "\r" &&
|
|
8636
|
+
if (c === "\r" && text21[++i] !== "\n") throw new Error("Bare CR in CSV");
|
|
8604
8637
|
record();
|
|
8605
8638
|
} else if (c === '"' && cell === "" && !closed) quoted = true;
|
|
8606
8639
|
else {
|
|
@@ -8612,8 +8645,8 @@ function readSourceCsv(bytes5) {
|
|
|
8612
8645
|
if (cell !== "" || row.length || closed) record();
|
|
8613
8646
|
return rows;
|
|
8614
8647
|
}
|
|
8615
|
-
function readProductSourceSelection(layout, selector,
|
|
8616
|
-
if (
|
|
8648
|
+
function readProductSourceSelection(layout, selector, bytes6) {
|
|
8649
|
+
if (bytes6 && bytes6.byteLength !== layout.byteLength)
|
|
8617
8650
|
throw new Error("Source byte length mismatch");
|
|
8618
8651
|
if (layout.kind === "binary_array" && selector.kind === "array_element") {
|
|
8619
8652
|
if (selector.indices.length !== layout.axes.length)
|
|
@@ -8648,11 +8681,11 @@ function readProductSourceSelection(layout, selector, bytes5) {
|
|
|
8648
8681
|
const timeAxis = layout.axes.find((axis2) => axis2.kind === "time");
|
|
8649
8682
|
if (timeAxis)
|
|
8650
8683
|
result.time = coordinates[timeAxis.name];
|
|
8651
|
-
if (
|
|
8684
|
+
if (bytes6) {
|
|
8652
8685
|
const view = new DataView(
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8686
|
+
bytes6.buffer,
|
|
8687
|
+
bytes6.byteOffset,
|
|
8688
|
+
bytes6.byteLength
|
|
8656
8689
|
), little = layout.byteOrder === "little";
|
|
8657
8690
|
result.value = layout.elementType === "float32" ? view.getFloat32(byteOffset, little) : layout.elementType === "float64" ? view.getFloat64(byteOffset, little) : layout.elementType === "int16" ? view.getInt16(byteOffset, little) : layout.elementType === "uint16" ? view.getUint16(byteOffset, little) : view.getUint8(byteOffset);
|
|
8658
8691
|
if (!Number.isFinite(result.value))
|
|
@@ -8665,8 +8698,8 @@ function readProductSourceSelection(layout, selector, bytes5) {
|
|
|
8665
8698
|
if (layout.kind === "csv_table" && selector.kind === "table_row") {
|
|
8666
8699
|
if (!integer(selector.row) || selector.row >= layout.rowCount)
|
|
8667
8700
|
throw new Error("CSV row outside extent");
|
|
8668
|
-
if (!
|
|
8669
|
-
const rows = readSourceCsv(
|
|
8701
|
+
if (!bytes6) return { mediaDecoding: "not_applicable" };
|
|
8702
|
+
const rows = readSourceCsv(bytes6), header = rows.shift();
|
|
8670
8703
|
if (!header || header.length !== layout.columns.length || header.some((value, i) => value !== layout.columns[i]))
|
|
8671
8704
|
throw new Error("CSV header mismatch");
|
|
8672
8705
|
if (rows.length !== layout.rowCount || rows.some((row) => row.length !== layout.columns.length))
|
|
@@ -8852,7 +8885,7 @@ async function evaluateProductSourceSelection(observationInput, selectionInput,
|
|
|
8852
8885
|
calibration: "not_checked",
|
|
8853
8886
|
mediaDecoding: "not_checked"
|
|
8854
8887
|
};
|
|
8855
|
-
const issue = (code, stage, pointer6,
|
|
8888
|
+
const issue = (code, stage, pointer6, message2) => result.issues.push({ code, stage, pointer: pointer6, message: message2 });
|
|
8856
8889
|
if (!observation.success)
|
|
8857
8890
|
for (const entry of observation.issues.filter(
|
|
8858
8891
|
(i) => i.severity === "error"
|
|
@@ -8991,15 +9024,15 @@ async function evaluateProductSourceSelection(observationInput, selectionInput,
|
|
|
8991
9024
|
const supports = (refs, target) => {
|
|
8992
9025
|
const queue = [...refs], seen = /* @__PURE__ */ new Set();
|
|
8993
9026
|
while (queue.length) {
|
|
8994
|
-
const
|
|
8995
|
-
if (
|
|
8996
|
-
if (seen.has(
|
|
8997
|
-
seen.add(
|
|
8998
|
-
const p = products.get(
|
|
9027
|
+
const ref18 = queue.pop();
|
|
9028
|
+
if (ref18 === target) return true;
|
|
9029
|
+
if (seen.has(ref18)) continue;
|
|
9030
|
+
seen.add(ref18);
|
|
9031
|
+
const p = products.get(ref18);
|
|
8999
9032
|
if (p?.kind === "derived")
|
|
9000
9033
|
queue.push(...processes.get(p.generatedBy).inputRefs);
|
|
9001
9034
|
const assertion = record.assertions.find(
|
|
9002
|
-
(a) => `assertion:${a.id}` ===
|
|
9035
|
+
(a) => `assertion:${a.id}` === ref18
|
|
9003
9036
|
);
|
|
9004
9037
|
if (assertion) queue.push(assertion.provenance.sourceRef);
|
|
9005
9038
|
}
|
|
@@ -9041,8 +9074,8 @@ async function evaluateProductSourceSelection(observationInput, selectionInput,
|
|
|
9041
9074
|
}
|
|
9042
9075
|
result.checks.semantic = "passed";
|
|
9043
9076
|
const assets2 = new Map(
|
|
9044
|
-
[...options.assets ?? []].map(([
|
|
9045
|
-
|
|
9077
|
+
[...options.assets ?? []].map(([ref18, value]) => [
|
|
9078
|
+
ref18,
|
|
9046
9079
|
Uint8Array.from(value)
|
|
9047
9080
|
])
|
|
9048
9081
|
);
|
|
@@ -9352,14 +9385,14 @@ function readRadarProducts(layouts, products, assets2) {
|
|
|
9352
9385
|
const table2 = (role) => {
|
|
9353
9386
|
const product = products[role];
|
|
9354
9387
|
if (!product) return [];
|
|
9355
|
-
const layout = layoutMap.get(product),
|
|
9356
|
-
if (!layout || layout.kind !== "csv_table" || !
|
|
9388
|
+
const layout = layoutMap.get(product), bytes6 = assets2.get(product);
|
|
9389
|
+
if (!layout || layout.kind !== "csv_table" || !bytes6 || bytes6.byteLength !== layout.byteLength)
|
|
9357
9390
|
throw new Error(`Missing or mismatched ${role} table.`);
|
|
9358
9391
|
if (layout.partition || layout.sample)
|
|
9359
9392
|
throw new Error(
|
|
9360
9393
|
`Radar ${role} tables must declare the complete table without a partition or scalar sample mapping.`
|
|
9361
9394
|
);
|
|
9362
|
-
const columns = RADAR_TABLE_COLUMNS[role], records = readSourceCsv(
|
|
9395
|
+
const columns = RADAR_TABLE_COLUMNS[role], records = readSourceCsv(bytes6), header = records.shift();
|
|
9363
9396
|
if (JSON.stringify(header) !== JSON.stringify(columns) || JSON.stringify(layout.columns) !== JSON.stringify(columns) || records.length !== layout.rowCount)
|
|
9364
9397
|
throw new Error(`Invalid ${role} columns or row count.`);
|
|
9365
9398
|
return records.map((row) => {
|
|
@@ -9402,15 +9435,15 @@ function readRadarProducts(layouts, products, assets2) {
|
|
|
9402
9435
|
});
|
|
9403
9436
|
};
|
|
9404
9437
|
const array2 = (role) => {
|
|
9405
|
-
const
|
|
9406
|
-
if (!
|
|
9407
|
-
const layout = layoutMap.get(
|
|
9408
|
-
if (!layout || layout.kind !== "binary_array" || layout.elementType !== (role === "eligibility" ? "uint8" : "float32") || layout.byteOrder !== "little" || !
|
|
9438
|
+
const ref18 = products[role];
|
|
9439
|
+
if (!ref18) return [];
|
|
9440
|
+
const layout = layoutMap.get(ref18), bytes6 = assets2.get(ref18), elementBytes = role === "eligibility" ? 1 : 4;
|
|
9441
|
+
if (!layout || layout.kind !== "binary_array" || layout.elementType !== (role === "eligibility" ? "uint8" : "float32") || layout.byteOrder !== "little" || !bytes6 || bytes6.byteLength !== layout.byteLength || layout.byteOffset < 0 || !Number.isSafeInteger(layout.byteOffset))
|
|
9409
9442
|
throw new Error(`Invalid ${role} array.`);
|
|
9410
9443
|
const count = layout.axes.reduce((n, axis2) => n * axis2.length, 1);
|
|
9411
|
-
if (!Number.isSafeInteger(count) || layout.byteOffset + count * elementBytes !==
|
|
9444
|
+
if (!Number.isSafeInteger(count) || layout.byteOffset + count * elementBytes !== bytes6.byteLength)
|
|
9412
9445
|
throw new Error(`Invalid ${role} extent.`);
|
|
9413
|
-
const view = new DataView(
|
|
9446
|
+
const view = new DataView(bytes6.buffer, bytes6.byteOffset, bytes6.byteLength), values = [];
|
|
9414
9447
|
for (let i = 0; i < count; i++) {
|
|
9415
9448
|
const n = elementBytes === 1 ? view.getUint8(layout.byteOffset + i) : view.getFloat32(layout.byteOffset + i * 4, true);
|
|
9416
9449
|
if (!Number.isFinite(n)) throw new Error(`Non-finite ${role} sample.`);
|
|
@@ -9442,7 +9475,7 @@ function radarCovarianceScaleSquared(probability) {
|
|
|
9442
9475
|
var close = (a, b, tolerance = 1e-6) => Math.abs(a - b) <= tolerance * Math.max(1, Math.abs(a), Math.abs(b));
|
|
9443
9476
|
var positionClose = (a, b) => Math.abs(a - b) <= 1e-6 + 32 * Number.EPSILON * Math.max(1, Math.abs(a), Math.abs(b));
|
|
9444
9477
|
var index = (n, length) => Number.isSafeInteger(n) && n >= 0 && n < length;
|
|
9445
|
-
var key = (
|
|
9478
|
+
var key = (id26, scan) => `${id26}/${scan}`;
|
|
9446
9479
|
var decimal = (value) => {
|
|
9447
9480
|
const match = /^(-?)(\d+)(?:\.(\d+))?(?:e([+-]?\d+))?$/i.exec(value);
|
|
9448
9481
|
const fraction = match[3] ?? "", exponent = Number(match[4] ?? 0) - fraction.length;
|
|
@@ -9474,8 +9507,8 @@ async function evaluateRadarProfile(observationInput, contextInput, selectionInp
|
|
|
9474
9507
|
physicalCalibration: "not_checked",
|
|
9475
9508
|
trackingPerformance: "not_checked"
|
|
9476
9509
|
};
|
|
9477
|
-
const issue = (code, pointer6,
|
|
9478
|
-
result.issues.push({ code, pointer: pointer6, message });
|
|
9510
|
+
const issue = (code, pointer6, message2) => {
|
|
9511
|
+
result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
9479
9512
|
};
|
|
9480
9513
|
const parsed = RadarProfileSchema.safeParse(profileInput), observation = parseExperimentalObservation(observationInput), context = parseAcquisitionContext(contextInput), selection = ProductSourceSelectionSchema.safeParse(selectionInput);
|
|
9481
9514
|
if (!parsed.success || !observation.success || !context.success || !selection.success) {
|
|
@@ -9495,7 +9528,7 @@ async function evaluateRadarProfile(observationInput, contextInput, selectionInp
|
|
|
9495
9528
|
"Profile identifiers must select these exact documents."
|
|
9496
9529
|
);
|
|
9497
9530
|
const roleRefs = Object.values(profile.products).filter(
|
|
9498
|
-
(
|
|
9531
|
+
(ref18) => ref18 !== void 0
|
|
9499
9532
|
);
|
|
9500
9533
|
if (new Set(roleRefs).size !== roleRefs.length)
|
|
9501
9534
|
issue(
|
|
@@ -9532,8 +9565,8 @@ async function evaluateRadarProfile(observationInput, contextInput, selectionInp
|
|
|
9532
9565
|
const layouts = new Map(
|
|
9533
9566
|
sources.layouts.map((layout) => [layout.productRef, layout])
|
|
9534
9567
|
);
|
|
9535
|
-
for (const [role,
|
|
9536
|
-
if (
|
|
9568
|
+
for (const [role, ref18] of Object.entries(profile.products))
|
|
9569
|
+
if (ref18 && !layouts.has(ref18))
|
|
9537
9570
|
issue(
|
|
9538
9571
|
"RADAR.LAYOUT",
|
|
9539
9572
|
`/products/${role}`,
|
|
@@ -9679,8 +9712,8 @@ async function evaluateRadarProfile(observationInput, contextInput, selectionInp
|
|
|
9679
9712
|
"/products/returns",
|
|
9680
9713
|
"The retained return array is the input capture for this profile. Derived inputs need a separately specified profile."
|
|
9681
9714
|
);
|
|
9682
|
-
const ancestors = (
|
|
9683
|
-
const found = /* @__PURE__ */ new Set(), queue = [
|
|
9715
|
+
const ancestors = (ref18) => {
|
|
9716
|
+
const found = /* @__PURE__ */ new Set(), queue = [ref18];
|
|
9684
9717
|
for (let i = 0; i < queue.length; i++) {
|
|
9685
9718
|
const current = queue[i];
|
|
9686
9719
|
if (found.has(current)) continue;
|
|
@@ -9774,7 +9807,7 @@ async function evaluateRadarProfile(observationInput, contextInput, selectionInp
|
|
|
9774
9807
|
obs.sources.map((source) => [`source:${source.id}`, source.kind])
|
|
9775
9808
|
);
|
|
9776
9809
|
const forbidden = [...ancestors(profile.products.truth)].filter(
|
|
9777
|
-
(
|
|
9810
|
+
(ref18) => !sharedSynthesis.has(ref18) || sourceKinds.get(ref18) !== "document"
|
|
9778
9811
|
);
|
|
9779
9812
|
if ([
|
|
9780
9813
|
thresholdInputs,
|
|
@@ -9789,7 +9822,7 @@ async function evaluateRadarProfile(observationInput, contextInput, selectionInp
|
|
|
9789
9822
|
] : [],
|
|
9790
9823
|
...profile.products.siteFeatures ? [ancestors(profile.products.siteFeatures)] : [],
|
|
9791
9824
|
...profile.products.platformPose ? [ancestors(profile.products.platformPose)] : []
|
|
9792
|
-
].some((inputs) => forbidden.some((
|
|
9825
|
+
].some((inputs) => forbidden.some((ref18) => inputs.has(ref18))))
|
|
9793
9826
|
issue(
|
|
9794
9827
|
"RADAR.TRUTH_LEAK",
|
|
9795
9828
|
"/products/truth",
|
|
@@ -9801,9 +9834,9 @@ async function evaluateRadarProfile(observationInput, contextInput, selectionInp
|
|
|
9801
9834
|
return result;
|
|
9802
9835
|
}
|
|
9803
9836
|
const assets2 = new Map(
|
|
9804
|
-
[...options.assets ?? []].map(([
|
|
9805
|
-
|
|
9806
|
-
Uint8Array.from(
|
|
9837
|
+
[...options.assets ?? []].map(([ref18, bytes6]) => [
|
|
9838
|
+
ref18,
|
|
9839
|
+
Uint8Array.from(bytes6)
|
|
9807
9840
|
])
|
|
9808
9841
|
);
|
|
9809
9842
|
const sourceResult = await evaluateProductSourceSelection(obs, sources, {
|
|
@@ -9991,12 +10024,12 @@ async function evaluateRadarProfile(observationInput, contextInput, selectionInp
|
|
|
9991
10024
|
siteGroups.set(vertex.feature_id, group);
|
|
9992
10025
|
previousFeature = vertex.feature_id;
|
|
9993
10026
|
}
|
|
9994
|
-
for (const [
|
|
10027
|
+
for (const [id26, vertices] of siteGroups) {
|
|
9995
10028
|
const first2 = vertices[0], last2 = vertices.at(-1), distinct = new Set(vertices.map((v) => `${v.east_m}/${v.north_m}`));
|
|
9996
10029
|
if (first2.closed ? vertices.length < 4 || distinct.size < 3 || first2.east_m !== last2.east_m || first2.north_m !== last2.north_m : vertices.length < 2 || distinct.size < 2)
|
|
9997
10030
|
issue(
|
|
9998
10031
|
"RADAR.SITE_GEOMETRY",
|
|
9999
|
-
`/products/siteFeatures/${
|
|
10032
|
+
`/products/siteFeatures/${id26}`,
|
|
10000
10033
|
"Closed features need at least three distinct vertices and repeated endpoint; open features need at least two distinct vertices."
|
|
10001
10034
|
);
|
|
10002
10035
|
}
|
|
@@ -10362,12 +10395,12 @@ function sourceReader(layouts, assets2) {
|
|
|
10362
10395
|
throw new Error("Duplicate radar source layout.");
|
|
10363
10396
|
const map = new Map(layouts.map((l) => [l.productRef, l]));
|
|
10364
10397
|
return {
|
|
10365
|
-
table(
|
|
10366
|
-
if (!
|
|
10367
|
-
const layout = map.get(
|
|
10368
|
-
if (!layout || layout.kind !== "csv_table" || layout.partition || layout.sample || !
|
|
10398
|
+
table(ref18, columns, nullable = false) {
|
|
10399
|
+
if (!ref18) return [];
|
|
10400
|
+
const layout = map.get(ref18), bytes6 = assets2.get(ref18);
|
|
10401
|
+
if (!layout || layout.kind !== "csv_table" || layout.partition || layout.sample || !bytes6 || bytes6.byteLength !== layout.byteLength)
|
|
10369
10402
|
throw new Error("Missing or mismatched radar table.");
|
|
10370
|
-
const rows = readSourceCsv(
|
|
10403
|
+
const rows = readSourceCsv(bytes6), header = rows.shift();
|
|
10371
10404
|
if (JSON.stringify(header) !== JSON.stringify(columns) || JSON.stringify(layout.columns) !== JSON.stringify(columns) || rows.length !== layout.rowCount)
|
|
10372
10405
|
throw new Error("Invalid radar table columns or extent.");
|
|
10373
10406
|
return rows.map((row) => {
|
|
@@ -10403,17 +10436,17 @@ function sourceReader(layouts, assets2) {
|
|
|
10403
10436
|
);
|
|
10404
10437
|
});
|
|
10405
10438
|
},
|
|
10406
|
-
array(
|
|
10407
|
-
const layout = map.get(
|
|
10408
|
-
if (!layout || layout.kind !== "binary_array" || layout.elementType !== "float32" || layout.byteOrder !== "little" || !
|
|
10439
|
+
array(ref18) {
|
|
10440
|
+
const layout = map.get(ref18), bytes6 = assets2.get(ref18);
|
|
10441
|
+
if (!layout || layout.kind !== "binary_array" || layout.elementType !== "float32" || layout.byteOrder !== "little" || !bytes6 || bytes6.byteLength !== layout.byteLength || !Number.isSafeInteger(layout.byteOffset) || layout.byteOffset < 0)
|
|
10409
10442
|
throw new Error("Invalid radar array.");
|
|
10410
10443
|
const count = layout.axes.reduce((n, axis2) => n * axis2.length, 1);
|
|
10411
|
-
if (!Number.isSafeInteger(count) || layout.byteOffset + count * 4 !==
|
|
10444
|
+
if (!Number.isSafeInteger(count) || layout.byteOffset + count * 4 !== bytes6.byteLength)
|
|
10412
10445
|
throw new Error("Invalid radar array extent.");
|
|
10413
10446
|
const view = new DataView(
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10447
|
+
bytes6.buffer,
|
|
10448
|
+
bytes6.byteOffset,
|
|
10449
|
+
bytes6.byteLength
|
|
10417
10450
|
), values = [];
|
|
10418
10451
|
for (let i = 0; i < count; i++) {
|
|
10419
10452
|
const value = view.getFloat32(layout.byteOffset + i * 4, true);
|
|
@@ -10485,7 +10518,7 @@ var compareOffset2 = (origin, seconds, boundary) => {
|
|
|
10485
10518
|
return delta < 0n ? -1 : delta > 0n ? 1 : 0;
|
|
10486
10519
|
};
|
|
10487
10520
|
async function prepare(profile, observationInput, contextInput, selectionInput, options, result) {
|
|
10488
|
-
const issue = (code, pointer6,
|
|
10521
|
+
const issue = (code, pointer6, message2) => result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
10489
10522
|
const observation = parseExperimentalObservation(observationInput), context = parseAcquisitionContext(contextInput), selection = ProductSourceSelectionSchema.safeParse(selectionInput);
|
|
10490
10523
|
if (!observation.success || !context.success || !selection.success) {
|
|
10491
10524
|
result.checks.structure = "failed";
|
|
@@ -10551,8 +10584,8 @@ async function prepare(profile, observationInput, contextInput, selectionInput,
|
|
|
10551
10584
|
);
|
|
10552
10585
|
const within = (seconds) => validOrigin && Number.isFinite(seconds) && seconds >= 0 && acquisition?.time.state === "known" && acquisition.time.kind === "interval" && compareOffset2(profile.timeOrigin, seconds, acquisition.time.start) >= 0 && compareOffset2(profile.timeOrigin, seconds, acquisition.time.end) <= 0;
|
|
10553
10586
|
const layouts = new Map(sources.layouts.map((l) => [l.productRef, l]));
|
|
10554
|
-
for (const [role,
|
|
10555
|
-
if (
|
|
10587
|
+
for (const [role, ref18] of Object.entries(profile.products))
|
|
10588
|
+
if (ref18 && !layouts.has(ref18))
|
|
10556
10589
|
issue(
|
|
10557
10590
|
"RADAR.LAYOUT",
|
|
10558
10591
|
`/products/${role}`,
|
|
@@ -10580,8 +10613,8 @@ async function prepare(profile, observationInput, contextInput, selectionInput,
|
|
|
10580
10613
|
"/products",
|
|
10581
10614
|
"The input capture must be a retained raw product."
|
|
10582
10615
|
);
|
|
10583
|
-
const ancestors = (
|
|
10584
|
-
const found = /* @__PURE__ */ new Set(), queue = [
|
|
10616
|
+
const ancestors = (ref18) => {
|
|
10617
|
+
const found = /* @__PURE__ */ new Set(), queue = [ref18];
|
|
10585
10618
|
for (let i = 0; i < queue.length; i++) {
|
|
10586
10619
|
const current = queue[i];
|
|
10587
10620
|
if (found.has(current)) continue;
|
|
@@ -10627,13 +10660,13 @@ async function prepare(profile, observationInput, contextInput, selectionInput,
|
|
|
10627
10660
|
obs.sources.map((source) => [`source:${source.id}`, source.kind])
|
|
10628
10661
|
);
|
|
10629
10662
|
const forbidden = [...ancestors(profile.products.truth)].filter(
|
|
10630
|
-
(
|
|
10663
|
+
(ref18) => !shared.has(ref18) || sourceKinds.get(ref18) !== "document"
|
|
10631
10664
|
);
|
|
10632
10665
|
if ([
|
|
10633
10666
|
...derived.map((role) => roleProducts[role]),
|
|
10634
10667
|
captureRef,
|
|
10635
10668
|
sourceRole
|
|
10636
|
-
].some((
|
|
10669
|
+
].some((ref18) => forbidden.some((r) => ancestors(ref18).has(r))))
|
|
10637
10670
|
issue(
|
|
10638
10671
|
"RADAR.TRUTH_LEAK",
|
|
10639
10672
|
"/products/truth",
|
|
@@ -10645,9 +10678,9 @@ async function prepare(profile, observationInput, contextInput, selectionInput,
|
|
|
10645
10678
|
return;
|
|
10646
10679
|
}
|
|
10647
10680
|
const assets2 = new Map(
|
|
10648
|
-
[...options.assets ?? []].map(([
|
|
10649
|
-
|
|
10650
|
-
Uint8Array.from(
|
|
10681
|
+
[...options.assets ?? []].map(([ref18, bytes6]) => [
|
|
10682
|
+
ref18,
|
|
10683
|
+
Uint8Array.from(bytes6)
|
|
10651
10684
|
])
|
|
10652
10685
|
);
|
|
10653
10686
|
const checked = await evaluateProductSourceSelection(obs, sources, {
|
|
@@ -11217,15 +11250,15 @@ function readSonarProducts(profile, layouts, assets2) {
|
|
|
11217
11250
|
);
|
|
11218
11251
|
if (matches.length !== 1)
|
|
11219
11252
|
throw new Error(`Sonar ${role} requires one source layout.`);
|
|
11220
|
-
const layout = matches[0],
|
|
11221
|
-
if (layout.kind !== "binary_array" || layout.elementType !== (role === "amplitudes" ? "float32" : "uint8") || layout.byteOrder !== "little" || layout.order !== "row_major" || layout.byteOffset !== 0 || layout.quantity !== (role === "amplitudes" ? "normalized_echo_amplitude" : "receive_availability") || layout.unit !== "1" || !
|
|
11253
|
+
const layout = matches[0], bytes6 = assets2.get(layout.productRef), size = role === "amplitudes" ? 4 : 1;
|
|
11254
|
+
if (layout.kind !== "binary_array" || layout.elementType !== (role === "amplitudes" ? "float32" : "uint8") || layout.byteOrder !== "little" || layout.order !== "row_major" || layout.byteOffset !== 0 || layout.quantity !== (role === "amplitudes" ? "normalized_echo_amplitude" : "receive_availability") || layout.unit !== "1" || !bytes6 || bytes6.byteLength !== total * size || layout.byteLength !== bytes6.byteLength)
|
|
11222
11255
|
throw new Error(`Invalid sonar ${role} layout or retained bytes.`);
|
|
11223
11256
|
const [ping, delay] = layout.axes;
|
|
11224
11257
|
if (layout.axes.length !== 2 || !ping || ping.kind !== "time" || ping.name !== "ping" || ping.length !== s.pings || ping.start !== profile.timeOrigin || !Number.isSafeInteger(ping.stepSeconds.numerator) || ping.stepSeconds.numerator <= 0 || !Number.isSafeInteger(ping.stepSeconds.denominator) || ping.stepSeconds.denominator <= 0 || BigInt(ping.stepSeconds.numerator) * decimal3(s.pingStepSeconds).d !== decimal3(s.pingStepSeconds).n * BigInt(ping.stepSeconds.denominator) || !delay || delay.kind !== "regular" || delay.name !== "two_way_delay" || delay.unit !== "s" || delay.length !== s.delayBins || delay.origin !== s.delayStartSeconds || delay.step !== s.delayStepSeconds)
|
|
11225
11258
|
throw new Error(
|
|
11226
11259
|
`Sonar ${role} must use the declared ping time and two-way delay axes.`
|
|
11227
11260
|
);
|
|
11228
|
-
const view = new DataView(
|
|
11261
|
+
const view = new DataView(bytes6.buffer, bytes6.byteOffset, bytes6.byteLength);
|
|
11229
11262
|
decoded[role] = Array.from(
|
|
11230
11263
|
{ length: total },
|
|
11231
11264
|
(_, i) => role === "amplitudes" ? view.getFloat32(i * 4, true) : view.getUint8(i)
|
|
@@ -11233,7 +11266,7 @@ function readSonarProducts(profile, layouts, assets2) {
|
|
|
11233
11266
|
readProductSourceSelection(
|
|
11234
11267
|
layout,
|
|
11235
11268
|
{ kind: "array_element", indices: [s.pings - 1, s.delayBins - 1] },
|
|
11236
|
-
|
|
11269
|
+
bytes6
|
|
11237
11270
|
);
|
|
11238
11271
|
}
|
|
11239
11272
|
for (let i = 0; i < total; i++) {
|
|
@@ -11284,8 +11317,8 @@ async function evaluateSonarProfile(observationInput, contextInput, selectionInp
|
|
|
11284
11317
|
physicalCalibration: "not_checked",
|
|
11285
11318
|
propagationAccuracy: "not_checked"
|
|
11286
11319
|
};
|
|
11287
|
-
const issue = (code, pointer6,
|
|
11288
|
-
result.issues.push({ code, pointer: pointer6, message });
|
|
11320
|
+
const issue = (code, pointer6, message2) => {
|
|
11321
|
+
result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
11289
11322
|
};
|
|
11290
11323
|
const parsed = SonarProfileSchema.safeParse(profileInput), observation = parseExperimentalObservation(observationInput), context = parseAcquisitionContext(contextInput), selection = ProductSourceSelectionSchema.safeParse(selectionInput);
|
|
11291
11324
|
if (!parsed.success || !observation.success || !context.success || !selection.success) {
|
|
@@ -11391,9 +11424,9 @@ async function evaluateSonarProfile(observationInput, contextInput, selectionInp
|
|
|
11391
11424
|
return result;
|
|
11392
11425
|
}
|
|
11393
11426
|
const assets2 = new Map(
|
|
11394
|
-
[...options.assets ?? []].map(([
|
|
11395
|
-
|
|
11396
|
-
Uint8Array.from(
|
|
11427
|
+
[...options.assets ?? []].map(([ref18, bytes6]) => [
|
|
11428
|
+
ref18,
|
|
11429
|
+
Uint8Array.from(bytes6)
|
|
11397
11430
|
])
|
|
11398
11431
|
);
|
|
11399
11432
|
const sourceResult = await evaluateProductSourceSelection(obs, sources, {
|
|
@@ -11635,7 +11668,7 @@ function readPassiveSonarProducts(p, layouts, assets2) {
|
|
|
11635
11668
|
const matches = layouts.filter((l) => l.productRef === p.products[role]);
|
|
11636
11669
|
if (matches.length !== 1)
|
|
11637
11670
|
throw new Error(`Passive sonar ${role} requires one source layout.`);
|
|
11638
|
-
const layout = matches[0],
|
|
11671
|
+
const layout = matches[0], bytes6 = assets2.get(layout.productRef), mask = role === "sampleMask" || role === "frameMask", waveform = role === "pressure" || role === "sampleMask";
|
|
11639
11672
|
const length = waveform ? s.samples : role === "frameMask" ? frames : frames * bins, size = mask ? 1 : 4;
|
|
11640
11673
|
const quantity = {
|
|
11641
11674
|
pressure: "sound_pressure",
|
|
@@ -11649,14 +11682,14 @@ function readPassiveSonarProducts(p, layouts, assets2) {
|
|
|
11649
11682
|
powerSpectralDensity: "Pa^2/Hz",
|
|
11650
11683
|
frameMask: "1"
|
|
11651
11684
|
}[role];
|
|
11652
|
-
if (layout.kind !== "binary_array" || layout.elementType !== (mask ? "uint8" : "float32") || layout.byteOrder !== "little" || layout.order !== "row_major" || layout.byteOffset !== 0 || layout.quantity !== quantity || layout.unit !== unit || !
|
|
11685
|
+
if (layout.kind !== "binary_array" || layout.elementType !== (mask ? "uint8" : "float32") || layout.byteOrder !== "little" || layout.order !== "row_major" || layout.byteOffset !== 0 || layout.quantity !== quantity || layout.unit !== unit || !bytes6 || bytes6.byteLength !== length * size || layout.byteLength !== bytes6.byteLength)
|
|
11653
11686
|
throw new Error(`Invalid passive sonar ${role} layout or bytes.`);
|
|
11654
11687
|
const axis2 = layout.axes[0], frequency = layout.axes[1], numerator = waveform ? 1 : t.hopSamples;
|
|
11655
11688
|
if (!axis2 || axis2.kind !== "time" || axis2.name !== (waveform ? "sample" : "window_start") || axis2.length !== (waveform ? s.samples : frames) || axis2.start !== p.timeOrigin || !Number.isSafeInteger(axis2.stepSeconds.numerator) || axis2.stepSeconds.numerator <= 0 || !Number.isSafeInteger(axis2.stepSeconds.denominator) || axis2.stepSeconds.denominator <= 0 || BigInt(axis2.stepSeconds.numerator) * BigInt(s.sampleRateHz) !== BigInt(numerator) * BigInt(axis2.stepSeconds.denominator) || layout.axes.length !== (role === "powerSpectralDensity" ? 2 : 1))
|
|
11656
11689
|
throw new Error(`Invalid passive sonar ${role} time axis.`);
|
|
11657
11690
|
if (role === "powerSpectralDensity" && (!frequency || frequency.kind !== "regular" || frequency.name !== "frequency" || frequency.unit !== "Hz" || frequency.length !== bins || frequency.origin !== 0 || frequency.step !== s.sampleRateHz / t.windowSamples))
|
|
11658
11691
|
throw new Error("Invalid passive sonar frequency axis.");
|
|
11659
|
-
const view = new DataView(
|
|
11692
|
+
const view = new DataView(bytes6.buffer, bytes6.byteOffset, bytes6.byteLength);
|
|
11660
11693
|
decoded[role] = Array.from(
|
|
11661
11694
|
{ length },
|
|
11662
11695
|
(_, i) => mask ? view.getUint8(i) : view.getFloat32(i * 4, true)
|
|
@@ -11667,7 +11700,7 @@ function readPassiveSonarProducts(p, layouts, assets2) {
|
|
|
11667
11700
|
kind: "array_element",
|
|
11668
11701
|
indices: role === "powerSpectralDensity" ? [frames - 1, bins - 1] : [length - 1]
|
|
11669
11702
|
},
|
|
11670
|
-
|
|
11703
|
+
bytes6
|
|
11671
11704
|
);
|
|
11672
11705
|
}
|
|
11673
11706
|
for (let sample = 0; sample < s.samples; sample++) {
|
|
@@ -11726,7 +11759,7 @@ async function evaluatePassiveSonarProfile(observationInput, contextInput, selec
|
|
|
11726
11759
|
physicalCalibration: "not_checked",
|
|
11727
11760
|
localization: "not_checked"
|
|
11728
11761
|
};
|
|
11729
|
-
const issue = (code, pointer6,
|
|
11762
|
+
const issue = (code, pointer6, message2) => result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
11730
11763
|
const parsed = PassiveSonarProfileSchema.safeParse(profileInput), observation = parseExperimentalObservation(observationInput), context = parseAcquisitionContext(contextInput), selection = ProductSourceSelectionSchema.safeParse(selectionInput);
|
|
11731
11764
|
if (!parsed.success || !observation.success || !context.success || !selection.success) {
|
|
11732
11765
|
result.checks.structure = "failed";
|
|
@@ -11832,9 +11865,9 @@ async function evaluatePassiveSonarProfile(observationInput, contextInput, selec
|
|
|
11832
11865
|
return result;
|
|
11833
11866
|
}
|
|
11834
11867
|
const assets2 = new Map(
|
|
11835
|
-
[...options.assets ?? []].map(([
|
|
11836
|
-
|
|
11837
|
-
Uint8Array.from(
|
|
11868
|
+
[...options.assets ?? []].map(([ref18, bytes6]) => [
|
|
11869
|
+
ref18,
|
|
11870
|
+
Uint8Array.from(bytes6)
|
|
11838
11871
|
])
|
|
11839
11872
|
);
|
|
11840
11873
|
const sourceResult = await evaluateProductSourceSelection(obs, sources, {
|
|
@@ -11986,40 +12019,40 @@ function validateLidarDeclaration(p) {
|
|
|
11986
12019
|
if (p.mode !== "static_discrete_return_raster" || f.kind !== "local_cartesian" || f.unit !== "m" || f.handedness !== "right_handed" || f.georeferencing !== "not_provided" || f.axes.join(",") !== "east,north,up" || !f.originDescription.trim() || f.sensorOrigin.length !== 3 || !f.sensorOrigin.every(finite4) || !integer3(s.rows, 1, 4096) || !integer3(s.columns, 1, 4096) || !integer3(s.pulses, 1, 65536) || s.rows * s.columns !== s.pulses || !integer3(s.points, 0, 983040) || s.points > s.pulses * 15 || s.order !== "row_major_index_not_time" || s.aim !== "direction_reference_not_surface_hit" || !finite4(g.nearRangeM) || !finite4(g.farRangeM) || g.nearRangeM <= 0 || g.farRangeM <= g.nearRangeM || !Number.isFinite(g.rayToleranceM) || g.rayToleranceM <= 0 || g.rayToleranceM > 0.1 || g.toleranceMeaning !== "encoding_consistency_not_measurement_uncertainty" || g.bounds.min.length !== 3 || g.bounds.max.length !== 3 || !g.bounds.min.every(finite4) || !g.bounds.max.every(finite4) || g.bounds.min.some((v, i) => v >= g.bounds.max[i]) || p.intensity.kind !== "normalized_return_amplitude" || p.intensity.min !== 0 || p.intensity.max !== 1 || p.intensity.calibration !== "not_calibrated_to_reflectance" || !["authored_annotations", "source_annotations"].includes(c.authority) || !c.method.trim() || !c.classes.length || c.classes.length > 256 || new Set(c.classes.map((v) => v.code)).size !== c.classes.length || c.classes.some((v) => !integer3(v.code, 0, 255) || !v.label.trim()) || p.availability.retained !== "complete_return_group" || p.availability.noReturn !== "zero_detected_returns_not_clear_space" || p.availability.unavailable !== "unknown_return_count_empty_cell" || p.availability.noTiming !== "no_per_pulse_timestamps" || new Set(Object.values(p.products)).size !== 2)
|
|
11987
12020
|
throw new Error("Invalid static lidar declaration.");
|
|
11988
12021
|
}
|
|
11989
|
-
function rowSpans(
|
|
12022
|
+
function rowSpans(bytes6) {
|
|
11990
12023
|
const spans = [];
|
|
11991
12024
|
let start = 0, quoted = false;
|
|
11992
|
-
for (let i = 0; i <
|
|
11993
|
-
if (
|
|
11994
|
-
if (quoted &&
|
|
12025
|
+
for (let i = 0; i < bytes6.length; i++) {
|
|
12026
|
+
if (bytes6[i] === 34) {
|
|
12027
|
+
if (quoted && bytes6[i + 1] === 34) i++;
|
|
11995
12028
|
else quoted = !quoted;
|
|
11996
|
-
} else if (!quoted && (
|
|
12029
|
+
} else if (!quoted && (bytes6[i] === 10 || bytes6[i] === 13)) {
|
|
11997
12030
|
spans.push({ byteOffset: start, byteLength: i - start });
|
|
11998
|
-
if (
|
|
12031
|
+
if (bytes6[i] === 13 && bytes6[i + 1] === 10) i++;
|
|
11999
12032
|
start = i + 1;
|
|
12000
12033
|
}
|
|
12001
12034
|
}
|
|
12002
|
-
if (start <
|
|
12003
|
-
spans.push({ byteOffset: start, byteLength:
|
|
12035
|
+
if (start < bytes6.length)
|
|
12036
|
+
spans.push({ byteOffset: start, byteLength: bytes6.length - start });
|
|
12004
12037
|
return spans.slice(1);
|
|
12005
12038
|
}
|
|
12006
|
-
function table(layouts, assets2,
|
|
12007
|
-
const matches = layouts.filter((l) => l.productRef ===
|
|
12008
|
-
const layout = matches[0],
|
|
12009
|
-
if (matches.length !== 1 || !layout || layout.kind !== "csv_table" || layout.mediaType !== "text/csv" || layout.encoding !== "utf-8" || layout.delimiter !== "," || layout.header !== true || layout.partition || layout.sample || layout.rowCount !== count || layout.columns.join(",") !== columns.join(",") || !
|
|
12010
|
-
throw new Error(`Invalid or absent lidar table ${
|
|
12011
|
-
const rows = readSourceCsv(
|
|
12039
|
+
function table(layouts, assets2, ref18, columns, count) {
|
|
12040
|
+
const matches = layouts.filter((l) => l.productRef === ref18);
|
|
12041
|
+
const layout = matches[0], bytes6 = assets2.get(ref18);
|
|
12042
|
+
if (matches.length !== 1 || !layout || layout.kind !== "csv_table" || layout.mediaType !== "text/csv" || layout.encoding !== "utf-8" || layout.delimiter !== "," || layout.header !== true || layout.partition || layout.sample || layout.rowCount !== count || layout.columns.join(",") !== columns.join(",") || !bytes6 || bytes6.byteLength !== layout.byteLength)
|
|
12043
|
+
throw new Error(`Invalid or absent lidar table ${ref18}.`);
|
|
12044
|
+
const rows = readSourceCsv(bytes6), header = rows.shift();
|
|
12012
12045
|
if (header?.join(",") !== columns.join(",") || rows.length !== count || rows.some((r) => r.length !== columns.length))
|
|
12013
|
-
throw new Error(`Unexpected lidar table rows or header ${
|
|
12014
|
-
const spans = rowSpans(
|
|
12046
|
+
throw new Error(`Unexpected lidar table rows or header ${ref18}.`);
|
|
12047
|
+
const spans = rowSpans(bytes6);
|
|
12015
12048
|
if (spans.length !== count)
|
|
12016
12049
|
throw new Error("CSV source row offsets are inconsistent.");
|
|
12017
12050
|
return { rows, spans };
|
|
12018
12051
|
}
|
|
12019
|
-
var number = (
|
|
12020
|
-
if (!/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?(?![\s\S])/.test(
|
|
12052
|
+
var number = (text21) => {
|
|
12053
|
+
if (!/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?(?![\s\S])/.test(text21))
|
|
12021
12054
|
throw new Error("Lidar numeric cell is empty or malformed.");
|
|
12022
|
-
const value = Number(
|
|
12055
|
+
const value = Number(text21);
|
|
12023
12056
|
if (!finite4(value))
|
|
12024
12057
|
throw new Error("Lidar numeric value is not finite or exceeds bounds.");
|
|
12025
12058
|
return value;
|
|
@@ -12042,19 +12075,19 @@ function readLidarProducts(p, layouts, assets2) {
|
|
|
12042
12075
|
const pulseMap = /* @__PURE__ */ new Map(), origin = p.coordinateFrame.sensorOrigin;
|
|
12043
12076
|
const inside = (v, i) => v >= p.geometry.bounds.min[i] && v <= p.geometry.bounds.max[i];
|
|
12044
12077
|
const pulses = a.rows.map((cells, index3) => {
|
|
12045
|
-
const [
|
|
12046
|
-
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/.test(
|
|
12078
|
+
const [id26, row, column, x, y, z32, status, count] = cells;
|
|
12079
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/.test(id26) || pulseMap.has(id26))
|
|
12047
12080
|
throw new Error("Duplicate or invalid pulse identifier.");
|
|
12048
|
-
const scanRow = number(row), scanColumn = number(column), aim = [number(x), number(y), number(
|
|
12081
|
+
const scanRow = number(row), scanColumn = number(column), aim = [number(x), number(y), number(z32)];
|
|
12049
12082
|
const returnCount = count === "" ? null : number(count);
|
|
12050
12083
|
if (scanRow !== Math.floor(index3 / p.scan.columns) || scanColumn !== index3 % p.scan.columns || !aim.every(inside) || Math.hypot(...aim.map((v, i) => v - origin[i])) < p.geometry.nearRangeM)
|
|
12051
12084
|
throw new Error("Pulse grid or aim reference is inconsistent.");
|
|
12052
12085
|
if (!["retained", "no_return", "unavailable"].includes(status) || status === "retained" && (returnCount === null || !integer3(returnCount, 1, 15)) || status === "no_return" && returnCount !== 0 || status === "unavailable" && returnCount !== null)
|
|
12053
12086
|
throw new Error("Pulse status and return count are inconsistent.");
|
|
12054
|
-
pulseMap.set(
|
|
12087
|
+
pulseMap.set(id26, index3);
|
|
12055
12088
|
return {
|
|
12056
12089
|
index: index3,
|
|
12057
|
-
id:
|
|
12090
|
+
id: id26,
|
|
12058
12091
|
scanRow,
|
|
12059
12092
|
scanColumn,
|
|
12060
12093
|
aim,
|
|
@@ -12070,12 +12103,12 @@ function readLidarProducts(p, layouts, assets2) {
|
|
|
12070
12103
|
const pulseIndex = pulseMap.get(pulseId), pulse = pulseIndex === void 0 ? void 0 : pulses[pulseIndex];
|
|
12071
12104
|
if (pulseIndex === void 0 || !pulse || pulse.status !== "retained")
|
|
12072
12105
|
throw new Error("Point does not belong to a retained pulse.");
|
|
12073
|
-
const returnNumber = number(n), returnCount = number(count), x = number(xs), y = number(ys),
|
|
12074
|
-
if (!integer3(returnNumber, 1, 15) || returnCount !== pulse.returnCount || returnNumber !== pulse.pointIndices.length + 1 || intensity < 0 || intensity > 1 || !classes.has(classCode) || ![x, y,
|
|
12106
|
+
const returnNumber = number(n), returnCount = number(count), x = number(xs), y = number(ys), z32 = number(zs), intensity = number(amplitude), classCode = number(classification);
|
|
12107
|
+
if (!integer3(returnNumber, 1, 15) || returnCount !== pulse.returnCount || returnNumber !== pulse.pointIndices.length + 1 || intensity < 0 || intensity > 1 || !classes.has(classCode) || ![x, y, z32].every(inside))
|
|
12075
12108
|
throw new Error(
|
|
12076
12109
|
"Invalid lidar return group, class, intensity or coordinate."
|
|
12077
12110
|
);
|
|
12078
|
-
const d = [x - origin[0], y - origin[1],
|
|
12111
|
+
const d = [x - origin[0], y - origin[1], z32 - origin[2]], direction = pulse.aim.map((v, i) => v - origin[i]), norm = Math.hypot(...direction), rangeM = Math.hypot(...d), along = d.reduce((sum, v, i) => sum + v * direction[i] / norm, 0), residual = Math.hypot(
|
|
12079
12112
|
...d.map((v, i) => v - along * direction[i] / norm)
|
|
12080
12113
|
);
|
|
12081
12114
|
if (rangeM < p.geometry.nearRangeM || rangeM > p.geometry.farRangeM || along <= 0 || residual > p.geometry.rayToleranceM)
|
|
@@ -12089,7 +12122,7 @@ function readLidarProducts(p, layouts, assets2) {
|
|
|
12089
12122
|
returnCount,
|
|
12090
12123
|
x,
|
|
12091
12124
|
y,
|
|
12092
|
-
z:
|
|
12125
|
+
z: z32,
|
|
12093
12126
|
intensity,
|
|
12094
12127
|
classCode,
|
|
12095
12128
|
rangeM,
|
|
@@ -12120,7 +12153,7 @@ async function evaluateLidarProfile(observationInput, contextInput, selectionInp
|
|
|
12120
12153
|
classificationAccuracy: "not_checked",
|
|
12121
12154
|
georeferencing: "not_checked"
|
|
12122
12155
|
};
|
|
12123
|
-
const issue = (code, pointer6,
|
|
12156
|
+
const issue = (code, pointer6, message2) => result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
12124
12157
|
const parsed = LidarProfileSchema.safeParse(profileInput), observation = parseExperimentalObservation(observationInput), context = parseAcquisitionContext(contextInput), selection = ProductSourceSelectionSchema.safeParse(selectionInput);
|
|
12125
12158
|
if (!parsed.success || !observation.success || !context.success || !selection.success) {
|
|
12126
12159
|
result.checks.structure = "failed";
|
|
@@ -12184,9 +12217,9 @@ async function evaluateLidarProfile(observationInput, contextInput, selectionInp
|
|
|
12184
12217
|
return result;
|
|
12185
12218
|
}
|
|
12186
12219
|
const assets2 = new Map(
|
|
12187
|
-
[...options.assets ?? []].map(([
|
|
12188
|
-
|
|
12189
|
-
Uint8Array.from(
|
|
12220
|
+
[...options.assets ?? []].map(([ref18, bytes6]) => [
|
|
12221
|
+
ref18,
|
|
12222
|
+
Uint8Array.from(bytes6)
|
|
12190
12223
|
])
|
|
12191
12224
|
);
|
|
12192
12225
|
const sourceResult = await evaluateProductSourceSelection(obs, sources, {
|
|
@@ -12355,13 +12388,13 @@ function satelliteCellBounds(p, row, column) {
|
|
|
12355
12388
|
};
|
|
12356
12389
|
}
|
|
12357
12390
|
function array(p, layouts, assets2, role) {
|
|
12358
|
-
const matches = layouts.filter((v) => v.productRef === p.products[role]), layout = matches[0],
|
|
12391
|
+
const matches = layouts.filter((v) => v.productRef === p.products[role]), layout = matches[0], bytes6 = assets2.get(p.products[role]);
|
|
12359
12392
|
const cube = role === "reflectance", lengths = cube ? [p.bands.length, p.grid.rows, p.grid.columns] : [p.grid.rows, p.grid.columns], names = cube ? ["band", "row", "column"] : ["row", "column"];
|
|
12360
12393
|
if (matches.length !== 1 || !layout || layout.kind !== "binary_array" || layout.elementType !== (cube ? "uint16" : "uint8") || layout.byteOrder !== "little" || layout.order !== "row_major" || layout.byteOffset !== 0 || layout.mediaType !== "application/octet-stream" || layout.quantity !== (cube ? "surface_reflectance_dn" : "pixel_quality_code") || layout.unit !== (cube ? "DN" : "code") || layout.axes.length !== lengths.length || layout.axes.some(
|
|
12361
12394
|
(a, i) => a.kind !== "index" || a.name !== names[i] || a.length !== lengths[i] || a.firstIndex !== 0
|
|
12362
|
-
) || layout.byteLength !== lengths.reduce((a, b) => a * b, 1) * (cube ? 2 : 1) || !
|
|
12395
|
+
) || layout.byteLength !== lengths.reduce((a, b) => a * b, 1) * (cube ? 2 : 1) || !bytes6 || bytes6.byteLength !== layout.byteLength)
|
|
12363
12396
|
throw new Error(`Invalid or absent satellite ${role} array.`);
|
|
12364
|
-
return { layout, bytes:
|
|
12397
|
+
return { layout, bytes: bytes6 };
|
|
12365
12398
|
}
|
|
12366
12399
|
function readSatelliteRasterProducts(p, layouts, assets2) {
|
|
12367
12400
|
validateSatelliteRasterDeclaration(p);
|
|
@@ -12441,7 +12474,7 @@ async function evaluateSatelliteRasterProfile(observationInput, contextInput, se
|
|
|
12441
12474
|
qualityAccuracy: "not_checked",
|
|
12442
12475
|
georeferencing: "not_checked"
|
|
12443
12476
|
};
|
|
12444
|
-
const issue = (code, pointer6,
|
|
12477
|
+
const issue = (code, pointer6, message2) => result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
12445
12478
|
const parsed = SatelliteRasterProfileSchema.safeParse(profileInput), observation = parseExperimentalObservation(observationInput), context = parseAcquisitionContext(contextInput), selection = ProductSourceSelectionSchema.safeParse(selectionInput);
|
|
12446
12479
|
if (!parsed.success || !observation.success || !context.success || !selection.success) {
|
|
12447
12480
|
result.checks.structure = "failed";
|
|
@@ -12511,9 +12544,9 @@ async function evaluateSatelliteRasterProfile(observationInput, contextInput, se
|
|
|
12511
12544
|
return result;
|
|
12512
12545
|
}
|
|
12513
12546
|
const assets2 = new Map(
|
|
12514
|
-
[...options.assets ?? []].map(([
|
|
12515
|
-
|
|
12516
|
-
Uint8Array.from(
|
|
12547
|
+
[...options.assets ?? []].map(([ref18, bytes6]) => [
|
|
12548
|
+
ref18,
|
|
12549
|
+
Uint8Array.from(bytes6)
|
|
12517
12550
|
])
|
|
12518
12551
|
);
|
|
12519
12552
|
const sourceResult = await evaluateProductSourceSelection(obs, sources, {
|
|
@@ -12551,37 +12584,37 @@ var VOCABULARY_BINDINGS_PROFILE = "urn:disclosureos:profile:vocabulary-reference
|
|
|
12551
12584
|
var key2 = (r) => JSON.stringify([r.schemaId, r.documentId, r.sha256]);
|
|
12552
12585
|
var termKey = (t) => JSON.stringify([t.catalogId, t.revision, key2(t.document), t.termId]);
|
|
12553
12586
|
var claimKey = (b) => JSON.stringify([key2(b.claim.document), b.claim.claimId]);
|
|
12554
|
-
var digest9 = async (
|
|
12587
|
+
var digest9 = async (bytes6) => Array.from(
|
|
12555
12588
|
new Uint8Array(
|
|
12556
|
-
await crypto.subtle.digest("SHA-256", Uint8Array.from(
|
|
12589
|
+
await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes6))
|
|
12557
12590
|
)
|
|
12558
12591
|
).map((n) => n.toString(16).padStart(2, "0")).join("");
|
|
12559
|
-
function decode9(
|
|
12560
|
-
const
|
|
12561
|
-
const parsed = JSON.parse(
|
|
12592
|
+
function decode9(bytes6) {
|
|
12593
|
+
const text21 = new TextDecoder("utf-8", { fatal: true }).decode(bytes6);
|
|
12594
|
+
const parsed = JSON.parse(text21);
|
|
12562
12595
|
let index3 = 0;
|
|
12563
12596
|
const ws = () => {
|
|
12564
|
-
while (/\s/.test(
|
|
12597
|
+
while (/\s/.test(text21[index3] ?? "") && index3 < text21.length) index3++;
|
|
12565
12598
|
};
|
|
12566
12599
|
function string() {
|
|
12567
12600
|
const start = index3++;
|
|
12568
|
-
while (index3 <
|
|
12569
|
-
if (
|
|
12570
|
-
if (
|
|
12601
|
+
while (index3 < text21.length) {
|
|
12602
|
+
if (text21[index3++] === '"') break;
|
|
12603
|
+
if (text21[index3 - 1] === "\\") index3++;
|
|
12571
12604
|
}
|
|
12572
|
-
return JSON.parse(
|
|
12605
|
+
return JSON.parse(text21.slice(start, index3));
|
|
12573
12606
|
}
|
|
12574
12607
|
function value() {
|
|
12575
12608
|
ws();
|
|
12576
|
-
if (
|
|
12609
|
+
if (text21[index3] === '"') {
|
|
12577
12610
|
string();
|
|
12578
12611
|
return;
|
|
12579
12612
|
}
|
|
12580
|
-
if (
|
|
12613
|
+
if (text21[index3] === "{") {
|
|
12581
12614
|
index3++;
|
|
12582
12615
|
ws();
|
|
12583
12616
|
const keys = /* @__PURE__ */ new Set();
|
|
12584
|
-
if (
|
|
12617
|
+
if (text21[index3] !== "}")
|
|
12585
12618
|
for (; ; ) {
|
|
12586
12619
|
ws();
|
|
12587
12620
|
const name = string();
|
|
@@ -12591,26 +12624,26 @@ function decode9(bytes5) {
|
|
|
12591
12624
|
index3++;
|
|
12592
12625
|
value();
|
|
12593
12626
|
ws();
|
|
12594
|
-
if (
|
|
12627
|
+
if (text21[index3] !== ",") break;
|
|
12595
12628
|
index3++;
|
|
12596
12629
|
}
|
|
12597
12630
|
index3++;
|
|
12598
12631
|
return;
|
|
12599
12632
|
}
|
|
12600
|
-
if (
|
|
12633
|
+
if (text21[index3] === "[") {
|
|
12601
12634
|
index3++;
|
|
12602
12635
|
ws();
|
|
12603
|
-
if (
|
|
12636
|
+
if (text21[index3] !== "]")
|
|
12604
12637
|
for (; ; ) {
|
|
12605
12638
|
value();
|
|
12606
12639
|
ws();
|
|
12607
|
-
if (
|
|
12640
|
+
if (text21[index3] !== ",") break;
|
|
12608
12641
|
index3++;
|
|
12609
12642
|
}
|
|
12610
12643
|
index3++;
|
|
12611
12644
|
return;
|
|
12612
12645
|
}
|
|
12613
|
-
while (index3 <
|
|
12646
|
+
while (index3 < text21.length && !/[\s,}\]]/.test(text21[index3])) index3++;
|
|
12614
12647
|
}
|
|
12615
12648
|
value();
|
|
12616
12649
|
return parsed;
|
|
@@ -12632,9 +12665,9 @@ var reviews = {
|
|
|
12632
12665
|
};
|
|
12633
12666
|
async function evaluateVocabularyBindings(input, options) {
|
|
12634
12667
|
const documents = new Map(
|
|
12635
|
-
[...options.documents].map(([
|
|
12636
|
-
|
|
12637
|
-
Uint8Array.from(
|
|
12668
|
+
[...options.documents].map(([hash8, bytes6]) => [
|
|
12669
|
+
hash8,
|
|
12670
|
+
Uint8Array.from(bytes6)
|
|
12638
12671
|
])
|
|
12639
12672
|
);
|
|
12640
12673
|
const parsed = [input, ...options.additionalBindings ?? []].map(
|
|
@@ -12657,8 +12690,8 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12657
12690
|
scientificValidity: "not_checked",
|
|
12658
12691
|
authenticity: "not_checked"
|
|
12659
12692
|
};
|
|
12660
|
-
const problem = (code, pointer6,
|
|
12661
|
-
result.issues.push({ code, pointer: pointer6, message, stage: "profile", status });
|
|
12693
|
+
const problem = (code, pointer6, message2, status = "failed") => {
|
|
12694
|
+
result.issues.push({ code, pointer: pointer6, message: message2, stage: "profile", status });
|
|
12662
12695
|
};
|
|
12663
12696
|
const bindingsDocs = [], seenDocs = /* @__PURE__ */ new Map();
|
|
12664
12697
|
for (const [i, p] of parsed.entries()) {
|
|
@@ -12688,19 +12721,19 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12688
12721
|
const snapshots = /* @__PURE__ */ new Map();
|
|
12689
12722
|
const loaded = /* @__PURE__ */ new Map(), resolvedHistories = /* @__PURE__ */ new Map(), resolvedCatalogs = /* @__PURE__ */ new Map();
|
|
12690
12723
|
const catalogRevisions = /* @__PURE__ */ new Map();
|
|
12691
|
-
function registerCatalog(catalog2,
|
|
12724
|
+
function registerCatalog(catalog2, ref18, pointer6) {
|
|
12692
12725
|
const identity = JSON.stringify([catalog2.catalogId, catalog2.revision]), prior = catalogRevisions.get(identity);
|
|
12693
|
-
if (prior && prior !== key2(
|
|
12726
|
+
if (prior && prior !== key2(ref18))
|
|
12694
12727
|
problem(
|
|
12695
12728
|
"VOCABULARY.REVISION_CONFLICT",
|
|
12696
12729
|
pointer6,
|
|
12697
12730
|
"One catalog revision identifies different supplied snapshots."
|
|
12698
12731
|
);
|
|
12699
|
-
catalogRevisions.set(identity, key2(
|
|
12732
|
+
catalogRevisions.set(identity, key2(ref18));
|
|
12700
12733
|
}
|
|
12701
|
-
for (const [
|
|
12734
|
+
for (const [hash8, bytes6] of documents) {
|
|
12702
12735
|
try {
|
|
12703
|
-
const raw = decode9(
|
|
12736
|
+
const raw = decode9(bytes6);
|
|
12704
12737
|
if (typeof raw === "object" && raw !== null && "kind" in raw && raw.kind === "vocabulary_catalog") {
|
|
12705
12738
|
const catalog2 = parseVocabularyCatalog(raw);
|
|
12706
12739
|
if (catalog2.success)
|
|
@@ -12709,32 +12742,32 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12709
12742
|
{
|
|
12710
12743
|
documentId: catalog2.data.id,
|
|
12711
12744
|
schemaId: VOCABULARY_CATALOG_SCHEMA_ID,
|
|
12712
|
-
sha256: await digest9(
|
|
12745
|
+
sha256: await digest9(bytes6)
|
|
12713
12746
|
},
|
|
12714
|
-
`/documents/${
|
|
12747
|
+
`/documents/${hash8}`
|
|
12715
12748
|
);
|
|
12716
12749
|
}
|
|
12717
12750
|
} catch {
|
|
12718
12751
|
}
|
|
12719
12752
|
}
|
|
12720
|
-
async function load(
|
|
12721
|
-
const k = key2(
|
|
12753
|
+
async function load(ref18, pointer6) {
|
|
12754
|
+
const k = key2(ref18);
|
|
12722
12755
|
if (snapshots.has(k)) return loaded.get(k);
|
|
12723
|
-
const snapshot3 = { ...
|
|
12756
|
+
const snapshot3 = { ...ref18, status: "not_checked" };
|
|
12724
12757
|
snapshots.set(k, snapshot3);
|
|
12725
|
-
const
|
|
12726
|
-
if (!
|
|
12758
|
+
const bytes6 = documents.get(ref18.sha256);
|
|
12759
|
+
if (!bytes6) {
|
|
12727
12760
|
problem(
|
|
12728
12761
|
"SNAPSHOT.UNAVAILABLE",
|
|
12729
12762
|
pointer6,
|
|
12730
12763
|
"Required snapshot bytes were not supplied.",
|
|
12731
12764
|
"not_checked"
|
|
12732
12765
|
);
|
|
12733
|
-
result.unresolvedReferences.push(
|
|
12766
|
+
result.unresolvedReferences.push(ref18);
|
|
12734
12767
|
return;
|
|
12735
12768
|
}
|
|
12736
12769
|
snapshot3.status = "failed";
|
|
12737
|
-
if (await digest9(
|
|
12770
|
+
if (await digest9(bytes6) !== ref18.sha256) {
|
|
12738
12771
|
problem(
|
|
12739
12772
|
"SNAPSHOT.DIGEST",
|
|
12740
12773
|
pointer6,
|
|
@@ -12743,8 +12776,8 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12743
12776
|
return;
|
|
12744
12777
|
}
|
|
12745
12778
|
try {
|
|
12746
|
-
const data = decode9(
|
|
12747
|
-
if (typeof data !== "object" || data === null || !("id" in data) || data.id !==
|
|
12779
|
+
const data = decode9(bytes6);
|
|
12780
|
+
if (typeof data !== "object" || data === null || !("id" in data) || data.id !== ref18.documentId) {
|
|
12748
12781
|
problem(
|
|
12749
12782
|
"SNAPSHOT.IDENTITY",
|
|
12750
12783
|
pointer6,
|
|
@@ -12762,9 +12795,9 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12762
12795
|
);
|
|
12763
12796
|
}
|
|
12764
12797
|
}
|
|
12765
|
-
async function catalog(
|
|
12766
|
-
const k = key2(
|
|
12767
|
-
if (Object.prototype.hasOwnProperty.call(histories,
|
|
12798
|
+
async function catalog(ref18, pointer6) {
|
|
12799
|
+
const k = key2(ref18.document);
|
|
12800
|
+
if (Object.prototype.hasOwnProperty.call(histories, ref18.document.schemaId)) {
|
|
12768
12801
|
problem(
|
|
12769
12802
|
"SNAPSHOT.CONTRACT",
|
|
12770
12803
|
pointer6,
|
|
@@ -12773,13 +12806,13 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12773
12806
|
return;
|
|
12774
12807
|
}
|
|
12775
12808
|
if (!snapshots.has(k)) {
|
|
12776
|
-
const raw = await load(
|
|
12809
|
+
const raw = await load(ref18.document, pointer6);
|
|
12777
12810
|
if (raw !== void 0) {
|
|
12778
12811
|
const snapshot3 = snapshots.get(k);
|
|
12779
|
-
if (
|
|
12812
|
+
if (ref18.document.schemaId !== VOCABULARY_CATALOG_SCHEMA_ID) {
|
|
12780
12813
|
if (Object.prototype.hasOwnProperty.call(
|
|
12781
12814
|
histories,
|
|
12782
|
-
|
|
12815
|
+
ref18.document.schemaId
|
|
12783
12816
|
))
|
|
12784
12817
|
problem(
|
|
12785
12818
|
"SNAPSHOT.CONTRACT",
|
|
@@ -12794,7 +12827,7 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12794
12827
|
"The declared catalog contract is not supported.",
|
|
12795
12828
|
"not_checked"
|
|
12796
12829
|
);
|
|
12797
|
-
result.unresolvedReferences.push(
|
|
12830
|
+
result.unresolvedReferences.push(ref18.document);
|
|
12798
12831
|
}
|
|
12799
12832
|
} else {
|
|
12800
12833
|
const p = parseVocabularyCatalog(raw);
|
|
@@ -12807,14 +12840,14 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12807
12840
|
else {
|
|
12808
12841
|
snapshot3.status = "passed";
|
|
12809
12842
|
resolvedCatalogs.set(k, p.data);
|
|
12810
|
-
registerCatalog(p.data,
|
|
12843
|
+
registerCatalog(p.data, ref18.document, pointer6);
|
|
12811
12844
|
}
|
|
12812
12845
|
}
|
|
12813
12846
|
}
|
|
12814
12847
|
}
|
|
12815
12848
|
const data = resolvedCatalogs.get(k);
|
|
12816
12849
|
if (!data) return;
|
|
12817
|
-
if (data.catalogId !==
|
|
12850
|
+
if (data.catalogId !== ref18.catalogId || data.revision !== ref18.revision) {
|
|
12818
12851
|
problem(
|
|
12819
12852
|
"VOCABULARY.IDENTITY",
|
|
12820
12853
|
pointer6,
|
|
@@ -12822,7 +12855,7 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12822
12855
|
);
|
|
12823
12856
|
return;
|
|
12824
12857
|
}
|
|
12825
|
-
const term = data.terms.find((t) => t.id ===
|
|
12858
|
+
const term = data.terms.find((t) => t.id === ref18.termId);
|
|
12826
12859
|
if (!term)
|
|
12827
12860
|
problem(
|
|
12828
12861
|
"VOCABULARY.TERM",
|
|
@@ -12831,9 +12864,9 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12831
12864
|
);
|
|
12832
12865
|
return term;
|
|
12833
12866
|
}
|
|
12834
|
-
async function history(
|
|
12835
|
-
const k = key2(
|
|
12836
|
-
if (
|
|
12867
|
+
async function history(ref18, pointer6) {
|
|
12868
|
+
const k = key2(ref18);
|
|
12869
|
+
if (ref18.schemaId === VOCABULARY_CATALOG_SCHEMA_ID) {
|
|
12837
12870
|
problem(
|
|
12838
12871
|
"SNAPSHOT.CONTRACT",
|
|
12839
12872
|
pointer6,
|
|
@@ -12842,11 +12875,11 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12842
12875
|
return;
|
|
12843
12876
|
}
|
|
12844
12877
|
if (!snapshots.has(k)) {
|
|
12845
|
-
const raw = await load(
|
|
12878
|
+
const raw = await load(ref18, pointer6);
|
|
12846
12879
|
if (raw !== void 0) {
|
|
12847
|
-
const snapshot3 = snapshots.get(k), parser = Object.prototype.hasOwnProperty.call(histories,
|
|
12880
|
+
const snapshot3 = snapshots.get(k), parser = Object.prototype.hasOwnProperty.call(histories, ref18.schemaId) ? histories[ref18.schemaId] : void 0;
|
|
12848
12881
|
if (!parser) {
|
|
12849
|
-
if (
|
|
12882
|
+
if (ref18.schemaId === VOCABULARY_CATALOG_SCHEMA_ID)
|
|
12850
12883
|
problem(
|
|
12851
12884
|
"SNAPSHOT.CONTRACT",
|
|
12852
12885
|
pointer6,
|
|
@@ -12860,7 +12893,7 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12860
12893
|
"The declared history contract is not supported.",
|
|
12861
12894
|
"not_checked"
|
|
12862
12895
|
);
|
|
12863
|
-
result.unresolvedReferences.push(
|
|
12896
|
+
result.unresolvedReferences.push(ref18);
|
|
12864
12897
|
}
|
|
12865
12898
|
} else {
|
|
12866
12899
|
const p = parser(raw);
|
|
@@ -12875,8 +12908,8 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
12875
12908
|
resolvedHistories.set(k, p.data);
|
|
12876
12909
|
const review2 = Object.prototype.hasOwnProperty.call(
|
|
12877
12910
|
reviews,
|
|
12878
|
-
|
|
12879
|
-
) ? reviews[
|
|
12911
|
+
ref18.schemaId
|
|
12912
|
+
) ? reviews[ref18.schemaId] : void 0;
|
|
12880
12913
|
if (review2) {
|
|
12881
12914
|
const reviewed = await review2(p.data, { documents });
|
|
12882
12915
|
for (const issue of reviewed.issues) {
|
|
@@ -13018,20 +13051,20 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
13018
13051
|
changed = false;
|
|
13019
13052
|
for (const c of assessed.values())
|
|
13020
13053
|
for (const prior of c.supersedes ?? []) {
|
|
13021
|
-
const
|
|
13022
|
-
if (assessed.has(
|
|
13023
|
-
if (!touched.has(c.id) || !touched.has(
|
|
13054
|
+
const id26 = prior.slice("claim:".length);
|
|
13055
|
+
if (assessed.has(id26) && (touched.has(c.id) || touched.has(id26))) {
|
|
13056
|
+
if (!touched.has(c.id) || !touched.has(id26)) changed = true;
|
|
13024
13057
|
touched.add(c.id);
|
|
13025
|
-
touched.add(
|
|
13058
|
+
touched.add(id26);
|
|
13026
13059
|
}
|
|
13027
13060
|
}
|
|
13028
13061
|
}
|
|
13029
13062
|
for (const c of assessed.values())
|
|
13030
13063
|
if (touched.has(c.id))
|
|
13031
13064
|
for (const prior of c.supersedes ?? []) {
|
|
13032
|
-
const
|
|
13033
|
-
if (!assessed.has(
|
|
13034
|
-
const current = criteria.get(JSON.stringify([historyKey, c.id])) ?? [], previous = criteria.get(JSON.stringify([historyKey,
|
|
13065
|
+
const id26 = prior.slice("claim:".length);
|
|
13066
|
+
if (!assessed.has(id26)) continue;
|
|
13067
|
+
const current = criteria.get(JSON.stringify([historyKey, c.id])) ?? [], previous = criteria.get(JSON.stringify([historyKey, id26])) ?? [];
|
|
13035
13068
|
const all = [...current, ...previous];
|
|
13036
13069
|
if (!current.length || !previous.length || all.some((e) => !e.resolution.resolvedTerm)) {
|
|
13037
13070
|
problem(
|
|
@@ -13063,7 +13096,645 @@ async function evaluateVocabularyBindings(input, options) {
|
|
|
13063
13096
|
result.success = result.checks.structural === "passed" && result.checks.semantic === "passed" && result.checks.profile === "passed";
|
|
13064
13097
|
return result;
|
|
13065
13098
|
}
|
|
13099
|
+
var id24 = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/);
|
|
13100
|
+
var ref16 = (kind) => z.string().regex(new RegExp(`^${kind}:[A-Za-z0-9][A-Za-z0-9._-]*(?![\\s\\S])`));
|
|
13101
|
+
var text20 = z.string().min(1).regex(/\S/);
|
|
13102
|
+
var digest10 = z.strictObject({
|
|
13103
|
+
algorithm: z.literal("sha256"),
|
|
13104
|
+
value: z.string().regex(/^[a-f0-9]{64}(?![\s\S])/)
|
|
13105
|
+
});
|
|
13106
|
+
var max64 = "18446744073709551615";
|
|
13107
|
+
var belowMax = [...max64].flatMap((digit, i) => {
|
|
13108
|
+
const low = i === 0 ? 1 : 0, high = Number(digit) - 1;
|
|
13109
|
+
return high < low ? [] : [`${max64.slice(0, i)}[${low}-${high}][0-9]{${19 - i}}`];
|
|
13110
|
+
});
|
|
13111
|
+
var uint64 = z.string().regex(
|
|
13112
|
+
new RegExp(
|
|
13113
|
+
`^(?:0|[1-9][0-9]{0,18}|${belowMax.join("|")}|${max64})(?![\\s\\S])`
|
|
13114
|
+
)
|
|
13115
|
+
);
|
|
13116
|
+
var uint16 = z.number().int().min(0).max(65535);
|
|
13117
|
+
var uint32 = z.number().int().min(0).max(4294967295);
|
|
13118
|
+
var schemaIdentity = z.union([
|
|
13119
|
+
z.strictObject({ id: z.literal(0) }),
|
|
13120
|
+
z.strictObject({
|
|
13121
|
+
id: uint16.min(1),
|
|
13122
|
+
name: z.string(),
|
|
13123
|
+
encoding: z.string(),
|
|
13124
|
+
digest: digest10
|
|
13125
|
+
})
|
|
13126
|
+
]);
|
|
13127
|
+
var location = z.discriminatedUnion("kind", [
|
|
13128
|
+
z.strictObject({ kind: z.literal("file"), offset: uint64 }),
|
|
13129
|
+
z.strictObject({
|
|
13130
|
+
kind: z.literal("chunk"),
|
|
13131
|
+
chunkOffset: uint64,
|
|
13132
|
+
recordOffset: uint64
|
|
13133
|
+
})
|
|
13134
|
+
]);
|
|
13135
|
+
var message = z.strictObject({
|
|
13136
|
+
location,
|
|
13137
|
+
sequence: uint32,
|
|
13138
|
+
logTimeNs: uint64,
|
|
13139
|
+
publishTimeNs: uint64
|
|
13140
|
+
});
|
|
13141
|
+
var MCAP_SOURCE_MAPPING_SCHEMA_ID = "urn:disclosureos:experimental:mcap-source-mapping:0.1.0";
|
|
13142
|
+
var McapSourceMappingSchema = z.strictObject({
|
|
13143
|
+
kind: z.literal("mcap_source_mapping"),
|
|
13144
|
+
schemaVersion: z.literal("0.1.0"),
|
|
13145
|
+
id: id24,
|
|
13146
|
+
observationId: id24,
|
|
13147
|
+
recordings: z.array(
|
|
13148
|
+
z.strictObject({
|
|
13149
|
+
id: id24,
|
|
13150
|
+
productRef: ref16("product"),
|
|
13151
|
+
digest: digest10,
|
|
13152
|
+
byteLength: uint64,
|
|
13153
|
+
mediaType: z.literal("application/mcap")
|
|
13154
|
+
})
|
|
13155
|
+
).min(1),
|
|
13156
|
+
channels: z.array(
|
|
13157
|
+
z.strictObject({
|
|
13158
|
+
id: id24,
|
|
13159
|
+
recordingRef: ref16("recording"),
|
|
13160
|
+
channelId: uint16,
|
|
13161
|
+
topic: z.string(),
|
|
13162
|
+
messageEncoding: text20,
|
|
13163
|
+
schema: schemaIdentity,
|
|
13164
|
+
decoder: z.strictObject({
|
|
13165
|
+
methodRef: ref16("method"),
|
|
13166
|
+
methodVersion: text20
|
|
13167
|
+
})
|
|
13168
|
+
})
|
|
13169
|
+
).min(1),
|
|
13170
|
+
selections: z.array(
|
|
13171
|
+
z.strictObject({
|
|
13172
|
+
id: id24,
|
|
13173
|
+
measurementRef: ref16("measurement"),
|
|
13174
|
+
channelRef: ref16("channel"),
|
|
13175
|
+
message,
|
|
13176
|
+
payloadPointer: z.string().regex(/^(?:\/(?:[^~]|~[01])*)?(?![\s\S])/)
|
|
13177
|
+
})
|
|
13178
|
+
)
|
|
13179
|
+
});
|
|
13180
|
+
function mcapSourceMappingJsonSchema() {
|
|
13181
|
+
return {
|
|
13182
|
+
...z.toJSONSchema(McapSourceMappingSchema, { target: "draft-2020-12" }),
|
|
13183
|
+
$id: MCAP_SOURCE_MAPPING_SCHEMA_ID
|
|
13184
|
+
};
|
|
13185
|
+
}
|
|
13186
|
+
var hash6 = async (bytes6) => [
|
|
13187
|
+
...new Uint8Array(
|
|
13188
|
+
await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes6))
|
|
13189
|
+
)
|
|
13190
|
+
].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
13191
|
+
function equal3(a, b) {
|
|
13192
|
+
if (a === b) return true;
|
|
13193
|
+
if (!a || !b || typeof a !== "object" || typeof b !== "object") return false;
|
|
13194
|
+
const x = a, y = b;
|
|
13195
|
+
return Object.keys(x).length === Object.keys(y).length && Object.keys(x).every(
|
|
13196
|
+
(k) => Object.prototype.hasOwnProperty.call(y, k) && equal3(x[k], y[k])
|
|
13197
|
+
);
|
|
13198
|
+
}
|
|
13199
|
+
function scalarAt(value, pointer6) {
|
|
13200
|
+
for (const token of pointer6 === "" ? [] : pointer6.slice(1).split("/")) {
|
|
13201
|
+
const key3 = token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
13202
|
+
if (!value || typeof value !== "object" || !Object.prototype.hasOwnProperty.call(value, key3) || Array.isArray(value) && !/^(0|[1-9][0-9]*)$/.test(key3))
|
|
13203
|
+
throw new Error("Payload pointer does not resolve.");
|
|
13204
|
+
value = value[key3];
|
|
13205
|
+
}
|
|
13206
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
13207
|
+
throw new Error("Selected payload must be a finite numeric scalar.");
|
|
13208
|
+
return value;
|
|
13209
|
+
}
|
|
13210
|
+
async function evaluateMcapSourceMapping(observationInput, mappingInput, options = {}) {
|
|
13211
|
+
const observation = parseExperimentalObservation(observationInput), parsed = McapSourceMappingSchema.safeParse(mappingInput);
|
|
13212
|
+
const result = {
|
|
13213
|
+
success: false,
|
|
13214
|
+
checks: {
|
|
13215
|
+
structural: "passed",
|
|
13216
|
+
semantic: "not_checked",
|
|
13217
|
+
external: "not_checked",
|
|
13218
|
+
content: "not_checked"
|
|
13219
|
+
},
|
|
13220
|
+
issues: [],
|
|
13221
|
+
selections: [],
|
|
13222
|
+
scientific: "not_checked",
|
|
13223
|
+
calibration: "not_checked",
|
|
13224
|
+
units: "not_checked"
|
|
13225
|
+
};
|
|
13226
|
+
const issue = (code, pointer6, message2) => result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
13227
|
+
if (!parsed.success)
|
|
13228
|
+
for (const e of parsed.error.issues)
|
|
13229
|
+
issue("STRUCT.VALUE", "/mapping/" + e.path.join("/"), e.message);
|
|
13230
|
+
if (!observation.success)
|
|
13231
|
+
for (const e of observation.issues.filter((i) => i.severity === "error"))
|
|
13232
|
+
issue(e.code, "/observation" + e.pointer, e.message);
|
|
13233
|
+
if (!parsed.success || observation.checks.structural === "failed") {
|
|
13234
|
+
result.checks.structural = "failed";
|
|
13235
|
+
return result;
|
|
13236
|
+
}
|
|
13237
|
+
if (!observation.success) {
|
|
13238
|
+
result.checks.semantic = "failed";
|
|
13239
|
+
return result;
|
|
13240
|
+
}
|
|
13241
|
+
const data = parsed.data, record = observation.data;
|
|
13242
|
+
const products = new Map(record.products.map((p) => [`product:${p.id}`, p]));
|
|
13243
|
+
const assertions = new Map(
|
|
13244
|
+
record.assertions.map((a) => [`assertion:${a.id}`, a])
|
|
13245
|
+
);
|
|
13246
|
+
const processing = new Map(
|
|
13247
|
+
record.processing.map((p) => [`process:${p.id}`, p])
|
|
13248
|
+
);
|
|
13249
|
+
const measurements = new Map(
|
|
13250
|
+
record.measurements.map((m) => [`measurement:${m.id}`, m])
|
|
13251
|
+
);
|
|
13252
|
+
const methods = new Map(record.methods.map((m) => [`method:${m.id}`, m]));
|
|
13253
|
+
function supports(refs, target, seen = /* @__PURE__ */ new Set()) {
|
|
13254
|
+
return refs.some((r) => {
|
|
13255
|
+
if (r === target) return true;
|
|
13256
|
+
if (seen.has(r)) return false;
|
|
13257
|
+
seen.add(r);
|
|
13258
|
+
const a = assertions.get(r), p = products.get(r);
|
|
13259
|
+
if (a) return supports([a.provenance.sourceRef], target, seen);
|
|
13260
|
+
if (p?.kind === "derived")
|
|
13261
|
+
return supports(
|
|
13262
|
+
processing.get(p.generatedBy)?.inputRefs ?? [],
|
|
13263
|
+
target,
|
|
13264
|
+
seen
|
|
13265
|
+
);
|
|
13266
|
+
return false;
|
|
13267
|
+
});
|
|
13268
|
+
}
|
|
13269
|
+
const recordings = /* @__PURE__ */ new Map();
|
|
13270
|
+
const channels = /* @__PURE__ */ new Map();
|
|
13271
|
+
const schemaIds = /* @__PURE__ */ new Map();
|
|
13272
|
+
const productIds = /* @__PURE__ */ new Set(), channelIds = /* @__PURE__ */ new Set(), selectionIds = /* @__PURE__ */ new Set(), measurementIds = /* @__PURE__ */ new Set();
|
|
13273
|
+
if (data.observationId !== record.id)
|
|
13274
|
+
issue(
|
|
13275
|
+
"MCAP.OBSERVATION",
|
|
13276
|
+
"/mapping/observationId",
|
|
13277
|
+
"Mapping identifies a different observation."
|
|
13278
|
+
);
|
|
13279
|
+
for (const [i, r] of data.recordings.entries()) {
|
|
13280
|
+
const p = `/mapping/recordings/${i}`, product = products.get(r.productRef);
|
|
13281
|
+
if (recordings.has(`recording:${r.id}`) || productIds.has(r.productRef))
|
|
13282
|
+
issue(
|
|
13283
|
+
"MCAP.UNIQUE",
|
|
13284
|
+
p,
|
|
13285
|
+
"Recording IDs and product mappings must be unique."
|
|
13286
|
+
);
|
|
13287
|
+
recordings.set(`recording:${r.id}`, r);
|
|
13288
|
+
productIds.add(r.productRef);
|
|
13289
|
+
if (!product || product.format !== r.mediaType || !equal3(product.digest, r.digest) || BigInt(r.byteLength) < 8n)
|
|
13290
|
+
issue(
|
|
13291
|
+
"MCAP.PRODUCT",
|
|
13292
|
+
p,
|
|
13293
|
+
"Recording must pin an existing MCAP product and its exact digest and length."
|
|
13294
|
+
);
|
|
13295
|
+
}
|
|
13296
|
+
for (const [i, c] of data.channels.entries()) {
|
|
13297
|
+
const p = `/mapping/channels/${i}`, key3 = `${c.recordingRef}/${c.channelId}`;
|
|
13298
|
+
if (channels.has(`channel:${c.id}`) || channelIds.has(key3))
|
|
13299
|
+
issue(
|
|
13300
|
+
"MCAP.UNIQUE",
|
|
13301
|
+
p,
|
|
13302
|
+
"Channel IDs and recording/channel mappings must be unique."
|
|
13303
|
+
);
|
|
13304
|
+
channels.set(`channel:${c.id}`, c);
|
|
13305
|
+
channelIds.add(key3);
|
|
13306
|
+
const schemaKey = `${c.recordingRef}/${c.schema.id}`;
|
|
13307
|
+
if (schemaIds.has(schemaKey) && !equal3(schemaIds.get(schemaKey), c.schema))
|
|
13308
|
+
issue(
|
|
13309
|
+
"MCAP.SCHEMA",
|
|
13310
|
+
p,
|
|
13311
|
+
"A recording-local schema ID must retain one identity."
|
|
13312
|
+
);
|
|
13313
|
+
schemaIds.set(schemaKey, c.schema);
|
|
13314
|
+
if (!recordings.has(c.recordingRef))
|
|
13315
|
+
issue("MCAP.RECORDING", p, "Channel recording does not exist.");
|
|
13316
|
+
if (methods.get(c.decoder.methodRef)?.version !== c.decoder.methodVersion)
|
|
13317
|
+
issue(
|
|
13318
|
+
"MCAP.DECODER",
|
|
13319
|
+
p,
|
|
13320
|
+
"Decoder must name a declared method and exact version."
|
|
13321
|
+
);
|
|
13322
|
+
}
|
|
13323
|
+
for (const [i, s] of data.selections.entries()) {
|
|
13324
|
+
const p = `/mapping/selections/${i}`, c = channels.get(s.channelRef), r = c && recordings.get(c.recordingRef), m = measurements.get(s.measurementRef);
|
|
13325
|
+
if (selectionIds.has(s.id) || measurementIds.has(s.measurementRef))
|
|
13326
|
+
issue(
|
|
13327
|
+
"MCAP.UNIQUE",
|
|
13328
|
+
p,
|
|
13329
|
+
"Selection IDs and measurement mappings must be unique."
|
|
13330
|
+
);
|
|
13331
|
+
selectionIds.add(s.id);
|
|
13332
|
+
measurementIds.add(s.measurementRef);
|
|
13333
|
+
if (!c || !r) issue("MCAP.CHANNEL", p, "Selected channel does not exist.");
|
|
13334
|
+
else {
|
|
13335
|
+
if (!m || !supports(m.sourceRefs, r.productRef))
|
|
13336
|
+
issue(
|
|
13337
|
+
"MCAP.MEASUREMENT",
|
|
13338
|
+
p,
|
|
13339
|
+
"Selected recording must be in the measurement's source or processing lineage."
|
|
13340
|
+
);
|
|
13341
|
+
const l = s.message.location, outer = BigInt(l.kind === "file" ? l.offset : l.chunkOffset);
|
|
13342
|
+
if (outer < 8n || outer + 9n > BigInt(r.byteLength))
|
|
13343
|
+
issue("MCAP.LOCATION", p, "Record location is outside the recording.");
|
|
13344
|
+
}
|
|
13345
|
+
}
|
|
13346
|
+
if (result.issues.length) {
|
|
13347
|
+
result.checks.semantic = "failed";
|
|
13348
|
+
return result;
|
|
13349
|
+
}
|
|
13350
|
+
result.checks.semantic = "passed";
|
|
13351
|
+
const assets2 = new Map(
|
|
13352
|
+
[...options.assets ?? []].map(([key3, bytes6]) => [
|
|
13353
|
+
key3,
|
|
13354
|
+
Uint8Array.from(bytes6)
|
|
13355
|
+
])
|
|
13356
|
+
);
|
|
13357
|
+
const valid = /* @__PURE__ */ new Set();
|
|
13358
|
+
for (const r of data.recordings) {
|
|
13359
|
+
const bytes6 = assets2.get(r.productRef);
|
|
13360
|
+
if (!bytes6) continue;
|
|
13361
|
+
if (BigInt(bytes6.length) !== BigInt(r.byteLength) || await hash6(bytes6) !== r.digest.value)
|
|
13362
|
+
issue(
|
|
13363
|
+
"MCAP.ARTIFACT",
|
|
13364
|
+
r.productRef,
|
|
13365
|
+
"Source byte length or digest differs."
|
|
13366
|
+
);
|
|
13367
|
+
else valid.add(r.productRef);
|
|
13368
|
+
}
|
|
13369
|
+
result.checks.external = result.issues.length ? "failed" : valid.size === recordings.size ? "passed" : "not_checked";
|
|
13370
|
+
const cache = /* @__PURE__ */ new Map();
|
|
13371
|
+
for (const [i, s] of data.selections.entries()) {
|
|
13372
|
+
const c = channels.get(s.channelRef), r = recordings.get(c.recordingRef);
|
|
13373
|
+
if (!valid.has(r.productRef) || !options.resolveMessage) {
|
|
13374
|
+
result.selections.push({
|
|
13375
|
+
id: s.id,
|
|
13376
|
+
status: valid.has(r.productRef) || !assets2.has(r.productRef) ? "not_checked" : "failed"
|
|
13377
|
+
});
|
|
13378
|
+
continue;
|
|
13379
|
+
}
|
|
13380
|
+
try {
|
|
13381
|
+
const key3 = JSON.stringify([r.id, c.id, s.message.location]);
|
|
13382
|
+
if (!cache.has(key3))
|
|
13383
|
+
cache.set(
|
|
13384
|
+
key3,
|
|
13385
|
+
Promise.resolve(
|
|
13386
|
+
options.resolveMessage({
|
|
13387
|
+
recording: structuredClone(r),
|
|
13388
|
+
channel: structuredClone(c),
|
|
13389
|
+
message: structuredClone(s.message),
|
|
13390
|
+
bytes: assets2.get(r.productRef)
|
|
13391
|
+
})
|
|
13392
|
+
).then((v) => structuredClone(v))
|
|
13393
|
+
);
|
|
13394
|
+
const found = await cache.get(key3);
|
|
13395
|
+
if (found.channelId !== c.channelId || found.topic !== c.topic || found.messageEncoding !== c.messageEncoding || !equal3(found.schema, c.schema) || !equal3(found.message, s.message))
|
|
13396
|
+
throw new Error("Located message identity differs from the reference.");
|
|
13397
|
+
const value = scalarAt(found.decoded, s.payloadPointer);
|
|
13398
|
+
if (value !== measurements.get(s.measurementRef).value.value)
|
|
13399
|
+
throw new Error("Selected payload value differs from the measurement.");
|
|
13400
|
+
result.selections.push({ id: s.id, status: "passed", value });
|
|
13401
|
+
} catch (error) {
|
|
13402
|
+
issue("MCAP.CONTENT", `/mapping/selections/${i}`, String(error));
|
|
13403
|
+
result.selections.push({ id: s.id, status: "failed" });
|
|
13404
|
+
}
|
|
13405
|
+
}
|
|
13406
|
+
result.checks.content = result.selections.some((s) => s.status === "failed") ? "failed" : result.selections.length > 0 && result.selections.every((s) => s.status === "passed") ? "passed" : "not_checked";
|
|
13407
|
+
result.success = result.checks.external === "passed" && result.checks.content === "passed";
|
|
13408
|
+
return result;
|
|
13409
|
+
}
|
|
13410
|
+
var id25 = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/);
|
|
13411
|
+
var ref17 = (kind) => z.string().regex(new RegExp(`^${kind}:[A-Za-z0-9][A-Za-z0-9._-]*(?![\\s\\S])`));
|
|
13412
|
+
var integer5 = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
|
13413
|
+
var positive2 = integer5.min(1);
|
|
13414
|
+
var tick = z.string().max(100).regex(/^(?:0|-?[1-9][0-9]*)(?![\s\S])/);
|
|
13415
|
+
var timeBase = z.strictObject({ numerator: positive2, denominator: positive2 });
|
|
13416
|
+
var stream = z.strictObject({
|
|
13417
|
+
streamIndex: integer5,
|
|
13418
|
+
timeBase,
|
|
13419
|
+
presentationTicks: z.array(tick).min(1)
|
|
13420
|
+
});
|
|
13421
|
+
var VIDEO_FRAME_SOURCE_MAPPING_SCHEMA_ID = "urn:disclosureos:experimental:video-frame-source-mapping:0.1.0";
|
|
13422
|
+
var VideoFrameSourceMappingSchema = z.strictObject({
|
|
13423
|
+
kind: z.literal("video_frame_source_mapping"),
|
|
13424
|
+
schemaVersion: z.literal("0.1.0"),
|
|
13425
|
+
id: id25,
|
|
13426
|
+
observationId: id25,
|
|
13427
|
+
productRef: ref17("product"),
|
|
13428
|
+
digest: z.strictObject({
|
|
13429
|
+
algorithm: z.literal("sha256"),
|
|
13430
|
+
value: z.string().regex(/^[a-f0-9]{64}(?![\s\S])/)
|
|
13431
|
+
}),
|
|
13432
|
+
byteLength: positive2,
|
|
13433
|
+
mediaType: z.string().regex(/^video\/[^\s]+(?![\s\S])/),
|
|
13434
|
+
indexer: z.strictObject({
|
|
13435
|
+
methodRef: ref17("method"),
|
|
13436
|
+
methodVersion: z.string().min(1).regex(/\S/)
|
|
13437
|
+
}),
|
|
13438
|
+
streams: z.array(stream).min(1),
|
|
13439
|
+
selections: z.array(z.strictObject({ id: id25, streamIndex: integer5, frameIndex: integer5 })).min(1)
|
|
13440
|
+
});
|
|
13441
|
+
function videoFrameSourceMappingJsonSchema() {
|
|
13442
|
+
return {
|
|
13443
|
+
...z.toJSONSchema(VideoFrameSourceMappingSchema, {
|
|
13444
|
+
target: "draft-2020-12"
|
|
13445
|
+
}),
|
|
13446
|
+
$id: VIDEO_FRAME_SOURCE_MAPPING_SCHEMA_ID
|
|
13447
|
+
};
|
|
13448
|
+
}
|
|
13449
|
+
function readVideoFrameReference(mapping, streamIndex, frameIndex) {
|
|
13450
|
+
const s = mapping.streams.find((s2) => s2.streamIndex === streamIndex);
|
|
13451
|
+
if (!s || !Number.isSafeInteger(frameIndex) || frameIndex < 0 || frameIndex >= s.presentationTicks.length)
|
|
13452
|
+
throw new Error(
|
|
13453
|
+
"Video stream or presentation-order frame is outside the index."
|
|
13454
|
+
);
|
|
13455
|
+
const pts = s.presentationTicks[frameIndex];
|
|
13456
|
+
const numerator = BigInt(s.timeBase.numerator), denominator = String(s.timeBase.denominator);
|
|
13457
|
+
return {
|
|
13458
|
+
productRef: mapping.productRef,
|
|
13459
|
+
digest: { ...mapping.digest },
|
|
13460
|
+
streamIndex,
|
|
13461
|
+
frameIndex,
|
|
13462
|
+
presentationTick: pts,
|
|
13463
|
+
timeBase: { ...s.timeBase },
|
|
13464
|
+
presentationSeconds: {
|
|
13465
|
+
numerator: String(BigInt(pts) * numerator),
|
|
13466
|
+
denominator
|
|
13467
|
+
},
|
|
13468
|
+
offsetFromFirstFrameSeconds: {
|
|
13469
|
+
numerator: String(
|
|
13470
|
+
(BigInt(pts) - BigInt(s.presentationTicks[0])) * numerator
|
|
13471
|
+
),
|
|
13472
|
+
denominator
|
|
13473
|
+
}
|
|
13474
|
+
};
|
|
13475
|
+
}
|
|
13476
|
+
async function evaluateVideoFrameSourceMapping(observationInput, mappingInput, options = {}) {
|
|
13477
|
+
const observation = parseExperimentalObservation(observationInput), parsed = VideoFrameSourceMappingSchema.safeParse(mappingInput);
|
|
13478
|
+
const result = {
|
|
13479
|
+
success: false,
|
|
13480
|
+
checks: {
|
|
13481
|
+
structural: "passed",
|
|
13482
|
+
semantic: "not_checked",
|
|
13483
|
+
external: "not_checked",
|
|
13484
|
+
frameTiming: "not_checked"
|
|
13485
|
+
},
|
|
13486
|
+
issues: [],
|
|
13487
|
+
selections: [],
|
|
13488
|
+
captureTime: "not_checked",
|
|
13489
|
+
scientific: "not_checked",
|
|
13490
|
+
calibration: "not_checked",
|
|
13491
|
+
pixelContent: "not_checked"
|
|
13492
|
+
};
|
|
13493
|
+
const issue = (code, pointer6, message2) => {
|
|
13494
|
+
result.issues.push({ code, pointer: pointer6, message: message2 });
|
|
13495
|
+
};
|
|
13496
|
+
if (!parsed.success)
|
|
13497
|
+
for (const e of parsed.error.issues)
|
|
13498
|
+
issue("STRUCT.VALUE", "/mapping/" + e.path.join("/"), e.message);
|
|
13499
|
+
if (!observation.success)
|
|
13500
|
+
for (const e of observation.issues.filter((e2) => e2.severity === "error"))
|
|
13501
|
+
issue(e.code, "/observation" + e.pointer, e.message);
|
|
13502
|
+
if (!parsed.success || observation.checks.structural === "failed") {
|
|
13503
|
+
result.checks.structural = "failed";
|
|
13504
|
+
return result;
|
|
13505
|
+
}
|
|
13506
|
+
if (!observation.success) {
|
|
13507
|
+
result.checks.semantic = "failed";
|
|
13508
|
+
return result;
|
|
13509
|
+
}
|
|
13510
|
+
const data = parsed.data, record = observation.data;
|
|
13511
|
+
if (data.observationId !== record.id)
|
|
13512
|
+
issue(
|
|
13513
|
+
"VIDEO.OBSERVATION",
|
|
13514
|
+
"/mapping/observationId",
|
|
13515
|
+
"Mapping identifies a different observation."
|
|
13516
|
+
);
|
|
13517
|
+
const product = record.products.find(
|
|
13518
|
+
(p) => `product:${p.id}` === data.productRef
|
|
13519
|
+
);
|
|
13520
|
+
if (!product || product.format !== data.mediaType || product.digest?.algorithm !== data.digest.algorithm || product.digest?.value !== data.digest.value)
|
|
13521
|
+
issue(
|
|
13522
|
+
"VIDEO.PRODUCT",
|
|
13523
|
+
"/mapping/productRef",
|
|
13524
|
+
"Mapping must pin an existing video product and its exact digest and media type."
|
|
13525
|
+
);
|
|
13526
|
+
const method2 = record.methods.find(
|
|
13527
|
+
(m) => `method:${m.id}` === data.indexer.methodRef
|
|
13528
|
+
);
|
|
13529
|
+
if (!method2 || method2.version !== data.indexer.methodVersion)
|
|
13530
|
+
issue(
|
|
13531
|
+
"VIDEO.INDEXER",
|
|
13532
|
+
"/mapping/indexer",
|
|
13533
|
+
"Indexer must name a declared method and exact version."
|
|
13534
|
+
);
|
|
13535
|
+
const streamIds = /* @__PURE__ */ new Set(), selectionIds = /* @__PURE__ */ new Set();
|
|
13536
|
+
for (const [i, s] of data.streams.entries()) {
|
|
13537
|
+
if (streamIds.has(s.streamIndex))
|
|
13538
|
+
issue(
|
|
13539
|
+
"VIDEO.UNIQUE",
|
|
13540
|
+
`/mapping/streams/${i}`,
|
|
13541
|
+
"Stream indexes must be unique within this product."
|
|
13542
|
+
);
|
|
13543
|
+
streamIds.add(s.streamIndex);
|
|
13544
|
+
for (let j = 1; j < s.presentationTicks.length; j++)
|
|
13545
|
+
if (BigInt(s.presentationTicks[j]) < BigInt(s.presentationTicks[j - 1])) {
|
|
13546
|
+
issue(
|
|
13547
|
+
"VIDEO.ORDER",
|
|
13548
|
+
`/mapping/streams/${i}/presentationTicks/${j}`,
|
|
13549
|
+
"Frames must be in nondecreasing presentation order, not packet decode order."
|
|
13550
|
+
);
|
|
13551
|
+
break;
|
|
13552
|
+
}
|
|
13553
|
+
}
|
|
13554
|
+
for (const [i, s] of data.selections.entries()) {
|
|
13555
|
+
if (selectionIds.has(s.id))
|
|
13556
|
+
issue(
|
|
13557
|
+
"VIDEO.UNIQUE",
|
|
13558
|
+
`/mapping/selections/${i}`,
|
|
13559
|
+
"Selection IDs must be unique."
|
|
13560
|
+
);
|
|
13561
|
+
selectionIds.add(s.id);
|
|
13562
|
+
try {
|
|
13563
|
+
readVideoFrameReference(data, s.streamIndex, s.frameIndex);
|
|
13564
|
+
} catch (e) {
|
|
13565
|
+
issue("VIDEO.LOCATOR", `/mapping/selections/${i}`, String(e));
|
|
13566
|
+
}
|
|
13567
|
+
}
|
|
13568
|
+
if (result.issues.length) {
|
|
13569
|
+
result.checks.semantic = "failed";
|
|
13570
|
+
return result;
|
|
13571
|
+
}
|
|
13572
|
+
result.checks.semantic = "passed";
|
|
13573
|
+
const supplied = options.assets?.get(data.productRef), bytes6 = supplied && Uint8Array.from(supplied);
|
|
13574
|
+
const resolveFrameIndex = options.resolveFrameIndex;
|
|
13575
|
+
if (bytes6) {
|
|
13576
|
+
const hash8 = [
|
|
13577
|
+
...new Uint8Array(await crypto.subtle.digest("SHA-256", bytes6))
|
|
13578
|
+
].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
13579
|
+
result.checks.external = bytes6.length === data.byteLength && hash8 === data.digest.value ? "passed" : "failed";
|
|
13580
|
+
if (result.checks.external === "failed")
|
|
13581
|
+
issue(
|
|
13582
|
+
"VIDEO.ARTIFACT",
|
|
13583
|
+
data.productRef,
|
|
13584
|
+
"Original byte length or digest differs."
|
|
13585
|
+
);
|
|
13586
|
+
else if (resolveFrameIndex) {
|
|
13587
|
+
try {
|
|
13588
|
+
const decoded = z.array(stream).min(1).parse(
|
|
13589
|
+
await resolveFrameIndex({
|
|
13590
|
+
bytes: bytes6,
|
|
13591
|
+
streamIndexes: data.streams.map((s) => s.streamIndex),
|
|
13592
|
+
indexer: { ...data.indexer }
|
|
13593
|
+
})
|
|
13594
|
+
);
|
|
13595
|
+
if (decoded.length !== data.streams.length || new Set(decoded.map((s) => s.streamIndex)).size !== decoded.length)
|
|
13596
|
+
throw new Error("Decoded stream set differs.");
|
|
13597
|
+
for (const s of data.streams) {
|
|
13598
|
+
const found = decoded.find((d) => d.streamIndex === s.streamIndex);
|
|
13599
|
+
if (!found || found.timeBase.numerator !== s.timeBase.numerator || found.timeBase.denominator !== s.timeBase.denominator || found.presentationTicks.length !== s.presentationTicks.length || found.presentationTicks.some((t, i) => t !== s.presentationTicks[i]))
|
|
13600
|
+
throw new Error(
|
|
13601
|
+
"Decoded stream identity, time base or frame timestamps differ."
|
|
13602
|
+
);
|
|
13603
|
+
}
|
|
13604
|
+
result.checks.frameTiming = "passed";
|
|
13605
|
+
} catch (e) {
|
|
13606
|
+
result.checks.frameTiming = "failed";
|
|
13607
|
+
issue("VIDEO.FRAME_TIMING", "/mapping/streams", String(e));
|
|
13608
|
+
}
|
|
13609
|
+
}
|
|
13610
|
+
}
|
|
13611
|
+
const status = result.checks.external === "failed" || result.checks.frameTiming === "failed" ? "failed" : result.checks.frameTiming === "passed" ? "passed" : "not_checked";
|
|
13612
|
+
for (const s of data.selections)
|
|
13613
|
+
result.selections.push({
|
|
13614
|
+
id: s.id,
|
|
13615
|
+
status,
|
|
13616
|
+
...status === "passed" ? {
|
|
13617
|
+
reference: readVideoFrameReference(
|
|
13618
|
+
data,
|
|
13619
|
+
s.streamIndex,
|
|
13620
|
+
s.frameIndex
|
|
13621
|
+
)
|
|
13622
|
+
} : {}
|
|
13623
|
+
});
|
|
13624
|
+
result.success = result.checks.external === "passed" && result.checks.frameTiming === "passed";
|
|
13625
|
+
return result;
|
|
13626
|
+
}
|
|
13627
|
+
var CLAIM_REVIEW_EVALUATION_SCHEMA_ID = "urn:disclosureos:experimental:claim-review-evaluation:0.1.0";
|
|
13628
|
+
var CLAIM_REVIEW_RECEIPT_SCHEMA_ID = "urn:disclosureos:experimental:claim-review-receipt:0.1.0";
|
|
13629
|
+
var CLAIM_REVIEW_EVALUATION_POLICY = Object.freeze({
|
|
13630
|
+
id: "urn:disclosureos:experimental:policy:claim-review-evaluation",
|
|
13631
|
+
version: "0.1.0",
|
|
13632
|
+
scope: "declared_claims_documentary_support_and_snapshot_identity"
|
|
13633
|
+
});
|
|
13634
|
+
var digest11 = z.string().regex(/^[a-f0-9]{64}(?![\s\S])/);
|
|
13635
|
+
var pin4 = z.strictObject({ sha256: digest11, byteLength: z.number().int().positive().max(Number.MAX_SAFE_INTEGER) });
|
|
13636
|
+
var ClaimReviewEvaluationSchema = z.strictObject({
|
|
13637
|
+
kind: z.literal("claim_review_evaluation"),
|
|
13638
|
+
schemaVersion: z.literal("0.1.0"),
|
|
13639
|
+
id: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/),
|
|
13640
|
+
review: z.strictObject({
|
|
13641
|
+
documentId: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/),
|
|
13642
|
+
schemaId: z.enum([OBSERVATION_CLAIM_HISTORY_SCHEMA_ID, CASE_CLAIM_HISTORY_V02_SCHEMA_ID]),
|
|
13643
|
+
sha256: digest11
|
|
13644
|
+
})
|
|
13645
|
+
});
|
|
13646
|
+
var ClaimReviewReceiptSchema = z.strictObject({
|
|
13647
|
+
kind: z.literal("claim_review_receipt"),
|
|
13648
|
+
schemaVersion: z.literal("0.1.0"),
|
|
13649
|
+
policy: z.strictObject({ id: z.literal(CLAIM_REVIEW_EVALUATION_POLICY.id), version: z.literal("0.1.0"), scope: z.literal(CLAIM_REVIEW_EVALUATION_POLICY.scope) }),
|
|
13650
|
+
serialization: z.literal("sorted-json-utf8:0.1.0"),
|
|
13651
|
+
input: pin4,
|
|
13652
|
+
output: pin4,
|
|
13653
|
+
inputJson: z.string().min(1),
|
|
13654
|
+
outputJson: z.string().min(1)
|
|
13655
|
+
});
|
|
13656
|
+
function claimReviewEvaluationJsonSchema() {
|
|
13657
|
+
return { ...z.toJSONSchema(ClaimReviewEvaluationSchema, { target: "draft-2020-12" }), $id: CLAIM_REVIEW_EVALUATION_SCHEMA_ID };
|
|
13658
|
+
}
|
|
13659
|
+
function claimReviewReceiptJsonSchema() {
|
|
13660
|
+
return { ...z.toJSONSchema(ClaimReviewReceiptSchema, { target: "draft-2020-12" }), $id: CLAIM_REVIEW_RECEIPT_SCHEMA_ID };
|
|
13661
|
+
}
|
|
13662
|
+
var bytes5 = (s) => new TextEncoder().encode(s);
|
|
13663
|
+
var hash7 = async (b) => [...new Uint8Array(await crypto.subtle.digest("SHA-256", Uint8Array.from(b)))].map((n) => n.toString(16).padStart(2, "0")).join("");
|
|
13664
|
+
function canonical(v) {
|
|
13665
|
+
if (Array.isArray(v)) return "[" + v.map(canonical).join(",") + "]";
|
|
13666
|
+
if (v && typeof v === "object") return "{" + Object.entries(v).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, x]) => JSON.stringify(k) + ":" + canonical(x)).join(",") + "}";
|
|
13667
|
+
const value = JSON.stringify(v);
|
|
13668
|
+
if (value === void 0) throw new Error("Receipt contains a non-JSON value.");
|
|
13669
|
+
return value;
|
|
13670
|
+
}
|
|
13671
|
+
var copy = (map) => new Map([...map ?? []].map(([k, v]) => [k, Uint8Array.from(v)]));
|
|
13672
|
+
async function evaluateClaimReview(input, options = {}) {
|
|
13673
|
+
const parsed = ClaimReviewEvaluationSchema.safeParse(input);
|
|
13674
|
+
const result = {
|
|
13675
|
+
success: false,
|
|
13676
|
+
checks: { structural: parsed.success ? "passed" : "failed", external: "not_checked", evaluation: "not_checked" },
|
|
13677
|
+
issues: [],
|
|
13678
|
+
output: null,
|
|
13679
|
+
receipt: null,
|
|
13680
|
+
scientificEligibility: "not_checked",
|
|
13681
|
+
processingChronology: "not_checked",
|
|
13682
|
+
publicationPolicy: "not_checked"
|
|
13683
|
+
};
|
|
13684
|
+
if (!parsed.success) {
|
|
13685
|
+
result.issues = parsed.error.issues.map((i) => ({ code: "STRUCT.VALUE", pointer: "/" + i.path.join("/"), message: i.message }));
|
|
13686
|
+
return result;
|
|
13687
|
+
}
|
|
13688
|
+
const reviewBytes = options.reviewBytes ? Uint8Array.from(options.reviewBytes) : void 0;
|
|
13689
|
+
const documents = copy(options.documents), assets2 = copy(options.assets), request = parsed.data;
|
|
13690
|
+
const fail = (code, message2) => {
|
|
13691
|
+
result.checks.external = "failed";
|
|
13692
|
+
result.issues.push({ code, pointer: "/review", message: message2 });
|
|
13693
|
+
return result;
|
|
13694
|
+
};
|
|
13695
|
+
if (!reviewBytes) return fail("SNAPSHOT.UNAVAILABLE", "Supply the exact review snapshot bytes.");
|
|
13696
|
+
if (await hash7(reviewBytes) !== request.review.sha256) return fail("SNAPSHOT.DIGEST", "Review bytes differ from the declared digest.");
|
|
13697
|
+
let raw;
|
|
13698
|
+
try {
|
|
13699
|
+
raw = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(reviewBytes));
|
|
13700
|
+
} catch {
|
|
13701
|
+
return fail("SNAPSHOT.JSON", "Review must be a UTF-8 JSON document.");
|
|
13702
|
+
}
|
|
13703
|
+
const review2 = request.review.schemaId === OBSERVATION_CLAIM_HISTORY_SCHEMA_ID ? parseObservationClaimHistory(raw) : parseCaseClaimHistoryV02(raw);
|
|
13704
|
+
if (!review2.success) return fail("SNAPSHOT.CONTRACT", "Review does not satisfy its pinned contract and local semantics.");
|
|
13705
|
+
if (review2.data.id !== request.review.documentId) return fail("SNAPSHOT.IDENTITY", "Review ID differs from the snapshot reference.");
|
|
13706
|
+
result.checks.external = "passed";
|
|
13707
|
+
result.output = request.review.schemaId === OBSERVATION_CLAIM_HISTORY_SCHEMA_ID ? await evaluateObservationClaimDocumentation(raw, { assets: assets2 }) : await evaluateCaseClaimHistoryV02(raw, { documents });
|
|
13708
|
+
result.checks.evaluation = result.output.success ? "passed" : "failed";
|
|
13709
|
+
result.success = result.output.success;
|
|
13710
|
+
const inventory = async (map) => Promise.all([...map].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(async ([ref18, value]) => ({ ref: ref18, sha256: await hash7(value), byteLength: value.length })));
|
|
13711
|
+
const inputJson = canonical({ request, review: { sha256: request.review.sha256, byteLength: reviewBytes.length }, documents: await inventory(documents), assets: await inventory(assets2) });
|
|
13712
|
+
const outputJson = canonical({ policy: CLAIM_REVIEW_EVALUATION_POLICY, output: result.output, scientificEligibility: result.scientificEligibility, processingChronology: result.processingChronology, publicationPolicy: result.publicationPolicy });
|
|
13713
|
+
result.receipt = {
|
|
13714
|
+
kind: "claim_review_receipt",
|
|
13715
|
+
schemaVersion: "0.1.0",
|
|
13716
|
+
policy: CLAIM_REVIEW_EVALUATION_POLICY,
|
|
13717
|
+
serialization: "sorted-json-utf8:0.1.0",
|
|
13718
|
+
input: { sha256: await hash7(bytes5(inputJson)), byteLength: bytes5(inputJson).length },
|
|
13719
|
+
output: { sha256: await hash7(bytes5(outputJson)), byteLength: bytes5(outputJson).length },
|
|
13720
|
+
inputJson,
|
|
13721
|
+
outputJson
|
|
13722
|
+
};
|
|
13723
|
+
return result;
|
|
13724
|
+
}
|
|
13725
|
+
async function verifyClaimReviewReceipt(input) {
|
|
13726
|
+
const p = ClaimReviewReceiptSchema.safeParse(input);
|
|
13727
|
+
if (!p.success) return false;
|
|
13728
|
+
const r = p.data;
|
|
13729
|
+
try {
|
|
13730
|
+
const output = JSON.parse(r.outputJson);
|
|
13731
|
+
if (canonical(JSON.parse(r.inputJson)) !== r.inputJson || canonical(output) !== r.outputJson || canonical(output.policy) !== canonical(r.policy)) return false;
|
|
13732
|
+
} catch {
|
|
13733
|
+
return false;
|
|
13734
|
+
}
|
|
13735
|
+
return r.input.byteLength === bytes5(r.inputJson).length && r.output.byteLength === bytes5(r.outputJson).length && r.input.sha256 === await hash7(bytes5(r.inputJson)) && r.output.sha256 === await hash7(bytes5(r.outputJson));
|
|
13736
|
+
}
|
|
13066
13737
|
|
|
13067
|
-
export { ACQUISITION_BINDINGS_PROFILE, ACQUISITION_BINDINGS_SCHEMA_ID, ARCHIVAL_CASE_PRESENTATION_SCHEMA_ID, ASSESSMENT_DOCUMENTATION_PROFILE, AcquisitionBindingsSchema, ArchivalCasePresentationSchema, CASE_PRESENTATION_SCHEMA_ID, CONTEXT_CASE_PRESENTATION_SCHEMA_ID, CONTEXT_MEASUREMENT_ROLES, CasePresentationSchema, ContextCasePresentationSchema, DATASET_RELEASE_PROFILE, DATASET_RELEASE_SCHEMA_ID, DOCUMENTATION_COMPLETION_POLICY, DOCUMENTATION_REQUIREMENTS, DatasetReleaseSchema, HISTORICAL_TESTIMONY_PROFILE, HISTORICAL_TESTIMONY_REQUIREMENTS, HISTORICAL_TESTIMONY_SELECTION_SCHEMA_ID, HistoricalTestimonySelectionSchema, INSTRUMENT_RESEARCH_COMPLETION_POLICY, INSTRUMENT_RESEARCH_PREREQUISITES_PROFILE, INSTRUMENT_RESEARCH_REQUIREMENTS, INSTRUMENT_RESEARCH_REVIEW_SCHEMA_ID, InstrumentResearchReviewSchema, LIDAR_POINT_COLUMNS, LIDAR_PROFILE, LIDAR_PROFILE_SCHEMA_ID, LIDAR_PULSE_COLUMNS, LidarProfileSchema, MATERIAL_CASE_PRESENTATION_SCHEMA_ID, MEASUREMENT_BINDINGS_PROFILE, MEASUREMENT_BINDINGS_SCHEMA_ID, MIGRATION_COMPATIBILITY_SCHEMA_ID, MIGRATION_LEGACY_SCORES_SCHEMA_ID, MIGRATION_RESOLUTION_SCHEMA_ID, MIGRATION_REVIEW_SCHEMA_ID, MaterialCasePresentationSchema, MeasurementBindingsSchema, MigrationCompatibilitySchema, MigrationLegacyScoresSchema, MigrationResolutionSchema, MigrationReviewSchema, PASSIVE_SONAR_PROFILE, PASSIVE_SONAR_PROFILE_SCHEMA_ID, PHYSICAL_SAMPLE_PROFILE, PHYSICAL_SAMPLE_REQUIREMENTS, PHYSICAL_SAMPLE_SELECTION_SCHEMA_ID, PRODUCT_SOURCE_SELECTION_PROFILE, PRODUCT_SOURCE_SELECTION_SCHEMA_ID, PROFILE_EVALUATION_POLICY, PROFILE_EVALUATION_SCHEMA_ID, PROFILE_PREPARATION_SCHEMA_ID, PassiveSonarProfileSchema, PhysicalSampleSelectionSchema, ProductSourceLayoutSchema, ProductSourceSelectionSchema, ProductSourceSelectorSchema, ProfileEvaluationSchema, ProfilePreparationSchema, RADAR_PROFILE, RADAR_PROFILE_SCHEMA_ID, RADAR_TABLE_COLUMNS, RELEASED_DOCUMENT_PROFILE, RELEASED_DOCUMENT_REQUIREMENTS, RELEASED_DOCUMENT_SELECTION_SCHEMA_ID, REPRODUCTION_PACKET_PROFILE, REPRODUCTION_PACKET_SCHEMA_ID, RESEARCH_EVALUATION_POLICY, RESEARCH_EVALUATION_SCHEMA_ID, RadarProfileSchema, ReleasedDocumentSelectionSchema, ReproductionPacketSchema, ResearchEvaluationSchema, SATELLITE_RASTER_PROFILE, SATELLITE_RASTER_PROFILE_SCHEMA_ID, SECONDARY_RADAR_PROFILE, SECONDARY_RADAR_PROFILE_SCHEMA_ID, SECONDARY_RADAR_TABLE_COLUMNS, SONAR_PROFILE, SONAR_PROFILE_SCHEMA_ID, SOURCE_INTAKE_PROFILE, SOURCE_INTAKE_SCHEMA_ID, STEERED_RADAR_PROFILE, STEERED_RADAR_PROFILE_SCHEMA_ID, STEERED_RADAR_TABLE_COLUMNS, SatelliteRasterProfileSchema, SecondaryRadarProfileSchema, SonarProfileSchema, SourceIntakeSchema, SteeredRadarProfileSchema, TESTIMONY_CASE_PRESENTATION_SCHEMA_ID, TestimonyCasePresentationSchema, VOCABULARY_BINDINGS_PROFILE, acquisitionBindingsJsonSchema, archivalCasePresentationJsonSchema, buildPublicArchivalCase, buildPublicArchivalCaseOutputs, buildPublicCase, buildPublicCaseOutputs, buildPublicContextCase, buildPublicContextCaseOutputs, buildPublicMaterialCase, buildPublicMaterialCaseOutputs, buildPublicTestimonyCase, buildPublicTestimonyCaseOutputs, casePresentationJsonSchema, computePassiveSonarSpectrum, contextCasePresentationJsonSchema, datasetReleaseJsonSchema, evaluateAcquisitionBindings, evaluateArchivalClaimHistory, evaluateAssessmentDocumentation, evaluateCaseClaimHistory, evaluateCaseLinks, evaluateCaseRecord, evaluateContextClaimHistory, evaluateDatasetRelease, evaluateDocumentationCompletion, evaluateHistoricalTestimony, evaluateInstrumentResearchCompletion, evaluateInstrumentResearchPrerequisites, evaluateLaboratoryClaimHistory, evaluateLidarProfile, evaluateMeasurementBindings, evaluatePassiveSonarProfile, evaluatePhysicalSamples, evaluateProductSourceSelection, evaluateProfileEvaluation, evaluateRadarProfile, evaluateReleasedDocuments, evaluateReproductionPacket, evaluateResearchClaimHistory, evaluateResearchEvaluation, evaluateSatelliteRasterProfile, evaluateSecondaryRadarProfile, evaluateSonarProfile, evaluateSourceIntake, evaluateSteeredRadarProfile, evaluateVocabularyBindings, formatPublicCaseOutputs, historicalTestimonySelectionJsonSchema, instrumentResearchReviewJsonSchema, lidarProfileJsonSchema, materialCasePresentationJsonSchema, measurementBindingsJsonSchema, migrationCompatibilityJsonSchema, migrationLegacyScoresJsonSchema, migrationResolutionJsonSchema, migrationReviewJsonSchema, parseArchivalCasePresentation, parseCasePresentation, parseContextCasePresentation, parseMaterialCasePresentation, parseTestimonyCasePresentation, passiveSonarBin, passiveSonarDensityDb, passiveSonarDimensions, passiveSonarProfileJsonSchema, passiveSonarSample, physicalSampleSelectionJsonSchema, productSourceSelectionJsonSchema, profileEvaluationJsonSchema, profilePreparationJsonSchema, radarCellPosition, radarCovarianceScaleSquared, radarProfileJsonSchema, readLidarProducts, readPassiveSonarBin, readPassiveSonarProducts, readPassiveSonarSample, readProductSourceSelection, readRadarProducts, readSatelliteRasterProducts, readSecondaryRadarProducts, readSonarProducts, readSonarSample, readSourceCsv, readSteeredRadarProducts, releasedDocumentSelectionJsonSchema, reproductionPacketJsonSchema, researchEvaluationJsonSchema, satelliteCellBounds, satelliteRasterProfileJsonSchema, secondaryRadarProfileJsonSchema, sonarDistance, sonarProfileJsonSchema, sonarSample, sourceElementBytes, sourceIntakeJsonSchema, steeredRadarProfileJsonSchema, testimonyCasePresentationJsonSchema, validateLidarDeclaration, validatePassiveSonarDeclaration, validateSatelliteRasterDeclaration, validateSonarDeclaration };
|
|
13738
|
+
export { ACQUISITION_BINDINGS_PROFILE, ACQUISITION_BINDINGS_SCHEMA_ID, ARCHIVAL_CASE_PRESENTATION_SCHEMA_ID, ASSESSMENT_DOCUMENTATION_PROFILE, AcquisitionBindingsSchema, ArchivalCasePresentationSchema, CASE_PRESENTATION_SCHEMA_ID, CLAIM_REVIEW_EVALUATION_POLICY, CLAIM_REVIEW_EVALUATION_SCHEMA_ID, CLAIM_REVIEW_RECEIPT_SCHEMA_ID, CONTEXT_CASE_PRESENTATION_SCHEMA_ID, CONTEXT_MEASUREMENT_ROLES, CasePresentationSchema, ClaimReviewEvaluationSchema, ClaimReviewReceiptSchema, ContextCasePresentationSchema, DATASET_RELEASE_PROFILE, DATASET_RELEASE_SCHEMA_ID, DOCUMENTATION_COMPLETION_POLICY, DOCUMENTATION_REQUIREMENTS, DatasetReleaseSchema, HISTORICAL_TESTIMONY_PROFILE, HISTORICAL_TESTIMONY_REQUIREMENTS, HISTORICAL_TESTIMONY_SELECTION_SCHEMA_ID, HistoricalTestimonySelectionSchema, INSTRUMENT_RESEARCH_COMPLETION_POLICY, INSTRUMENT_RESEARCH_PREREQUISITES_PROFILE, INSTRUMENT_RESEARCH_REQUIREMENTS, INSTRUMENT_RESEARCH_REVIEW_SCHEMA_ID, InstrumentResearchReviewSchema, LIDAR_POINT_COLUMNS, LIDAR_PROFILE, LIDAR_PROFILE_SCHEMA_ID, LIDAR_PULSE_COLUMNS, LidarProfileSchema, MATERIAL_CASE_PRESENTATION_SCHEMA_ID, MCAP_SOURCE_MAPPING_SCHEMA_ID, MEASUREMENT_BINDINGS_PROFILE, MEASUREMENT_BINDINGS_SCHEMA_ID, MIGRATION_COMPATIBILITY_SCHEMA_ID, MIGRATION_LEGACY_SCORES_SCHEMA_ID, MIGRATION_RESOLUTION_SCHEMA_ID, MIGRATION_REVIEW_SCHEMA_ID, MaterialCasePresentationSchema, McapSourceMappingSchema, MeasurementBindingsSchema, MigrationCompatibilitySchema, MigrationLegacyScoresSchema, MigrationResolutionSchema, MigrationReviewSchema, OBSERVATION_CLAIM_DOCUMENTATION_PROFILE, PASSIVE_SONAR_PROFILE, PASSIVE_SONAR_PROFILE_SCHEMA_ID, PHYSICAL_SAMPLE_PROFILE, PHYSICAL_SAMPLE_REQUIREMENTS, PHYSICAL_SAMPLE_SELECTION_SCHEMA_ID, PRODUCT_SOURCE_SELECTION_PROFILE, PRODUCT_SOURCE_SELECTION_SCHEMA_ID, PROFILE_EVALUATION_POLICY, PROFILE_EVALUATION_SCHEMA_ID, PROFILE_PREPARATION_SCHEMA_ID, PassiveSonarProfileSchema, PhysicalSampleSelectionSchema, ProductSourceLayoutSchema, ProductSourceSelectionSchema, ProductSourceSelectorSchema, ProfileEvaluationSchema, ProfilePreparationSchema, RADAR_PROFILE, RADAR_PROFILE_SCHEMA_ID, RADAR_TABLE_COLUMNS, RELEASED_DOCUMENT_PROFILE, RELEASED_DOCUMENT_REQUIREMENTS, RELEASED_DOCUMENT_SELECTION_SCHEMA_ID, REPRODUCTION_PACKET_PROFILE, REPRODUCTION_PACKET_SCHEMA_ID, RESEARCH_EVALUATION_POLICY, RESEARCH_EVALUATION_SCHEMA_ID, RadarProfileSchema, ReleasedDocumentSelectionSchema, ReproductionPacketSchema, ResearchEvaluationSchema, SATELLITE_RASTER_PROFILE, SATELLITE_RASTER_PROFILE_SCHEMA_ID, SECONDARY_RADAR_PROFILE, SECONDARY_RADAR_PROFILE_SCHEMA_ID, SECONDARY_RADAR_TABLE_COLUMNS, SONAR_PROFILE, SONAR_PROFILE_SCHEMA_ID, SOURCE_INTAKE_PROFILE, SOURCE_INTAKE_SCHEMA_ID, STEERED_RADAR_PROFILE, STEERED_RADAR_PROFILE_SCHEMA_ID, STEERED_RADAR_TABLE_COLUMNS, SatelliteRasterProfileSchema, SecondaryRadarProfileSchema, SonarProfileSchema, SourceIntakeSchema, SteeredRadarProfileSchema, TESTIMONY_CASE_PRESENTATION_SCHEMA_ID, TestimonyCasePresentationSchema, VIDEO_FRAME_SOURCE_MAPPING_SCHEMA_ID, VOCABULARY_BINDINGS_PROFILE, VideoFrameSourceMappingSchema, acquisitionBindingsJsonSchema, archivalCasePresentationJsonSchema, buildPublicArchivalCase, buildPublicArchivalCaseOutputs, buildPublicCase, buildPublicCaseOutputs, buildPublicContextCase, buildPublicContextCaseOutputs, buildPublicMaterialCase, buildPublicMaterialCaseOutputs, buildPublicTestimonyCase, buildPublicTestimonyCaseOutputs, casePresentationJsonSchema, claimReviewEvaluationJsonSchema, claimReviewReceiptJsonSchema, computePassiveSonarSpectrum, contextCasePresentationJsonSchema, datasetReleaseJsonSchema, evaluateAcquisitionBindings, evaluateArchivalClaimHistory, evaluateAssessmentDocumentation, evaluateCaseClaimHistory, evaluateCaseClaimHistoryV02, evaluateCaseLinks, evaluateCaseRecord, evaluateCaseRecordV02, evaluateClaimReview, evaluateContextClaimHistory, evaluateDatasetRelease, evaluateDocumentationCompletion, evaluateHistoricalTestimony, evaluateInstrumentResearchCompletion, evaluateInstrumentResearchPrerequisites, evaluateLaboratoryClaimHistory, evaluateLidarProfile, evaluateMcapSourceMapping, evaluateMeasurementBindings, evaluateObservationClaimDocumentation, evaluatePassiveSonarProfile, evaluatePhysicalSamples, evaluateProductSourceSelection, evaluateProfileEvaluation, evaluateRadarProfile, evaluateReleasedDocuments, evaluateReproductionPacket, evaluateResearchClaimHistory, evaluateResearchEvaluation, evaluateSatelliteRasterProfile, evaluateSecondaryRadarProfile, evaluateSonarProfile, evaluateSourceIntake, evaluateSteeredRadarProfile, evaluateVideoFrameSourceMapping, evaluateVocabularyBindings, formatPublicCaseOutputs, historicalTestimonySelectionJsonSchema, instrumentResearchReviewJsonSchema, lidarProfileJsonSchema, materialCasePresentationJsonSchema, mcapSourceMappingJsonSchema, measurementBindingsJsonSchema, migrationCompatibilityJsonSchema, migrationLegacyScoresJsonSchema, migrationResolutionJsonSchema, migrationReviewJsonSchema, parseArchivalCasePresentation, parseCasePresentation, parseContextCasePresentation, parseMaterialCasePresentation, parseTestimonyCasePresentation, passiveSonarBin, passiveSonarDensityDb, passiveSonarDimensions, passiveSonarProfileJsonSchema, passiveSonarSample, physicalSampleSelectionJsonSchema, productSourceSelectionJsonSchema, profileEvaluationJsonSchema, profilePreparationJsonSchema, radarCellPosition, radarCovarianceScaleSquared, radarProfileJsonSchema, readLidarProducts, readPassiveSonarBin, readPassiveSonarProducts, readPassiveSonarSample, readProductSourceSelection, readRadarProducts, readSatelliteRasterProducts, readSecondaryRadarProducts, readSonarProducts, readSonarSample, readSourceCsv, readSteeredRadarProducts, readVideoFrameReference, releasedDocumentSelectionJsonSchema, reproductionPacketJsonSchema, researchEvaluationJsonSchema, satelliteCellBounds, satelliteRasterProfileJsonSchema, secondaryRadarProfileJsonSchema, sonarDistance, sonarProfileJsonSchema, sonarSample, sourceElementBytes, sourceIntakeJsonSchema, steeredRadarProfileJsonSchema, testimonyCasePresentationJsonSchema, validateLidarDeclaration, validatePassiveSonarDeclaration, validateSatelliteRasterDeclaration, validateSonarDeclaration, verifyClaimReviewReceipt, videoFrameSourceMappingJsonSchema };
|
|
13068
13739
|
//# sourceMappingURL=index.js.map
|
|
13069
13740
|
//# sourceMappingURL=index.js.map
|