@bcts/provenance-mark 1.0.0-alpha.16 → 1.0.0-alpha.18

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/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import { chacha20 } from "@noble/ciphers/chacha.js";
6
6
  import { randomData } from "@bcts/rand";
7
7
  import { PROVENANCE_MARK } from "@bcts/tags";
8
8
  import { BytewordsStyle, UR, decodeBytewords, encodeBytemojisIdentifier, encodeBytewords, encodeBytewordsIdentifier } from "@bcts/uniform-resources";
9
- import { Envelope } from "@bcts/envelope";
9
+ import { Envelope, FormatContext, registerTagsIn as registerTagsIn$1, withFormatContextMut } from "@bcts/envelope";
10
10
 
11
11
  //#region rolldown:runtime
12
12
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
@@ -16,54 +16,54 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
16
16
  /**
17
17
  * Error types for Provenance Mark operations.
18
18
  */
19
- let ProvenanceMarkErrorType = /* @__PURE__ */ function(ProvenanceMarkErrorType$1) {
19
+ let ProvenanceMarkErrorType = /* @__PURE__ */ function(ProvenanceMarkErrorType) {
20
20
  /** Invalid Seed length */
21
- ProvenanceMarkErrorType$1["InvalidSeedLength"] = "InvalidSeedLength";
21
+ ProvenanceMarkErrorType["InvalidSeedLength"] = "InvalidSeedLength";
22
22
  /** Duplicate key */
23
- ProvenanceMarkErrorType$1["DuplicateKey"] = "DuplicateKey";
23
+ ProvenanceMarkErrorType["DuplicateKey"] = "DuplicateKey";
24
24
  /** Missing key */
25
- ProvenanceMarkErrorType$1["MissingKey"] = "MissingKey";
25
+ ProvenanceMarkErrorType["MissingKey"] = "MissingKey";
26
26
  /** Invalid key */
27
- ProvenanceMarkErrorType$1["InvalidKey"] = "InvalidKey";
27
+ ProvenanceMarkErrorType["InvalidKey"] = "InvalidKey";
28
28
  /** Extra keys */
29
- ProvenanceMarkErrorType$1["ExtraKeys"] = "ExtraKeys";
29
+ ProvenanceMarkErrorType["ExtraKeys"] = "ExtraKeys";
30
30
  /** Invalid key length for the given resolution */
31
- ProvenanceMarkErrorType$1["InvalidKeyLength"] = "InvalidKeyLength";
31
+ ProvenanceMarkErrorType["InvalidKeyLength"] = "InvalidKeyLength";
32
32
  /** Invalid next key length for the given resolution */
33
- ProvenanceMarkErrorType$1["InvalidNextKeyLength"] = "InvalidNextKeyLength";
33
+ ProvenanceMarkErrorType["InvalidNextKeyLength"] = "InvalidNextKeyLength";
34
34
  /** Invalid chain ID length for the given resolution */
35
- ProvenanceMarkErrorType$1["InvalidChainIdLength"] = "InvalidChainIdLength";
35
+ ProvenanceMarkErrorType["InvalidChainIdLength"] = "InvalidChainIdLength";
36
36
  /** Invalid message length for the given resolution */
37
- ProvenanceMarkErrorType$1["InvalidMessageLength"] = "InvalidMessageLength";
37
+ ProvenanceMarkErrorType["InvalidMessageLength"] = "InvalidMessageLength";
38
38
  /** Invalid CBOR data in info field */
39
- ProvenanceMarkErrorType$1["InvalidInfoCbor"] = "InvalidInfoCbor";
39
+ ProvenanceMarkErrorType["InvalidInfoCbor"] = "InvalidInfoCbor";
40
40
  /** Date out of range for serialization */
41
- ProvenanceMarkErrorType$1["DateOutOfRange"] = "DateOutOfRange";
41
+ ProvenanceMarkErrorType["DateOutOfRange"] = "DateOutOfRange";
42
42
  /** Invalid date components */
43
- ProvenanceMarkErrorType$1["InvalidDate"] = "InvalidDate";
43
+ ProvenanceMarkErrorType["InvalidDate"] = "InvalidDate";
44
44
  /** Missing required URL parameter */
45
- ProvenanceMarkErrorType$1["MissingUrlParameter"] = "MissingUrlParameter";
45
+ ProvenanceMarkErrorType["MissingUrlParameter"] = "MissingUrlParameter";
46
46
  /** Year out of range for 2-byte serialization */
47
- ProvenanceMarkErrorType$1["YearOutOfRange"] = "YearOutOfRange";
47
+ ProvenanceMarkErrorType["YearOutOfRange"] = "YearOutOfRange";
48
48
  /** Invalid month or day */
49
- ProvenanceMarkErrorType$1["InvalidMonthOrDay"] = "InvalidMonthOrDay";
49
+ ProvenanceMarkErrorType["InvalidMonthOrDay"] = "InvalidMonthOrDay";
50
50
  /** Resolution serialization error */
51
- ProvenanceMarkErrorType$1["ResolutionError"] = "ResolutionError";
51
+ ProvenanceMarkErrorType["ResolutionError"] = "ResolutionError";
52
52
  /** Bytewords encoding/decoding error */
53
- ProvenanceMarkErrorType$1["BytewordsError"] = "BytewordsError";
53
+ ProvenanceMarkErrorType["BytewordsError"] = "BytewordsError";
54
54
  /** CBOR encoding/decoding error */
55
- ProvenanceMarkErrorType$1["CborError"] = "CborError";
55
+ ProvenanceMarkErrorType["CborError"] = "CborError";
56
56
  /** URL parsing error */
57
- ProvenanceMarkErrorType$1["UrlError"] = "UrlError";
57
+ ProvenanceMarkErrorType["UrlError"] = "UrlError";
58
58
  /** Base64 decoding error */
59
- ProvenanceMarkErrorType$1["Base64Error"] = "Base64Error";
59
+ ProvenanceMarkErrorType["Base64Error"] = "Base64Error";
60
60
  /** JSON serialization error */
61
- ProvenanceMarkErrorType$1["JsonError"] = "JsonError";
61
+ ProvenanceMarkErrorType["JsonError"] = "JsonError";
62
62
  /** Integer conversion error */
63
- ProvenanceMarkErrorType$1["IntegerConversionError"] = "IntegerConversionError";
63
+ ProvenanceMarkErrorType["IntegerConversionError"] = "IntegerConversionError";
64
64
  /** Validation error */
65
- ProvenanceMarkErrorType$1["ValidationError"] = "ValidationError";
66
- return ProvenanceMarkErrorType$1;
65
+ ProvenanceMarkErrorType["ValidationError"] = "ValidationError";
66
+ return ProvenanceMarkErrorType;
67
67
  }({});
68
68
  /**
69
69
  * Error class for Provenance Mark operations.
@@ -258,12 +258,12 @@ function dateToDateString(date) {
258
258
  * Resolution levels for provenance marks.
259
259
  * Higher resolution provides more security but larger mark sizes.
260
260
  */
261
- let ProvenanceMarkResolution = /* @__PURE__ */ function(ProvenanceMarkResolution$1) {
262
- ProvenanceMarkResolution$1[ProvenanceMarkResolution$1["Low"] = 0] = "Low";
263
- ProvenanceMarkResolution$1[ProvenanceMarkResolution$1["Medium"] = 1] = "Medium";
264
- ProvenanceMarkResolution$1[ProvenanceMarkResolution$1["Quartile"] = 2] = "Quartile";
265
- ProvenanceMarkResolution$1[ProvenanceMarkResolution$1["High"] = 3] = "High";
266
- return ProvenanceMarkResolution$1;
261
+ let ProvenanceMarkResolution = /* @__PURE__ */ function(ProvenanceMarkResolution) {
262
+ ProvenanceMarkResolution[ProvenanceMarkResolution["Low"] = 0] = "Low";
263
+ ProvenanceMarkResolution[ProvenanceMarkResolution["Medium"] = 1] = "Medium";
264
+ ProvenanceMarkResolution[ProvenanceMarkResolution["Quartile"] = 2] = "Quartile";
265
+ ProvenanceMarkResolution[ProvenanceMarkResolution["High"] = 3] = "High";
266
+ return ProvenanceMarkResolution;
267
267
  }({});
268
268
  /**
269
269
  * Convert a resolution to its numeric value.
@@ -694,9 +694,9 @@ var ProvenanceSeed = class ProvenanceSeed {
694
694
  /**
695
695
  * Create a new seed using custom random data.
696
696
  */
697
- static newUsing(randomData$1) {
698
- if (randomData$1.length < PROVENANCE_SEED_LENGTH) throw new ProvenanceMarkError(ProvenanceMarkErrorType.InvalidSeedLength, void 0, { actual: randomData$1.length });
699
- return ProvenanceSeed.fromBytes(randomData$1.slice(0, PROVENANCE_SEED_LENGTH));
697
+ static newUsing(randomData) {
698
+ if (randomData.length < PROVENANCE_SEED_LENGTH) throw new ProvenanceMarkError(ProvenanceMarkErrorType.InvalidSeedLength, void 0, { actual: randomData.length });
699
+ return ProvenanceSeed.fromBytes(randomData.slice(0, PROVENANCE_SEED_LENGTH));
700
700
  }
701
701
  /**
702
702
  * Create a new seed from a passphrase.
@@ -802,6 +802,279 @@ function fromBase64(base64) {
802
802
  throw new Error("atob not available and require is not defined");
803
803
  }
804
804
 
805
+ //#endregion
806
+ //#region src/validate.ts
807
+ /**
808
+ * Format for validation report output.
809
+ */
810
+ let ValidationReportFormat = /* @__PURE__ */ function(ValidationReportFormat) {
811
+ /** Human-readable text format */
812
+ ValidationReportFormat["Text"] = "text";
813
+ /** Compact JSON format (no whitespace) */
814
+ ValidationReportFormat["JsonCompact"] = "json-compact";
815
+ /** Pretty-printed JSON format (with indentation) */
816
+ ValidationReportFormat["JsonPretty"] = "json-pretty";
817
+ return ValidationReportFormat;
818
+ }({});
819
+ /**
820
+ * Format a validation issue as a string.
821
+ */
822
+ function formatValidationIssue(issue) {
823
+ switch (issue.type) {
824
+ case "HashMismatch": return `hash mismatch: expected ${issue.expected}, got ${issue.actual}`;
825
+ case "KeyMismatch": return "key mismatch: current hash was not generated from next key";
826
+ case "SequenceGap": return `sequence number gap: expected ${issue.expected}, got ${issue.actual}`;
827
+ case "DateOrdering": return `date must be equal or later: previous is ${issue.previous}, next is ${issue.next}`;
828
+ case "NonGenesisAtZero": return "non-genesis mark at sequence 0";
829
+ case "InvalidGenesisKey": return "genesis mark must have key equal to chain_id";
830
+ }
831
+ }
832
+ /**
833
+ * Get the chain ID as a hex string for display.
834
+ */
835
+ function chainIdHex(report) {
836
+ return hexEncode(report.chainId);
837
+ }
838
+ /**
839
+ * Check if the validation report has any issues.
840
+ */
841
+ function hasIssues(report) {
842
+ for (const chain of report.chains) if (!chain.hasGenesis) return true;
843
+ for (const chain of report.chains) for (const seq of chain.sequences) for (const mark of seq.marks) if (mark.issues.length > 0) return true;
844
+ if (report.chains.length > 1) return true;
845
+ if (report.chains.length === 1 && report.chains[0].sequences.length > 1) return true;
846
+ return false;
847
+ }
848
+ /**
849
+ * Check if the validation report contains interesting information.
850
+ */
851
+ function isInteresting(report) {
852
+ if (report.chains.length === 0) return false;
853
+ for (const chain of report.chains) if (!chain.hasGenesis) return true;
854
+ if (report.chains.length === 1) {
855
+ const chain = report.chains[0];
856
+ if (chain.sequences.length === 1) {
857
+ if (chain.sequences[0].marks.every((m) => m.issues.length === 0)) return false;
858
+ }
859
+ }
860
+ return true;
861
+ }
862
+ /**
863
+ * Format the validation report as human-readable text.
864
+ */
865
+ function formatText(report) {
866
+ if (!isInteresting(report)) return "";
867
+ const lines = [];
868
+ lines.push(`Total marks: ${report.marks.length}`);
869
+ lines.push(`Chains: ${report.chains.length}`);
870
+ lines.push("");
871
+ for (let chainIdx = 0; chainIdx < report.chains.length; chainIdx++) {
872
+ const chain = report.chains[chainIdx];
873
+ const chainIdStr = chainIdHex(chain);
874
+ const shortChainId = chainIdStr.length > 8 ? chainIdStr.slice(0, 8) : chainIdStr;
875
+ lines.push(`Chain ${chainIdx + 1}: ${shortChainId}`);
876
+ if (!chain.hasGenesis) lines.push(" Warning: No genesis mark found");
877
+ for (const seq of chain.sequences) for (const flaggedMark of seq.marks) {
878
+ const mark = flaggedMark.mark;
879
+ const shortId = mark.identifier();
880
+ const seqNum = mark.seq();
881
+ const annotations = [];
882
+ if (mark.isGenesis()) annotations.push("genesis mark");
883
+ for (const issue of flaggedMark.issues) {
884
+ let issueStr;
885
+ switch (issue.type) {
886
+ case "SequenceGap":
887
+ issueStr = `gap: ${issue.expected} missing`;
888
+ break;
889
+ case "DateOrdering":
890
+ issueStr = `date ${issue.previous} < ${issue.next}`;
891
+ break;
892
+ case "HashMismatch":
893
+ issueStr = "hash mismatch";
894
+ break;
895
+ case "KeyMismatch":
896
+ issueStr = "key mismatch";
897
+ break;
898
+ case "NonGenesisAtZero":
899
+ issueStr = "non-genesis at seq 0";
900
+ break;
901
+ case "InvalidGenesisKey":
902
+ issueStr = "invalid genesis key";
903
+ break;
904
+ }
905
+ annotations.push(issueStr);
906
+ }
907
+ if (annotations.length === 0) lines.push(` ${seqNum}: ${shortId}`);
908
+ else lines.push(` ${seqNum}: ${shortId} (${annotations.join(", ")})`);
909
+ }
910
+ lines.push("");
911
+ }
912
+ return lines.join("\n").trimEnd();
913
+ }
914
+ /**
915
+ * Format the validation report.
916
+ */
917
+ function formatReport(report, format) {
918
+ switch (format) {
919
+ case ValidationReportFormat.Text: return formatText(report);
920
+ case ValidationReportFormat.JsonCompact: return JSON.stringify(reportToJSON(report));
921
+ case ValidationReportFormat.JsonPretty: return JSON.stringify(reportToJSON(report), null, 2);
922
+ }
923
+ }
924
+ /**
925
+ * Convert a report to a JSON-serializable object.
926
+ */
927
+ function reportToJSON(report) {
928
+ return {
929
+ marks: report.marks.map((m) => m.urString()),
930
+ chains: report.chains.map((chain) => ({
931
+ chain_id: hexEncode(chain.chainId),
932
+ has_genesis: chain.hasGenesis,
933
+ marks: chain.marks.map((m) => m.urString()),
934
+ sequences: chain.sequences.map((seq) => ({
935
+ start_seq: seq.startSeq,
936
+ end_seq: seq.endSeq,
937
+ marks: seq.marks.map((fm) => ({
938
+ mark: fm.mark.urString(),
939
+ issues: fm.issues.map(issueToJSON)
940
+ }))
941
+ }))
942
+ }))
943
+ };
944
+ }
945
+ /**
946
+ * Convert a ValidationIssue to JSON matching Rust's serde format.
947
+ *
948
+ * Rust uses `#[serde(tag = "type", content = "data")]` which wraps
949
+ * struct variant data in a `"data"` field. Unit variants have no
950
+ * `"data"` field.
951
+ */
952
+ function issueToJSON(issue) {
953
+ switch (issue.type) {
954
+ case "HashMismatch": return {
955
+ type: "HashMismatch",
956
+ data: {
957
+ expected: issue.expected,
958
+ actual: issue.actual
959
+ }
960
+ };
961
+ case "SequenceGap": return {
962
+ type: "SequenceGap",
963
+ data: {
964
+ expected: issue.expected,
965
+ actual: issue.actual
966
+ }
967
+ };
968
+ case "DateOrdering": return {
969
+ type: "DateOrdering",
970
+ data: {
971
+ previous: issue.previous,
972
+ next: issue.next
973
+ }
974
+ };
975
+ case "KeyMismatch": return { type: "KeyMismatch" };
976
+ case "NonGenesisAtZero": return { type: "NonGenesisAtZero" };
977
+ case "InvalidGenesisKey": return { type: "InvalidGenesisKey" };
978
+ }
979
+ }
980
+ /**
981
+ * Build sequence bins for a chain.
982
+ */
983
+ function buildSequenceBins(marks) {
984
+ const sequences = [];
985
+ let currentSequence = [];
986
+ for (let i = 0; i < marks.length; i++) {
987
+ const mark = marks[i];
988
+ if (i === 0) currentSequence.push({
989
+ mark,
990
+ issues: []
991
+ });
992
+ else {
993
+ const prev = marks[i - 1];
994
+ try {
995
+ prev.precedesOpt(mark);
996
+ currentSequence.push({
997
+ mark,
998
+ issues: []
999
+ });
1000
+ } catch (e) {
1001
+ if (currentSequence.length > 0) sequences.push(createSequenceReport(currentSequence));
1002
+ let issue;
1003
+ if (e instanceof ProvenanceMarkError && e.details?.["validationIssue"] !== void 0) issue = e.details["validationIssue"];
1004
+ else issue = { type: "KeyMismatch" };
1005
+ currentSequence = [{
1006
+ mark,
1007
+ issues: [issue]
1008
+ }];
1009
+ }
1010
+ }
1011
+ }
1012
+ if (currentSequence.length > 0) sequences.push(createSequenceReport(currentSequence));
1013
+ return sequences;
1014
+ }
1015
+ /**
1016
+ * Create a sequence report from flagged marks.
1017
+ */
1018
+ function createSequenceReport(marks) {
1019
+ return {
1020
+ startSeq: marks.length > 0 ? marks[0].mark.seq() : 0,
1021
+ endSeq: marks.length > 0 ? marks[marks.length - 1].mark.seq() : 0,
1022
+ marks
1023
+ };
1024
+ }
1025
+ /**
1026
+ * Validate a collection of provenance marks.
1027
+ */
1028
+ function validate(marks) {
1029
+ const seen = /* @__PURE__ */ new Set();
1030
+ const deduplicatedMarks = [];
1031
+ for (const mark of marks) {
1032
+ const key = `${mark.res()}:${hexEncode(mark.message())}`;
1033
+ if (!seen.has(key)) {
1034
+ seen.add(key);
1035
+ deduplicatedMarks.push(mark);
1036
+ }
1037
+ }
1038
+ const chainBins = /* @__PURE__ */ new Map();
1039
+ for (const mark of deduplicatedMarks) {
1040
+ const chainIdKey = hexEncode(mark.chainId());
1041
+ const bin = chainBins.get(chainIdKey);
1042
+ if (bin !== void 0) bin.push(mark);
1043
+ else chainBins.set(chainIdKey, [mark]);
1044
+ }
1045
+ const chains = [];
1046
+ for (const [chainIdKey, chainMarks] of chainBins) {
1047
+ chainMarks.sort((a, b) => a.seq() - b.seq());
1048
+ const hasGenesis = chainMarks.length > 0 && chainMarks[0].seq() === 0 && chainMarks[0].isGenesis();
1049
+ const sequences = buildSequenceBins(chainMarks);
1050
+ chains.push({
1051
+ chainId: hexDecode(chainIdKey),
1052
+ hasGenesis,
1053
+ marks: chainMarks,
1054
+ sequences
1055
+ });
1056
+ }
1057
+ chains.sort((a, b) => hexEncode(a.chainId).localeCompare(hexEncode(b.chainId)));
1058
+ return {
1059
+ marks: deduplicatedMarks,
1060
+ chains
1061
+ };
1062
+ }
1063
+ /**
1064
+ * Helper function to encode bytes as hex.
1065
+ */
1066
+ function hexEncode(bytes) {
1067
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1068
+ }
1069
+ /**
1070
+ * Helper function to decode hex to bytes.
1071
+ */
1072
+ function hexDecode(hex) {
1073
+ const bytes = new Uint8Array(hex.length / 2);
1074
+ for (let i = 0; i < hex.length; i += 2) bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
1075
+ return bytes;
1076
+ }
1077
+
805
1078
  //#endregion
806
1079
  //#region src/mark.ts
807
1080
  /**
@@ -953,6 +1226,33 @@ var ProvenanceMark = class ProvenanceMark {
953
1226
  return prefix ? `\u{1F151} ${s}` : s;
954
1227
  }
955
1228
  /**
1229
+ * A compact 8-letter identifier derived from the upper-case ByteWords
1230
+ * identifier by taking the first and last letter of each ByteWords word
1231
+ * (4 words x 2 letters = 8 letters).
1232
+ *
1233
+ * Example: "ABLE ACID ALSO APEX" -> "AEADAOAX"
1234
+ * If prefix is true, prepends the provenance mark prefix character.
1235
+ */
1236
+ bytewordsMinimalIdentifier(prefix) {
1237
+ const full = encodeBytewordsIdentifier(this._hash.slice(0, 4));
1238
+ const words = full.split(/\s+/);
1239
+ let out = "";
1240
+ if (words.length === 4) for (const w of words) {
1241
+ if (w.length === 0) continue;
1242
+ out += w[0].toUpperCase();
1243
+ out += w[w.length - 1].toUpperCase();
1244
+ }
1245
+ if (out.length !== 8) {
1246
+ out = "";
1247
+ const compact = full.replace(/[^a-zA-Z]/g, "").toUpperCase();
1248
+ for (let i = 0; i + 3 < compact.length; i += 4) {
1249
+ out += compact[i];
1250
+ out += compact[i + 3];
1251
+ }
1252
+ }
1253
+ return prefix ? `\u{1F151} ${out}` : out;
1254
+ }
1255
+ /**
956
1256
  * Get the first four bytes of the hash as Bytemoji.
957
1257
  */
958
1258
  bytemojiIdentifier(prefix) {
@@ -972,18 +1272,39 @@ var ProvenanceMark = class ProvenanceMark {
972
1272
  }
973
1273
  /**
974
1274
  * Check if this mark precedes another mark, throwing on validation errors.
1275
+ * Errors carry a structured `validationIssue` in their details, matching Rust's
1276
+ * `Error::Validation(ValidationIssue)` pattern.
975
1277
  */
976
1278
  precedesOpt(next) {
977
- if (next._seq === 0) throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, void 0, { message: "non-genesis mark at sequence 0" });
978
- if (arraysEqual(next._key, next._chainId)) throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, void 0, { message: "genesis mark must have key equal to chain_id" });
979
- if (this._seq !== next._seq - 1) throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, void 0, { message: `sequence gap: expected ${this._seq + 1}, got ${next._seq}` });
980
- if (this._date > next._date) throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, void 0, { message: `date ordering: ${this._date.toISOString()} > ${next._date.toISOString()}` });
1279
+ if (next._seq === 0) throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, "non-genesis mark at sequence 0", { validationIssue: { type: "NonGenesisAtZero" } });
1280
+ if (arraysEqual(next._key, next._chainId)) throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, "genesis mark must have key equal to chain_id", { validationIssue: { type: "InvalidGenesisKey" } });
1281
+ if (this._seq !== next._seq - 1) {
1282
+ const issue = {
1283
+ type: "SequenceGap",
1284
+ expected: this._seq + 1,
1285
+ actual: next._seq
1286
+ };
1287
+ throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, `sequence gap: expected ${this._seq + 1}, got ${next._seq}`, { validationIssue: issue });
1288
+ }
1289
+ if (this._date > next._date) {
1290
+ const dateStr = this._date.toISOString().replace(".000Z", "Z");
1291
+ const nextDateStr = next._date.toISOString().replace(".000Z", "Z");
1292
+ const issue = {
1293
+ type: "DateOrdering",
1294
+ previous: dateStr,
1295
+ next: nextDateStr
1296
+ };
1297
+ throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, `date ordering: ${dateStr} > ${nextDateStr}`, { validationIssue: issue });
1298
+ }
981
1299
  const expectedHash = ProvenanceMark.makeHash(this._res, this._key, next._key, this._chainId, this._seqBytes, this._dateBytes, this._infoBytes);
982
- if (!arraysEqual(this._hash, expectedHash)) throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, void 0, {
983
- message: "hash mismatch",
984
- expected: Array.from(expectedHash).map((b) => b.toString(16).padStart(2, "0")).join(""),
985
- actual: Array.from(this._hash).map((b) => b.toString(16).padStart(2, "0")).join("")
986
- });
1300
+ if (!arraysEqual(this._hash, expectedHash)) {
1301
+ const issue = {
1302
+ type: "HashMismatch",
1303
+ expected: bytesToHex(expectedHash),
1304
+ actual: bytesToHex(this._hash)
1305
+ };
1306
+ throw new ProvenanceMarkError(ProvenanceMarkErrorType.ValidationError, `hash mismatch: expected ${bytesToHex(expectedHash)}, got ${bytesToHex(this._hash)}`, { validationIssue: issue });
1307
+ }
987
1308
  }
988
1309
  /**
989
1310
  * Check if a sequence of marks is valid.
@@ -1181,30 +1502,35 @@ var ProvenanceMark = class ProvenanceMark {
1181
1502
  return new ProvenanceMark(res, key, hash, chainId, seqBytes, dateBytes, infoBytes, seq, date);
1182
1503
  }
1183
1504
  /**
1184
- * Convert this provenance mark to a Gordian Envelope.
1505
+ * Validate a collection of provenance marks.
1185
1506
  *
1186
- * The envelope contains the tagged CBOR representation of the mark.
1507
+ * Matches Rust: `ProvenanceMark::validate()` which delegates to
1508
+ * `ValidationReport::validate()`.
1509
+ */
1510
+ static validate(marks) {
1511
+ return validate(marks);
1512
+ }
1513
+ /**
1514
+ * Convert this provenance mark to a Gordian Envelope.
1187
1515
  *
1188
- * Note: Use provenanceMarkToEnvelope() for a standalone function alternative.
1516
+ * Creates a leaf envelope containing the tagged CBOR representation.
1517
+ * Matches Rust: `Envelope::new(mark.to_cbor())` which creates a CBOR leaf.
1189
1518
  */
1190
1519
  intoEnvelope() {
1191
- return Envelope.new(this.toCborData());
1520
+ return Envelope.newLeaf(this.taggedCbor());
1192
1521
  }
1193
1522
  /**
1194
1523
  * Extract a ProvenanceMark from a Gordian Envelope.
1195
1524
  *
1525
+ * Matches Rust: `envelope.subject().try_leaf()?.try_into()`
1526
+ *
1196
1527
  * @param envelope - The envelope to extract from
1197
1528
  * @returns The extracted provenance mark
1198
1529
  * @throws ProvenanceMarkError if extraction fails
1199
1530
  */
1200
1531
  static fromEnvelope(envelope) {
1201
- const bytes = envelope.asByteString();
1202
- if (bytes !== void 0) return ProvenanceMark.fromCborData(bytes);
1203
- const envCase = envelope.case();
1204
- if (envCase.type === "node") {
1205
- const subjectBytes = envCase.subject.asByteString();
1206
- if (subjectBytes !== void 0) return ProvenanceMark.fromCborData(subjectBytes);
1207
- }
1532
+ const leaf = envelope.subject().asLeaf();
1533
+ if (leaf !== void 0) return ProvenanceMark.fromTaggedCbor(leaf);
1208
1534
  throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: "Could not extract ProvenanceMark from envelope" });
1209
1535
  }
1210
1536
  };
@@ -1269,8 +1595,8 @@ var ProvenanceMarkGenerator = class ProvenanceMarkGenerator {
1269
1595
  /**
1270
1596
  * Create a new generator with custom random data.
1271
1597
  */
1272
- static newUsing(res, randomData$1) {
1273
- const seed = ProvenanceSeed.newUsing(randomData$1);
1598
+ static newUsing(res, randomData) {
1599
+ const seed = ProvenanceSeed.newUsing(randomData);
1274
1600
  return ProvenanceMarkGenerator.newWithSeed(res, seed);
1275
1601
  }
1276
1602
  /**
@@ -1397,276 +1723,6 @@ var ProvenanceMarkGenerator = class ProvenanceMarkGenerator {
1397
1723
  }
1398
1724
  };
1399
1725
 
1400
- //#endregion
1401
- //#region src/validate.ts
1402
- /**
1403
- * Format for validation report output.
1404
- */
1405
- let ValidationReportFormat = /* @__PURE__ */ function(ValidationReportFormat$1) {
1406
- /** Human-readable text format */
1407
- ValidationReportFormat$1["Text"] = "text";
1408
- /** Compact JSON format (no whitespace) */
1409
- ValidationReportFormat$1["JsonCompact"] = "json-compact";
1410
- /** Pretty-printed JSON format (with indentation) */
1411
- ValidationReportFormat$1["JsonPretty"] = "json-pretty";
1412
- return ValidationReportFormat$1;
1413
- }({});
1414
- /**
1415
- * Format a validation issue as a string.
1416
- */
1417
- function formatValidationIssue(issue) {
1418
- switch (issue.type) {
1419
- case "HashMismatch": return `hash mismatch: expected ${issue.expected}, got ${issue.actual}`;
1420
- case "KeyMismatch": return "key mismatch: current hash was not generated from next key";
1421
- case "SequenceGap": return `sequence number gap: expected ${issue.expected}, got ${issue.actual}`;
1422
- case "DateOrdering": return `date must be equal or later: previous is ${issue.previous}, next is ${issue.next}`;
1423
- case "NonGenesisAtZero": return "non-genesis mark at sequence 0";
1424
- case "InvalidGenesisKey": return "genesis mark must have key equal to chain_id";
1425
- }
1426
- }
1427
- /**
1428
- * Get the chain ID as a hex string for display.
1429
- */
1430
- function chainIdHex(report) {
1431
- return hexEncode(report.chainId);
1432
- }
1433
- /**
1434
- * Check if the validation report has any issues.
1435
- */
1436
- function hasIssues(report) {
1437
- for (const chain of report.chains) if (!chain.hasGenesis) return true;
1438
- for (const chain of report.chains) for (const seq of chain.sequences) for (const mark of seq.marks) if (mark.issues.length > 0) return true;
1439
- if (report.chains.length > 1) return true;
1440
- if (report.chains.length === 1 && report.chains[0].sequences.length > 1) return true;
1441
- return false;
1442
- }
1443
- /**
1444
- * Check if the validation report contains interesting information.
1445
- */
1446
- function isInteresting(report) {
1447
- if (report.chains.length === 0) return false;
1448
- for (const chain of report.chains) if (!chain.hasGenesis) return true;
1449
- if (report.chains.length === 1) {
1450
- const chain = report.chains[0];
1451
- if (chain.sequences.length === 1) {
1452
- if (chain.sequences[0].marks.every((m) => m.issues.length === 0)) return false;
1453
- }
1454
- }
1455
- return true;
1456
- }
1457
- /**
1458
- * Format the validation report as human-readable text.
1459
- */
1460
- function formatText(report) {
1461
- if (!isInteresting(report)) return "";
1462
- const lines = [];
1463
- lines.push(`Total marks: ${report.marks.length}`);
1464
- lines.push(`Chains: ${report.chains.length}`);
1465
- lines.push("");
1466
- for (let chainIdx = 0; chainIdx < report.chains.length; chainIdx++) {
1467
- const chain = report.chains[chainIdx];
1468
- const chainIdStr = chainIdHex(chain);
1469
- const shortChainId = chainIdStr.length > 8 ? chainIdStr.slice(0, 8) : chainIdStr;
1470
- lines.push(`Chain ${chainIdx + 1}: ${shortChainId}`);
1471
- if (!chain.hasGenesis) lines.push(" Warning: No genesis mark found");
1472
- for (const seq of chain.sequences) for (const flaggedMark of seq.marks) {
1473
- const mark = flaggedMark.mark;
1474
- const shortId = mark.identifier();
1475
- const seqNum = mark.seq();
1476
- const annotations = [];
1477
- if (mark.isGenesis()) annotations.push("genesis mark");
1478
- for (const issue of flaggedMark.issues) {
1479
- let issueStr;
1480
- switch (issue.type) {
1481
- case "SequenceGap":
1482
- issueStr = `gap: ${issue.expected} missing`;
1483
- break;
1484
- case "DateOrdering":
1485
- issueStr = `date ${issue.previous} < ${issue.next}`;
1486
- break;
1487
- case "HashMismatch":
1488
- issueStr = "hash mismatch";
1489
- break;
1490
- case "KeyMismatch":
1491
- issueStr = "key mismatch";
1492
- break;
1493
- case "NonGenesisAtZero":
1494
- issueStr = "non-genesis at seq 0";
1495
- break;
1496
- case "InvalidGenesisKey":
1497
- issueStr = "invalid genesis key";
1498
- break;
1499
- }
1500
- annotations.push(issueStr);
1501
- }
1502
- if (annotations.length === 0) lines.push(` ${seqNum}: ${shortId}`);
1503
- else lines.push(` ${seqNum}: ${shortId} (${annotations.join(", ")})`);
1504
- }
1505
- lines.push("");
1506
- }
1507
- return lines.join("\n").trimEnd();
1508
- }
1509
- /**
1510
- * Format the validation report.
1511
- */
1512
- function formatReport(report, format) {
1513
- switch (format) {
1514
- case ValidationReportFormat.Text: return formatText(report);
1515
- case ValidationReportFormat.JsonCompact: return JSON.stringify(reportToJSON(report));
1516
- case ValidationReportFormat.JsonPretty: return JSON.stringify(reportToJSON(report), null, 2);
1517
- }
1518
- }
1519
- /**
1520
- * Convert a report to a JSON-serializable object.
1521
- */
1522
- function reportToJSON(report) {
1523
- return {
1524
- marks: report.marks.map((m) => m.toUrlEncoding()),
1525
- chains: report.chains.map((chain) => ({
1526
- chain_id: hexEncode(chain.chainId),
1527
- has_genesis: chain.hasGenesis,
1528
- marks: chain.marks.map((m) => m.toUrlEncoding()),
1529
- sequences: chain.sequences.map((seq) => ({
1530
- start_seq: seq.startSeq,
1531
- end_seq: seq.endSeq,
1532
- marks: seq.marks.map((fm) => ({
1533
- mark: fm.mark.toUrlEncoding(),
1534
- issues: fm.issues
1535
- }))
1536
- }))
1537
- }))
1538
- };
1539
- }
1540
- /**
1541
- * Build sequence bins for a chain.
1542
- */
1543
- function buildSequenceBins(marks) {
1544
- const sequences = [];
1545
- let currentSequence = [];
1546
- for (let i = 0; i < marks.length; i++) {
1547
- const mark = marks[i];
1548
- if (i === 0) currentSequence.push({
1549
- mark,
1550
- issues: []
1551
- });
1552
- else {
1553
- const prev = marks[i - 1];
1554
- try {
1555
- prev.precedesOpt(mark);
1556
- currentSequence.push({
1557
- mark,
1558
- issues: []
1559
- });
1560
- } catch (e) {
1561
- if (currentSequence.length > 0) sequences.push(createSequenceReport(currentSequence));
1562
- currentSequence = [{
1563
- mark,
1564
- issues: [parseValidationError(e, prev, mark)]
1565
- }];
1566
- }
1567
- }
1568
- }
1569
- if (currentSequence.length > 0) sequences.push(createSequenceReport(currentSequence));
1570
- return sequences;
1571
- }
1572
- /**
1573
- * Parse a validation error into a ValidationIssue.
1574
- */
1575
- function parseValidationError(e, prev, next) {
1576
- const message = e instanceof Error ? e.message : "";
1577
- if (message !== "" && message.includes("non-genesis mark at sequence 0")) return { type: "NonGenesisAtZero" };
1578
- if (message !== "" && message.includes("genesis mark must have key equal to chain_id")) return { type: "InvalidGenesisKey" };
1579
- if (message !== "" && message.includes("sequence gap")) {
1580
- const match = /expected (\d+), got (\d+)/.exec(message);
1581
- if (match !== null) return {
1582
- type: "SequenceGap",
1583
- expected: parseInt(match[1], 10),
1584
- actual: parseInt(match[2], 10)
1585
- };
1586
- }
1587
- if (message !== "" && message.includes("date ordering")) return {
1588
- type: "DateOrdering",
1589
- previous: prev.date().toISOString(),
1590
- next: next.date().toISOString()
1591
- };
1592
- if (message !== "" && message.includes("hash mismatch")) {
1593
- const match = /expected: (\w+), actual: (\w+)/.exec(message);
1594
- if (match !== null) return {
1595
- type: "HashMismatch",
1596
- expected: match[1],
1597
- actual: match[2]
1598
- };
1599
- return {
1600
- type: "HashMismatch",
1601
- expected: "",
1602
- actual: ""
1603
- };
1604
- }
1605
- return { type: "KeyMismatch" };
1606
- }
1607
- /**
1608
- * Create a sequence report from flagged marks.
1609
- */
1610
- function createSequenceReport(marks) {
1611
- return {
1612
- startSeq: marks.length > 0 ? marks[0].mark.seq() : 0,
1613
- endSeq: marks.length > 0 ? marks[marks.length - 1].mark.seq() : 0,
1614
- marks
1615
- };
1616
- }
1617
- /**
1618
- * Validate a collection of provenance marks.
1619
- */
1620
- function validate(marks) {
1621
- const seen = /* @__PURE__ */ new Set();
1622
- const deduplicatedMarks = [];
1623
- for (const mark of marks) {
1624
- const key = mark.toUrlEncoding();
1625
- if (!seen.has(key)) {
1626
- seen.add(key);
1627
- deduplicatedMarks.push(mark);
1628
- }
1629
- }
1630
- const chainBins = /* @__PURE__ */ new Map();
1631
- for (const mark of deduplicatedMarks) {
1632
- const chainIdKey = hexEncode(mark.chainId());
1633
- const bin = chainBins.get(chainIdKey);
1634
- if (bin !== void 0) bin.push(mark);
1635
- else chainBins.set(chainIdKey, [mark]);
1636
- }
1637
- const chains = [];
1638
- for (const [chainIdKey, chainMarks] of chainBins) {
1639
- chainMarks.sort((a, b) => a.seq() - b.seq());
1640
- const hasGenesis = chainMarks.length > 0 && chainMarks[0].seq() === 0 && chainMarks[0].isGenesis();
1641
- const sequences = buildSequenceBins(chainMarks);
1642
- chains.push({
1643
- chainId: hexDecode(chainIdKey),
1644
- hasGenesis,
1645
- marks: chainMarks,
1646
- sequences
1647
- });
1648
- }
1649
- chains.sort((a, b) => hexEncode(a.chainId).localeCompare(hexEncode(b.chainId)));
1650
- return {
1651
- marks: deduplicatedMarks,
1652
- chains
1653
- };
1654
- }
1655
- /**
1656
- * Helper function to encode bytes as hex.
1657
- */
1658
- function hexEncode(bytes) {
1659
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1660
- }
1661
- /**
1662
- * Helper function to decode hex to bytes.
1663
- */
1664
- function hexDecode(hex) {
1665
- const bytes = new Uint8Array(hex.length / 2);
1666
- for (let i = 0; i < hex.length; i += 2) bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
1667
- return bytes;
1668
- }
1669
-
1670
1726
  //#endregion
1671
1727
  //#region src/mark-info.ts
1672
1728
  /**
@@ -1716,7 +1772,7 @@ var ProvenanceMarkInfo = class ProvenanceMarkInfo {
1716
1772
  const lines = [];
1717
1773
  lines.push("---");
1718
1774
  lines.push("");
1719
- lines.push(this._mark.date().toISOString());
1775
+ lines.push(this._mark.date().toISOString().replace(".000Z", "Z"));
1720
1776
  lines.push("");
1721
1777
  lines.push(`#### ${this._ur.toString()}`);
1722
1778
  lines.push("");
@@ -1771,110 +1827,86 @@ var ProvenanceMarkInfo = class ProvenanceMarkInfo {
1771
1827
  /**
1772
1828
  * Registers provenance mark tags in the global format context.
1773
1829
  *
1774
- * This function sets up a summarizer for the PROVENANCE_MARK tag that displays
1775
- * provenance marks in a human-readable format.
1830
+ * Matches Rust: register_tags()
1776
1831
  */
1777
1832
  function registerTags() {
1778
- registerTagsIn(globalTagsContext);
1833
+ withFormatContextMut((context) => {
1834
+ registerTagsIn(context);
1835
+ });
1779
1836
  }
1780
1837
  /**
1781
1838
  * Registers provenance mark tags in a specific format context.
1782
1839
  *
1840
+ * Matches Rust: register_tags_in()
1841
+ *
1783
1842
  * @param context - The format context to register tags in
1784
1843
  */
1785
1844
  function registerTagsIn(context) {
1786
- context.setSummarizer(Number(PROVENANCE_MARK.value), (cborValue) => {
1787
- return ProvenanceMark.fromUntaggedCbor(cborValue).toString();
1845
+ registerTagsIn$1(context);
1846
+ context.tags().setSummarizer(BigInt(PROVENANCE_MARK.value), (untaggedCbor, _flat) => {
1847
+ try {
1848
+ return {
1849
+ ok: true,
1850
+ value: ProvenanceMark.fromUntaggedCbor(untaggedCbor).toString()
1851
+ };
1852
+ } catch {
1853
+ return {
1854
+ ok: false,
1855
+ error: {
1856
+ type: "Custom",
1857
+ message: "invalid provenance mark"
1858
+ }
1859
+ };
1860
+ }
1788
1861
  });
1789
1862
  }
1790
- const globalTagsContext = { setSummarizer(_tag, _summarizer) {} };
1791
1863
  /**
1792
1864
  * Convert a ProvenanceMark to an Envelope.
1793
1865
  *
1794
- * The envelope contains the tagged CBOR representation of the mark.
1866
+ * Delegates to ProvenanceMark.intoEnvelope() single source of truth.
1795
1867
  *
1796
1868
  * @param mark - The provenance mark to convert
1797
1869
  * @returns An envelope containing the mark
1798
1870
  */
1799
1871
  function provenanceMarkToEnvelope(mark) {
1800
- return Envelope.new(mark.toCborData());
1872
+ return mark.intoEnvelope();
1801
1873
  }
1802
1874
  /**
1803
1875
  * Extract a ProvenanceMark from an Envelope.
1804
1876
  *
1877
+ * Delegates to ProvenanceMark.fromEnvelope() — single source of truth.
1878
+ *
1805
1879
  * @param envelope - The envelope to extract from
1806
1880
  * @returns The extracted provenance mark
1807
1881
  * @throws ProvenanceMarkError if extraction fails
1808
1882
  */
1809
1883
  function provenanceMarkFromEnvelope(envelope) {
1810
- const bytes = envelope.asByteString();
1811
- if (bytes !== void 0) return ProvenanceMark.fromCborData(bytes);
1812
- const envCase = envelope.case();
1813
- if (envCase.type === "node") {
1814
- const subjectBytes = envCase.subject.asByteString();
1815
- if (subjectBytes !== void 0) return ProvenanceMark.fromCborData(subjectBytes);
1816
- }
1817
- throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: "Could not extract ProvenanceMark from envelope" });
1884
+ return ProvenanceMark.fromEnvelope(envelope);
1818
1885
  }
1819
1886
  /**
1820
1887
  * Convert a ProvenanceMarkGenerator to an Envelope.
1821
1888
  *
1822
- * The envelope contains structured assertions for all generator fields:
1823
- * - type: "provenance-generator"
1824
- * - res: The resolution
1825
- * - seed: The seed
1826
- * - next-seq: The next sequence number
1827
- * - rng-state: The RNG state
1889
+ * Delegates to ProvenanceMarkGenerator.intoEnvelope() single source of truth.
1828
1890
  *
1829
1891
  * @param generator - The generator to convert
1830
1892
  * @returns An envelope containing the generator
1831
1893
  */
1832
1894
  function provenanceMarkGeneratorToEnvelope(generator) {
1833
- let envelope = Envelope.new(generator.chainId());
1834
- envelope = envelope.addType("provenance-generator");
1835
- envelope = envelope.addAssertion("res", resolutionToNumber(generator.res()));
1836
- envelope = envelope.addAssertion("seed", generator.seed().toBytes());
1837
- envelope = envelope.addAssertion("next-seq", generator.nextSeq());
1838
- envelope = envelope.addAssertion("rng-state", generator.rngState().toBytes());
1839
- return envelope;
1895
+ return generator.intoEnvelope();
1840
1896
  }
1841
1897
  /**
1842
1898
  * Extract a ProvenanceMarkGenerator from an Envelope.
1843
1899
  *
1900
+ * Delegates to ProvenanceMarkGenerator.fromEnvelope() — single source of truth.
1901
+ *
1844
1902
  * @param envelope - The envelope to extract from
1845
1903
  * @returns The extracted generator
1846
1904
  * @throws ProvenanceMarkError if extraction fails
1847
1905
  */
1848
1906
  function provenanceMarkGeneratorFromEnvelope(envelope) {
1849
- const env = envelope;
1850
- if (!env.hasType("provenance-generator")) throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: "Envelope is not a provenance-generator" });
1851
- const chainId = env.subject().asByteString();
1852
- if (chainId === void 0) throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: "Could not extract chain ID" });
1853
- const extractAssertion = (predicate) => {
1854
- const assertions = env.assertionsWithPredicate(predicate);
1855
- if (assertions.length === 0) throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: `Missing ${predicate} assertion` });
1856
- const assertionCase = assertions[0].case();
1857
- if (assertionCase.type !== "assertion") throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: `Invalid ${predicate} assertion` });
1858
- const obj = assertionCase.assertion.object();
1859
- const objCase = obj.case();
1860
- if (objCase.type === "leaf") return {
1861
- cbor: objCase.cbor,
1862
- bytes: obj.asByteString()
1863
- };
1864
- throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: `Invalid ${predicate} value` });
1865
- };
1866
- const res = resolutionFromCbor(extractAssertion("res").cbor);
1867
- const seedValue = extractAssertion("seed");
1868
- if (seedValue.bytes === void 0) throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: "Invalid seed data" });
1869
- const seed = ProvenanceSeed.fromBytes(seedValue.bytes);
1870
- const seqValue = extractAssertion("next-seq");
1871
- const nextSeq = Number(seqValue.cbor);
1872
- const rngValue = extractAssertion("rng-state");
1873
- if (rngValue.bytes === void 0) throw new ProvenanceMarkError(ProvenanceMarkErrorType.CborError, void 0, { message: "Invalid rng-state data" });
1874
- const rngState = RngState.fromBytes(rngValue.bytes);
1875
- return ProvenanceMarkGenerator.new(res, seed, chainId, nextSeq, rngState);
1907
+ return ProvenanceMarkGenerator.fromEnvelope(envelope);
1876
1908
  }
1877
1909
 
1878
1910
  //#endregion
1879
- export { PROVENANCE_SEED_LENGTH, ProvenanceMark, ProvenanceMarkError, ProvenanceMarkErrorType, ProvenanceMarkGenerator, ProvenanceMarkInfo, ProvenanceMarkResolution, ProvenanceSeed, RNG_STATE_LENGTH, RngState, SHA256_SIZE, ValidationReportFormat, Xoshiro256StarStar, chainIdHex, chainIdRange, dateBytesLength, dateBytesRange, dateFromIso8601, dateToDateString, dateToIso8601, deserialize2Bytes, deserialize4Bytes, deserialize6Bytes, deserializeDate, deserializeSeq, extendKey, fixedLength, formatReport, formatValidationIssue, hasIssues, hashRange, hkdfHmacSha256, infoRangeStart, keyRange, linkLength, obfuscate, provenanceMarkFromEnvelope, provenanceMarkGeneratorFromEnvelope, provenanceMarkGeneratorToEnvelope, provenanceMarkToEnvelope, rangeOfDaysInMonth, registerTags, registerTagsIn, resolutionFromCbor, resolutionFromNumber, resolutionToCbor, resolutionToNumber, resolutionToString, seqBytesLength, seqBytesRange, serialize2Bytes, serialize4Bytes, serialize6Bytes, serializeDate, serializeSeq, sha256, sha256Prefix, validate };
1911
+ export { FormatContext, PROVENANCE_SEED_LENGTH, ProvenanceMark, ProvenanceMarkError, ProvenanceMarkErrorType, ProvenanceMarkGenerator, ProvenanceMarkInfo, ProvenanceMarkResolution, ProvenanceSeed, RNG_STATE_LENGTH, RngState, SHA256_SIZE, ValidationReportFormat, Xoshiro256StarStar, chainIdHex, chainIdRange, dateBytesLength, dateBytesRange, dateFromIso8601, dateToDateString, dateToIso8601, deserialize2Bytes, deserialize4Bytes, deserialize6Bytes, deserializeDate, deserializeSeq, extendKey, fixedLength, formatReport, formatValidationIssue, hasIssues, hashRange, hkdfHmacSha256, infoRangeStart, keyRange, linkLength, obfuscate, provenanceMarkFromEnvelope, provenanceMarkGeneratorFromEnvelope, provenanceMarkGeneratorToEnvelope, provenanceMarkToEnvelope, rangeOfDaysInMonth, registerTags, registerTagsIn, resolutionFromCbor, resolutionFromNumber, resolutionToCbor, resolutionToNumber, resolutionToString, seqBytesLength, seqBytesRange, serialize2Bytes, serialize4Bytes, serialize6Bytes, serializeDate, serializeSeq, sha256, sha256Prefix, validate };
1880
1912
  //# sourceMappingURL=index.mjs.map