@disclosureos/records 2.0.0-beta.2 → 2.0.0-beta.3

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.
@@ -126,9 +126,9 @@ function parsePrimitiveRecord(input) {
126
126
  unchecked.add(ref2);
127
127
  continue;
128
128
  }
129
- const target3 = assertions.get(ref2.slice("assertion:".length));
130
- if (!target3) issues.push({ code: "REF.LOCAL_RESOLUTION", stage: "semantic", pointer: `/${field}/sourceRefs/${index}`, message: "Local assertion does not exist." });
131
- else if (target3.field !== field) issues.push({ code: "REF.FIELD_MISMATCH", stage: "semantic", pointer: `/${field}/sourceRefs/${index}`, message: "Assertion concerns a different field." });
129
+ const target4 = assertions.get(ref2.slice("assertion:".length));
130
+ if (!target4) issues.push({ code: "REF.LOCAL_RESOLUTION", stage: "semantic", pointer: `/${field}/sourceRefs/${index}`, message: "Local assertion does not exist." });
131
+ else if (target4.field !== field) issues.push({ code: "REF.FIELD_MISMATCH", stage: "semantic", pointer: `/${field}/sourceRefs/${index}`, message: "Assertion concerns a different field." });
132
132
  }
133
133
  const selection = value.selection;
134
134
  if (!selection) continue;
@@ -137,13 +137,13 @@ function parsePrimitiveRecord(input) {
137
137
  if (!Number.isFinite(instantParts(selection.evaluatedAt).milliseconds)) issues.push({ code: "TIME.INSTANT", stage: "semantic", pointer: `${path}/evaluatedAt`, message: "Selection timestamp cannot be resolved with its declared UTC offset." });
138
138
  if (!selection.consideredAssertionRefs.includes(selection.assertionRef)) issues.push({ code: "SELECTION.INPUTS", stage: "semantic", pointer: `${path}/assertionRef`, message: "Selected assertion must be among the considered inputs." });
139
139
  if (!value.sourceRefs.includes(selection.assertionRef)) issues.push({ code: "SELECTION.SOURCE_REF", stage: "semantic", pointer: `/${field}/sourceRefs`, message: "Field provenance must cite the selected assertion." });
140
- const refs = /* @__PURE__ */ new Set();
140
+ const refs2 = /* @__PURE__ */ new Set();
141
141
  for (const [index, ref2] of selection.consideredAssertionRefs.entries()) {
142
- if (refs.has(ref2)) issues.push({ code: "REF.UNIQUE_ID", stage: "semantic", pointer: `${path}/consideredAssertionRefs/${index}`, message: "Considered assertion is repeated." });
143
- refs.add(ref2);
144
- const target3 = assertions.get(ref2.slice("assertion:".length));
145
- if (!target3) issues.push({ code: "REF.LOCAL_RESOLUTION", stage: "semantic", pointer: `${path}/consideredAssertionRefs/${index}`, message: "Considered assertion does not exist." });
146
- else if (target3.field !== field) issues.push({ code: "REF.FIELD_MISMATCH", stage: "semantic", pointer: `${path}/consideredAssertionRefs/${index}`, message: "Considered assertion concerns a different field." });
142
+ if (refs2.has(ref2)) issues.push({ code: "REF.UNIQUE_ID", stage: "semantic", pointer: `${path}/consideredAssertionRefs/${index}`, message: "Considered assertion is repeated." });
143
+ refs2.add(ref2);
144
+ const target4 = assertions.get(ref2.slice("assertion:".length));
145
+ if (!target4) issues.push({ code: "REF.LOCAL_RESOLUTION", stage: "semantic", pointer: `${path}/consideredAssertionRefs/${index}`, message: "Considered assertion does not exist." });
146
+ else if (target4.field !== field) issues.push({ code: "REF.FIELD_MISMATCH", stage: "semantic", pointer: `${path}/consideredAssertionRefs/${index}`, message: "Considered assertion concerns a different field." });
147
147
  }
148
148
  const selected = assertions.get(selection.assertionRef.slice("assertion:".length));
149
149
  if (!selected) issues.push({ code: "REF.LOCAL_RESOLUTION", stage: "semantic", pointer: `${path}/assertionRef`, message: "Selected assertion does not exist." });
@@ -313,9 +313,9 @@ function parseExperimentalObservation(input) {
313
313
  if (owner) graph.get(owner)?.add(ref2);
314
314
  return true;
315
315
  }
316
- function references(refs, path, owner) {
316
+ function references(refs2, path, owner) {
317
317
  const seen = /* @__PURE__ */ new Set();
318
- for (const [i, ref2] of refs.entries()) {
318
+ for (const [i, ref2] of refs2.entries()) {
319
319
  if (seen.has(ref2)) problem("REF.UNIQUE_ID", `${path}/${i}`, "Reference is repeated.");
320
320
  seen.add(ref2);
321
321
  resolve(ref2, `${path}/${i}`, owner);
@@ -365,15 +365,15 @@ function parseExperimentalObservation(input) {
365
365
  const assertion = assertions.get(key(ref2));
366
366
  return assertion?.field === field && (assertion.field !== "measurement" || assertion.measurementId === measurementId);
367
367
  }
368
- function fieldReferences(refs, field, path, owner, measurementId) {
369
- references(refs, path, owner);
370
- for (const [i, ref2] of refs.entries()) {
368
+ function fieldReferences(refs2, field, path, owner, measurementId) {
369
+ references(refs2, path, owner);
370
+ for (const [i, ref2] of refs2.entries()) {
371
371
  if (ref2.startsWith("assertion:") && assertions.has(key(ref2)) && !matchesField(ref2, field, measurementId)) problem("REF.FIELD_MISMATCH", `${path}/${i}`, "Assertion concerns a different field or measurement.");
372
372
  }
373
373
  }
374
- function selection(value, selectedValue, refs, field, path, owner, measurementId) {
374
+ function selection(value, selectedValue, refs2, field, path, owner, measurementId) {
375
375
  if (!value) {
376
- if (refs.some((ref2) => ref2.startsWith("assertion:"))) problem("SELECTION.REQUIRED", `${path}/selection`, "A curated value citing local assertions requires an explicit selection record.");
376
+ if (refs2.some((ref2) => ref2.startsWith("assertion:"))) problem("SELECTION.REQUIRED", `${path}/selection`, "A curated value citing local assertions requires an explicit selection record.");
377
377
  return;
378
378
  }
379
379
  const selectionPath = `${path}/selection`;
@@ -382,10 +382,10 @@ function parseExperimentalObservation(input) {
382
382
  fieldReferences(value.consideredAssertionRefs, field, `${selectionPath}/consideredAssertionRefs`, owner, measurementId);
383
383
  resolve(value.assertionRef, `${selectionPath}/assertionRef`, owner);
384
384
  if (!value.consideredAssertionRefs.includes(value.assertionRef)) problem("SELECTION.INPUTS", `${selectionPath}/assertionRef`, "Selected assertion must be among considered inputs.");
385
- if (!refs.includes(value.assertionRef)) problem("SELECTION.SOURCE_REF", `${path}/sourceRefs`, "Field must cite the selected assertion.");
386
- const target3 = assertions.get(key(value.assertionRef));
387
- if (target3 && !matchesField(value.assertionRef, field, measurementId)) problem("REF.FIELD_MISMATCH", `${selectionPath}/assertionRef`, "Selected assertion concerns a different field or measurement.");
388
- else if (target3 && JSON.stringify(target3.value) !== JSON.stringify(selectedValue)) problem("SELECTION.VALUE_MISMATCH", `${path}/value`, "Selection must copy the cited assertion value exactly; processing is declared separately.");
385
+ if (!refs2.includes(value.assertionRef)) problem("SELECTION.SOURCE_REF", `${path}/sourceRefs`, "Field must cite the selected assertion.");
386
+ const target4 = assertions.get(key(value.assertionRef));
387
+ if (target4 && !matchesField(value.assertionRef, field, measurementId)) problem("REF.FIELD_MISMATCH", `${selectionPath}/assertionRef`, "Selected assertion concerns a different field or measurement.");
388
+ else if (target4 && JSON.stringify(target4.value) !== JSON.stringify(selectedValue)) problem("SELECTION.VALUE_MISMATCH", `${path}/value`, "Selection must copy the cited assertion value exactly; processing is declared separately.");
389
389
  }
390
390
  instant(data.createdAt, "/createdAt");
391
391
  instant(data.updatedAt, "/updatedAt");
@@ -457,10 +457,10 @@ function parseExperimentalObservation(input) {
457
457
  }
458
458
  if (queue.length !== graph.size) problem("PROCESS.CYCLE", "/processing", "Local processing/provenance dependencies contain a cycle.");
459
459
  const checks = { structural: "passed", semantic: issues.length ? "failed" : "passed", profile: "not_checked", external: "not_checked" };
460
- const uncheckedRefs = [...sources.keys()].map((id7) => `source:${id7}`).concat(
461
- [...products.keys()].map((id7) => `product:${id7}`),
462
- [...methods.keys()].map((id7) => `method:${id7}`),
463
- [...frames.keys()].map((id7) => `frame:${id7}`)
460
+ const uncheckedRefs = [...sources.keys()].map((id10) => `source:${id10}`).concat(
461
+ [...products.keys()].map((id10) => `product:${id10}`),
462
+ [...methods.keys()].map((id10) => `method:${id10}`),
463
+ [...frames.keys()].map((id10) => `frame:${id10}`)
464
464
  );
465
465
  return issues.length ? { success: false, issues, checks, uncheckedRefs } : { success: true, data, issues, checks, uncheckedRefs };
466
466
  }
@@ -561,9 +561,9 @@ function parseExperimentalClaimHistory(input) {
561
561
  if (!available.has(ref2)) problem("REF.LOCAL_RESOLUTION", path, `Undeclared local reference: ${ref2}`);
562
562
  else if (owner && claims.has(ref2)) graph.get(owner)?.add(ref2);
563
563
  }
564
- function refs(values3, path, owner) {
564
+ function refs2(values4, path, owner) {
565
565
  const seen = /* @__PURE__ */ new Set();
566
- for (const [i, ref2] of values3.entries()) {
566
+ for (const [i, ref2] of values4.entries()) {
567
567
  if (seen.has(ref2)) problem("REF.UNIQUE_ID", `${path}/${i}`, "Reference is repeated.");
568
568
  seen.add(ref2);
569
569
  resolve(ref2, `${path}/${i}`, owner);
@@ -575,7 +575,7 @@ function parseExperimentalClaimHistory(input) {
575
575
  instant(claim.recordedAt, `${path}/recordedAt`);
576
576
  if (claim.subject.kind === "measurement") resolve(`measurement:${claim.subject.measurementId}`, `${path}/subject/measurementId`);
577
577
  if (claim.supersedes) {
578
- refs(claim.supersedes, `${path}/supersedes`, owner);
578
+ refs2(claim.supersedes, `${path}/supersedes`, owner);
579
579
  for (const [j, ref2] of claim.supersedes.entries()) {
580
580
  const previous = claims.get(ref2);
581
581
  if (!previous) continue;
@@ -600,7 +600,7 @@ function parseExperimentalClaimHistory(input) {
600
600
  const locator = claim.provenance.locator;
601
601
  if (locator?.kind === "time_range" && locator.endSeconds < locator.startSeconds) problem("TIME.INTERVAL", `${path}/provenance/locator/endSeconds`, "Locator end precedes its start.");
602
602
  } else {
603
- refs(claim.inputRefs, `${path}/inputRefs`, owner);
603
+ refs2(claim.inputRefs, `${path}/inputRefs`, owner);
604
604
  if (claim.status === "assessed") {
605
605
  instant(claim.evaluatedAt, `${path}/evaluatedAt`);
606
606
  if (comparePoints(point(claim.evaluatedAt), point(claim.recordedAt)) > 0) problem("CLAIM.EVALUATION_ORDER", `${path}/evaluatedAt`, "Evaluation cannot occur after the assessment was recorded.");
@@ -1438,8 +1438,8 @@ function observationContextJsonSchema() {
1438
1438
  }
1439
1439
 
1440
1440
  // src/experimental/v2/context.ts
1441
- function contextAssertions(entity3) {
1442
- return Object.entries(entity3.fields).flatMap(
1441
+ function contextAssertions(entity4) {
1442
+ return Object.entries(entity4.fields).flatMap(
1443
1443
  ([field, assertions]) => (assertions ?? []).map((assertion) => ({
1444
1444
  field,
1445
1445
  assertion
@@ -1475,12 +1475,12 @@ function parseObservationContext(input) {
1475
1475
  const data = parsed.data;
1476
1476
  const entities = /* @__PURE__ */ new Map();
1477
1477
  const relativeGraph = /* @__PURE__ */ new Map();
1478
- for (const [i, entity3] of data.entities.entries()) {
1479
- const key2 = `${entity3.kind}:${entity3.id}`;
1478
+ for (const [i, entity4] of data.entities.entries()) {
1479
+ const key2 = `${entity4.kind}:${entity4.id}`;
1480
1480
  if (entities.has(key2))
1481
1481
  error("REF.UNIQUE_ID", `/entities/${i}/id`, "Duplicate entity identity.");
1482
- entities.set(key2, entity3);
1483
- if (entity3.kind === "temporal") relativeGraph.set(entity3.id, /* @__PURE__ */ new Set());
1482
+ entities.set(key2, entity4);
1483
+ if (entity4.kind === "temporal") relativeGraph.set(entity4.id, /* @__PURE__ */ new Set());
1484
1484
  }
1485
1485
  function time(value, path) {
1486
1486
  const found = [];
@@ -1493,9 +1493,9 @@ function parseObservationContext(input) {
1493
1493
  );
1494
1494
  const unchecked = /* @__PURE__ */ new Set([data.observationRef.sha256]);
1495
1495
  if (data.acquisitionRef) unchecked.add(data.acquisitionRef.sha256);
1496
- for (const [i, entity3] of data.entities.entries()) {
1496
+ for (const [i, entity4] of data.entities.entries()) {
1497
1497
  const path = `/entities/${i}`;
1498
- const assertions = contextAssertions(entity3);
1498
+ const assertions = contextAssertions(entity4);
1499
1499
  const ids = /* @__PURE__ */ new Set();
1500
1500
  for (const { field, assertion } of assertions) {
1501
1501
  const p = `${path}/fields/${field}`;
@@ -1528,8 +1528,8 @@ function parseObservationContext(input) {
1528
1528
  "Context entity reference does not resolve."
1529
1529
  );
1530
1530
  if (field === "placeIds") {
1531
- for (const id7 of content.value)
1532
- if (!entities.has(`place:${id7}`))
1531
+ for (const id10 of content.value)
1532
+ if (!entities.has(`place:${id10}`))
1533
1533
  error(
1534
1534
  "REF.LOCAL_RESOLUTION",
1535
1535
  p,
@@ -1552,7 +1552,7 @@ function parseObservationContext(input) {
1552
1552
  p,
1553
1553
  "Relative date anchor does not resolve."
1554
1554
  );
1555
- relativeGraph.get(entity3.id)?.add(relative2.anchorTemporalId);
1555
+ relativeGraph.get(entity4.id)?.add(relative2.anchorTemporalId);
1556
1556
  if (relative2.relation === "during" && relative2.offset)
1557
1557
  error(
1558
1558
  "TIME.RELATIVE_OFFSET",
@@ -1608,7 +1608,7 @@ function parseObservationContext(input) {
1608
1608
  }
1609
1609
  }
1610
1610
  const selectedFields = /* @__PURE__ */ new Set();
1611
- for (const selection of entity3.selections ?? []) {
1611
+ for (const selection of entity4.selections ?? []) {
1612
1612
  const p = `${path}/selections`;
1613
1613
  if (selectedFields.has(selection.field))
1614
1614
  error(
@@ -1625,9 +1625,9 @@ function parseObservationContext(input) {
1625
1625
  );
1626
1626
  if (new Set(selection.consideredAssertionIds).size !== selection.consideredAssertionIds.length)
1627
1627
  error("REF.UNIQUE_ID", p, "Considered assertions are repeated.");
1628
- for (const id7 of selection.consideredAssertionIds)
1628
+ for (const id10 of selection.consideredAssertionIds)
1629
1629
  if (!assertions.some(
1630
- (a) => a.field === selection.field && a.assertion.id === id7
1630
+ (a) => a.field === selection.field && a.assertion.id === id10
1631
1631
  ))
1632
1632
  error(
1633
1633
  "REF.FIELD_MISMATCH",
@@ -1661,7 +1661,7 @@ function parseObservationContext(input) {
1661
1661
  unchecked.add(selection.methodRef);
1662
1662
  }
1663
1663
  const measurements = /* @__PURE__ */ new Set();
1664
- for (const link of entity3.measurements ?? []) {
1664
+ for (const link of entity4.measurements ?? []) {
1665
1665
  if (measurements.has(link.id))
1666
1666
  error(
1667
1667
  "REF.UNIQUE_ID",
@@ -1882,9 +1882,9 @@ function parseContextClaimHistory(input) {
1882
1882
  );
1883
1883
  else if (owner && claims.has(ref2)) graph.get(owner)?.add(ref2);
1884
1884
  }
1885
- function refs(values3, path, owner) {
1885
+ function refs2(values4, path, owner) {
1886
1886
  const seen = /* @__PURE__ */ new Set();
1887
- for (const [i, ref2] of values3.entries()) {
1887
+ for (const [i, ref2] of values4.entries()) {
1888
1888
  if (seen.has(ref2))
1889
1889
  problem("REF.UNIQUE_ID", `${path}/${i}`, "Reference is repeated.");
1890
1890
  seen.add(ref2);
@@ -1927,7 +1927,7 @@ function parseContextClaimHistory(input) {
1927
1927
  `${path}/subject/measurementId`
1928
1928
  );
1929
1929
  if (claim.supersedes) {
1930
- refs(claim.supersedes, `${path}/supersedes`, owner);
1930
+ refs2(claim.supersedes, `${path}/supersedes`, owner);
1931
1931
  for (const [j, ref2] of claim.supersedes.entries()) {
1932
1932
  const previous = claims.get(ref2);
1933
1933
  if (!previous) continue;
@@ -1973,7 +1973,7 @@ function parseContextClaimHistory(input) {
1973
1973
  "Locator end precedes its start."
1974
1974
  );
1975
1975
  } else {
1976
- refs(claim.inputRefs, `${path}/inputRefs`, owner);
1976
+ refs2(claim.inputRefs, `${path}/inputRefs`, owner);
1977
1977
  if (claim.status === "assessed") {
1978
1978
  instant(claim.evaluatedAt, `${path}/evaluatedAt`);
1979
1979
  if (comparePoints(point2(claim.evaluatedAt), point2(claim.recordedAt)) > 0)
@@ -2382,29 +2382,25 @@ function researchEntitiesJsonSchema() {
2382
2382
  };
2383
2383
  }
2384
2384
 
2385
- // src/experimental/v2/research-entities.ts
2386
- function researchEntityAssertions(entity3) {
2387
- return Object.entries(entity3.fields).flatMap(
2385
+ // src/experimental/v2/entity-document-validation.ts
2386
+ function researchEntityAssertions(entity4) {
2387
+ return Object.entries(entity4.fields).flatMap(
2388
2388
  ([field, list]) => (list ?? []).map((assertion) => ({
2389
2389
  field,
2390
2390
  assertion
2391
2391
  }))
2392
2392
  );
2393
2393
  }
2394
- function researchEntityContextReferences(entity3) {
2395
- return researchEntityAssertions(entity3).flatMap(({ field, assertion }) => {
2394
+ function researchEntityContextReferences(entity4) {
2395
+ return researchEntityAssertions(entity4).flatMap(({ field, assertion }) => {
2396
2396
  const value = assertion.content.value;
2397
2397
  if (field === "eventContext" && value)
2398
2398
  return [value];
2399
2399
  return value?.relevantTime?.kind === "context" ? [value.relevantTime.reference] : [];
2400
2400
  });
2401
2401
  }
2402
- function parseResearchEntities(input) {
2403
- const parsed = ResearchEntitiesSchema.safeParse(input);
2404
- const contract = {
2405
- schemaId: RESEARCH_ENTITIES_SCHEMA_ID,
2406
- rulesetVersion: "0.1.0"
2407
- };
2402
+ function parseEntityDocument(input, schema, contract) {
2403
+ const parsed = schema.safeParse(input);
2408
2404
  if (!parsed.success)
2409
2405
  return {
2410
2406
  success: false,
@@ -2477,19 +2473,19 @@ function parseResearchEntities(input) {
2477
2473
  if (relevant?.kind === "calendar") time(relevant.value, p);
2478
2474
  const targetKind = field === "speakerWitnessIds" || field === "witnessIds" || field === "witnessId" ? "witness" : field === "accountId" ? "account" : void 0;
2479
2475
  if (targetKind) {
2480
- const refs = Array.isArray(value) ? value : [value];
2481
- if (new Set(refs).size !== refs.length)
2476
+ const refs2 = Array.isArray(value) ? value : [value];
2477
+ if (new Set(refs2).size !== refs2.length)
2482
2478
  problem("REF.UNIQUE_ID", p, "Typed local links repeat.");
2483
- for (const id7 of refs)
2484
- if (!identities.has(`${targetKind}:${id7}`))
2479
+ for (const id10 of refs2)
2480
+ if (!identities.has(`${targetKind}:${id10}`))
2485
2481
  problem("REF.ENTITY", p, "Typed local entity does not exist.");
2486
2482
  }
2487
2483
  if (field === "sourceDocument") unchecked.add(value);
2488
2484
  if (field === "supportRefs") {
2489
- const refs = value;
2490
- if (new Set(refs).size !== refs.length)
2485
+ const refs2 = value;
2486
+ if (new Set(refs2).size !== refs2.length)
2491
2487
  problem("REF.UNIQUE_ID", p, "Support references repeat.");
2492
- refs.forEach((r) => unchecked.add(r));
2488
+ refs2.forEach((r) => unchecked.add(r));
2493
2489
  }
2494
2490
  }
2495
2491
  for (const ref2 of researchEntityContextReferences(e))
@@ -2513,6 +2509,14 @@ function parseResearchEntities(input) {
2513
2509
  };
2514
2510
  return issues.length ? { ...validation, success: false } : { ...validation, success: true, data };
2515
2511
  }
2512
+
2513
+ // src/experimental/v2/research-entities.ts
2514
+ function parseResearchEntities(input) {
2515
+ return parseEntityDocument(input, ResearchEntitiesSchema, {
2516
+ schemaId: RESEARCH_ENTITIES_SCHEMA_ID,
2517
+ rulesetVersion: "0.1.0"
2518
+ });
2519
+ }
2516
2520
  var text7 = z.string().min(1).regex(/\S/, "must contain non-whitespace text");
2517
2521
  var id6 = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/);
2518
2522
  var claimRef3 = z.string().regex(/^claim:[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/);
@@ -2617,20 +2621,15 @@ function researchClaimHistoryJsonSchema() {
2617
2621
  };
2618
2622
  }
2619
2623
 
2620
- // src/experimental/v2/research-claim-history.ts
2624
+ // src/experimental/v2/entity-claim-history-validation.ts
2621
2625
  var point3 = (value) => ({
2622
2626
  kind: "instant",
2623
2627
  value,
2624
2628
  timeScale: "UTC"
2625
2629
  });
2626
2630
  var pointer5 = (path) => path.map((p) => `/${String(p).replace(/~/g, "~0").replace(/\//g, "~1")}`).join("");
2627
- function parseResearchClaimHistory(input) {
2628
- const contract = {
2629
- kind: "claim_history",
2630
- schemaId: RESEARCH_CLAIM_HISTORY_SCHEMA_ID,
2631
- rulesetVersion: RESEARCH_CLAIM_HISTORY_RULESET_VERSION
2632
- };
2633
- const parsed = ResearchClaimHistorySchema.safeParse(input);
2631
+ function parseEntityClaimHistory(input, schema, contract) {
2632
+ const parsed = schema.safeParse(input);
2634
2633
  if (!parsed.success)
2635
2634
  return {
2636
2635
  success: false,
@@ -2712,9 +2711,9 @@ function parseResearchClaimHistory(input) {
2712
2711
  );
2713
2712
  else if (owner && claims.has(ref2)) graph.get(owner)?.add(ref2);
2714
2713
  }
2715
- function refs(values3, path, owner) {
2714
+ function refs2(values4, path, owner) {
2716
2715
  const seen = /* @__PURE__ */ new Set();
2717
- for (const [i, ref2] of values3.entries()) {
2716
+ for (const [i, ref2] of values4.entries()) {
2718
2717
  if (seen.has(ref2))
2719
2718
  problem("REF.UNIQUE_ID", `${path}/${i}`, "Reference is repeated.");
2720
2719
  seen.add(ref2);
@@ -2753,11 +2752,11 @@ function parseResearchClaimHistory(input) {
2753
2752
  if (entitySnapshots.size !== data.entityRefs.length)
2754
2753
  problem("REF.UNIQUE_ID", "/entityRefs", "Entity snapshots repeat.");
2755
2754
  for (const [i, claim] of data.claims.entries()) {
2756
- const refs2 = [
2755
+ const refs3 = [
2757
2756
  ...claim.subject.kind === "entity" ? [claim.subject.reference] : [],
2758
2757
  ...claim.kind === "assessment" ? claim.entityInputRefs ?? [] : []
2759
2758
  ];
2760
- for (const ref2 of refs2)
2759
+ for (const ref2 of refs3)
2761
2760
  if (!entitySnapshots.has(JSON.stringify(ref2.document)))
2762
2761
  problem(
2763
2762
  "REF.LOCAL_RESOLUTION",
@@ -2780,7 +2779,7 @@ function parseResearchClaimHistory(input) {
2780
2779
  `/claims/${i}/witnessReview`,
2781
2780
  "Witness review requires a typed research-entity subject."
2782
2781
  );
2783
- if (claim.inputRefs.length + (claim.entityInputRefs?.length ?? 0) + (claim.contextInputRefs?.length ?? 0) === 0)
2782
+ if (claim.inputRefs.length + (claim.entityInputRefs?.length ?? 0) + (claim.contextInputRefs?.length ?? 0) + ("editionInputRefs" in claim ? claim.editionInputRefs?.length ?? 0 : 0) === 0)
2784
2783
  problem(
2785
2784
  "REF.LOCAL_RESOLUTION",
2786
2785
  `/claims/${i}/witnessReview`,
@@ -2799,7 +2798,7 @@ function parseResearchClaimHistory(input) {
2799
2798
  `${path}/subject/measurementId`
2800
2799
  );
2801
2800
  if (claim.supersedes) {
2802
- refs(claim.supersedes, `${path}/supersedes`, owner);
2801
+ refs2(claim.supersedes, `${path}/supersedes`, owner);
2803
2802
  for (const [j, ref2] of claim.supersedes.entries()) {
2804
2803
  const previous = claims.get(ref2);
2805
2804
  if (!previous) continue;
@@ -2845,7 +2844,7 @@ function parseResearchClaimHistory(input) {
2845
2844
  "Locator end precedes its start."
2846
2845
  );
2847
2846
  } else {
2848
- refs(claim.inputRefs, `${path}/inputRefs`, owner);
2847
+ refs2(claim.inputRefs, `${path}/inputRefs`, owner);
2849
2848
  if (claim.status === "assessed") {
2850
2849
  instant(claim.evaluatedAt, `${path}/evaluatedAt`);
2851
2850
  if (comparePoints(point3(claim.evaluatedAt), point3(claim.recordedAt)) > 0)
@@ -2915,6 +2914,781 @@ function parseResearchClaimHistory(input) {
2915
2914
  };
2916
2915
  }
2917
2916
 
2918
- export { AssessedClaimSchema, CLAIM_HISTORY_RULESET_VERSION, CONTEXT_CLAIM_HISTORY_RULESET_VERSION, CONTEXT_CLAIM_HISTORY_SCHEMA_ID, ClaimSubjectSchema, ContextAssertionReferenceSchema, ContextAssessedClaimSchema, ContextClaimHistorySchema, ContextClaimSubjectSchema, ContextCollectionFields, ContextEntitySchema, ContextEnvironmentFields, ContextEventFields, ContextHistoricalClaimSchema, ContextMeasurementLinkSchema, ContextObjectFields, ContextPlaceFields, ContextPlatformFields, ContextReferenceSchema, ContextSourceStatementSchema, ContextTargetSchema, ContextTemporalFields, ContextUnassessedClaimSchema, DocumentSnapshotRefSchema, EXPERIMENTAL_CLAIM_HISTORY_SCHEMA_ID, EXPERIMENTAL_OBSERVATION_SCHEMA_ID, EventTimeIntervalSchema, EventTimePointSchema, EventTimeSchema, EventTimeValueSchema, ExperimentalClaimHistorySchema, ExperimentalObservationSchema, FramedPositionSchema, HistoricalClaimSchema, MeasuredQuantitySchema, OBSERVATION_CONTEXT_SCHEMA_ID, ObservationAssertionSchema, ObservationContextSchema, ObservationMeasurementSchema, ObservationMethodSchema, ObservationPositionSchema, ObservationProductSchema, ObservationSnapshotRefSchema, ObservationSourceSchema, ObservationTimeSchema, PRIMITIVES_SCHEMA_ID, PositionSchema, PositionValueSchema, PrimitiveRecordSchema, ProcessingActivitySchema, QuantitativeUncertaintySchema, RESEARCH_CLAIM_HISTORY_RULESET_VERSION, RESEARCH_CLAIM_HISTORY_SCHEMA_ID, RESEARCH_ENTITIES_SCHEMA_ID, ReferenceFrameSchema, ResearchAccountFields, ResearchAssessedClaimSchema, ResearchClaimHistorySchema, ResearchClaimSubjectSchema, ResearchEntitiesSchema, ResearchEntityAssertionReferenceSchema, ResearchEntityReferenceSchema, ResearchEntitySchema, ResearchEntityTargetSchema, ResearchHistoricalClaimSchema, ResearchProcedureFields, ResearchSourceStatementSchema, ResearchUnassessedClaimSchema, ResearchWitnessFields, ResearchWitnessGroupFields, SourceProvenanceSchema, SourceStatementSchema, UnassessedClaimSchema, ValueAssertionSchema, ValueSelectionSchema, WitnessReviewSchema, compareUtcInstants, contextAssertions, contextClaimHistoryJsonSchema, experimentalClaimHistoryJsonSchema, experimentalObservationJsonSchema, observationContextJsonSchema, parseContextClaimHistory, parseExperimentalClaimHistory, parseExperimentalObservation, parseObservationContext, parsePrimitiveRecord, parseResearchClaimHistory, parseResearchEntities, primitivesJsonSchema, researchClaimHistoryJsonSchema, researchEntitiesJsonSchema, researchEntityAssertions, researchEntityContextReferences };
2917
+ // src/experimental/v2/research-claim-history.ts
2918
+ function parseResearchClaimHistory(input) {
2919
+ return parseEntityClaimHistory(input, ResearchClaimHistorySchema, {
2920
+ kind: "claim_history",
2921
+ schemaId: RESEARCH_CLAIM_HISTORY_SCHEMA_ID,
2922
+ rulesetVersion: RESEARCH_CLAIM_HISTORY_RULESET_VERSION
2923
+ });
2924
+ }
2925
+ var text8 = z.string().min(1).regex(/\S/);
2926
+ var id7 = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/);
2927
+ var sourceRef4 = z.string().regex(/^(source|product):[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/);
2928
+ var provenance4 = SourceProvenanceSchema.extend({ sourceRef: sourceRef4 });
2929
+ function values3(schema) {
2930
+ return z.array(
2931
+ z.strictObject({
2932
+ id: id7.describe(
2933
+ "Assertion identity within this entity, independent of array order."
2934
+ ),
2935
+ content: z.union([
2936
+ z.strictObject({
2937
+ state: z.literal("known"),
2938
+ value: schema,
2939
+ provenance: provenance4,
2940
+ originalWording: text8.optional()
2941
+ }),
2942
+ z.strictObject({
2943
+ state: z.literal("approximate"),
2944
+ value: schema,
2945
+ precision: text8,
2946
+ provenance: provenance4,
2947
+ originalWording: text8.optional()
2948
+ }),
2949
+ z.strictObject({
2950
+ state: z.literal("unknown"),
2951
+ reason: z.enum(["not_recorded", "not_collected", "unavailable"])
2952
+ }),
2953
+ z.strictObject({ state: z.literal("redacted"), reason: text8 }),
2954
+ z.strictObject({
2955
+ state: z.literal("unmapped"),
2956
+ originalWording: text8,
2957
+ provenance: provenance4
2958
+ })
2959
+ ])
2960
+ })
2961
+ ).min(1).optional();
2962
+ }
2963
+ function entity3(kind, fields) {
2964
+ return z.strictObject({
2965
+ kind: z.literal(kind),
2966
+ id: id7,
2967
+ fields: z.strictObject(fields)
2968
+ });
2969
+ }
2970
+ function target3(kind, fields) {
2971
+ return z.strictObject({
2972
+ kind: z.literal(kind),
2973
+ id: id7,
2974
+ field: z.enum(Object.keys(fields)).optional()
2975
+ });
2976
+ }
2977
+ var DocumentTypeSchema = z.enum([
2978
+ "foia_release",
2979
+ "official_report",
2980
+ "congressional_record",
2981
+ "military_memo",
2982
+ "intelligence_assessment",
2983
+ "inspector_general",
2984
+ "presidential_directive",
2985
+ "executive_order",
2986
+ "declassified_cable",
2987
+ "investigation_file",
2988
+ "other"
2989
+ ]).describe("Kind of government/official document.");
2990
+ z.object({
2991
+ documentType: DocumentTypeSchema,
2992
+ classificationLevel: z.string().optional().describe('Current classification of the document (e.g. "UNCLASSIFIED", "SECRET//NOFORN").'),
2993
+ originatingAgency: z.string().optional().describe("Agency that produced the document."),
2994
+ controlNumbers: z.array(z.string()).optional().describe("Agency control or tracking numbers stamped on the document."),
2995
+ foiaRequestNumber: z.string().optional().describe("FOIA request number that produced the document."),
2996
+ declassificationDate: z.string().optional().describe("When the document was declassified (ISO date)."),
2997
+ originalClassification: z.string().optional().describe("Classification the document carried when created."),
2998
+ pageCount: z.number().optional().describe("Number of pages in the document."),
2999
+ redactionLevel: z.enum(["none", "partial", "heavy", "unknown"]).optional().describe("How much of the document is redacted.")
3000
+ }).meta({ id: "DocumentMetadata" }).describe("Provenance metadata for a source document (classification, agency, redaction).");
3001
+ var IdentifierSystemSchema = z.enum([
3002
+ "nuforc",
3003
+ "mufon",
3004
+ "geipan",
3005
+ "cufos",
3006
+ "nicap",
3007
+ "bluebook",
3008
+ "nara",
3009
+ "foia",
3010
+ "aaro",
3011
+ "congress",
3012
+ "doi",
3013
+ "arxiv",
3014
+ "orcid",
3015
+ "pubmed",
3016
+ "isbn",
3017
+ "issn",
3018
+ "youtube",
3019
+ "vimeo",
3020
+ "internet_archive",
3021
+ "wayback",
3022
+ "url",
3023
+ "uri",
3024
+ "custom"
3025
+ ]).describe("External identifier namespace (reporting centers, archives, academic registries, media hosts).");
3026
+ var ExternalIdentifierSchema = z.object({
3027
+ system: IdentifierSystemSchema,
3028
+ systemName: z.string().optional().describe('Display name of the system, required when `system` is "custom".'),
3029
+ value: z.string().describe("The identifier value within the external system (e.g. a case number)."),
3030
+ url: z.string().optional().describe("Direct link to the record in the external system."),
3031
+ verified: z.boolean().optional().describe("Whether the identifier has been confirmed to point at this observation."),
3032
+ verifiedDate: z.string().optional().describe("When the identifier was last verified (ISO date)."),
3033
+ accessible: z.boolean().optional().describe("Whether the external record is currently reachable."),
3034
+ accessCheckedDate: z.string().optional().describe("When accessibility was last checked (ISO date)."),
3035
+ notes: z.string().optional().describe("Free-text context about the cross-reference.")
3036
+ }).meta({ id: "ExternalIdentifier" }).describe("A reference to this observation in an external system or archive.");
3037
+ z.object({
3038
+ primary: ExternalIdentifierSchema.optional(),
3039
+ identifiers: z.array(ExternalIdentifierSchema)
3040
+ }).meta({ id: "CrossReferences" }).describe("External identifiers cross-referencing this observation, with an optional primary.");
3041
+
3042
+ // src/experimental/v2/archival-entities-schema.ts
3043
+ var text9 = z.string().min(1).regex(/\S/);
3044
+ var id8 = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/);
3045
+ var refs = z.array(id8).min(1);
3046
+ var url = z.url();
3047
+ var ArtifactSnapshotRefSchema = z.strictObject({
3048
+ sourceRef: z.string().regex(/^(source|product):[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/),
3049
+ digest: z.strictObject({
3050
+ algorithm: z.literal("sha256"),
3051
+ value: z.string().regex(/^[a-f0-9]{64}(?![\s\S])/)
3052
+ })
3053
+ }).describe(
3054
+ "One exact artifact in the scoped observation inventory. A URL, title or legacy hash cannot substitute for this identity."
3055
+ );
3056
+ var SourceEditionFields = {
3057
+ title: values3(text9),
3058
+ type: values3(SourceTypeSchema),
3059
+ author: values3(text9),
3060
+ organization: values3(text9),
3061
+ issuedAt: values3(EventTimeValueSchema),
3062
+ archiveLocation: values3(text9),
3063
+ primaryDisplay: values3(z.boolean()),
3064
+ originalUrl: values3(url),
3065
+ archiveUrl: values3(url),
3066
+ reference: values3(text9),
3067
+ isPrimarySource: values3(
3068
+ z.strictObject({ value: z.boolean(), context: text9 })
3069
+ ),
3070
+ documentType: values3(DocumentTypeSchema),
3071
+ originatingAgency: values3(text9),
3072
+ controlNumbers: values3(z.array(text9).min(1)),
3073
+ foiaRequestNumber: values3(text9),
3074
+ originalClassification: values3(text9),
3075
+ classificationLevel: values3(text9),
3076
+ pageCount: values3(z.number().int().min(1)),
3077
+ redactionLevel: values3(z.enum(["none", "partial", "heavy", "unknown"])),
3078
+ redactionDescription: values3(text9),
3079
+ redactionPercent: values3(z.number().min(0).max(100)),
3080
+ notes: values3(text9)
3081
+ };
3082
+ var DocumentEventFields = {
3083
+ eventType: values3(
3084
+ z.enum(["creation", "release", "classification", "declassification"])
3085
+ ),
3086
+ occurredAt: values3(EventTimeValueSchema),
3087
+ authority: values3(text9),
3088
+ reference: values3(text9),
3089
+ marking: values3(text9),
3090
+ notes: values3(text9)
3091
+ };
3092
+ var declaredHash = z.discriminatedUnion("algorithm", [
3093
+ z.strictObject({
3094
+ algorithm: z.literal("sha256"),
3095
+ value: z.string().regex(/^[a-fA-F0-9]{64}(?![\s\S])/)
3096
+ }),
3097
+ z.strictObject({
3098
+ algorithm: z.literal("sha512"),
3099
+ value: z.string().regex(/^[a-fA-F0-9]{128}(?![\s\S])/)
3100
+ }),
3101
+ z.strictObject({
3102
+ algorithm: z.literal("sha1"),
3103
+ value: z.string().regex(/^[a-fA-F0-9]{40}(?![\s\S])/)
3104
+ }),
3105
+ z.strictObject({
3106
+ algorithm: z.literal("md5"),
3107
+ value: z.string().regex(/^[a-fA-F0-9]{32}(?![\s\S])/)
3108
+ })
3109
+ ]);
3110
+ var DigitalArtifactFields = {
3111
+ declaredHashes: values3(
3112
+ z.array(
3113
+ z.strictObject({
3114
+ hash: declaredHash,
3115
+ appliesTo: z.union([
3116
+ z.strictObject({
3117
+ kind: z.literal("artifact"),
3118
+ reference: ArtifactSnapshotRefSchema
3119
+ }),
3120
+ z.strictObject({
3121
+ kind: z.literal("unavailable_original"),
3122
+ description: text9
3123
+ })
3124
+ ])
3125
+ })
3126
+ ).min(1)
3127
+ ),
3128
+ device: values3(text9),
3129
+ manufacturer: values3(text9),
3130
+ model: values3(text9),
3131
+ software: values3(text9),
3132
+ originalFilename: values3(text9),
3133
+ originalCreationDate: values3(EventTimeValueSchema),
3134
+ gpsCoordinates: values3(
3135
+ z.strictObject({
3136
+ latitude: z.number().min(-90).max(90),
3137
+ longitude: z.number().min(-180).max(180),
3138
+ altitude: z.strictObject({
3139
+ value: z.number(),
3140
+ unit: z.union([text9, z.null()]),
3141
+ datum: text9.optional()
3142
+ }).optional()
3143
+ })
3144
+ ),
3145
+ metadataPreserved: values3(z.boolean()),
3146
+ metadataStripped: values3(z.boolean()),
3147
+ strippedReason: values3(text9),
3148
+ custodyStatus: values3(ChainOfCustodySchema),
3149
+ provenanceChainDescription: values3(z.array(text9).min(1)),
3150
+ derivedFromArtifactIds: values3(refs),
3151
+ lastUpdated: values3(EventTimeValueSchema),
3152
+ notes: values3(text9)
3153
+ };
3154
+ var DigitalCustodyFields = {
3155
+ action: values3(CustodyActionSchema),
3156
+ occurredAt: values3(EventTimeValueSchema),
3157
+ from: values3(text9),
3158
+ to: values3(text9),
3159
+ location: values3(text9),
3160
+ reference: values3(text9),
3161
+ notes: values3(text9)
3162
+ };
3163
+ var ExternalIdentifierFields = {
3164
+ value: values3(
3165
+ z.strictObject({
3166
+ system: IdentifierSystemSchema,
3167
+ systemName: text9.optional(),
3168
+ value: text9,
3169
+ url: url.optional(),
3170
+ notes: text9.optional()
3171
+ })
3172
+ ),
3173
+ primaryDisplay: values3(z.boolean()),
3174
+ notes: values3(text9)
3175
+ };
3176
+ var IdentifierCheckFields = {
3177
+ checkedAt: values3(EventTimeValueSchema),
3178
+ agent: values3(text9),
3179
+ method: values3(text9),
3180
+ methodVersion: values3(text9),
3181
+ outcome: values3(
3182
+ z.discriminatedUnion("kind", [
3183
+ z.strictObject({
3184
+ kind: z.literal("access"),
3185
+ result: z.enum(["accessible", "inaccessible", "unknown"])
3186
+ }),
3187
+ z.strictObject({
3188
+ kind: z.literal("identity"),
3189
+ result: z.enum(["matches", "does_not_match", "unknown"])
3190
+ })
3191
+ ])
3192
+ ),
3193
+ notes: values3(text9)
3194
+ };
3195
+ for (const fields of [
3196
+ SourceEditionFields,
3197
+ DocumentEventFields,
3198
+ DigitalArtifactFields,
3199
+ DigitalCustodyFields,
3200
+ ExternalIdentifierFields,
3201
+ IdentifierCheckFields
3202
+ ])
3203
+ for (const [key2, schema] of Object.entries(fields))
3204
+ fields[key2] = schema.describe(
3205
+ `Sourced ${key2.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase()} assertions. Alternatives and missingness are retained; declarations are not independent verification.`
3206
+ );
3207
+ var edition = entity3("source_edition", SourceEditionFields).extend({
3208
+ artifact: ArtifactSnapshotRefSchema
3209
+ });
3210
+ var artifact = entity3("digital_artifact", DigitalArtifactFields).extend({
3211
+ artifact: ArtifactSnapshotRefSchema
3212
+ });
3213
+ var documentEvent = entity3("document_event", DocumentEventFields).extend({
3214
+ editionId: id8
3215
+ });
3216
+ var custody = entity3("digital_custody_action", DigitalCustodyFields).extend({
3217
+ artifactId: id8,
3218
+ predecessor: z.discriminatedUnion("kind", [
3219
+ z.strictObject({ kind: z.literal("action"), id: id8 }),
3220
+ z.strictObject({ kind: z.literal("start") }),
3221
+ z.strictObject({ kind: z.literal("unknown"), reason: text9 })
3222
+ ]).describe(
3223
+ "Declared preceding action on the same artifact, a declared beginning, or an explicit gap. Array order carries no chronology."
3224
+ )
3225
+ });
3226
+ var identifier2 = entity3(
3227
+ "external_identifier",
3228
+ ExternalIdentifierFields
3229
+ ).extend({
3230
+ subject: z.discriminatedUnion("kind", [
3231
+ z.strictObject({ kind: z.literal("observation") }),
3232
+ z.strictObject({ kind: z.literal("source_edition"), editionId: id8 })
3233
+ ]).describe(
3234
+ "The scoped observation or one exact source edition. A catalog identifier is not automatically an event identifier."
3235
+ )
3236
+ });
3237
+ var check = entity3("identifier_check", IdentifierCheckFields).extend({
3238
+ identifierId: id8,
3239
+ identifierAssertionId: id8
3240
+ });
3241
+ var ArchivalEntitySchema = z.discriminatedUnion("kind", [
3242
+ ...ResearchEntitySchema.options,
3243
+ edition,
3244
+ documentEvent,
3245
+ artifact,
3246
+ custody,
3247
+ identifier2,
3248
+ check
3249
+ ]);
3250
+ var ARCHIVAL_ENTITIES_SCHEMA_ID = "urn:disclosureos:experimental:research-entities:0.2.0";
3251
+ var ArchivalEntitiesSchema = ResearchEntitiesSchema.extend({
3252
+ schemaVersion: z.literal("0.2.0"),
3253
+ entities: z.array(ArchivalEntitySchema).min(1)
3254
+ }).describe(
3255
+ "Public research declarations including exact source editions and digital artifact custody. No source authentication, public-release permission or complete custody is inferred."
3256
+ );
3257
+ var ArchivalEntityTargetSchema = z.discriminatedUnion("kind", [
3258
+ ...ResearchEntityTargetSchema.options,
3259
+ target3("source_edition", SourceEditionFields),
3260
+ target3("document_event", DocumentEventFields),
3261
+ target3("digital_artifact", DigitalArtifactFields),
3262
+ target3("digital_custody_action", DigitalCustodyFields),
3263
+ target3("external_identifier", ExternalIdentifierFields),
3264
+ target3("identifier_check", IdentifierCheckFields)
3265
+ ]);
3266
+ var ArchivalEntityReferenceSchema = z.strictObject({
3267
+ document: DocumentSnapshotRefSchema.extend({
3268
+ schemaId: z.literal(ARCHIVAL_ENTITIES_SCHEMA_ID)
3269
+ }),
3270
+ target: ArchivalEntityTargetSchema
3271
+ });
3272
+ var ArchivalEntityAssertionReferenceSchema = ArchivalEntityReferenceSchema.extend({ assertionId: id8 });
3273
+ function archivalEntitiesJsonSchema() {
3274
+ return {
3275
+ ...z.toJSONSchema(ArchivalEntitiesSchema, {
3276
+ target: "draft-2020-12",
3277
+ reused: "ref"
3278
+ }),
3279
+ $id: ARCHIVAL_ENTITIES_SCHEMA_ID
3280
+ };
3281
+ }
3282
+
3283
+ // src/experimental/v2/archival-entities.ts
3284
+ function archivalArtifactReferences(entity4) {
3285
+ const direct = "artifact" in entity4 ? [entity4.artifact] : [];
3286
+ if (entity4.kind !== "digital_artifact") return direct;
3287
+ return [
3288
+ ...direct,
3289
+ ...(entity4.fields.declaredHashes ?? []).flatMap(
3290
+ (a) => "value" in a.content ? a.content.value.flatMap(
3291
+ (d) => d.appliesTo.kind === "artifact" ? [d.appliesTo.reference] : []
3292
+ ) : []
3293
+ )
3294
+ ];
3295
+ }
3296
+ function parseArchivalEntities(input) {
3297
+ const result = parseEntityDocument(input, ArchivalEntitiesSchema, {
3298
+ schemaId: ARCHIVAL_ENTITIES_SCHEMA_ID,
3299
+ rulesetVersion: "0.2.0"
3300
+ });
3301
+ if (!result.success) return result;
3302
+ const data = result.data, issues = [];
3303
+ const problem = (code, pointer6, message) => issues.push({ code, stage: "semantic", pointer: pointer6, message });
3304
+ const index = new Map(data.entities.map((e) => [`${e.kind}:${e.id}`, e]));
3305
+ const unchecked = new Set(result.uncheckedRefs);
3306
+ const derivation = /* @__PURE__ */ new Map(), custody2 = /* @__PURE__ */ new Map();
3307
+ const known = (entity4, field) => {
3308
+ const a = researchEntityAssertions(entity4).filter((a2) => a2.field === field);
3309
+ return a.length === 1 && a[0].assertion.content.state === "known" ? a[0].assertion.content.value : void 0;
3310
+ };
3311
+ for (const [i, e] of data.entities.entries()) {
3312
+ const p = `/entities/${i}`;
3313
+ const link = (kind, id10, field) => {
3314
+ const target4 = index.get(`${kind}:${id10}`);
3315
+ if (!target4)
3316
+ problem(
3317
+ "REF.ENTITY",
3318
+ `${p}/${field}`,
3319
+ "Typed local archival entity does not exist."
3320
+ );
3321
+ return target4;
3322
+ };
3323
+ for (const ref2 of archivalArtifactReferences(e))
3324
+ unchecked.add(ref2.sourceRef);
3325
+ if (e.kind === "document_event")
3326
+ link("source_edition", e.editionId, "editionId");
3327
+ if (e.kind === "external_identifier" && e.subject.kind === "source_edition")
3328
+ link("source_edition", e.subject.editionId, "subject/editionId");
3329
+ if (e.kind === "identifier_check") {
3330
+ const identifier3 = link(
3331
+ "external_identifier",
3332
+ e.identifierId,
3333
+ "identifierId"
3334
+ );
3335
+ if (identifier3?.kind === "external_identifier" && !identifier3.fields.value?.some((a) => a.id === e.identifierAssertionId))
3336
+ problem(
3337
+ "REF.ASSERTION",
3338
+ `${p}/identifierAssertionId`,
3339
+ "Identifier check must name an existing value assertion in the selected identifier revision."
3340
+ );
3341
+ }
3342
+ for (const { field, assertion } of researchEntityAssertions(e)) {
3343
+ const value = assertion.content.value;
3344
+ if (value === void 0) continue;
3345
+ if ([
3346
+ "issuedAt",
3347
+ "occurredAt",
3348
+ "originalCreationDate",
3349
+ "lastUpdated",
3350
+ "checkedAt"
3351
+ ].includes(field)) {
3352
+ const found = [];
3353
+ checkTime(value, `${p}/fields/${field}`, found);
3354
+ found.forEach((v) => problem(v.code, v.pointer, v.message));
3355
+ }
3356
+ if (e.kind === "external_identifier" && field === "value") {
3357
+ const v = value;
3358
+ if (v.system === "custom" && !v.systemName)
3359
+ problem(
3360
+ "ARCHIVE.IDENTIFIER_SYSTEM",
3361
+ `${p}/fields/value`,
3362
+ "A custom identifier system needs a declared system name."
3363
+ );
3364
+ }
3365
+ }
3366
+ if (e.kind === "digital_artifact") {
3367
+ const parents = (e.fields.derivedFromArtifactIds ?? []).flatMap(
3368
+ (a) => "value" in a.content ? a.content.value : []
3369
+ );
3370
+ for (const a of e.fields.derivedFromArtifactIds ?? [])
3371
+ if ("value" in a.content && new Set(a.content.value).size !== a.content.value.length)
3372
+ problem(
3373
+ "REF.UNIQUE_ID",
3374
+ `${p}/fields/derivedFromArtifactIds`,
3375
+ "Parent artifact links repeat within an assertion."
3376
+ );
3377
+ parents.forEach(
3378
+ (id10) => link("digital_artifact", id10, "fields/derivedFromArtifactIds")
3379
+ );
3380
+ derivation.set(e.id, [...new Set(parents)]);
3381
+ }
3382
+ if (e.kind === "digital_custody_action") {
3383
+ link("digital_artifact", e.artifactId, "artifactId");
3384
+ custody2.set(
3385
+ e.id,
3386
+ e.predecessor.kind === "action" ? [e.predecessor.id] : []
3387
+ );
3388
+ if (e.predecessor.kind === "action") {
3389
+ const previous = link(
3390
+ "digital_custody_action",
3391
+ e.predecessor.id,
3392
+ "predecessor"
3393
+ );
3394
+ if (previous?.kind !== "digital_custody_action") continue;
3395
+ if (previous.artifactId !== e.artifactId)
3396
+ problem(
3397
+ "ARCHIVE.CUSTODY_SCOPE",
3398
+ `${p}/predecessor`,
3399
+ "A custody predecessor must concern the same exact artifact, not a different edition or derived file."
3400
+ );
3401
+ const from = known(e, "from"), to = known(previous, "to");
3402
+ if (typeof from === "string" && typeof to === "string" && from !== to)
3403
+ problem(
3404
+ "ARCHIVE.CUSTODY_HANDOFF",
3405
+ `${p}/fields/from`,
3406
+ "Explicit predecessor recipient and next sender differ. Missing or conflicting parties are not repaired automatically."
3407
+ );
3408
+ const now = known(e, "occurredAt");
3409
+ const before = known(previous, "occurredAt");
3410
+ if (now && before && now.kind !== "interval" && before.kind === now.kind) {
3411
+ if (comparePoints(before, now) > 0)
3412
+ problem(
3413
+ "ARCHIVE.CUSTODY_ORDER",
3414
+ `${p}/fields/occurredAt`,
3415
+ "Declared custody action precedes its explicit predecessor."
3416
+ );
3417
+ }
3418
+ }
3419
+ }
3420
+ }
3421
+ function acyclic(graph, code) {
3422
+ const indegree = new Map([...graph.keys()].map((id10) => [id10, 0]));
3423
+ for (const edges of graph.values())
3424
+ for (const id10 of edges)
3425
+ if (indegree.has(id10)) indegree.set(id10, indegree.get(id10) + 1);
3426
+ const queue = [...indegree].filter(([, n]) => n === 0).map(([id10]) => id10);
3427
+ for (let i = 0; i < queue.length; i++)
3428
+ for (const id10 of graph.get(queue[i]) ?? [])
3429
+ if (indegree.has(id10)) {
3430
+ const count = indegree.get(id10) - 1;
3431
+ indegree.set(id10, count);
3432
+ if (count === 0) queue.push(id10);
3433
+ }
3434
+ if (queue.length !== graph.size)
3435
+ problem(
3436
+ code,
3437
+ "/entities",
3438
+ "Declared archival dependency links must be acyclic."
3439
+ );
3440
+ }
3441
+ acyclic(derivation, "ARCHIVE.DERIVATION_CYCLE");
3442
+ acyclic(custody2, "ARCHIVE.CUSTODY_CYCLE");
3443
+ const validation = {
3444
+ contract: result.contract,
3445
+ issues,
3446
+ uncheckedRefs: [...unchecked],
3447
+ checks: {
3448
+ ...result.checks,
3449
+ semantic: issues.length ? "failed" : "passed"
3450
+ }
3451
+ };
3452
+ return issues.length ? { ...validation, success: false } : { ...validation, success: true, data };
3453
+ }
3454
+ var HashAlgorithmSchema = z.enum(["sha256", "sha512", "sha1", "md5"]).describe("Cryptographic hash algorithm used to fingerprint a file.");
3455
+ var FileHashSchema = z.object({
3456
+ algorithm: HashAlgorithmSchema,
3457
+ value: z.string().describe("Hex-encoded hash digest of the file contents.")
3458
+ }).meta({ id: "FileHash" }).describe("A content hash of a file.");
3459
+ var VerificationMethodSchema = z.enum([
3460
+ "metadata_analysis",
3461
+ "forensic_analysis",
3462
+ "hash_verification",
3463
+ "chain_of_custody",
3464
+ "source_confirmation",
3465
+ "expert_review",
3466
+ "ai_analysis",
3467
+ "other"
3468
+ ]).describe("Method used to verify media authenticity.");
3469
+ var VerificationResultSchema = z.enum([
3470
+ "authentic",
3471
+ "likely_authentic",
3472
+ "inconclusive",
3473
+ "likely_manipulated",
3474
+ "manipulated",
3475
+ "ai_generated",
3476
+ "deepfake",
3477
+ "composite",
3478
+ "unknown"
3479
+ ]).describe("Outcome of an authenticity verification.");
3480
+ var ThirdPartyVerificationSchema = z.object({
3481
+ verifier: z.string().describe("Name of the person who performed the verification."),
3482
+ organization: z.string().optional().describe("Organization the verifier represents."),
3483
+ credentials: z.string().optional().describe('Verifier\u2019s relevant qualifications (e.g. "certified forensic video analyst").'),
3484
+ date: z.string().describe("When the verification was performed (ISO date)."),
3485
+ method: VerificationMethodSchema,
3486
+ methodDescription: z.string().optional().describe("Fuller description of how the verification was performed."),
3487
+ result: VerificationResultSchema,
3488
+ confidence: z.enum(["high", "medium", "low"]).optional().describe("Verifier\u2019s confidence in their own result."),
3489
+ findings: z.string().optional().describe("Summary of what the verification found."),
3490
+ reportUrl: z.string().optional().describe("Link to the full verification report.")
3491
+ }).meta({ id: "ThirdPartyVerification" }).describe("An independent authenticity assessment of media or a document.");
3492
+ var CaptureMetadataSchema = z.object({
3493
+ device: z.string().optional().describe('Capture device as recorded in metadata (e.g. "iPhone 14 Pro").'),
3494
+ manufacturer: z.string().optional().describe("Device manufacturer from metadata."),
3495
+ model: z.string().optional().describe("Device model from metadata."),
3496
+ software: z.string().optional().describe("Software that produced or processed the file."),
3497
+ originalFilename: z.string().optional().describe("Filename as originally captured, before any renaming."),
3498
+ originalCreationDate: z.string().optional().describe("Creation timestamp embedded in the file metadata."),
3499
+ gpsCoordinates: z.object({
3500
+ latitude: z.number(),
3501
+ longitude: z.number(),
3502
+ altitude: z.number().optional()
3503
+ }).optional().describe("GPS position embedded in the file metadata."),
3504
+ metadataPreserved: z.boolean().optional().describe("Whether the original metadata survives intact."),
3505
+ metadataStripped: z.boolean().optional().describe("Whether metadata was removed at some point."),
3506
+ strippedReason: z.string().optional().describe('Why metadata was stripped (e.g. "platform re-encoding", "privacy redaction").')
3507
+ }).meta({ id: "CaptureMetadata" }).describe("Capture/EXIF-style metadata extracted from a media file.");
3508
+ z.object({
3509
+ hash: FileHashSchema.optional(),
3510
+ additionalHashes: z.array(FileHashSchema).optional(),
3511
+ captureMetadata: CaptureMetadataSchema.optional(),
3512
+ verifications: z.array(ThirdPartyVerificationSchema).optional(),
3513
+ provenanceChain: z.array(z.string()).optional().describe('Ordered hops the file took from capture to here (e.g. "witness phone \u2192 NYT \u2192 public release").'),
3514
+ manipulationDetected: z.boolean().optional().describe("Whether any analysis found evidence of manipulation."),
3515
+ manipulationDescription: z.string().optional().describe("What manipulation was found, if any."),
3516
+ authenticityAssessment: VerificationResultSchema.optional(),
3517
+ authenticityConfidence: z.enum(["high", "medium", "low", "unassessed"]).optional().describe("Overall confidence in the authenticity assessment."),
3518
+ lastUpdated: z.string().optional().describe("When this provenance record was last updated (ISO timestamp)."),
3519
+ notes: z.string().optional().describe("Free-text context about the provenance trail.")
3520
+ }).meta({ id: "DigitalProvenance" }).describe("Digital authenticity trail for media: hashes, capture metadata, and verifications.");
3521
+
3522
+ // src/experimental/v2/archival-claim-history-schema.ts
3523
+ var text10 = z.string().min(1).regex(/\S/);
3524
+ var id9 = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*(?![\s\S])/);
3525
+ var EditionCitationSchema = z.strictObject({
3526
+ document: DocumentSnapshotRefSchema.extend({
3527
+ schemaId: z.literal(ARCHIVAL_ENTITIES_SCHEMA_ID)
3528
+ }),
3529
+ editionId: id9,
3530
+ artifact: ArtifactSnapshotRefSchema,
3531
+ locator: SourceProvenanceSchema.shape.locator.unwrap()
3532
+ }).describe(
3533
+ "A citation bound to an exact edition declaration and artifact digest. Similar titles do not permit edition substitution."
3534
+ );
3535
+ var ArtifactReviewSchema = z.strictObject({
3536
+ verifier: text10.optional(),
3537
+ organization: text10.optional(),
3538
+ credentials: text10.optional(),
3539
+ reviewedAt: EventTimeValueSchema.optional(),
3540
+ verificationMethod: VerificationMethodSchema.optional(),
3541
+ methodDescription: text10.optional(),
3542
+ result: VerificationResultSchema.optional(),
3543
+ confidence: z.enum(["high", "medium", "low", "unassessed"]).optional(),
3544
+ sourceCredibility: SourceCredibilitySchema.optional(),
3545
+ findings: text10.optional(),
3546
+ reportRef: ArtifactSnapshotRefSchema.shape.sourceRef.optional(),
3547
+ reportUrl: z.url().optional(),
3548
+ manipulationDetected: z.boolean().optional(),
3549
+ manipulationDescription: text10.optional(),
3550
+ notes: text10.optional()
3551
+ }).describe(
3552
+ "An attributed authenticity or source-credibility review, not an automatic result of snapshot validation."
3553
+ );
3554
+ var ArchivalClaimSubjectSchema = z.discriminatedUnion("kind", [
3555
+ ResearchClaimSubjectSchema.options[0],
3556
+ z.strictObject({
3557
+ kind: z.literal("entity"),
3558
+ reference: ArchivalEntityReferenceSchema
3559
+ }),
3560
+ ResearchClaimSubjectSchema.options[2],
3561
+ ResearchClaimSubjectSchema.options[3]
3562
+ ]);
3563
+ var subject = ArchivalClaimSubjectSchema;
3564
+ var ArchivalSourceStatementSchema = ResearchSourceStatementSchema.extend({
3565
+ subject,
3566
+ editionCitation: EditionCitationSchema.optional(),
3567
+ reportedArtifactReview: ArtifactReviewSchema.optional()
3568
+ });
3569
+ var assessment4 = {
3570
+ subject,
3571
+ entityInputRefs: z.array(ArchivalEntityAssertionReferenceSchema).optional(),
3572
+ editionInputRefs: z.array(EditionCitationSchema).optional()
3573
+ };
3574
+ var ArchivalUnassessedClaimSchema = ResearchUnassessedClaimSchema.extend(assessment4);
3575
+ var ArchivalAssessedClaimSchema = ResearchAssessedClaimSchema.extend({
3576
+ ...assessment4,
3577
+ artifactReview: ArtifactReviewSchema.optional()
3578
+ });
3579
+ var ArchivalHistoricalClaimSchema = z.union([
3580
+ ArchivalSourceStatementSchema,
3581
+ ArchivalUnassessedClaimSchema,
3582
+ ArchivalAssessedClaimSchema
3583
+ ]);
3584
+ var ARCHIVAL_CLAIM_HISTORY_SCHEMA_ID = "urn:disclosureos:experimental:claim-history:0.4.0";
3585
+ var ArchivalClaimHistorySchema = ResearchClaimHistorySchema.extend({
3586
+ schemaVersion: z.literal("0.4.0"),
3587
+ claims: z.array(ArchivalHistoricalClaimSchema),
3588
+ entityRefs: z.array(
3589
+ DocumentSnapshotRefSchema.extend({
3590
+ schemaId: z.literal(ARCHIVAL_ENTITIES_SCHEMA_ID)
3591
+ })
3592
+ )
3593
+ });
3594
+ function archivalClaimHistoryJsonSchema() {
3595
+ return {
3596
+ ...z.toJSONSchema(ArchivalClaimHistorySchema, {
3597
+ target: "draft-2020-12",
3598
+ reused: "ref"
3599
+ }),
3600
+ $id: ARCHIVAL_CLAIM_HISTORY_SCHEMA_ID
3601
+ };
3602
+ }
3603
+
3604
+ // src/experimental/v2/archival-claim-history.ts
3605
+ function parseArchivalClaimHistory(input) {
3606
+ const result = parseEntityClaimHistory(input, ArchivalClaimHistorySchema, {
3607
+ kind: "claim_history",
3608
+ schemaId: ARCHIVAL_CLAIM_HISTORY_SCHEMA_ID,
3609
+ rulesetVersion: "0.4.0"
3610
+ });
3611
+ if (!result.success) return result;
3612
+ const data = result.data, issues = [];
3613
+ const problem = (code, pointer6, message) => issues.push({ code, stage: "semantic", pointer: pointer6, message });
3614
+ const snapshots = new Set(data.entityRefs.map((r) => JSON.stringify(r)));
3615
+ const sources = new Map([
3616
+ ...data.observation.sources.map((s) => [`source:${s.id}`, s]),
3617
+ ...data.observation.products.map((s) => [`product:${s.id}`, s])
3618
+ ]);
3619
+ for (const [i, claim] of data.claims.entries()) {
3620
+ const p = `/claims/${i}`;
3621
+ const citations = claim.kind === "source_assertion" ? claim.editionCitation ? [claim.editionCitation] : [] : claim.editionInputRefs ?? [];
3622
+ if (new Set(citations.map((c) => JSON.stringify(c))).size !== citations.length)
3623
+ problem("REF.UNIQUE_ID", p, "Edition citations repeat.");
3624
+ for (const citation of citations) {
3625
+ if (!snapshots.has(JSON.stringify(citation.document)))
3626
+ problem(
3627
+ "REF.LOCAL_RESOLUTION",
3628
+ p,
3629
+ "Edition citation must select a declared entity snapshot."
3630
+ );
3631
+ const source = sources.get(citation.artifact.sourceRef);
3632
+ if (!source?.digest || source.digest.value !== citation.artifact.digest.value)
3633
+ problem(
3634
+ "ARCHIVE.ARTIFACT_IDENTITY",
3635
+ p,
3636
+ "Edition citation must match an inventory artifact's SHA-256 declaration."
3637
+ );
3638
+ if (citation.locator.kind === "time_range" && citation.locator.endSeconds < citation.locator.startSeconds)
3639
+ problem("TIME.INTERVAL", p, "Edition locator end precedes its start.");
3640
+ if (claim.kind === "source_assertion" && (claim.provenance.sourceRef !== citation.artifact.sourceRef || claim.provenance.sourceDigest && claim.provenance.sourceDigest.value !== citation.artifact.digest.value || JSON.stringify(claim.provenance.locator) !== JSON.stringify(citation.locator)))
3641
+ problem(
3642
+ "ARCHIVE.CITATION_SCOPE",
3643
+ p,
3644
+ "A source statement's provenance and edition citation must name the same artifact and locator."
3645
+ );
3646
+ }
3647
+ const review = claim.kind === "source_assertion" ? claim.reportedArtifactReview : claim.status === "assessed" ? claim.artifactReview : void 0;
3648
+ if (!review) continue;
3649
+ if (claim.subject.kind !== "entity" || !["source_edition", "digital_artifact"].includes(
3650
+ claim.subject.reference.target.kind
3651
+ ))
3652
+ problem(
3653
+ "ARCHIVE.REVIEW_SUBJECT",
3654
+ p,
3655
+ "Artifact review requires an exact source-edition or digital-artifact subject."
3656
+ );
3657
+ if (claim.kind === "assessment" && claim.inputRefs.length + (claim.entityInputRefs?.length ?? 0) + (claim.contextInputRefs?.length ?? 0) + citations.length === 0)
3658
+ problem(
3659
+ "REF.LOCAL_RESOLUTION",
3660
+ p,
3661
+ "Artifact review requires explicit inputs."
3662
+ );
3663
+ if (review.reportRef && !sources.has(review.reportRef))
3664
+ problem(
3665
+ "REF.LOCAL_RESOLUTION",
3666
+ p,
3667
+ "Review report is absent from the observation inventory."
3668
+ );
3669
+ if (review.reviewedAt) {
3670
+ const found = [];
3671
+ checkTime(review.reviewedAt, `${p}/artifactReview/reviewedAt`, found);
3672
+ found.forEach((v) => problem(v.code, v.pointer, v.message));
3673
+ }
3674
+ }
3675
+ const validation = {
3676
+ contract: result.contract,
3677
+ issues,
3678
+ uncheckedRefs: result.uncheckedRefs,
3679
+ checks: {
3680
+ ...result.checks,
3681
+ semantic: issues.length ? "failed" : "passed"
3682
+ }
3683
+ };
3684
+ return issues.length ? { ...validation, success: false } : {
3685
+ ...validation,
3686
+ success: true,
3687
+ data,
3688
+ currentClaimRefs: result.currentClaimRefs
3689
+ };
3690
+ }
3691
+
3692
+ export { ARCHIVAL_CLAIM_HISTORY_SCHEMA_ID, ARCHIVAL_ENTITIES_SCHEMA_ID, ArchivalAssessedClaimSchema, ArchivalClaimHistorySchema, ArchivalClaimSubjectSchema, ArchivalEntitiesSchema, ArchivalEntityAssertionReferenceSchema, ArchivalEntityReferenceSchema, ArchivalEntitySchema, ArchivalEntityTargetSchema, ArchivalHistoricalClaimSchema, ArchivalSourceStatementSchema, ArchivalUnassessedClaimSchema, ArtifactReviewSchema, ArtifactSnapshotRefSchema, AssessedClaimSchema, CLAIM_HISTORY_RULESET_VERSION, CONTEXT_CLAIM_HISTORY_RULESET_VERSION, CONTEXT_CLAIM_HISTORY_SCHEMA_ID, ClaimSubjectSchema, ContextAssertionReferenceSchema, ContextAssessedClaimSchema, ContextClaimHistorySchema, ContextClaimSubjectSchema, ContextCollectionFields, ContextEntitySchema, ContextEnvironmentFields, ContextEventFields, ContextHistoricalClaimSchema, ContextMeasurementLinkSchema, ContextObjectFields, ContextPlaceFields, ContextPlatformFields, ContextReferenceSchema, ContextSourceStatementSchema, ContextTargetSchema, ContextTemporalFields, ContextUnassessedClaimSchema, DigitalArtifactFields, DigitalCustodyFields, DocumentEventFields, DocumentSnapshotRefSchema, EXPERIMENTAL_CLAIM_HISTORY_SCHEMA_ID, EXPERIMENTAL_OBSERVATION_SCHEMA_ID, EditionCitationSchema, EventTimeIntervalSchema, EventTimePointSchema, EventTimeSchema, EventTimeValueSchema, ExperimentalClaimHistorySchema, ExperimentalObservationSchema, ExternalIdentifierFields, FramedPositionSchema, HistoricalClaimSchema, IdentifierCheckFields, MeasuredQuantitySchema, OBSERVATION_CONTEXT_SCHEMA_ID, ObservationAssertionSchema, ObservationContextSchema, ObservationMeasurementSchema, ObservationMethodSchema, ObservationPositionSchema, ObservationProductSchema, ObservationSnapshotRefSchema, ObservationSourceSchema, ObservationTimeSchema, PRIMITIVES_SCHEMA_ID, PositionSchema, PositionValueSchema, PrimitiveRecordSchema, ProcessingActivitySchema, QuantitativeUncertaintySchema, RESEARCH_CLAIM_HISTORY_RULESET_VERSION, RESEARCH_CLAIM_HISTORY_SCHEMA_ID, RESEARCH_ENTITIES_SCHEMA_ID, ReferenceFrameSchema, ResearchAccountFields, ResearchAssessedClaimSchema, ResearchClaimHistorySchema, ResearchClaimSubjectSchema, ResearchEntitiesSchema, ResearchEntityAssertionReferenceSchema, ResearchEntityReferenceSchema, ResearchEntitySchema, ResearchEntityTargetSchema, ResearchHistoricalClaimSchema, ResearchProcedureFields, ResearchSourceStatementSchema, ResearchUnassessedClaimSchema, ResearchWitnessFields, ResearchWitnessGroupFields, SourceEditionFields, SourceProvenanceSchema, SourceStatementSchema, UnassessedClaimSchema, ValueAssertionSchema, ValueSelectionSchema, WitnessReviewSchema, archivalArtifactReferences, archivalClaimHistoryJsonSchema, archivalEntitiesJsonSchema, compareUtcInstants, contextAssertions, contextClaimHistoryJsonSchema, experimentalClaimHistoryJsonSchema, experimentalObservationJsonSchema, observationContextJsonSchema, parseArchivalClaimHistory, parseArchivalEntities, parseContextClaimHistory, parseExperimentalClaimHistory, parseExperimentalObservation, parseObservationContext, parsePrimitiveRecord, parseResearchClaimHistory, parseResearchEntities, primitivesJsonSchema, researchClaimHistoryJsonSchema, researchEntitiesJsonSchema, researchEntityAssertions, researchEntityContextReferences };
2919
3693
  //# sourceMappingURL=index.js.map
2920
3694
  //# sourceMappingURL=index.js.map