studio: config-drift dashboard (live vs declared, one-click re-apply) - #175
Merged
Conversation
…ail panel + one-click re-apply (issue #153) Adds forceStepIds to @redeploy/config's applyConfig() to allow re-executing already-journaled steps on demand, threads it through deploy-server's POST /api/apply-config as a validated ?forceStepIds= query param (never in the body, which is already the spec), and wires a studio drift detail panel (expected vs actual) with a confirm-gated per-step "Re-apply" button that refreshes drift badges via runVerifyConfig on success. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rift re-apply (issue #153) Fixes B1-B5 from the review of feat/issue-159... err feat/issue-153-config-drift-reapply: - B1 (correctness+security, most serious): the re-apply confirm modal claimed "1 step, all others unaffected" while POSTing the studio's ENTIRE config spec — applyConfig() executes every not-yet-applied step in the POSTed spec regardless of forceStepIds. Now narrows the POSTed spec to just the target step (narrowConfigToStep), making the modal's claim structurally true, and rewords the "already applied" claim which was false for never-journaled drifted steps. - B2: pin that a forced step whose executor throws does not double-journal. - B3: cover the `if (applying) return;` guard in onReapplyStep — the only thing preventing a second real broadcast from a second click in flight. - B4: cover the untested `driftOutcome.ok` false branch on the post-re-apply drift refresh, and document the deliberate on-failure behaviour (leave driftResults stale rather than clearing, unlike handleVerify). - B5: fix the forceStepIds comma round-trip — client now sends one repeated query param per id (rejecting any id containing a comma before sending) instead of comma-joining; server merges repeated params via URLSearchParams.getAll() instead of dropping all but the first. Also folds in the non-blocking cleanup items from the same review pass (fresh completedAt assertion, full-apply verify-call-count test, Inspector keyboard/stringify branch coverage, constant drift-badge style objects, and a corrected doc comment on the forceStepIds cap-before-dedupe ordering). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ply (issue #153) - App.reapplyNarrowing.test.tsx: T1 (blocking) — the B1 regression test was vacuous because the canvas config was empty, making the narrowed-vs-full spec comparison trivially true. Add a real canvas step before triggering re-apply and assert directly on the POSTed request body (no step id other than the re-apply target may appear), independent of the narrowConfigToStep spy. Mutation-verified: fails when the narrowed spec is computed then discarded, passes against the real implementation. - execute.test.ts: strengthen the fresh-completedAt assertion with a controlled clock so a stale-copy regression (not just a genuinely newer timestamp) is caught, instead of toBeGreaterThanOrEqual which a byte-copy would also satisfy. - narrow-config.test.ts: add a case for the same step id appearing in both `steps` and `orderedSteps`, pinning that narrowConfigToStep keeps both entries (de-duplication/rejection happens downstream via validateConfig's DUPLICATE_STEP_ID check). - Inspector.tsx: guard DRIFT_BADGE_STYLES lookup with Object.hasOwn so a server-supplied drift.status of "constructor"/"toString" can't return an inherited Object.prototype function instead of falling through to the default badge style (security lens nit, assessed harmless but cheap to fix). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
#153) Security review (finding H1) caught that POST /api/verify/config always read the server's default-network deployment while the forced re-apply it gates writes to the user-selected network — a wrong-network drift reading could let a one-click "Re-apply" broadcast a real transaction for a mismatch that doesn't exist (or hide one that does) on the network actually being written to. Thread the same ?network= convention already used by /api/apply-config through /api/verify/config and runVerifyConfig, and fix a route-matching bug (matching the query-string-bearing url instead of pathname) that this change exposed.
…sue #153) Assert the rpcUrl half of network isolation in the new verify/config multi-network test (previously only deploymentDir was checked, so a revert of the rpcUrl line would have gone undetected), and update the handleRequest route doc comment to list /api/verify/config among the pathname-matched, ?network=-aware routes.
Collaborator
Author
|
studio: config-drift dashboard (live vs declared, one-click re-apply) (not yet reviewed) |
robercano
approved these changes
Aug 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #153.
Summary
deploy-server:POST /api/verify/configrunsverifyConfig's config-drift check against the live chain viaChainReader, network-aware (?network=, mirroring/api/apply-config).studio: drift badges (match/drift/error) on each config step in the Inspector, a drift detail panel (expected vs actual + message), and a one-click "Re-apply" action wired to the apply-config endpoint for a single drifted/errored step.Review
Routed through all four required lenses (correctness, tests, security, performance) with consensus "all" — security's initial reject (drift check not network-aware) was fixed and re-reviewed to approve.
Test plan
pnpm -r buildpnpm -r lintpnpm -r typecheckpnpm -r test(packages/config 159, apps/studio 1229, apps/deploy-server 304, plusforge test)pnpm -r coverage— packages/config 95.58%, apps/studio 97.14%, apps/deploy-server 97.59% (threshold 80%)🤖 Generated with the reDeploy autonomous PR loop.