docs(mule-image): OIDC auto-redirect + deploy.sh caveat

LoginPage now bounces straight through Authentik when OIDC is on,
with skipAutoSso escape hatches for logout / error / explicit
password use. Also flagging that the first deploy.sh --force-recreate
run raced with a manual --no-deps recreate and broke the stack;
recovery via docker compose down && up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claudio
2026-05-10 22:03:47 +02:00
parent 0ad7cc9da0
commit 8a17a8dcf5

View File

@@ -80,6 +80,12 @@ For pushes from inside the LXC, gitea creds at `/etc/mule-deploy/git-credentials
## Changelog ## Changelog
### 2026-05-10 — OIDC auto-redirect on LoginPage
`OIDC_ENABLED=true` was already set in `.env`, so the LoginPage rendered a "Sign in with Authentik" button next to the password form. With a single trusted IdP and a logged-in Authentik session, that extra click was friction without upside.
`LoginPage.tsx` now reads `/auth/config` on mount and, if OIDC is on, immediately navigates to the OIDC login URL. Authentik recognizes the existing session and bounces back through the callback with no user interaction. Two escape hatches: `?password=1` in the URL forces the password form, and a `skipAutoSso` sessionStorage flag (set by `AuthContext.logout` and by the OIDC callback's error branch) suppresses the next auto-redirect so logouts actually log out and OIDC failures surface their error instead of looping. While the redirect is in flight the page shows "Signing in with Authentik..." plus a "Use password instead" link.
### 2026-05-10 — right sidebar restructure (heap pinned, single scroll, collapsible Metadata) ### 2026-05-10 — right sidebar restructure (heap pinned, single scroll, collapsible Metadata)
The right sidepanel had three stacked flex regions: `<ActiveHeapCard />`, `<Header />`, and `<PhotoInfoPanel />` — with `PhotoInfoPanel` carrying its own internal scroll. That left the editable fields (filename, title, notes, rating, color, flag) stuck above the readonly metadata scroll, effectively two scroll boundaries on one sidebar. The right sidepanel had three stacked flex regions: `<ActiveHeapCard />`, `<Header />`, and `<PhotoInfoPanel />` — with `PhotoInfoPanel` carrying its own internal scroll. That left the editable fields (filename, title, notes, rating, color, flag) stuck above the readonly metadata scroll, effectively two scroll boundaries on one sidebar.
@@ -102,7 +108,9 @@ User reported slow load. Five fixes shipped, in order:
4. **Frontend page size + idle polling.** `usePhotosQuery.ts` was first-fetching `per_page=500` (slow paint + 500 thumb requests at once). Split into `PER_PAGE_INITIAL=100` for first paint, `PER_PAGE_BACKGROUND=500` for the cursor-chain prefetch. Idle polling for `scan-status` and `worker-status` (`useScanActivity.ts`, `ScanProgress.tsx`) bumped from 10s/15s to 30s/30s while idle; active cadence (2s/3s) unchanged. 4. **Frontend page size + idle polling.** `usePhotosQuery.ts` was first-fetching `per_page=500` (slow paint + 500 thumb requests at once). Split into `PER_PAGE_INITIAL=100` for first paint, `PER_PAGE_BACKGROUND=500` for the cursor-chain prefetch. Idle polling for `scan-status` and `worker-status` (`useScanActivity.ts`, `ScanProgress.tsx`) bumped from 10s/15s to 30s/30s while idle; active cadence (2s/3s) unchanged.
5. **Partial index on `photos`.** Default list query `WHERE NOT is_trashed AND NOT is_hidden ORDER BY taken_at DESC NULLS LAST, id DESC LIMIT N` was doing a seq-scan + top-N heapsort (~25ms standalone, worse under concurrency). Added migration `0017_photos_list_index` creating `ix_photos_list_visible` (partial index on the sort key, restricted to visible rows). EXPLAIN now shows an Index Only Scan → **24.7ms → 0.097ms**, ~250× speedup. 5. **Partial index on `photos`.** Default list query `WHERE NOT is_trashed AND NOT is_hidden ORDER BY taken_at DESC NULLS LAST, id DESC LIMIT N` was doing a seq-scan + top-N heapsort (~25ms standalone, worse under concurrency). Added migration `0017_photos_list_index` creating `ix_photos_list_visible` (partial index on the sort key, restricted to visible rows). EXPLAIN now shows an Index Only Scan → **24.7ms → 0.097ms**, ~250× speedup.
**Deploy gotcha — fixed.** The original `docker compose up -d --build` in `deploy.sh` did not reliably recreate containers when only runtime config (`command:`, env-only) or migration files changed; image hash would change but compose treated the existing container as "current enough". Bit three times this session before `/opt/mule-deploy/deploy.sh` was updated to `docker compose up -d --build --force-recreate`. Trade-off accepted: an extra restart cycle on deploys where nothing user-visible changed. **Deploy gotcha — fixed (with caveat).** The original `docker compose up -d --build` in `deploy.sh` did not reliably recreate containers when only runtime config (`command:`, env-only) or migration files changed; image hash would change but compose treated the existing container as "current enough". Bit three times this session before `/opt/mule-deploy/deploy.sh` was updated to `docker compose up -d --build --force-recreate`. Trade-off accepted: an extra restart cycle on deploys where nothing user-visible changed.
**Caveat:** the first auto-deploy after the flag flip raced with my own earlier manual `docker compose up -d --no-deps --force-recreate frontend` and landed the stack in a half-broken state — `mulita-frontend` got stuck under a renamed temp container, several services dropped off `mule-image_mulita-network`, frontend nginx restarted in a loop with `host not found in upstream "backend"`. Fixed by `docker compose down && docker compose up -d`. Don't issue a manual `--force-recreate` on a single service while the auto-deploy webhook is also expected to fire — let the deploy own the lifecycle.
**Data drift still outstanding.** 4,154 photo rows + 1 unregistered folder (`Photo Archive 2004-2024`) on disk that's not a SourceRoot. The reconcile endpoints now work — user decides when to call them. The new folder needs to be added as a SourceRoot via the Settings UI before its files will be indexed. **Data drift still outstanding.** 4,154 photo rows + 1 unregistered folder (`Photo Archive 2004-2024`) on disk that's not a SourceRoot. The reconcile endpoints now work — user decides when to call them. The new folder needs to be added as a SourceRoot via the Settings UI before its files will be indexed.