Feature: 060-settings-page | Spec: spec.md | Plan: plan.md
TDD on the backend; frontend verified via Chrome extension.
- T001 Baseline green:
go build ./cmd/mcpproxy,cd frontend && npm run build(ormake build) pass before changes.
- T002 [P] Failing test
internal/httpapi/server_config_patch_test.go: PATCH /config with{"quarantine_enabled":false}applies only that field; an untouched secret (api_key, secret header) is preserved; nested merge ({"docker_isolation":{"enabled":true}}) keeps sibling docker fields; invalid value returns validation error;changed_fieldsreflects the patch. - T003 Implement
handlePatchConfig+deepMergeJSONhelper ininternal/httpapi/server.go(GetConfig→map→merge patch→unmarshal→ApplyConfig), modeled onhandlePatchDockerIsolation. Register routePATCH /api/v1/config. Make T002 pass. - T004 Regenerate swagger (
make swagger) for the new endpoint;./scripts/verify-oas-coverage.shgreen.
- T005 [P] Add
patchConfig(partial)tofrontend/src/services/api.ts(PATCH /api/v1/config). - T006 [P] Field-metadata catalogue
frontend/src/views/settings/fields.ts(SettingField[] per data-model: key/label/help/control/section/options/min/max/danger/restart; hidden keys excluded). - T007 Control atoms in
frontend/src/components/settings/:SettingToggle.vue,SettingSelect.vue,SettingNumber.vue,SettingText.vue(secret/show),RestartBadge.vue,ConfirmDialog.vue— each withdata-testids. (frontend-design skill.) - T008
SettingsSection.vue— renders fields for a section + per-section Save (builds nested partial from dirty keys →patchConfig), toast + restart/changed-fields feedback, danger-confirm gating.
- T009 [US1] Redesign
frontend/src/views/Settings.vueinto a tab shell (Security/General/Advanced/Raw JSON/Teams), loadingGET /configonce; keep existing Monaco editor as the Raw JSON tab. - T010 [US1]
SecuritySection.vuewith the 9 ordered fields; api_key masked + regenerate; danger confirms for reveal_secret_headers / disable_management / quarantine-off / non-loopback listen; restart badges. Save persists only changed fields.
- T011 [US2]
GeneralSection.vue: routing_mode, tools_limit (1–1000), tool_response_limit, call_tool_timeout, logging.level, telemetry.enabled, enable_prompts; number-bound validation before save.
- T012 [US3]
AdvancedSection.vuewith DaisyUI accordions per subsystem (code execution, docker isolation detail, sensitive-data detection incl. categories + custom patterns, output validation, output sanitisation, activity retention, logging, TLS, tokenizer, intent, environment, scanner, misc). - T013 [US3] Verify Raw JSON tab retains validate+apply behaviour;
TeamsSection.vuerendered only whenconfig.teamspresent (personal edition shows no Teams tab).
- T014 [P]
cd frontend && npm run buildclean (TS6/Vite8);go test ./internal/httpapi/... ./internal/runtime/... -count=1;./scripts/test-api-e2e.shgreen. - T015 Docs:
docs/settings page note; cross-link from config docs. (CLAUDE.md only if under 40k.) - T016 Mandatory verification (Chrome extension): drive live Web UI — capture Security/General/Advanced/Raw JSON; toggle quarantine + save + re-read to confirm persistence + secret preserved; danger-confirm flow. Build a local QA report (NOT committed, per policy); end with
open <report>.
- T002–T004 (backend) block T008's save path.
- T005–T008 foundation block US1/US2/US3.
- US1 is the MVP; US2/US3 extend the same section framework.
- T010's tab shell (T009) is shared by all sections — build once.
- Backend (T002–T004) ∥ frontend foundation (T005–T007) — different stacks. Dispatch backend to a subagent while building the frontend.
- T005 ∥ T006 (different files).
US1 (T009–T010) + backend PATCH (T002–T003) + foundation (T005–T008): a working, secure Security & Access form with partial saves.