Repository navigation
Commit ad6b2fd
feat(listen): expose --cli-key, adopt its project, and save it when unauthenticated (#329)
* feat(listen): expose --cli-key and adopt it when unauthenticated
The Hookdeck Console hands users a ready-to-run command:
npx hookdeck-cli listen [port] <source> --cli-key <key>
Two things made that worse than it needed to be.
The flag was invisible. --cli-key is declared on the root command as
"(deprecated)" and MarkHidden, so it appears in no help output, even
though listen's own help documents it with an example. Anything that
introspects the CLI concludes the flag does not exist. Declaring it on
listen, bound to the same Config field, changes no behaviour and makes
it discoverable in `hookdeck listen --help`.
The key was also forgotten immediately. It applied to one invocation, so
every later run needed it pasted again. listen now validates and saves
the key when the machine has no stored credential, after which the flag
can be dropped.
It deliberately does not save when a credential already exists.
Forwarding a Console source for a few minutes should not silently
replace an existing login, so in that case the key applies to the run
only. Validation happens before the write, so a typo fails with a clear
error instead of being persisted.
Config.HasStoredAPIKey records whether a key was on disk before
InitConfig folds in the flag value, which the coalesced Profile.APIKey
can no longer distinguish.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHJQ1QSdKmJMivqw7SER6t
* fix(listen): use the supplied --cli-key's own project, and cover it
A key given on the command line was sent alongside the project id read
from the config file. Those belong to different logins, so anyone with an
existing profile who ran the command the Hookdeck Console gives them got
"your API key is invalid or expired" and no way to see why.
Validation is already project-agnostic (Client.clientForCLIAuthValidate
sends an empty ProjectID), so it resolves the project the key really
belongs to. Adopting that response replaces the stale project for the
run. Saving stays conditional on there being no stored credential, so an
existing login is still never replaced.
Renames the helper to applyCliKey, since it now always resolves context
and only sometimes saves.
Tests cover the four branches without touching the network, using the
httptest pattern from gateway_test.go: the flag-absent no-op (pointed at
a dead port, so a stray validate call fails loudly), adopting the key's
project over a stale one, leaving an existing login on disk, and
refusing to write a key that fails validation. A mutation check confirms
the project-adoption test fails when the fix is removed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHJQ1QSdKmJMivqw7SER6t
* fix(listen): reject an empty --cli-key locally
`--cli-key=` satisfies cobra's Changed check but carries nothing to
authenticate with. The empty value then fell through InitConfig's
coalesce and the run failed with "your API key is invalid or expired",
which describes neither what happened nor how to fix it, after a
pointless round-trip to the API.
Fail immediately with an error naming the flag. Reads the flag value
rather than Profile.APIKey, which by that point may hold a stored key
from the config file instead of what the user typed.
Raised by Copilot review on #329.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHJQ1QSdKmJMivqw7SER6t
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent e0297b5 commit ad6b2fd
4 files changed
Lines changed: 360 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
| |||
42 | 43 | | |
43 | 44 | | |
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 | + | |
45 | 112 | | |
46 | 113 | | |
47 | 114 | | |
| |||
162 | 229 | | |
163 | 230 | | |
164 | 231 | | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
165 | 240 | | |
166 | 241 | | |
167 | 242 | | |
| |||
241 | 316 | | |
242 | 317 | | |
243 | 318 | | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
244 | 323 | | |
245 | 324 | | |
246 | 325 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
45 | 52 | | |
46 | 53 | | |
47 | 54 | | |
| |||
338 | 345 | | |
339 | 346 | | |
340 | 347 | | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
341 | 353 | | |
342 | 354 | | |
343 | 355 | | |
| |||
0 commit comments