|
| 1 | +## T002 — Identifier grammar (Must Have) |
| 2 | + |
| 3 | +**Intent** |
| 4 | +Define a **canonical identifier grammar** for: |
| 5 | + |
| 6 | +* **Messages** (catalog entries, error codes, notifications) |
| 7 | +* **Topics/Events** (pub/sub subjects, event types) |
| 8 | +* **Channels** (delivery channels: UI, email, webhook, system log, etc.) |
| 9 | + …and impose **constraints** on naming, immutability, versioning, and compatibility. |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +## 1) Objects that require canonical IDs |
| 14 | + |
| 15 | +Minimum set (extend as needed): |
| 16 | + |
| 17 | +1. **Message ID** (catalog entry identity) |
| 18 | +2. **Message Key** (stable lookup key used by code; can be same as ID if you choose) |
| 19 | +3. **Event Type / Topic ID** (AsyncAPI-style event name or topic subject) |
| 20 | +4. **Channel ID** (delivery channel identity) |
| 21 | +5. **Contract ID** (optional but recommended: ties messages/topics to interface contracts) |
| 22 | + |
| 23 | +--- |
| 24 | + |
| 25 | +## 2) Canonical grammar (normative) |
| 26 | + |
| 27 | +### 2.1 Common lexical rules (apply to all IDs) |
| 28 | + |
| 29 | +* Character set: `A–Z`, `0–9`, `_`, `-`, `.` (explicitly disallow spaces) |
| 30 | +* Case: **UPPERCASE** for tokens; lowercase allowed only for semantic segments if you formalize it (pick one and enforce). |
| 31 | +* Separator rules: |
| 32 | + |
| 33 | + * Use `_` for token boundaries (stable machine parsing) |
| 34 | + * Use `-` inside tokens only when the token is itself a standard label (e.g., `ATA-21`) |
| 35 | + * Use `.` only for hierarchical topic segments (pub/sub) |
| 36 | +* Length: |
| 37 | + |
| 38 | + * Overall ID length ≤ 96 chars |
| 39 | + * Individual token length ≤ 24 chars |
| 40 | +* Forbidden: |
| 41 | + |
| 42 | + * Leading/trailing separators |
| 43 | + * Double separators (`__`, `..`, `--`) unless explicitly reserved |
| 44 | + * Non-ASCII characters |
| 45 | + |
| 46 | +### 2.2 Message ID grammar |
| 47 | + |
| 48 | +**Purpose:** immutable identity for catalog entry and audit. |
| 49 | + |
| 50 | +**EBNF (recommended)** |
| 51 | + |
| 52 | +``` |
| 53 | +MSG_ID = "MSG" "_" DOMAIN "_" SCOPE "_" CLASS "_" NUM ; |
| 54 | +DOMAIN = 1*(ALNUM / "_") ; |
| 55 | +SCOPE = ("ATA-" 2DIGIT) / 1*(ALNUM / "_") ; |
| 56 | +CLASS = "INFO" / "WARN" / "ERR" / "CRIT" ; |
| 57 | +NUM = 4DIGIT ; |
| 58 | +``` |
| 59 | + |
| 60 | +**Example** |
| 61 | + |
| 62 | +* `MSG_PORTAL_ATA-21_ERR_0042` |
| 63 | +* `MSG_CM_ATA-00_WARN_0107` |
| 64 | + |
| 65 | +**Rules** |
| 66 | + |
| 67 | +* `MSG_ID` is immutable once released. |
| 68 | +* `NUM` is unique per `{DOMAIN, SCOPE, CLASS}` or per `{DOMAIN, SCOPE}` (pick one and enforce in CI). |
| 69 | + |
| 70 | +### 2.3 Message key grammar (if distinct from Message ID) |
| 71 | + |
| 72 | +**Purpose:** stable developer-facing lookup key; can encode context without the numeric sequence. |
| 73 | + |
| 74 | +``` |
| 75 | +MSG_KEY = DOMAIN "." SCOPE "." NAME ; |
| 76 | +NAME = 1*(ALNUM / "_" ) ; |
| 77 | +``` |
| 78 | + |
| 79 | +**Example** |
| 80 | + |
| 81 | +* `portal.ata21.power_insufficient` |
| 82 | +* `cm.ata00.schema_violation` |
| 83 | + |
| 84 | +**Rules** |
| 85 | + |
| 86 | +* `MSG_KEY` must be unique globally. |
| 87 | +* Renaming a `MSG_KEY` is breaking unless an alias map is maintained. |
| 88 | + |
| 89 | +### 2.4 Event Type / Topic grammar |
| 90 | + |
| 91 | +You want two layers: **event type** (semantic) and **topic/subject** (routing). Keep them related but not identical. |
| 92 | + |
| 93 | +**Event Type (semantic identifier)** |
| 94 | + |
| 95 | +``` |
| 96 | +EVT_TYPE = DOMAIN "." SCOPE "." ENTITY "." ACTION ".v" MAJOR ; |
| 97 | +ENTITY = 1*(ALNUM / "_" ) ; |
| 98 | +ACTION = 1*(ALNUM / "_" ) ; |
| 99 | +MAJOR = 1*DIGIT ; |
| 100 | +``` |
| 101 | + |
| 102 | +**Examples** |
| 103 | + |
| 104 | +* `portal.ata21.ecs.requirement_updated.v1` |
| 105 | +* `cm.ata00.contract_released.v2` |
| 106 | + |
| 107 | +**Topic/Subject (routing)** |
| 108 | + |
| 109 | +``` |
| 110 | +TOPIC = ENV "." DOMAIN "." SCOPE "." EVT_FAMILY ; |
| 111 | +ENV = "dev" / "stg" / "prd" ; |
| 112 | +EVT_FAMILY = 1*(ALNUM / "_" / ".") ; |
| 113 | +``` |
| 114 | + |
| 115 | +**Examples** |
| 116 | + |
| 117 | +* `prd.portal.ata21.ecs.requirement_updated` |
| 118 | +* `dev.cm.ata00.contract_released` |
| 119 | + |
| 120 | +**Rules** |
| 121 | + |
| 122 | +* Bump `EVT_TYPE` major when payload breaking changes occur. |
| 123 | +* Topic naming stays stable across minor changes; include major version in event type to keep routing stable. |
| 124 | + |
| 125 | +### 2.5 Channel ID grammar |
| 126 | + |
| 127 | +Channels represent delivery mechanisms, not semantics. |
| 128 | + |
| 129 | +``` |
| 130 | +CH_ID = "CH" "_" MEDIUM "_" AUDIENCE "_" SENS ; |
| 131 | +MEDIUM = "UI" / "EMAIL" / "SMS" / "WEBHOOK" / "LOG" / "API" ; |
| 132 | +AUDIENCE = "USER" / "ADMIN" / "SYSTEM" / "PARTNER" ; |
| 133 | +SENS = "PUBLIC" / "INTERNAL" / "RESTRICTED" ; |
| 134 | +``` |
| 135 | + |
| 136 | +**Examples** |
| 137 | + |
| 138 | +* `CH_UI_USER_PUBLIC` |
| 139 | +* `CH_WEBHOOK_PARTNER_RESTRICTED` |
| 140 | + |
| 141 | +**Rules** |
| 142 | + |
| 143 | +* Channel IDs are controlled vocabulary; additions require governance approval. |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +## 3) Naming constraints and controlled vocabulary |
| 148 | + |
| 149 | +### 3.1 Controlled vocabularies (minimum) |
| 150 | + |
| 151 | +* `DOMAIN`: e.g., `PORTAL`, `CM`, `CERT`, `OPS`, `MRO` (use your AoR/portal taxonomy if desired) |
| 152 | +* `SCOPE`: `ATA-XX` or `CROSS` for cross-ATA |
| 153 | +* `CLASS`: `INFO/WARN/ERR/CRIT` |
| 154 | +* `MEDIUM/AUDIENCE/SENS`: enumerated list only |
| 155 | + |
| 156 | +### 3.2 Collision rules |
| 157 | + |
| 158 | +* **Global uniqueness** required for: |
| 159 | + |
| 160 | + * `MSG_ID` |
| 161 | + * `MSG_KEY` |
| 162 | + * `EVT_TYPE` |
| 163 | +* **Namespacing** must be enforced via the `DOMAIN` and `SCOPE` tokens. |
| 164 | + |
| 165 | +### 3.3 Immutability rules |
| 166 | + |
| 167 | +Immutable after release: |
| 168 | + |
| 169 | +* `MSG_ID` |
| 170 | +* `EVT_TYPE` major (`.v1`, `.v2`, …) is immutable once published |
| 171 | +* Topic names in `prd` should be immutable; any change requires parallel publishing for a deprecation window. |
| 172 | + |
| 173 | +Mutable: |
| 174 | + |
| 175 | +* Message text/localization strings (non-breaking if keys/ids unchanged) |
| 176 | +* Non-breaking additions to payload schemas (minor version metadata only) |
| 177 | + |
| 178 | +--- |
| 179 | + |
| 180 | +## 4) Versioning policy (contracts + messages + events) |
| 181 | + |
| 182 | +### 4.1 Messages |
| 183 | + |
| 184 | +* ID/key stable; content evolves. |
| 185 | +* If meaning materially changes, create a **new** `MSG_ID` and deprecate old. |
| 186 | + |
| 187 | +### 4.2 Events / Contracts |
| 188 | + |
| 189 | +* Payload schema versioning aligns to: |
| 190 | + |
| 191 | + * **Major**: breaking (remove/rename field, change type/meaning) |
| 192 | + * **Minor**: additive optional fields |
| 193 | + * **Patch**: documentation/examples only |
| 194 | +* Encode **major** in `EVT_TYPE` (`.vN`) and optionally in schema metadata. |
| 195 | + |
| 196 | +--- |
| 197 | + |
| 198 | +## 5) CI-enforceable constraints (Definition of Done) |
| 199 | + |
| 200 | +At minimum, your validator must fail if: |
| 201 | + |
| 202 | +* Any ID violates regex/EBNF rules |
| 203 | +* Duplicate `MSG_ID`, `MSG_KEY`, or `EVT_TYPE` |
| 204 | +* Any released (tagged) `MSG_ID`/`EVT_TYPE` was modified/renamed |
| 205 | +* Event payload breaking change without major bump |
| 206 | +* Channel IDs not in controlled vocabulary |
| 207 | + |
| 208 | +--- |
| 209 | + |
| 210 | +## 6) Minimal regex set (practical enforcement) |
| 211 | + |
| 212 | +* `MSG_ID`: |
| 213 | + |
| 214 | + * `^MSG_[A-Z0-9_]+_(ATA-\d{2}|[A-Z0-9_]+)_(INFO|WARN|ERR|CRIT)_\d{4}$` |
| 215 | +* `MSG_KEY`: |
| 216 | + |
| 217 | + * `^[a-z0-9]+(\.[a-z0-9]+)*\.[a-z0-9_]+$` |
| 218 | +* `EVT_TYPE`: |
| 219 | + |
| 220 | + * `^[a-z0-9]+(\.[a-z0-9]+)*\.[a-z0-9_]+\.[a-z0-9_]+\.v[1-9]\d*$` |
| 221 | +* `TOPIC`: |
| 222 | + |
| 223 | + * `^(dev|stg|prd)\.[a-z0-9]+(\.[a-z0-9]+)+$` |
| 224 | +* `CH_ID`: |
| 225 | + |
| 226 | + * `^CH_(UI|EMAIL|SMS|WEBHOOK|LOG|API)_(USER|ADMIN|SYSTEM|PARTNER)_(PUBLIC|INTERNAL|RESTRICTED)$` |
| 227 | + |
| 228 | +--- |
| 229 | + |
0 commit comments