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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! Wing identity: canonical keys and id minting for the *scope* axis.
//!
//! Why (ADR-0027 D2): a Wing is the "who" axis (scope / ownership) and a Room
//! is the "what" axis (topic). Separating them is what lets `engineer/Planning`
//! and `pm/Planning` coexist without the name mangling that gave the live
//! `trusty-tools` palace twelve ad-hoc labels. This module supplies the two
//! pure ingredients the `WINGS` table needs — the canonical key a wing label
//! resolves through, and the UUIDv5 minted for a key that has no row yet.
//! What: `WING_NAMESPACE`, `DEFAULT_WING_LABEL`, `canonical_wing_key`,
//! `default_wing_key`, `mint_wing_id`. Deliberately mirrors
//! [`crate::memory_core::room_identity`] so the two axes have one shape, not
//! two. No I/O, no redb — every function here is pure and total.
//!
//! [`DEFAULT_WING_ID`] itself lives in `room_identity` because `RoomRecord`
//! reserved it first (ADR-0027 D1.2); it is re-exported here so wing-side call
//! sites have one import.
//!
//! Test: `wing_namespace_matches_its_documented_derivation`,
//! `canonical_wing_key_is_case_insensitive`, `mint_wing_id_is_stable`,
//! `default_wing_id_is_not_the_minted_id`.
use Uuid;
pub use crateDEFAULT_WING_ID;
/// UUIDv5 namespace for wing ids.
///
/// Why: minting a wing id must be reproducible across processes and machines
/// without coordination. A namespace distinct from `ROOM_NAMESPACE` means a
/// wing and a room that happen to share a label can never mint the same id,
/// so a caller cannot accidentally pass one where the other is expected.
/// What: `uuid5(NAMESPACE_URL,
/// "https://github.com/bobmatnyc/trusty-tools/adr-0027/wing-namespace")`,
/// hardcoded so it needs no lazy global (this workspace forbids those).
/// Test: `wing_namespace_matches_its_documented_derivation`.
pub const WING_NAMESPACE: Uuid = from_bytes;
/// Display label of the wing every room falls into when nobody names one.
///
/// Why (ADR-0027 D2): "Wing is never a required concept for a caller." Every
/// palace gets this wing, every room defaults into it, and a caller who never
/// heard of wings sees identical behaviour before and after T9.
pub const DEFAULT_WING_LABEL: &str = "default";
/// The `WING_KEYS` lookup key for `label`.
///
/// Why: same case-folding rule as rooms (ADR-0027 D1.3) — the *key* is
/// lowercased while the record keeps the first-seen *spelling*, so `Engineer`
/// and `engineer` are one wing without destroying the capitalisation a human
/// chose. Unlike a room key there is no parent id to prefix: a wing is
/// top-level within a palace, and `WING_KEYS` is its own table, so no two
/// namespaces can alias.
/// What: the trimmed, lowercased label.
/// Test: `canonical_wing_key_is_case_insensitive`.
/// Canonical key of the default wing.
///
/// Test: `default_wing_id_is_not_the_minted_id`.
/// Mint the id for a wing that has no row yet.
///
/// Why: UUIDv5 over a canonical key is reproducible without coordination and
/// carries no fold, so the legacy `room_to_uuid` collision class (ADR-0027
/// C3.1) has no wing-side analogue. A random v4 would not be reproducible.
/// What: `Uuid::new_v5(WING_NAMESPACE, key.as_bytes())`.
///
/// Note that the DEFAULT wing is **not** minted with this — its id is the
/// pre-existing [`DEFAULT_WING_ID`] constant that every `RoomRecord` written
/// since ADR-0027 T1 already carries, and it is seeded verbatim exactly the
/// way a legacy room id is (ADR-0027 D1.3, "ids are read from the table,
/// never recomputed"). `default_wing_id_is_not_the_minted_id` pins that the
/// two genuinely differ, so the seeding is load-bearing rather than
/// incidental.
/// Test: `mint_wing_id_is_stable`, `default_wing_id_is_not_the_minted_id`.