Commit fc4051f
committed
feat(headers): unify display + server-side convert-to-secret for redacted values
User feedback: the Headers card looked split-brained. A non-sensitive
header showed `••••XX (NN chars)` with a Convert-to-secret button. The
Authorization header showed `***REDACTED***` with no button — exactly
the most-likely candidate for "move me to keyring" was the one the UI
refused to convert, because the client side couldn't hand the real value
to the existing two-step (POST /secrets, then PATCH server) flow.
This change unifies both display and conversion:
1. **Single mask format on the wire** — internal/oauth/logging.go
replaces the `***REDACTED***` sentinel in RedactStringHeaders with
MaskValue(v), producing `••••<last2> (<N> chars)` for literal
secrets. The same format the Web UI / macOS tray have been computing
client-side. Bare ${keyring:NAME} / ${env:VAR} references pass
through unchanged (they're labels, not secrets; the UI needs to
recognise them to render the keyring chip).
2. **Server-side atomic convert** — new endpoint:
POST /api/v1/servers/{name}/config-to-secret
body: {"scope": "header"|"env", "key": "<k>", "secret_name": "<n>"}
The backend reads the real value from the loaded config, stores it
in the OS keyring under secret_name, and rewrites the config field
with ${keyring:<n>}. The client never has to possess the plaintext,
so Convert-to-secret now works on the redacted-on-read path too.
3. **Reveal button removed from KVValueCell.vue** — with all literals
displayed identically and Convert-to-secret available everywhere,
the reveal toggle was a security-shaped speed bump with no real use
case. The two paths to peek at a value (open the config file, or
edit-cancel) remain. revealedKeys reactive state and the
reveal/hide events disappear from the parent too.
4. **Symmetric macOS Swift cleanup** — ServerDetailView.swift::kvRow
drops the `value != "***REDACTED***"` gate on the Convert-to-secret
button. maskedHeaderValue() drops the sentinel special case.
performConvertToSecret() calls the new atomic endpoint via the new
APIClient.convertConfigToSecret helper instead of two-stepping
through storeSecret + PATCH.
Backend tests updated for the new format:
- internal/oauth/logging_test.go::TestRedactStringHeaders — asserts the
••••et (40 chars) mask shape with length + last-2 suffix. New
sub-tests pin the keyring/env-ref pass-through, short-value (<=4
chars -> bare ••••), and empty-value ((empty)) edge cases.
- internal/runtime/event_bus_payload_test.go — SSE redaction test
asserts the new format on the wire.
- internal/server/e2e_test.go — both PR #425 round-trip tests now
assert mask shape instead of literal sentinel.
New backend test coverage:
- internal/httpapi/patch_server_test.go — 9 new sub-tests for the
/config-to-secret endpoint validation paths: missing scope / key /
secret_name, invalid scope, key not on server, value already a
reference (keyring + env separately), empty value, server not found.
Happy-path lives in the live verification because secret.Resolver is
a concrete struct without a mock.
End-to-end verification on live local mcpproxy:
GET /api/v1/servers
-> synapbus.headers.Authorization = ••••59 (71 chars) # new format
-> kaggle.headers.Authorization = ••••N} (30 chars) # Bearer\${k...} also masked
POST /api/v1/servers/synapbus/config-to-secret
{"scope":"header","key":"Authorization","secret_name":"synapbus-authorization"}
-> 200 {"reference":"\${keyring:synapbus-authorization}"}
-> on disk: {"Authorization": "\${keyring:synapbus-authorization}"}
-> GET response: passes the bare reference through unchanged
Web UI: Headers row transformed from
`Authorization ••••59 (71 chars) [lock] Convert to secret`
to
`Authorization [key-chip] stored in keyring: synapbus-authorization`
via the Convert-to-secret modal — no intermediate steps for
the user, no plaintext on the client.
CLI: `upstream patch synapbus --header X-Cli-Verify=hello` /
`upstream patch synapbus --header-remove X-Cli-Verify` still
work; the keyring reference on Authorization survives both.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent f952885 commit fc4051f
13 files changed
Lines changed: 596 additions & 138 deletions
File tree
- frontend/src
- components
- services
- views
- internal
- httpapi
- oauth
- runtime
- server
- native/macos/MCPProxy/MCPProxy
- API
- Views
- oas
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
23 | | - | |
| 23 | + | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
41 | 42 | | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
63 | 53 | | |
64 | 54 | | |
65 | 55 | | |
| |||
70 | 60 | | |
71 | 61 | | |
72 | 62 | | |
73 | | - | |
74 | | - | |
75 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
76 | 66 | | |
77 | 67 | | |
78 | 68 | | |
79 | 69 | | |
80 | 70 | | |
81 | 71 | | |
82 | | - | |
83 | 72 | | |
84 | 73 | | |
85 | 74 | | |
86 | 75 | | |
87 | | - | |
88 | | - | |
89 | 76 | | |
90 | 77 | | |
91 | 78 | | |
| |||
123 | 110 | | |
124 | 111 | | |
125 | 112 | | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | 113 | | |
135 | | - | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
136 | 123 | | |
137 | 124 | | |
138 | | - | |
139 | | - | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
140 | 128 | | |
141 | 129 | | |
142 | 130 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
294 | 294 | | |
295 | 295 | | |
296 | 296 | | |
297 | | - | |
298 | | - | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
299 | 300 | | |
300 | 301 | | |
301 | 302 | | |
302 | 303 | | |
303 | 304 | | |
304 | 305 | | |
305 | 306 | | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
306 | 328 | | |
307 | 329 | | |
308 | 330 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
676 | 676 | | |
677 | 677 | | |
678 | 678 | | |
679 | | - | |
680 | 679 | | |
681 | | - | |
682 | | - | |
683 | 680 | | |
684 | 681 | | |
685 | 682 | | |
| |||
743 | 740 | | |
744 | 741 | | |
745 | 742 | | |
746 | | - | |
747 | 743 | | |
748 | | - | |
749 | | - | |
750 | 744 | | |
751 | 745 | | |
752 | 746 | | |
| |||
2321 | 2315 | | |
2322 | 2316 | | |
2323 | 2317 | | |
2324 | | - | |
2325 | 2318 | | |
2326 | 2319 | | |
2327 | 2320 | | |
| |||
2461 | 2454 | | |
2462 | 2455 | | |
2463 | 2456 | | |
2464 | | - | |
| 2457 | + | |
2465 | 2458 | | |
2466 | 2459 | | |
2467 | | - | |
2468 | | - | |
2469 | | - | |
| 2460 | + | |
| 2461 | + | |
| 2462 | + | |
| 2463 | + | |
| 2464 | + | |
| 2465 | + | |
| 2466 | + | |
| 2467 | + | |
| 2468 | + | |
2470 | 2469 | | |
2471 | 2470 | | |
2472 | | - | |
2473 | | - | |
2474 | | - | |
2475 | | - | |
2476 | | - | |
| 2471 | + | |
| 2472 | + | |
2477 | 2473 | | |
2478 | 2474 | | |
2479 | 2475 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
136 | | - | |
137 | | - | |
138 | | - | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
157 | | - | |
158 | | - | |
| 157 | + | |
| 158 | + | |
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
| |||
335 | 335 | | |
336 | 336 | | |
337 | 337 | | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
0 commit comments