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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
//! The unconditional `provider ↔ canonical env var` table (#4564, moved #8236).
//!
//! Why: the table is pure data with no dependency of its own, but it lived
//! inside the `credentials`-feature-gated module tree. #8236 needs it from
//! [`crate::launchd_secrets`], which is deliberately ungated — "a guard that
//! compiles out under some feature set is not a guard". Hoisting the data here
//! lets the plist scanner name a credential by REGISTRY membership rather than
//! by a suffix guess, on every feature set.
//!
//! What: [`REGISTRY`] is the table, [`env_var_for`] the provider → variable
//! lookup, [`provider_for_env_var`] the reverse (what #8236's `--fix` needs to
//! know WHERE to migrate a plist entry to), and
//! [`is_registered_credential_env_var`] the membership predicate the plist
//! scanner asks first. `credentials::registry` re-exports all four, so the
//! documented import path is unchanged.
//!
//! Test: `crate::credentials::registry::tests` (the census assertions stayed
//! with the module that owns the spec reference), plus
//! `provider_for_env_var_round_trips` and
//! `is_registered_credential_env_var_is_case_insensitive` here.
//!
//! [`REGISTRY`]: crate::credential_registry::REGISTRY
//! [`env_var_for`]: crate::credential_registry::env_var_for
//! [`provider_for_env_var`]: crate::credential_registry::provider_for_env_var
//! [`is_registered_credential_env_var`]: crate::credential_registry::is_registered_credential_env_var
/// Every credential this workspace knows how to name, as
/// `(provider key, canonical environment-variable name)`.
///
/// Why: a table rather than a `match` arm so a test can enumerate it. The
/// acceptance criterion for #4564 is that the registry is *checkable* — an
/// opaque `match` cannot be asserted complete, and completeness is the whole
/// point of the ticket.
/// What: provider keys are lowercase-kebab and are the identifier a caller
/// passes to [`env_var_for`] / `resolve_key`; lookup is case-insensitive
/// (see [`env_var_for`]). Two keys may name the same provider where the
/// provider genuinely has two distinct secrets (`slack` / `slack-user` /
/// `slack-app`, `github` / `github-app` / `github-webhook`). Entries are
/// grouped by origin and each non-inference group cites the ticket that
/// introduced it.
/// Test: `crate::credentials::registry::tests::registry_covers_the_full_census`.
///
/// DOC-45 `C-2.7`: a `CredentialRef` (#4565) resolves *through* this table, so
/// a provider absent from it fails with `Missing` rather than silently.
pub const REGISTRY: & = &;
/// Canonical process-env variable name for a provider's credential.
///
/// Why: every call site (the resolver's env tier, the `config` clap module's
/// `--env` hint, and — from #4565 — `CredentialRef` resolution) must agree on
/// one name per provider rather than re-deriving `{PROVIDER}_API_KEY` ad hoc,
/// which breaks for every provider whose canonical variable does not follow
/// that shape (`SLACK_BOT_TOKEN`, `GH_TOKEN`, `GITHUB_APP_PRIVATE_KEY`, …).
/// What: case-insensitive lookup over [`REGISTRY`]. `None` for an unregistered
/// provider; callers treat that as "the env tier does not apply", not an error.
/// Test: `crate::credentials::registry::tests::registry_covers_the_full_census`,
/// `crate::credentials::registry::tests::env_var_for_is_case_insensitive_for_every_provider`.
/// The provider key a canonical environment-variable name belongs to.
///
/// Why: #8236's `tm doctor --fix` reads a credential KEY out of a LaunchAgent
/// plist and has to decide where that value belongs in the credential store.
/// Stripping the plist entry without an import target would remove a working
/// configuration and disable the feature, so a key with no answer here is
/// REPORTED and left alone rather than deleted.
/// What: the reverse of [`env_var_for`], case-insensitive on the variable name.
/// `None` when the variable is not registered.
/// Test: `provider_for_env_var_round_trips`,
/// `provider_for_env_var_is_none_for_an_unregistered_name`.
/// Is `var` a registered credential environment variable?
///
/// Why: the registry-first half of #8236's plist detection. A name in this
/// table is a credential by declaration, so it never depends on a suffix
/// heuristic agreeing — which is what let `AWS_PROFILE`-shaped keys and
/// `SLACK_APP_TOKEN` disagree with each other before.
/// Test: `is_registered_credential_env_var_is_case_insensitive`.
/// Every registered `(provider key, env var)` pair.
///
/// Why: #4565's `CredentialRef` grammar and the `config keys list` surface both
/// need to enumerate what is nameable; reaching into [`REGISTRY`] directly
/// would leak the table's layout into consumers.
/// Test: `crate::credentials::registry::tests::registered_providers_matches_the_table`.