fix(dogfood 2026-06-18): guard unauth settings actions + retention input (ISSUE-006/007)#154
Merged
Merged
Conversation
…E-006) SvelteKit form actions do not run the route's redirecting `load`, so a same-origin POST from an unauthenticated browser landed directly in the dashboard/settings handlers and dereferenced `locals.user!.id`, throwing a TypeError surfaced as HTTP 500. Add `requireUserAction`/`requireUserActions` to the auth guards (mirroring the existing `requireAdminActions`) returning `fail(401)` when `locals.user` is absent, and wrap the dashboard/settings actions with it. Also guard the page `load` with an unauthenticated redirect (mirroring the layout's isSafeReturnPath returnTo carrier) so the parallel `load` race can no longer 500. Regression test asserts each of the three user-only actions returns 401 (not a TypeError/500) for an anonymous caller, and that the authenticated path still reaches the handler.
…-007) The retention-days number input lacked the `step="1"` attribute that its sibling max-log-count input already carries, so the browser accepted fractional values like 3.5. The server-side `LogSettingsSchema.retentionDays.int()` already rejects non-integers; this aligns the client input with that contract for consistent native validation and a clearer stepper UX.
🤖 Augment PR SummarySummary: This PR remediates the remaining 2026-06-18 dogfood findings by preventing unauthenticated POSTs to user-only settings actions from crashing (500) and aligning a retention input with the server’s integer contract. Changes:
Technical Notes: The dashboard settings change addresses the SvelteKit nuance that form actions don’t run the route’s redirecting 🤖 Was this summary useful? React with 👍 or 👎 |
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.
Summary
Verify-then-fix remediation of the 2026-06-18 dogfood findings (ISSUE-001…007). Per the plan (
.omc/plans/fix-dogfood-2026-06-18-findings.md), every finding was first re-verified against current HEAD; only the two still-broken ones received code changes. The other five were already fixed by a concurrent remediation cycle or are third-party, and are documented here rather than re-patched.Phase 0 verification table
onboarding/claim/+page.svelte:51-53rendersrole="alert"from the action'sform.error; server returnsfail(400,{error})(claim/+page.server.ts:36).admin/+layout.svelte:50-148—isMobileSidebar,.menu-button, overlay, Tab focus-trap.auth/plex/+server.ts. No Obzorarr code emits it; console deliberately not monkey-patched.sync/scheduler.tspausedByOperator→getSchedulerStatus().isPaused;admin/sync/+page.svelte:546/586distinct "Paused" badge + "Resume" button.admin/settings/security/+page.server.ts:179runsCsrfOriginSchema.safeParse→fail(400,'Invalid origin URL').ISSUE-006 — unauthenticated settings actions return 401, not 500
SvelteKit form actions do not run the route's redirecting
load, so a same-origin POST from an unauthenticated browser landed directly in thedashboard/settingshandlers and dereferencedlocals.user!.id→TypeError→ HTTP 500.requireUserAction/requireUserActionstosrc/lib/server/auth/guards.ts(mirroring the existingrequireAdminActions), returningfail(401, { error: 'Authentication required' })whenlocals.useris absent.dashboard/settingsactions (updateShareMode,regenerateToken,updateLogoPreference) with it.loadwith an unauthenticated redirect mirroring the layout'sisSafeReturnPathreturnTo carrier, closing the parallel-loadrace.tests/unit/dashboard/settings-auth-guard.test.ts): each user-only action returns 401 (no TypeError) for an anonymous caller; the authenticated path still reaches the handler.ISSUE-007 — whole-number retention-days input
admin/settings/system/+page.svelteretention-days input gainsstep="1"to match the sibling max-log-count input. The serverLogSettingsSchema.retentionDays.int()remains the authoritative guard; this aligns the client with that contract.Verification
bun run check— 0 errors / 0 warningsbun run test— 2158 pass / 0 failbun run check:biome— cleanwrapped/[identifier]already inlines the 401 guard).