1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Identity — the id *type*, and what makes one well-formed.
//!
//! An id is a stable, opaque name for a document. This module is the read half
//! of prov's identity layer: the [`Id`] newtype, the alphabet and length it is
//! spelled in, and [`verify`] — the check-character arithmetic that catches a
//! typo'd `id:` link before it dangles silently.
//!
//! *Minting* an id is a write, and lives in `prov-identity`.
//! alongside the trigger set that decides when a document earns one. The split
//! matters because this crate never issues an id; it only recognizes ids
//! something else issued, which is exactly what link resolution needs.
//!
//! ## The ID scheme
//!
//! Prov's internal IDs share their lineage with diaryx's ARK blades but
//! carry no NAAN or shoulder — they are workspace-internal, not published
//! permalinks (DESIGN §4's two identity layers). The primitives come from the
//! [`moid`] crate (*minimal opaque ID*): an ID is [`BLADE_RANDOM_LEN`]
//! random characters from the 29-character NOID extended-digit alphabet
//! ([`moid::Alphabet::noid_xdigit`] — digits plus consonants: no vowels, so no
//! accidental words; no `l`, so no ambiguity with `1`) plus one NOID check
//! character, so a typo'd ID is *detected* rather than silently resolving to
//! nothing. The alphabet is the canonical NOID one, so the check character
//! agrees with a real NOID minter and not merely with our own arithmetic. An ID
//! may therefore contain — and begin with — a digit; anything stamping one into
//! metadata must keep it a *string*.
use Alphabet;
/// A stable, opaque document identifier.
;
/// Random characters per ID (excluding the check character). 29^6 ≈ 595M —
/// collision-free in practice for a workspace, enforced absolutely by
/// mint-with-rejection.
pub const BLADE_RANDOM_LEN: usize = 6;
/// Total ID length: the random body plus one check character.
pub const BLADE_LEN: usize = BLADE_RANDOM_LEN + 1;
/// Prov IDs use [`BLADE_RANDOM_LEN`] random NOID extended-digit characters plus
/// a NOID check character. Minting lives in `prov-identity`; this crate only
/// verifies IDs.
/// Whether `id` is a well-formed prov ID: correct length, alphabet-only,
/// and a matching trailing check character. This is what catches a typo'd
/// `prov:` link before it dangles silently.
/// Where a document's stable ID is persisted — the identity-storage axis
/// (DESIGN §5). Orthogonal to *when* an ID is minted (`prov`'s `Registration`) and to
/// how references are spelled; this is purely the ID's *home*.