Repository navigation
feat(backups): take, list, verify and delete database backups in Studio - #2079
Merged
Merged
Conversation
Adds a Backups tab under Config, for super users on Harper 5.2+. Pick a database, then take a backup (following its job until it ends), list the backups with id, time, size and whether file attachments are included, verify one, delete one, or keep only the newest N with a confirmation that names what goes. On a cluster each member is listed and reached on its own through /HDBInstance/<id>/operation, because a backup lives on the disk of the node that took it and the cluster's own address reaches whichever member runs first. Restore stays out of scope. Refs #2008 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Harper reuses backup ids once every backup is deleted, so delete now re-reads the list and refuses when the confirmed backup's timestamp no longer matches. A cluster page and its nav entry show once any member runs 5.2, not on whichever member answers registration_info. A job poll Harper refuses with a 403 ends the follow as unknown and frees the node, an accepted create or verify that names no job reads as an unknown outcome, and Verify waits while a backup is being taken. Refs #2008 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntity A job that read as missing once and then turns up keeps being followed. Delete refuses when either side has no timestamp to tell two backups apart, and a verify badge needs one too. Verify waits behind the same per-node hold as every other write, a purge answer without a count no longer states one, and held buttons say why. Refs #2008 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A describe_all refetch can change the page's default database while a dialog is open. Each dialog now records the database it was opened for and closes if that changes, so a purge never runs against a database the user didn't choose. Refs #2008 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Switching back to the database a dialog was opened for no longer brings the dialog back unasked. Refs #2008 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The page no longer flashes a verdict the other answer would reverse, and a registration_info with no version reads as unreadable rather than "runs undefined". Refs #2008 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dawsontoth
marked this pull request as ready for review
November 9, 2026 17:04
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive database backup management feature for Harper databases (version 5.2.0+). It adds a new 'Backups' section under the instance configuration, allowing users to take, verify, delete, and purge backups on a per-node basis. The implementation includes React components for dialogs and job tracking, API integrations, routing updates, detailed design documentation, and extensive unit and integration tests. I have no feedback to provide as there are no review comments to assess.
kriszyp
approved these changes
Nov 10, 2026
kriszyp
left a comment
Member
There was a problem hiding this comment.
🤖 Reviewed with Muse Wonder 1.0 · adjudicated by Codex
…ing a 403 Verify now re-reads the list and refuses when the id names a different backup, as delete does, and both compare size and file count as well as the timestamp. A job poll answered 403 gives up at once rather than after three retries, so the node's write hold clears promptly. A member list that couldn't be read no longer counts as proof that no node runs 5.2. Refs #2008 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
⊙ Problem
Harper 5.2+ can take and manage database backups. Studio has no screen for them. Fabric customers must type operations into the Operations console.
💡 Solution
/HDBInstance/<id>/operation. The cluster's own address reaches whichever node runs first.🤔 Keep newest N starts at 1
Harper accepts
keep_count: 0, which deletes every backup. The dialog asks for at least 1, so clearing a database's backups takes one Delete per row. Say if 0 should be allowed.🤔 Leaving the page stops following a job
Studio follows a job only while the page is open. The backup still finishes and shows in the list later, but its result message is lost. Keeping followed jobs per node across pages is possible; say if it's wanted.
⚖️ Alternatives
Decisions the review raised
registration_infoor the cluster record can show the page, but it says backups are unsupported only once both are in, so neither can flash a verdict the other reverses.timestamp, so only a malformed answer hits this.🔧 Changes
backups.ts— the five operations, taken as a background job, behind the 5.2.0 gate (no 5.2.0 prerelease has them). The job poll is pinned to the node running the job, sincehdb_jobdoesn't replicate, and never retries a 403. Verify and delete re-read the list and refuse when the id names another backup, matching timestamp, size and file count; Harper offers no other identity and no precondition, so a narrow window remains. Purge reports Harper's own count, and the confirmation says what it removes. An accepted request with no job id is an unknown outcome.backups/index.tsx— the super-user gate, a cluster shown once any member runs 5.2 and no verdict from a member list it couldn't read, the database picker and the on-page warnings. Each member gets a client pinned to it through Fabric; without cluster update permission, or on a self-hosted cluster, the page says why instead.BackupNodeSection.tsx— one card per node. Every write is held while one runs, a dialog is bound to its database, a verify result matches on id and timestamp, a refusal re-reads the list, and a purge toast never invents a count.BackupJobLine.tsx— job progress. A job missing for 20 s or refused with a 403 ends as unknown and frees the node.BackupDialogs.tsx— the take, verify and keep-newest confirmations.backupNodes.ts— which members to list: removed ones are skipped, unreachable or old ones say why, sorted by name.config/index.tsx,routes.ts— the version rule and nav entry, the route and where it mounts.queryClient.ts— the unknown-outcome wording for an accepted request with no job.backups/DESIGN.md,DESIGN.md— why requests are pinned to a node and what size and id mean; the root index entry and unknown-outcome list.✅ Verification
index.test.tsxdrives the page against fake per-node clients with a real QueryClient: jobs followed on their node, a delete refused on id reuse, a partly upgraded cluster.backupNodes.test.tsandbackups.test.tscover member selection and request shapes. Removing any of the node pinning, the busy hold, the list refresh, the identity checks, the any-member rule, the 403 handling, the missing-job recheck or the dialog binding turns a test red.tsc -b, oxlint, dprint. The Fabric per-node route needs Fabric and wasn't run live; it is the clientInstanceStatusCellalready uses.Closes #2008
🤖 Generated by Anthropic Claude (Claude Code); posted via @dawsontoth.
Related PRs: #2031 overlaps (Config nav entries and route list), #2065 overlaps (Config nav entries and route list)
Complexity: medium
Deferred findings
2e5a2c17d141883cnit maintainability —src/integrations/api/instance/backups/backups.test.ts— relative imports lack the .ts extension — NOT FILEDReview-Coverage: authored=claude; ran=cursor-composer,gemini,codex,cursor-grok; late=cursor-grok:adjudicated; adjudicated=domain; declined=muse; rounds=6; full=2 @ 293f578
Review-Attention: study ~11m (decisions: do-less-alternative, version-gate-waits-for-both, verify-lock-scope, delete-refuses-without-timestamp) @ 293f578