Skip to content

Commit 01c59c0

Browse files
authored
Merge pull request #14 from GetStream/codex/inf-1722-controller-gui
[INF-1722] Add configurable migration controller
2 parents 7d97873 + 80d445f commit 01c59c0

40 files changed

Lines changed: 13686 additions & 484 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ coverage.*
88
*.prof
99
*.pprof
1010

11+
# Local blueprint execution logs
12+
/docs/blueprints/*.log
13+
1114
# Go workspace files, which are always local to one checkout
1215
go.work
1316
go.work.sum

Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
GO ?= go
22
GOFLAGS ?=
33

4-
.PHONY: fmt vet test race integration bench cdc-bench e2e crash-e2e
4+
.PHONY: fmt vet test race integration bench cdc-bench e2e controller-e2e restart-e2e crash-e2e
55

66
fmt:
77
$(GO) $(GOFLAGS) fmt ./...
@@ -29,6 +29,14 @@ e2e:
2929
$(GO) $(GOFLAGS) build -o ./pgmigrate ./cmd/pgmigrate
3030
test/e2e/scripts/run-migration.sh
3131

32+
controller-e2e:
33+
$(GO) $(GOFLAGS) build -o ./pgmigrate ./cmd/pgmigrate
34+
PGMIGRATE_DRIVER=controller test/e2e/scripts/run-migration.sh
35+
36+
restart-e2e:
37+
$(GO) $(GOFLAGS) build -o ./pgmigrate ./cmd/pgmigrate
38+
PGMIGRATE_DRIVER=controller PGMIGRATE_TEST_DROP_SLOT_RESTART=1 test/e2e/scripts/run-migration.sh
39+
3240
crash-e2e:
3341
$(GO) $(GOFLAGS) build -o ./pgmigrate ./cmd/pgmigrate
3442
test/e2e/scripts/run-crash-loop.sh

README.md

Lines changed: 219 additions & 39 deletions
Large diffs are not rendered by default.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Controller UI Configuration Implementation Blueprint
2+
3+
## Meta
4+
5+
- **Design Doc:** N/A
6+
7+
## Overview
8+
9+
Allow an authenticated operator to configure every setting used by controller-managed preflight, run, and verification from the embedded dashboard. Controller bootstrap settings remain process-owned, credentials remain write-only and memory-only, and cutover and sequence advancement remain CLI-only.
10+
11+
### Cross-Cutting Requirements
12+
13+
- The controller must continue to start idle and must not create migration state or connect to either database on startup.
14+
- Controller token, listen address, and migration directory remain startup-only.
15+
- Source and target DSNs are never returned by an API, logged, written to state, or stored in browser storage.
16+
- Configuration updates are rejected while a migration or verification operation is active.
17+
- Existing CLI behavior and lifecycle guards remain unchanged.
18+
- All new code passes `go vet ./...`, `go test ./...`, and `go test -race ./...`.
19+
20+
---
21+
22+
## Tasks
23+
24+
### Task 1: Add an authenticated mutable configuration API
25+
**Type:** code
26+
27+
**Subtasks:**
28+
- Add a concurrency-safe controller configuration store initialized from CLI/environment defaults.
29+
- Add authenticated `GET /api/config` and `PUT /api/config` routes covering every configuration field used by preflight, run, and verify, excluding status-only, cutover/sequence, directory, listener, and token settings.
30+
- Make source and target DSNs write-only: GET reports only whether each is configured, and an omitted/blank PUT value retains the current DSN.
31+
- Parse human-readable durations and numeric settings, validate the complete candidate configuration, and atomically replace it only when no operation is active.
32+
- Snapshot the current configuration when an action starts so an in-flight action cannot observe later mutations.
33+
- Add handler and concurrency tests for authentication, redaction, validation, update locking, default preservation, and action snapshots.
34+
35+
**Acceptance Criteria:**
36+
- AC1.1: An authenticated client can configure source, target, and every preflight/run/verify option after controller startup.
37+
- AC1.2: Neither config GET nor status responses contain either DSN.
38+
- AC1.3: Invalid configuration returns HTTP 400 without changing the active configuration.
39+
- AC1.4: Configuration updates during active migration or verification return HTTP 409.
40+
- AC1.5: Controller and CLI unit tests pass under the race detector.
41+
42+
---
43+
44+
### Task 2: Add complete configuration forms to the embedded UI
45+
**Type:** code
46+
47+
**Subtasks:**
48+
- Add database connection, migration, copy, tuning, and verification form sections with basic settings visible and advanced settings collapsible.
49+
- Load non-secret defaults from the config API after authentication without placing DSNs in the DOM or browser storage.
50+
- Save configuration through the authenticated API, clearly report validation errors, and show configured/not-configured connection state.
51+
- Keep controls disabled until a valid configuration is saved and preserve all existing lifecycle, confirmation, progress, and stop behavior.
52+
- Add static UI regression assertions for the configuration form, write-only DSNs, and absence of DSN browser persistence.
53+
- Update README controller documentation with configuration security and lifecycle behavior.
54+
55+
**Acceptance Criteria:**
56+
- AC2.1: Every preflight/run/verify configuration field can be edited from the dashboard.
57+
- AC2.2: Source/target inputs are password fields, remain empty after reload, and are never stored in localStorage or sessionStorage.
58+
- AC2.3: Bootstrap settings and CLI-only cutover/sequences are not editable from the dashboard.
59+
- AC2.4: Existing progress and action controls remain functional and accessible.
60+
- AC2.5: Controller tests and `git diff --check` pass.
61+
62+
---
63+
64+
### Task 3: Prove UI-supplied configuration end to end
65+
**Type:** go-tests
66+
67+
**Subtasks:**
68+
- Change the controller E2E driver to start without source/target DSNs and populate the complete action configuration through the authenticated config API.
69+
- Exercise authenticated preflight, run, live verification, final verification, CLI-only cutover, cleanup checks, and independent source/target comparison.
70+
- Add focused coverage that controller startup alone leaves the migration directory untouched.
71+
- Validate the dashboard in a browser from unauthenticated state through configuration save, action enablement, progress rendering, and completed-state locking.
72+
73+
**Acceptance Criteria:**
74+
- AC3.1: `make controller-e2e` passes while supplying both DSNs through the controller config API.
75+
- AC3.2: Independent table inventory, row counts, and canonical source/target digests match after cutover.
76+
- AC3.3: Starting the controller without taking an action creates no migration state and opens no database connection.
77+
- AC3.4: `go vet ./...`, `go test ./...`, and `go test -race ./...` pass.
78+
79+
## Files to Modify
80+
81+
- `internal/controller/controller.go` - mutable config API and action snapshots.
82+
- `internal/controller/controller_test.go` - API, redaction, locking, and startup regression tests.
83+
- `internal/controller/ui.html` - complete configuration dashboard.
84+
- `test/e2e/scripts/run-migration.sh` - configure controller through API.
85+
- `README.md` and `test/README.md` - operator and E2E documentation.
86+
87+
## References
88+
89+
- Current controller server: `internal/controller/controller.go`
90+
- Current embedded dashboard: `internal/controller/ui.html`
91+
- CLI configuration flags: `internal/cli/cli.go`
92+
- Shared configuration model: `internal/config/config.go`

0 commit comments

Comments
 (0)