- Enforce authoritative administrator global image_gen_enabled disable in get_user_setting, do_generate_image, and image_editing_provider_available, preventing non-admin user preference overrides while preserving user-disabled opt-outs and can_generate_images privilege checks across direct, gallery, and editor paths.
- Filter non-admin preference persistence in saveImagePreferences to user preference keys only (image_model, image_edit_model, image_quality), preventing global policy toggles from leaking into user preferences.
- Return accurate 200 OK Response from saveImagePreferences after fallback persistence succeeds so settings UI displays 'Saved' instead of false 403 error, while retaining visibility of real errors.
- Load per-user preferences via readImagePreferences in initImageSettings so non-admin selections persist and display correctly after page reload.
- Clear per-user model preferences on successful admin save (POST /api/auth/settings) via PUT /api/prefs/{key} with value: null to prevent stale per-user preferences from shadowing updated global settings.
- Support clearing keys in PUT /api/prefs/{key} when value is null.
- Add comprehensive Python regression tests for global-disabled/user-enabled, global-enabled/user-disabled, and authorized generation, plus Node and browser regression tests for non-admin persistence, toggle isolation, reload, and admin clearing.
Reconcile branch with current dev (bebf53be).
Resolve conflicts in static/sw.js (bump cache version and preserve panel precache)
and src/ai_interaction.py (preserve upstream quality handling with per-user settings).
Remediate PR #6992 findings:
- A (CI & Playwright): Pin playwright==1.62.0 in requirements-dev and CI workflow; guard browser test imports against pytest runner collection failure.
- B (Per-User Image Model Settings): Support per-user image_model and image_edit_model in editor_image_models() and ai_interaction; enable non-admin preference persistence via /api/prefs fallback.
- C (CodeQL Regex Alert 1212): Replace polynomial-backtracking regex in routes/editor_agent_routes.py with linear token-based intent matcher.
- D (Undo/Redo rembg layer): Clear stale rembgLiveLayer and rembgLiveSnap references in _restoreState() to prevent edge tuner from corrupting detached layers.
Six regexes over tool output backtracked polynomially on long whitespace
runs or repeated openers: the browser snapshot generic-line filter and
post-interaction split, the task-row and skill-bullet parsers, the email
"no results" check, and the Google /sorry/ interstitial check.
Rewrite each without overlapping quantifiers, keeping the same matches for
the text these tools emit. Move the /sorry/ check into
is_google_sorry_url() so it can be tested.
Preserve complete scientific notation and signed floating-point literals across
arbitrary streaming chunk boundaries in _DegenerateStreamGuard. Buffer pending
tokens until delimiter characters arrive to avoid splitting numbers into
incomplete or arbitrary alphanumeric tokens, while maintaining the 2048-number
runaway backstop and detection of repeated phrases and word loops.