@bcts/provenance-mark 1.0.0-alpha.9 → 1.0.0-beta.1

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.d.cts CHANGED
@@ -1,7 +1,13 @@
1
1
  import { Cbor } from "@bcts/dcbor";
2
2
  import { BytewordsStyle, UR } from "@bcts/uniform-resources";
3
+ import { Envelope, FormatContext, FormatContext as FormatContext$1 } from "@bcts/envelope";
3
4
 
4
5
  //#region src/error.d.ts
6
+ /**
7
+ * Copyright © 2023-2026 Blockchain Commons, LLC
8
+ * Copyright © 2025-2026 Parity Technologies
9
+ *
10
+ */
5
11
  /**
6
12
  * Error types for Provenance Mark operations.
7
13
  */
@@ -52,6 +58,19 @@ declare enum ProvenanceMarkErrorType {
52
58
  IntegerConversionError = "IntegerConversionError",
53
59
  /** Validation error */
54
60
  ValidationError = "ValidationError",
61
+ /**
62
+ * Envelope serialization/deserialization error.
63
+ *
64
+ * Mirrors Rust `Error::Envelope(...)`
65
+ * (`provenance-mark-rust/src/error.rs`). The Rust enum surfaces
66
+ * envelope-format failures as their own variant; in earlier
67
+ * revisions of this port they collapsed into `CborError`. Both
68
+ * shapes are still emitted in practice (CBOR errors during envelope
69
+ * round-trip stay as `CborError`); this variant exists for the
70
+ * structural-level mismatches the Rust port tags as
71
+ * `Error::Envelope`.
72
+ */
73
+ EnvelopeError = "EnvelopeError"
55
74
  }
56
75
  /**
57
76
  * Error class for Provenance Mark operations.
@@ -76,7 +95,7 @@ declare enum ProvenanceMarkResolution {
76
95
  Low = 0,
77
96
  Medium = 1,
78
97
  Quartile = 2,
79
- High = 3,
98
+ High = 3
80
99
  }
81
100
  /**
82
101
  * Convert a resolution to its numeric value.
@@ -151,6 +170,14 @@ declare function serializeDate(res: ProvenanceMarkResolution, date: Date): Uint8
151
170
  declare function deserializeDate(res: ProvenanceMarkResolution, data: Uint8Array): Date;
152
171
  /**
153
172
  * Serialize a sequence number into bytes based on the resolution.
173
+ *
174
+ * Mirrors Rust's typed `u32` parameter (`generator.rs::serialize_seq`)
175
+ * — the input must be a non-negative integer in `[0, 2^32-1]` (a u32).
176
+ * For Low resolution the upper bound additionally narrows to `2^16-1`
177
+ * (a u16) per Rust `if seq > 0xFFFF`. Earlier revisions of this port
178
+ * accepted any JS `number` for the 4-byte branch and would silently
179
+ * truncate values above `2^32-1`; now we raise `ResolutionError` so
180
+ * the wire output never deviates from Rust's u32 contract.
154
181
  */
155
182
  declare function serializeSeq(res: ProvenanceMarkResolution, seq: number): Uint8Array;
156
183
  /**
@@ -171,6 +198,11 @@ declare function resolutionToCbor(res: ProvenanceMarkResolution): Cbor;
171
198
  declare function resolutionFromCbor(cborValue: Cbor): ProvenanceMarkResolution;
172
199
  //#endregion
173
200
  //#region src/date.d.ts
201
+ /**
202
+ * Copyright © 2023-2026 Blockchain Commons, LLC
203
+ * Copyright © 2025-2026 Parity Technologies
204
+ *
205
+ */
174
206
  /**
175
207
  * Interface for serializable date operations.
176
208
  */
@@ -224,8 +256,116 @@ declare function dateFromIso8601(str: string): Date;
224
256
  * Format a date as a simple date string (YYYY-MM-DD).
225
257
  */
226
258
  declare function dateToDateString(date: Date): string;
259
+ /**
260
+ * Renders a `Date` the way Rust's `dcbor::Date::Display` does
261
+ * (`bc-dcbor-rust/src/date.rs:485-492`):
262
+ *
263
+ * - When the UTC time is exactly `00:00:00` (subsecond precision is
264
+ * ignored — Rust's check is `hour == 0 && minute == 0 && second == 0`,
265
+ * matching `chrono::SecondsFormat::Secs`), emit just `YYYY-MM-DD`.
266
+ * - Otherwise emit RFC 3339 with second precision (no fractional
267
+ * seconds), e.g. `2023-02-08T15:30:45Z`.
268
+ *
269
+ * This is the canonical "Rust string" for dates across the
270
+ * provenance-mark public surface — `mark.toDebugString`,
271
+ * `mark.precedesOpt` `DateOrdering` issue, `markdownSummary`, and the
272
+ * validation report's `DateOrdering` payload all use it. Centralising
273
+ * here keeps every call site in lockstep with the Rust output.
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * dateToDisplay(new Date("2023-06-20T00:00:00Z")); // "2023-06-20"
278
+ * dateToDisplay(new Date("2023-06-20T15:30:45Z")); // "2023-06-20T15:30:45Z"
279
+ * dateToDisplay(new Date("2023-06-20T15:30:45.123Z")); // "2023-06-20T15:30:45Z"
280
+ * ```
281
+ */
282
+ declare function dateToDisplay(date: Date): string;
283
+ //#endregion
284
+ //#region src/seed.d.ts
285
+ declare const PROVENANCE_SEED_LENGTH = 32;
286
+ /**
287
+ * A seed for generating provenance marks.
288
+ */
289
+ declare class ProvenanceSeed {
290
+ private readonly data;
291
+ private constructor();
292
+ /**
293
+ * Create a new random seed using secure random number generation.
294
+ */
295
+ static new(): ProvenanceSeed;
296
+ /**
297
+ * Create a new seed using custom random data.
298
+ */
299
+ static newUsing(randomData: Uint8Array): ProvenanceSeed;
300
+ /**
301
+ * Create a new seed from a passphrase.
302
+ */
303
+ static newWithPassphrase(passphrase: string): ProvenanceSeed;
304
+ /**
305
+ * Get the raw bytes.
306
+ */
307
+ toBytes(): Uint8Array;
308
+ /**
309
+ * Create from a 32-byte array.
310
+ */
311
+ static fromBytes(bytes: Uint8Array): ProvenanceSeed;
312
+ /**
313
+ * Create from a slice (validates length).
314
+ */
315
+ static fromSlice(bytes: Uint8Array): ProvenanceSeed;
316
+ /**
317
+ * Get the hex representation.
318
+ */
319
+ hex(): string;
320
+ /**
321
+ * Convert to CBOR (byte string).
322
+ */
323
+ toCbor(): Cbor;
324
+ /**
325
+ * Create from CBOR (byte string).
326
+ */
327
+ static fromCbor(cborValue: Cbor): ProvenanceSeed;
328
+ }
329
+ //#endregion
330
+ //#region src/utils.d.ts
331
+ /**
332
+ * Parse a base64-encoded provenance seed.
333
+ *
334
+ * Mirrors Rust's `parse_seed` user helper
335
+ * (`provenance-mark-rust/src/util.rs:34-38`), which round-trips the
336
+ * input through serde JSON / `deserialize_block` and so requires the
337
+ * decoded bytes to be exactly {@link PROVENANCE_SEED_LENGTH} (32) long.
338
+ * The TS equivalent decodes the base64 directly and delegates to
339
+ * {@link ProvenanceSeed.fromBytes} for the length check.
340
+ *
341
+ * @param s - Base64-encoded 32-byte seed string.
342
+ * @returns The decoded {@link ProvenanceSeed}.
343
+ * @throws {ProvenanceMarkError} If the input is not valid base64 or the
344
+ * decoded length is not exactly 32 bytes.
345
+ */
346
+ declare function parseSeed(s: string): ProvenanceSeed;
347
+ /**
348
+ * Parse a date string (`YYYY-MM-DD` or full RFC 3339) into a `Date`.
349
+ *
350
+ * Mirrors Rust's `parse_date` user helper
351
+ * (`provenance-mark-rust/src/util.rs:40-42`), which delegates to
352
+ * `Date::from_string` (the same parser the JSON deserializer uses).
353
+ * Accepts the same shapes the Rust parser does:
354
+ *
355
+ * - `YYYY-MM-DD` (interpreted as UTC midnight, matching JS spec).
356
+ * - Full RFC 3339, e.g. `2023-06-20T15:30:45Z` or
357
+ * `2023-06-20T15:30:45.123Z`.
358
+ *
359
+ * @throws {ProvenanceMarkError} If the input fails to parse.
360
+ */
361
+ declare function parseDate(s: string): Date;
227
362
  //#endregion
228
363
  //#region src/crypto-utils.d.ts
364
+ /**
365
+ * Copyright © 2023-2026 Blockchain Commons, LLC
366
+ * Copyright © 2025-2026 Parity Technologies
367
+ *
368
+ */
229
369
  declare const SHA256_SIZE = 32;
230
370
  /**
231
371
  * Compute SHA-256 hash of data.
@@ -250,6 +390,11 @@ declare function hkdfHmacSha256(keyMaterial: Uint8Array, salt: Uint8Array, keyLe
250
390
  declare function obfuscate(key: Uint8Array, message: Uint8Array): Uint8Array;
251
391
  //#endregion
252
392
  //#region src/xoshiro256starstar.d.ts
393
+ /**
394
+ * Copyright © 2023-2026 Blockchain Commons, LLC
395
+ * Copyright © 2025-2026 Parity Technologies
396
+ *
397
+ */
253
398
  /**
254
399
  * Xoshiro256** PRNG implementation.
255
400
  * A fast, high-quality pseudorandom number generator.
@@ -341,51 +486,91 @@ declare class RngState {
341
486
  static fromCbor(cborValue: Cbor): RngState;
342
487
  }
343
488
  //#endregion
344
- //#region src/seed.d.ts
345
- declare const PROVENANCE_SEED_LENGTH = 32;
489
+ //#region src/validate.d.ts
346
490
  /**
347
- * A seed for generating provenance marks.
491
+ * Format for validation report output.
348
492
  */
349
- declare class ProvenanceSeed {
350
- private readonly data;
351
- private constructor();
352
- /**
353
- * Create a new random seed using secure random number generation.
354
- */
355
- static new(): ProvenanceSeed;
356
- /**
357
- * Create a new seed using custom random data.
358
- */
359
- static newUsing(randomData: Uint8Array): ProvenanceSeed;
360
- /**
361
- * Create a new seed from a passphrase.
362
- */
363
- static newWithPassphrase(passphrase: string): ProvenanceSeed;
364
- /**
365
- * Get the raw bytes.
366
- */
367
- toBytes(): Uint8Array;
368
- /**
369
- * Create from a 32-byte array.
370
- */
371
- static fromBytes(bytes: Uint8Array): ProvenanceSeed;
372
- /**
373
- * Create from a slice (validates length).
374
- */
375
- static fromSlice(bytes: Uint8Array): ProvenanceSeed;
376
- /**
377
- * Get the hex representation.
378
- */
379
- hex(): string;
380
- /**
381
- * Convert to CBOR (byte string).
382
- */
383
- toCbor(): Cbor;
384
- /**
385
- * Create from CBOR (byte string).
386
- */
387
- static fromCbor(cborValue: Cbor): ProvenanceSeed;
493
+ declare enum ValidationReportFormat {
494
+ /** Human-readable text format */
495
+ Text = "text",
496
+ /** Compact JSON format (no whitespace) */
497
+ JsonCompact = "json-compact",
498
+ /** Pretty-printed JSON format (with indentation) */
499
+ JsonPretty = "json-pretty"
388
500
  }
501
+ /**
502
+ * Issue flagged during validation.
503
+ */
504
+ type ValidationIssue = {
505
+ type: "HashMismatch";
506
+ expected: string;
507
+ actual: string;
508
+ } | {
509
+ type: "KeyMismatch";
510
+ } | {
511
+ type: "SequenceGap";
512
+ expected: number;
513
+ actual: number;
514
+ } | {
515
+ type: "DateOrdering";
516
+ previous: string;
517
+ next: string;
518
+ } | {
519
+ type: "NonGenesisAtZero";
520
+ } | {
521
+ type: "InvalidGenesisKey";
522
+ };
523
+ /**
524
+ * Format a validation issue as a string.
525
+ */
526
+ declare function formatValidationIssue(issue: ValidationIssue): string;
527
+ /**
528
+ * A mark with any issues flagged during validation.
529
+ */
530
+ interface FlaggedMark {
531
+ mark: ProvenanceMark;
532
+ issues: ValidationIssue[];
533
+ }
534
+ /**
535
+ * Report for a contiguous sequence of marks within a chain.
536
+ */
537
+ interface SequenceReport {
538
+ startSeq: number;
539
+ endSeq: number;
540
+ marks: FlaggedMark[];
541
+ }
542
+ /**
543
+ * Report for a chain of marks with the same chain ID.
544
+ */
545
+ interface ChainReport {
546
+ chainId: Uint8Array;
547
+ hasGenesis: boolean;
548
+ marks: ProvenanceMark[];
549
+ sequences: SequenceReport[];
550
+ }
551
+ /**
552
+ * Get the chain ID as a hex string for display.
553
+ */
554
+ declare function chainIdHex(report: ChainReport): string;
555
+ /**
556
+ * Complete validation report.
557
+ */
558
+ interface ValidationReport {
559
+ marks: ProvenanceMark[];
560
+ chains: ChainReport[];
561
+ }
562
+ /**
563
+ * Check if the validation report has any issues.
564
+ */
565
+ declare function hasIssues(report: ValidationReport): boolean;
566
+ /**
567
+ * Format the validation report.
568
+ */
569
+ declare function formatReport(report: ValidationReport, format: ValidationReportFormat): string;
570
+ /**
571
+ * Validate a collection of provenance marks.
572
+ */
573
+ declare function validate(marks: ProvenanceMark[]): ValidationReport;
389
574
  //#endregion
390
575
  //#region src/mark.d.ts
391
576
  /**
@@ -428,23 +613,106 @@ declare class ProvenanceMark {
428
613
  static fromMessage(res: ProvenanceMarkResolution, message: Uint8Array): ProvenanceMark;
429
614
  private static makeHash;
430
615
  /**
431
- * Get the first four bytes of the hash as a hex string identifier.
616
+ * The 32-byte Mark ID.
617
+ *
618
+ * The first `linkLength` bytes are the mark's stored hash. The remaining
619
+ * bytes come from the mark's fingerprint (SHA-256 of CBOR encoding),
620
+ * ensuring a full 32-byte value is always available regardless of
621
+ * resolution.
622
+ */
623
+ id(): Uint8Array;
624
+ /**
625
+ * The full 32-byte Mark ID as a 64-character hex string.
626
+ */
627
+ idHex(): string;
628
+ /**
629
+ * The first `wordCount` bytes of the Mark ID as upper-case ByteWords.
630
+ *
631
+ * @param wordCount Number of bytes to encode, must be in `4..=32`.
632
+ * @param prefix If `true`, prepends the provenance-mark prefix character.
633
+ * @throws if `wordCount` is not in the range `4..=32`.
634
+ */
635
+ idBytewords(wordCount: number, prefix: boolean): string;
636
+ /**
637
+ * The first `wordCount` bytes of the Mark ID as Bytemoji.
638
+ *
639
+ * @param wordCount Number of bytes to encode, must be in `4..=32`.
640
+ * @param prefix If `true`, prepends the provenance-mark prefix character.
641
+ * @throws if `wordCount` is not in the range `4..=32`.
642
+ */
643
+ idBytemoji(wordCount: number, prefix: boolean): string;
644
+ /**
645
+ * The first `wordCount` bytes of the Mark ID as upper-case minimal
646
+ * ByteWords (2 letters per byte, concatenated without separator).
647
+ *
648
+ * @param wordCount Number of bytes to encode, must be in `4..=32`.
649
+ * @param prefix If `true`, prepends the provenance-mark prefix character.
650
+ * @throws if `wordCount` is not in the range `4..=32`.
651
+ */
652
+ idBytewordsMinimal(wordCount: number, prefix: boolean): string;
653
+ /**
654
+ * Legacy 8-character hex identifier — the first 4 bytes of the Mark ID.
655
+ *
656
+ * @deprecated Use {@link idHex} for the full 64-char hex, or
657
+ * `idHex().slice(0, 8)` for this legacy short form. Retained for
658
+ * backwards compatibility; will be removed in a future alpha.
432
659
  */
433
660
  identifier(): string;
434
661
  /**
435
- * Get the first four bytes of the hash as upper-case ByteWords.
662
+ * Legacy 4-byte upper-case ByteWords identifier.
663
+ *
664
+ * @deprecated Equivalent to `idBytewords(4, prefix)`. Retained for
665
+ * backwards compatibility; will be removed in a future alpha.
436
666
  */
437
667
  bytewordsIdentifier(prefix: boolean): string;
438
668
  /**
439
- * Get the first four bytes of the hash as Bytemoji.
669
+ * Legacy 8-letter minimal ByteWords identifier (first+last letter of each
670
+ * of the 4 ByteWords). Example: "ABLE ACID ALSO APEX" -> "AEADAOAX".
671
+ *
672
+ * @deprecated Equivalent to `idBytewordsMinimal(4, prefix)`. Retained
673
+ * for backwards compatibility; will be removed in a future alpha.
674
+ */
675
+ bytewordsMinimalIdentifier(prefix: boolean): string;
676
+ /**
677
+ * Legacy 4-byte upper-case Bytemoji identifier.
678
+ *
679
+ * @deprecated Equivalent to `idBytemoji(4, prefix)`. Retained for
680
+ * backwards compatibility; will be removed in a future alpha.
440
681
  */
441
682
  bytemojiIdentifier(prefix: boolean): string;
683
+ /**
684
+ * Computes the minimum prefix length (in bytes, `4..=32`) each mark needs
685
+ * so that every mark in the set has a unique Mark ID prefix.
686
+ *
687
+ * Non-colliding marks get the minimum of 4. Only marks whose 4-byte
688
+ * prefixes collide are extended.
689
+ */
690
+ private static minimalNoncollidingPrefixLengths;
691
+ private static resolveCollisionGroup;
692
+ /**
693
+ * Returns disambiguated upper-case ByteWords Mark IDs for a set of marks.
694
+ *
695
+ * Non-colliding marks get 4-word identifiers. Only marks whose 4-byte
696
+ * prefixes collide are extended with additional words (up to 32 bytes
697
+ * per identifier).
698
+ */
699
+ static disambiguatedIdBytewords(marks: ProvenanceMark[], prefix: boolean): string[];
700
+ /**
701
+ * Returns disambiguated Bytemoji Mark IDs for a set of marks.
702
+ *
703
+ * Non-colliding marks get 4-emoji identifiers. Only marks whose 4-byte
704
+ * prefixes collide are extended with additional emojis (up to 32 bytes
705
+ * per identifier).
706
+ */
707
+ static disambiguatedIdBytemoji(marks: ProvenanceMark[], prefix: boolean): string[];
442
708
  /**
443
709
  * Check if this mark precedes another mark in the chain.
444
710
  */
445
711
  precedes(next: ProvenanceMark): boolean;
446
712
  /**
447
713
  * Check if this mark precedes another mark, throwing on validation errors.
714
+ * Errors carry a structured `validationIssue` in their details, matching Rust's
715
+ * `Error::Validation(ValidationIssue)` pattern.
448
716
  */
449
717
  precedesOpt(next: ProvenanceMark): void;
450
718
  /**
@@ -468,13 +736,31 @@ declare class ProvenanceMark {
468
736
  */
469
737
  static fromBytewords(res: ProvenanceMarkResolution, bytewords: string): ProvenanceMark;
470
738
  /**
471
- * Encode for URL (minimal bytewords of CBOR).
739
+ * Encode for URL (minimal bytewords of tagged CBOR).
472
740
  */
473
741
  toUrlEncoding(): string;
474
742
  /**
475
743
  * Decode from URL encoding.
476
744
  */
477
745
  static fromUrlEncoding(urlEncoding: string): ProvenanceMark;
746
+ /**
747
+ * Returns the {@link UR} representation of this mark (untagged CBOR
748
+ * with type `"provenance"`).
749
+ *
750
+ * Mirrors Rust `UREncodable::ur()` for `ProvenanceMark` — the
751
+ * blanket impl on `CBORTaggedEncodable` produces a UR whose
752
+ * payload is the *untagged* CBOR (the type name itself stands in
753
+ * for the tag). See `bc-ur-rust/src/ur_encodable.rs:8-18`.
754
+ */
755
+ ur(): UR;
756
+ /**
757
+ * Get the UR string representation (e.g., "ur:provenance/...").
758
+ */
759
+ urString(): string;
760
+ /**
761
+ * Create from a UR string.
762
+ */
763
+ static fromURString(urString: string): ProvenanceMark;
478
764
  /**
479
765
  * Build a URL with this mark as a query parameter.
480
766
  */
@@ -513,10 +799,24 @@ declare class ProvenanceMark {
513
799
  fingerprint(): Uint8Array;
514
800
  /**
515
801
  * Debug string representation.
802
+ *
803
+ * As of provenance-mark v0.24, this includes the full 64-character Mark ID
804
+ * hex (matching rust's `Display` impl). Pre-v0.24 callers that depended on
805
+ * the 8-character prefix should use `idHex().slice(0, 8)` directly.
516
806
  */
517
807
  toString(): string;
518
808
  /**
519
809
  * Detailed debug representation.
810
+ *
811
+ * Mirrors Rust `Mark::Debug` exactly: every field is rendered
812
+ * Rust-style (hex bytes for keys/hashes/IDs, plain integer for
813
+ * `seq`, `Date::Display` for the date). The Low-resolution test
814
+ * vector in Rust `tests/mark.rs::test_low_resolution` ends with
815
+ * `date: 2023-06-20` — i.e. midnight-UTC dates are rendered without
816
+ * a time suffix. We use {@link dateToDisplay} to mirror that
817
+ * exactly; earlier revisions of this port stripped just the
818
+ * `.000Z` fractional component, which left `2023-06-20T00:00:00Z`
819
+ * and broke the Low-resolution debug-string parity.
520
820
  */
521
821
  toDebugString(): string;
522
822
  /**
@@ -524,13 +824,41 @@ declare class ProvenanceMark {
524
824
  */
525
825
  equals(other: ProvenanceMark): boolean;
526
826
  /**
527
- * JSON serialization.
827
+ * JSON serialization. Field order, names, and date format mirror Rust's
828
+ * `#[derive(Serialize)]` on `ProvenanceMark` (provenance-mark-rust/src/mark.rs):
829
+ * `seq, date, res, chain_id, key, hash[, info_bytes]`. The date uses
830
+ * `dateToDisplay()` (date-only when midnight, RFC3339-seconds with `Z`
831
+ * otherwise), matching Rust's `serialize_iso8601` / `Date::to_string()`.
528
832
  */
529
833
  toJSON(): Record<string, unknown>;
530
834
  /**
531
835
  * Create from JSON object.
532
836
  */
533
837
  static fromJSON(json: Record<string, unknown>): ProvenanceMark;
838
+ /**
839
+ * Validate a collection of provenance marks.
840
+ *
841
+ * Matches Rust: `ProvenanceMark::validate()` which delegates to
842
+ * `ValidationReport::validate()`.
843
+ */
844
+ static validate(marks: ProvenanceMark[]): ValidationReport;
845
+ /**
846
+ * Convert this provenance mark to a Gordian Envelope.
847
+ *
848
+ * Creates a leaf envelope containing the tagged CBOR representation.
849
+ * Matches Rust: `Envelope::new(mark.to_cbor())` which creates a CBOR leaf.
850
+ */
851
+ intoEnvelope(): Envelope;
852
+ /**
853
+ * Extract a ProvenanceMark from a Gordian Envelope.
854
+ *
855
+ * Matches Rust: `envelope.subject().try_leaf()?.try_into()`
856
+ *
857
+ * @param envelope - The envelope to extract from
858
+ * @returns The extracted provenance mark
859
+ * @throws ProvenanceMarkError if extraction fails
860
+ */
861
+ static fromEnvelope(envelope: Envelope): ProvenanceMark;
534
862
  }
535
863
  //#endregion
536
864
  //#region src/generator.d.ts
@@ -575,6 +903,20 @@ declare class ProvenanceMarkGenerator {
575
903
  next(date: Date, info?: Cbor): ProvenanceMark;
576
904
  /**
577
905
  * String representation.
906
+ *
907
+ * Mirrors Rust `Display for ProvenanceMarkGenerator`
908
+ * (`provenance-mark-rust/src/generator.rs:135-147`):
909
+ *
910
+ * ```rust
911
+ * write!(f, "ProvenanceMarkGenerator(chainID: {}, res: {}, seed: {}, nextSeq: {}, rngState: {:?})",
912
+ * hex::encode(&self.chain_id), self.res, self.seed.hex(), self.next_seq, self.rng_state)
913
+ * ```
914
+ *
915
+ * The `rngState` field uses Rust's `{:?}` (Debug) format, which on a
916
+ * `RngState([u8; 32])` tuple struct produces `RngState([n0, n1, ...])`
917
+ * with each byte rendered as a decimal integer. Earlier revisions of
918
+ * this port omitted `rngState` entirely from `toString()`, so the
919
+ * output diverged from Rust's `Display`.
578
920
  */
579
921
  toString(): string;
580
922
  /**
@@ -585,94 +927,29 @@ declare class ProvenanceMarkGenerator {
585
927
  * Create from JSON object.
586
928
  */
587
929
  static fromJSON(json: Record<string, unknown>): ProvenanceMarkGenerator;
930
+ /**
931
+ * Convert this generator to a Gordian Envelope.
932
+ *
933
+ * The envelope contains structured assertions for all generator fields:
934
+ * - isA: "provenance-generator"
935
+ * - res: The resolution
936
+ * - seed: The seed
937
+ * - next-seq: The next sequence number
938
+ * - rng-state: The RNG state
939
+ *
940
+ * Note: Use provenanceMarkGeneratorToEnvelope() for a standalone function alternative.
941
+ */
942
+ intoEnvelope(): Envelope;
943
+ /**
944
+ * Extract a ProvenanceMarkGenerator from a Gordian Envelope.
945
+ *
946
+ * @param envelope - The envelope to extract from
947
+ * @returns The extracted generator
948
+ * @throws ProvenanceMarkError if extraction fails
949
+ */
950
+ static fromEnvelope(envelope: Envelope): ProvenanceMarkGenerator;
588
951
  }
589
952
  //#endregion
590
- //#region src/validate.d.ts
591
- /**
592
- * Format for validation report output.
593
- */
594
- declare enum ValidationReportFormat {
595
- /** Human-readable text format */
596
- Text = "text",
597
- /** Compact JSON format (no whitespace) */
598
- JsonCompact = "json-compact",
599
- /** Pretty-printed JSON format (with indentation) */
600
- JsonPretty = "json-pretty",
601
- }
602
- /**
603
- * Issue flagged during validation.
604
- */
605
- type ValidationIssue = {
606
- type: "HashMismatch";
607
- expected: string;
608
- actual: string;
609
- } | {
610
- type: "KeyMismatch";
611
- } | {
612
- type: "SequenceGap";
613
- expected: number;
614
- actual: number;
615
- } | {
616
- type: "DateOrdering";
617
- previous: string;
618
- next: string;
619
- } | {
620
- type: "NonGenesisAtZero";
621
- } | {
622
- type: "InvalidGenesisKey";
623
- };
624
- /**
625
- * Format a validation issue as a string.
626
- */
627
- declare function formatValidationIssue(issue: ValidationIssue): string;
628
- /**
629
- * A mark with any issues flagged during validation.
630
- */
631
- interface FlaggedMark {
632
- mark: ProvenanceMark;
633
- issues: ValidationIssue[];
634
- }
635
- /**
636
- * Report for a contiguous sequence of marks within a chain.
637
- */
638
- interface SequenceReport {
639
- startSeq: number;
640
- endSeq: number;
641
- marks: FlaggedMark[];
642
- }
643
- /**
644
- * Report for a chain of marks with the same chain ID.
645
- */
646
- interface ChainReport {
647
- chainId: Uint8Array;
648
- hasGenesis: boolean;
649
- marks: ProvenanceMark[];
650
- sequences: SequenceReport[];
651
- }
652
- /**
653
- * Get the chain ID as a hex string for display.
654
- */
655
- declare function chainIdHex(report: ChainReport): string;
656
- /**
657
- * Complete validation report.
658
- */
659
- interface ValidationReport {
660
- marks: ProvenanceMark[];
661
- chains: ChainReport[];
662
- }
663
- /**
664
- * Check if the validation report has any issues.
665
- */
666
- declare function hasIssues(report: ValidationReport): boolean;
667
- /**
668
- * Format the validation report.
669
- */
670
- declare function formatReport(report: ValidationReport, format: ValidationReportFormat): string;
671
- /**
672
- * Validate a collection of provenance marks.
673
- */
674
- declare function validate(marks: ProvenanceMark[]): ValidationReport;
675
- //#endregion
676
953
  //#region src/mark-info.d.ts
677
954
  /**
678
955
  * Wrapper for a provenance mark with additional display information.
@@ -686,6 +963,16 @@ declare class ProvenanceMarkInfo {
686
963
  private constructor();
687
964
  /**
688
965
  * Create a new ProvenanceMarkInfo from a mark.
966
+ *
967
+ * Mirrors Rust `ProvenanceMarkInfo::new`
968
+ * (`provenance-mark-rust/src/mark_info.rs`), which calls
969
+ * `mark.ur()` — i.e. the `UREncodable` implementation, whose
970
+ * payload is the **untagged** CBOR with type `"provenance"`. Earlier
971
+ * revisions of this port called `decodeCbor(mark.toCborData())` and
972
+ * wrapped the resulting *tagged* CBOR in `UR.new("provenance", ...)`,
973
+ * which prepended the CBOR tag to the UR bytewords and broke
974
+ * cross-impl interop (UR strings produced by Rust would not parse,
975
+ * and vice versa).
689
976
  */
690
977
  static new(mark: ProvenanceMark, comment?: string): ProvenanceMarkInfo;
691
978
  mark(): ProvenanceMark;
@@ -695,17 +982,83 @@ declare class ProvenanceMarkInfo {
695
982
  comment(): string;
696
983
  /**
697
984
  * Generate a markdown summary of the mark.
985
+ *
986
+ * Date rendering uses {@link dateToDisplay} so midnight-UTC dates
987
+ * appear as `YYYY-MM-DD` (matching Rust `format!("{}",
988
+ * self.mark.date())`), not as `YYYY-MM-DDT00:00:00Z`.
698
989
  */
699
990
  markdownSummary(): string;
700
991
  /**
701
- * JSON serialization.
992
+ * JSON serialization. Field order mirrors Rust's `#[derive(Serialize)]`
993
+ * on `ProvenanceMarkInfo` (provenance-mark-rust/src/mark_info.rs):
994
+ * `ur, bytewords, bytemoji, [comment,] mark` — `comment` (when present)
995
+ * comes BEFORE `mark`. Rust uses `skip_serializing_if = "String::is_empty"`,
996
+ * matched here by the `if (...length > 0)` guard.
702
997
  */
703
998
  toJSON(): Record<string, unknown>;
704
999
  /**
705
1000
  * Create from JSON object.
1001
+ *
1002
+ * Decodes the UR string through {@link ProvenanceMark.fromURString},
1003
+ * which correctly handles the **untagged** CBOR payload that
1004
+ * `mark.ur()` produces — symmetric with the constructor.
706
1005
  */
707
1006
  static fromJSON(json: Record<string, unknown>): ProvenanceMarkInfo;
708
1007
  }
709
1008
  //#endregion
710
- export { type ChainReport, type FlaggedMark, PROVENANCE_SEED_LENGTH, ProvenanceMark, ProvenanceMarkError, ProvenanceMarkErrorType, ProvenanceMarkGenerator, ProvenanceMarkInfo, ProvenanceMarkResolution, type ProvenanceMarkResult, ProvenanceSeed, RNG_STATE_LENGTH, RngState, SHA256_SIZE, type SequenceReport, type SerializableDate, type ValidationIssue, type ValidationReport, 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, rangeOfDaysInMonth, resolutionFromCbor, resolutionFromNumber, resolutionToCbor, resolutionToNumber, resolutionToString, seqBytesLength, seqBytesRange, serialize2Bytes, serialize4Bytes, serialize6Bytes, serializeDate, serializeSeq, sha256, sha256Prefix, validate };
1009
+ //#region src/envelope.d.ts
1010
+ /**
1011
+ * Registers provenance mark tags in the global format context.
1012
+ *
1013
+ * Matches Rust: register_tags()
1014
+ */
1015
+ declare function registerTags(): void;
1016
+ /**
1017
+ * Registers provenance mark tags in a specific format context.
1018
+ *
1019
+ * Matches Rust: register_tags_in()
1020
+ *
1021
+ * @param context - The format context to register tags in
1022
+ */
1023
+ declare function registerTagsIn(context: FormatContext$1): void;
1024
+ /**
1025
+ * Convert a ProvenanceMark to an Envelope.
1026
+ *
1027
+ * Delegates to ProvenanceMark.intoEnvelope() — single source of truth.
1028
+ *
1029
+ * @param mark - The provenance mark to convert
1030
+ * @returns An envelope containing the mark
1031
+ */
1032
+ declare function provenanceMarkToEnvelope(mark: ProvenanceMark): Envelope;
1033
+ /**
1034
+ * Extract a ProvenanceMark from an Envelope.
1035
+ *
1036
+ * Delegates to ProvenanceMark.fromEnvelope() — single source of truth.
1037
+ *
1038
+ * @param envelope - The envelope to extract from
1039
+ * @returns The extracted provenance mark
1040
+ * @throws ProvenanceMarkError if extraction fails
1041
+ */
1042
+ declare function provenanceMarkFromEnvelope(envelope: Envelope): ProvenanceMark;
1043
+ /**
1044
+ * Convert a ProvenanceMarkGenerator to an Envelope.
1045
+ *
1046
+ * Delegates to ProvenanceMarkGenerator.intoEnvelope() — single source of truth.
1047
+ *
1048
+ * @param generator - The generator to convert
1049
+ * @returns An envelope containing the generator
1050
+ */
1051
+ declare function provenanceMarkGeneratorToEnvelope(generator: ProvenanceMarkGenerator): Envelope;
1052
+ /**
1053
+ * Extract a ProvenanceMarkGenerator from an Envelope.
1054
+ *
1055
+ * Delegates to ProvenanceMarkGenerator.fromEnvelope() — single source of truth.
1056
+ *
1057
+ * @param envelope - The envelope to extract from
1058
+ * @returns The extracted generator
1059
+ * @throws ProvenanceMarkError if extraction fails
1060
+ */
1061
+ declare function provenanceMarkGeneratorFromEnvelope(envelope: Envelope): ProvenanceMarkGenerator;
1062
+ //#endregion
1063
+ export { type ChainReport, type FlaggedMark, FormatContext, PROVENANCE_SEED_LENGTH, ProvenanceMark, ProvenanceMarkError, ProvenanceMarkErrorType, ProvenanceMarkGenerator, ProvenanceMarkInfo, ProvenanceMarkResolution, type ProvenanceMarkResult, ProvenanceSeed, RNG_STATE_LENGTH, RngState, SHA256_SIZE, type SequenceReport, type SerializableDate, type ValidationIssue, type ValidationReport, ValidationReportFormat, Xoshiro256StarStar, chainIdHex, chainIdRange, dateBytesLength, dateBytesRange, dateFromIso8601, dateToDateString, dateToDisplay, dateToIso8601, deserialize2Bytes, deserialize4Bytes, deserialize6Bytes, deserializeDate, deserializeSeq, extendKey, fixedLength, formatReport, formatValidationIssue, hasIssues, hashRange, hkdfHmacSha256, infoRangeStart, keyRange, linkLength, obfuscate, parseDate, parseSeed, provenanceMarkFromEnvelope, provenanceMarkGeneratorFromEnvelope, provenanceMarkGeneratorToEnvelope, provenanceMarkToEnvelope, rangeOfDaysInMonth, registerTags, registerTagsIn, resolutionFromCbor, resolutionFromNumber, resolutionToCbor, resolutionToNumber, resolutionToString, seqBytesLength, seqBytesRange, serialize2Bytes, serialize4Bytes, serialize6Bytes, serializeDate, serializeSeq, sha256, sha256Prefix, validate };
711
1064
  //# sourceMappingURL=index.d.cts.map