From 97c584733a40572611fb9502b82e6f06b27e9227 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sat, 8 Aug 2026 01:01:16 +0200 Subject: [PATCH] =?UTF-8?q?fix(seed):=20mark=20instance=20configured=20in?= =?UTF-8?q?=20e2e=5Fseed=20so=20a=20prod=E2=86=92dev=20reseed=20skips=20se?= =?UTF-8?q?tup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `siftlode seed-dev-from-prod` TRUNCATEs app_state (excluded from the data allow-list as local/operational state), which dropped localdev back into the first-run "Setup needed" gate and blocked login/UAT. e2e_seed runs at the end of both `seed` and `seed-dev-from-prod` and always leaves a loginable admin, so it now also flips app_state.configured=true (idempotent; the running api re-reads and promotes its one-way cache, no restart needed). --- scripts/e2e_seed.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/e2e_seed.py b/scripts/e2e_seed.py index f2ac5994..fcc35365 100644 --- a/scripts/e2e_seed.py +++ b/scripts/e2e_seed.py @@ -24,6 +24,7 @@ from sqlalchemy import delete, func, select # noqa: E402 from app.db import SessionLocal # noqa: E402 from app.models import ( # noqa: E402 + AppState, Channel, Playlist, PlaylistItem, @@ -46,6 +47,21 @@ def _now() -> datetime: def main() -> None: db = SessionLocal() try: + # 0. Mark the instance configured so the first-run setup wizard is skipped. A prod→dev + # reseed (siftlode seed-dev-from-prod) TRUNCATEs app_state — it's excluded from the + # data allow-list, being local/operational state — which would otherwise drop the box + # back into "Setup needed" and block login/UAT. Since e2e_seed always leaves a loginable + # admin below, the instance is legitimately set up. Idempotent (mirrors state._row + + # state.mark_configured). The running api process caches `configured` one-way from False, + # so it re-reads the DB and promotes on the next request — no restart needed. + app_state = db.get(AppState, 1) + if app_state is None: + app_state = AppState(id=1, sync_paused=False) + db.add(app_state) + app_state.configured = True + app_state.setup_token_hash = None + db.commit() + # 1. Upsert the account and always reset it to a clean, loginable baseline # (email_verified + is_active + not suspended + not demo + password set). user = db.scalar(select(User).where(User.email == EMAIL))