Skip to content

Add Backup & Recovery to V2 Admin Settings with V1 parity - #1682

Merged
Paul Lizer (paullizer) merged 5 commits into
paullizer-react-v2-uifrom
paullizer-v2-admin-backup-recovery
Oct 7, 2026
Merged

Paul Lizer (paullizer) merged 5 commits into
paullizer-react-v2-uifrom
paullizer-v2-admin-backup-recovery

Conversation

@paullizer

@paullizer Paul Lizer (paullizer) commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • V2 Admin Settings listed the Backup & Recovery group but showed "No settings match" for it. Admins had to switch to the classic page to back up, restore, migrate, repair a Cosmos DB document, or follow a job.
    • Each of the group's nine sections now has a V2 card with the classic page's capabilities.
    • The cards follow V2's design: section cards, list-and-detail workbenches like the Model Catalog, and V2 dialogs.
    • They call the existing admin-only /api/admin/data-management/* routes. There are no backend changes.
  • Backup settings join the page's Save bar. They save after the main settings, as the same 42-key document the classic page sends.
    • Actions that run against saved settings save pending backup edits first: queueing a backup, retention cleanup, restore review and queue, and starting a migration.
    • Retry and resume never save.
    • When unsaved Enhanced Citations or Key Vault settings would change how an action is checked, the action offers "Save all and continue".
    • Leaving the page with unsaved work asks first.
  • Restore and migration queue only from a current, passing server review. Overwrite restores and mirror migrations need a typed confirmation.
    • Restore asks for a destination only for the surfaces being restored.
    • Migration "All" shows the server's count, and the Confirm step shows the plan as the server normalized it.
    • The Cosmos DB editor stays locked until the admin accepts the risk, and its saves are ETag-guarded.
    • Jobs follows running jobs and offers retry/resume, cancel, and manifest downloads.
  • Also fixes the literal & in the "Backup Inventory & Restore" navigation label, on both the classic and V2 pages.

Notes for reviewers

  • Up to date with the base. paullizer-react-v2-ui is merged in, at b8db49d71, including Governance (Add the Governance group to V2 Admin Settings #1680) and Scale (Bring V2 admin Scale settings to parity with the classic page #1681). Conflicts were resolved by keeping both sides, except for the two points below.
  • One navigation blocker. The base added a useBlocker that asks before opening a global agent or action editor with unsaved settings. React Router honours one blocker at a time and silently ignores the others, so the page now has a single guard:
    • Opening an editor with only main settings unsaved keeps the base's "Discard unsaved changes?" prompt.
    • Anything else asks with this PR's "Leave Admin settings?" dialog, which also covers unsaved Backup & Recovery settings, an edited Cosmos DB document, or a request still being sent.
    • Whether the held navigation targets an editor is decided inside the blocker function, because blocker.location keeps the /v2 base path.
    • A functional test fails if the page ever has more than one useBlocker.
  • Agent delegation. The base removed it from this page, so it is no longer part of the leave guard.
  • XSS checker change. scripts/check_xss_sinks.py now lists migrationManifestUrl as a reviewed same-origin URL builder. It is apiUrl() over a literal prefix and an encoded job id, and a functional test pins that shape. Worth a look since it is a security tool.
  • State. The cards unmount when a category or search hides them, so their state lives in a zustand store that outlives them. An epoch counter discards async results that arrive after the page is left.
  • Left out deliberately.
    • Light-mode contrast of status text on tinted fills: the same pattern appears in about 89 other V2 files, so it needs a theme-level fix.
    • Toasts appearing above dialogs, and small touch targets: both come from shared V2 primitives.

Linked issue

N/A - no tracking issue was filed for this work.

Release Notes & Latest Features

  • New Feature
  • Bug Fix
  • UI Enhancement
  • Breaking Change
  • Internal only

Is this visible to end users?

  • Yes
  • No

Is this admin-facing (Admin Settings, governance, deployment, config)?

  • Yes
  • No

Should this become a Latest Feature card?

  • Yes
  • No
  • Already added

Screenshot needed for the card?

  • Yes
  • No
  • Attached

Version bump

  • application/single_app/config.py VERSION third segment bumped, or not needed because this is docs-only
    • 0.261.274 (base) -> 0.261.275. The release-notes entry is in its own v0.261.275 section, and this feature's test and doc headers use the same version.
  • deployers/version.txt bumped, or not needed because deployers/ was not changed

Testing / validation

All results are from the branch after the base was merged in.

  • npx tsc -p tsconfig.json --noEmit (in application/v2_ui): passed
  • npm run build (in application/v2_ui): passed
  • python -m pytest ui_tests/test_v2_admin*.py: 223 passed. This includes the 64 Backup & Recovery browser tests, which run against the built SPA with an in-memory copy of the data-management API, and the base's global agents/actions tests for its editor prompt.
  • python functional_tests/test_v2_admin_backup_recovery.py: 4/4 passed, including 42 TypeScript logic checks
  • python functional_tests/test_v2_admin_backup_recovery_parity.py: 5/5 passed
  • python -m pytest functional_tests/test_v2_admin_*.py: 367 passed, 3 failed. None of the three is caused by this PR:
    • test_v2_admin_security_parity.py::test_every_v1_security_field_is_claimed fails without this PR.
    • test_v2_admin_settings_schema.py::test_defaults_match_their_field_type fails without this PR.
    • test_v2_admin_settings_rail_collapse.py::test_the_rail_collapses_to_labelled_icons fails on the base itself: it still expects disabled={delegationDirty}, which the base removed.
  • python functional_tests/test_docs_app_surface_coverage.py: 7/7 passed. Regenerating the inventory with python scripts/build_docs_inventory.py changed nothing.
  • python functional_tests/test_docs_site_quality.py: 6/6 passed
  • python functional_tests/test_data_management_security_patterns.py: passed
  • python scripts/check_xss_sinks.py over the 24 .ts/.tsx files this PR changes: passed. Run over every file the merge brought in, it also flags pages/workspace/AgentEditorPage.tsx:195, which is unchanged from the base.
  • git diff --check: clean
  • An independent code review raised 8 findings, including a job-detail fetch loop and a Cosmos container retry loop. All 8 are fixed, and the reviewer re-checked each fix.

Documentation

  • Release notes updated, or not needed (v0.261.275 entry)
  • Feature documentation updated, or not needed
    • New docs/explanation/features/V2_ADMIN_BACKUP_RECOVERY.md.
    • Rewrote the section text and settings tables in docs/admin/backup-recovery.md.
  • Fix documentation updated, or not needed (not needed: the label fix is one line and is covered in the release notes)

Security checklist

  • New Flask routes include @swagger_route(security=get_auth_security()) (no new routes)
  • Settings sent to non-admin frontends use sanitize_settings_for_user() (no change: the cards use the existing admin-only routes)
  • Browser JavaScript is served from local SimpleChat static assets only; no CDN-hosted JS
  • No secrets, keys, connection strings, or local-only artifacts are included

Paul Lizer (paullizer) and others added 5 commits October 6, 2026 22:45
V2 listed the Backup & Recovery group but showed "No settings match" for it.
Each of its nine sections now has a V2 card with parity to the classic page,
over the existing admin-only data-management API:

- Start Here readiness, Backup runs, Schedule, Storage, Encryption
- Six-step Migration wizard with preflight review and live progress
- Backup Inventory workbench with restore review, delete and retention cleanup
- Locked Cosmos DB editor with ETag-guarded saves
- Job history workbench with live detail, retry/resume and cancel

Backup settings join the page Save bar and save after the main settings.
Actions that run against saved settings save first; retry never does. A
cross-document guard asks to save all when Enhanced Citations or Key Vault
settings have unsaved edits, and leaving the page with unsaved work asks first.

Also fixes the literal "&" in the Backup Inventory & Restore nav label,
approves the reviewed migrationManifestUrl builder in the XSS sink checker,
and documents the group and the V2 save model.

Version 0.261.260.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Parity, design and code audits compared every classic Backup & Recovery
control with the V2 cards. Fixes for the verified gaps:

- Migration: All asks the server for each scope's count and totals the
  principal scopes, as the classic page does; a failed count waits for
  Retry instead of re-requesting. A known total of 0 blocks review. Confirm
  now shows the server-normalized plan from the review, and Validate Cosmos
  access reports data-copy access. Empty searches say "No matches found."
- Restore: a destination is required only for the selected surfaces, and
  the create-only copy now says the review blocks when the destination
  Cosmos DB or AI Search already holds data.
- Inventory and Jobs step back a page when a later page empties; deleting
  a backup clears it from Job detail; stacked workbenches scroll the
  selected detail into view.
- Accessibility and copy: contextual names for the Start Here buttons,
  latest full backup kept by default, storage-test and RU Boost guide notes,
  no duplicate unlock toast.

Docs: the settings tables in docs/admin/backup-recovery.md are rewritten
with verified descriptions, defaults and bounds, and the admin and feature
docs describe the new behavior. Browser coverage grows from 26 to 64 tests.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolves conflicts with 65 target commits:

- admin_settings_fields.py: keep both appended groups (Backup & Recovery
  components, then Operations, in navigation order) and both new field
  descriptors (keywords, on_enable).
- AdminSettingsPage.tsx: keep both sets of imports and renderer cases, and
  pass fieldsByKey to computeSectionStatus alongside the Backup & Recovery
  statuses. The target removed agent delegation, so its delegationDirty
  input is dropped from the leave guard.
- One navigation blocker: the target added a useBlocker for opening a global
  agent or action editor with unsaved settings. React Router honours one
  blocker at a time, so the two guards are combined. Opening an editor with
  only main settings unsaved keeps the editors' discard prompt; anything
  else asks with the page's dialog. Whether the held navigation targets an
  editor is decided inside the blocker function, which sees basename-relative
  paths (blocker.location keeps the base path).
- adminFields.ts: search text includes both keywords and endpoint lists.
- test_v2_admin_capability_placement.py: Backup & Recovery joins the target's
  fully described groups.
- Version 0.261.274; the release-notes entry moves to that version.

Also waits for the inventory and job lists to load before the two
invalid-date-range browser tests take their request baseline, and pins a
single useBlocker on the page in the functional test.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Brings in the Scale settings parity work (#1681), which also took 0.261.274.

- admin_settings_fields.py: Scale joins the fully described groups in the
  module notes, alongside the Backup & Recovery component note.
- adminFields.ts: search text includes keywords, label variants and
  endpoint lists.
- AdminSettingsPage.tsx: keep both sets of imports; section status keeps the
  Backup & Recovery override and passes the target's runtimeFlags; keep the
  target's section-dependents and throughput-validation memos; render both
  the leave dialog and CosmosCapacityConfirm. Still one useBlocker.
- test_v2_admin_capability_placement.py: Backup & Recovery and Scale are both
  fully described groups.
- Version 0.261.275: the Backup & Recovery release-notes entry moves to its
  own section above Scale's 0.261.274, and this feature's test and doc
  headers follow it.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit 919375b into paullizer-react-v2-ui Oct 7, 2026
11 checks passed
Paul Lizer (paullizer) added a commit that referenced this pull request Oct 7, 2026
…61.276

Brings in Backup & Recovery (#1682), which took 0.261.275, so this branch
moves to 0.261.276. Four conflicts, each resolved by keeping both sides:

- admin_settings_fields.py: the related_section docstring stays. The
  fully described groups list Governance, Help and Scale, followed by the
  base's note that Backup & Recovery is described one component per
  section.
- AdminSettingsPage.tsx: the Help component cases sit beside the base's
  nine data-management cases.
- release_notes.md: this branch's entries move to a v0.261.276 section,
  above the base's v0.261.275 Backup & Recovery section.
- test_v2_admin_capability_placement.py: both history lines are kept, and
  invariant 1 names Backup & Recovery and Help, matching the tuple, which
  auto-merged with both ids.

The nav redirect block auto-merged beside the base's "Backup Inventory &
Restore" label fix. Regenerating docs/_data/app_surface.yml leaves it
unchanged. This branch's own version references move to 0.261.276; the
base's 0.261.275 Backup & Recovery lines are left as they are.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer) added a commit to paullizer/simplechat that referenced this pull request Oct 7, 2026
Brings in V2 at 919375b (microsoft#1682, VERSION 0.261.275), which also
includes microsoft#1681 (VERSION 0.261.274).

Conflicts:
- docs/explanation/release_notes.md: V2's file byte-for-byte, with this
  branch's own (v0.261.256) section inserted at the very top, above V2's
  first section, (v0.261.275). Every V2 section is unchanged.
- application/single_app/config.py merged cleanly to V2's file (VERSION
  0.261.275), because this branch hadn't changed it since the last
  merge. The renumber commit sets the final number.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant