From a07a63ae5c1be16d674943f4b397a232d07f740b Mon Sep 17 00:00:00 2001 From: Guilhem Lemouel Date: Mon, 24 Aug 2026 09:39:12 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20address=20review=20round=204=20=E2=80=94?= =?UTF-8?q?=20unreviewed=20SQL,=20premature=20finish,=20stale=20Back?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Setup ran hub SQL nobody had seen.** Step 3 reviews the migrations it can run there, but the ones deferred to setup went straight to `applyOneMigration` against whatever database the wizard was pointed at — which can be an existing resource holding unrelated objects. Each unconfigured row now carries a disclosure showing exactly what will run, before "Set up" runs it. **Finish was live while the setup decision was still outstanding.** For a project with migrations but no resources, `execution.done` exposed the button while `listDataTables` was still in flight and `setupNeeded` was still false — clicking in that window left for the workspace and skipped a step the answer, a moment later, said was needed. It now reads "Checking…" and is disabled until the check settles. **A reload on step 4 turned Back into a re-import.** `resume` only carries the page's in-memory execution, so after a reload Back mounted a fresh step 3 offering Import over a bundle already in — and on a new workspace, a create that now fails because the finished run cleared its parking. Back exists only while the page still holds the run, which excludes exactly that case. **`validateWorkspaceId` over-rejected a fork named `global`.** It reaches the backend as `wm-fork-global`, which is accepted; only the effective id is checked now, so a plain `global` is still refused. Covered by a test. **An abandoned run left the migrate row spinning.** It is appended once the review settles and set running by `onMigrationsStart`; stopping before its loop left it on `running` forever, reading as work still in progress on a run that had stopped. Also moves the `run()` contract back onto `run()`, and gives `ImportSetupRow` an optional `extra` snippet for detail that does not fit on one line. Co-Authored-By: Claude Opus 5 (1M context) --- .../lib/components/ImportProjectStep.svelte | 16 ++++++- .../src/lib/components/ImportSetupRow.svelte | 43 +++++++++++-------- .../src/lib/components/ImportSetupStep.svelte | 21 +++++++++ .../src/lib/importWizard/execution.svelte.ts | 20 ++++++--- frontend/src/lib/utils/workspaceId.test.ts | 4 ++ frontend/src/lib/utils/workspaceId.ts | 5 ++- .../projects/import/+page@(root).svelte | 18 +++++++- 7 files changed, 97 insertions(+), 30 deletions(-) diff --git a/frontend/src/lib/components/ImportProjectStep.svelte b/frontend/src/lib/components/ImportProjectStep.svelte index 6d61826886..c8b02621e9 100644 --- a/frontend/src/lib/components/ImportProjectStep.svelte +++ b/frontend/src/lib/components/ImportProjectStep.svelte @@ -30,6 +30,8 @@ onFinish: () => void /** True once the run reveals data tables the destination has yet to configure. */ setupPending?: boolean + /** The page has not settled whether a setup step follows. Finishing now would skip it. */ + setupUndecided?: boolean /** Hands the run to the page, which needs the export's data tables to know * whether a setup step follows this one. */ onExecution?: (execution: ImportExecution | undefined) => void @@ -50,6 +52,7 @@ onFinish, onBack, setupPending = false, + setupUndecided = false, onExecution, resume }: Props = $props() @@ -402,8 +405,17 @@ {/if} {#if execution?.done} - {:else}