update 1.2.2.2 beta

This commit is contained in:
MacRimi
2026-07-02 20:57:11 +02:00
parent 872f79a9ea
commit 827c88d24f
6 changed files with 42 additions and 93 deletions

View File

@@ -1989,11 +1989,6 @@ function CreateJobDialog({
// Backend-specific fields
const [pbsRepository, setPbsRepository] = useState<string>("")
const [pbsBackupId, setPbsBackupId] = useState<string>("")
// Explicit acknowledgement to proceed with encryption but WITHOUT a
// recovery passphrase. Mirrors the shell's 3-way gate: without this
// flag (or a filled passphrase pair), submit is blocked when the
// operator ticks "Encrypt". Same rationale as ManualBackup below.
const [pbsAcceptedNoRecovery, setPbsAcceptedNoRecovery] = useState<boolean>(false)
// Client-side PBS encryption — sent as `pbs_encrypt` in the payload.
// Backend resolves the shared keyfile + injects PBS_KEYFILE into
// the job .env so the runner adds `--keyfile` to the backup call.
@@ -2187,7 +2182,6 @@ function CreateJobDialog({
setPbsRecoveryPass("")
setPbsRecoveryPass2("")
setPbsRecoveryChange(false)
setPbsAcceptedNoRecovery(false)
setLocalDestDir("")
setBorgRepoSelected("")
setBorgPassphrase("")
@@ -2274,11 +2268,15 @@ function CreateJobDialog({
? true
: /* borg */ !!borgRepoSelected
// PBS encryption 3-way gate — see ManualBackup for full rationale.
// PBS encryption gate — choosing "Encrypt" makes the recovery
// passphrase mandatory. The button stays disabled until a matching
// passphrase pair is entered (or an already-saved escrow is reused).
// There is no opt-out: encrypting without recovery would leave the
// keyfile only on this host, and a reinstall would render every
// encrypted backup unrecoverable.
const pbsRecoveryOk = !(backend === "pbs" && pbsEncrypt) ||
(pbsRecoveryStatus?.has_recovery && !pbsRecoveryChange) ||
(pbsRecoveryPass !== "" && pbsRecoveryPass === pbsRecoveryPass2) ||
pbsAcceptedNoRecovery
(pbsRecoveryPass !== "" && pbsRecoveryPass === pbsRecoveryPass2)
const canSubmit =
canAdvanceFrom1 && canAdvanceFrom2 && canAdvanceFrom3 && canAdvanceFrom4 && backendValid && pbsRecoveryOk
@@ -2974,24 +2972,6 @@ function CreateJobDialog({
<p className="text-[11px] text-red-400 mt-1">Passphrases don't match.</p>
)}
</div>
{!pbsRecoveryPass && !pbsRecoveryPass2 && (
<div className="mt-2 rounded-md border border-red-500/40 bg-red-500/10 p-2.5 space-y-1.5">
<div className="flex items-start gap-1.5 text-[11px] text-red-300">
<AlertTriangle className="h-3.5 w-3.5 shrink-0 mt-0.5" />
<div>
<span className="font-medium">Without a recovery passphrase, the keyfile lives ONLY on this host.</span> If this host is lost or reinstalled, every encrypted backup becomes unrecoverable.
</div>
</div>
<Label className="flex items-center gap-2 text-[11px] cursor-pointer">
<Checkbox
id="pbsSchedAcceptNoRec"
checked={pbsAcceptedNoRecovery}
onCheckedChange={(v) => setPbsAcceptedNoRecovery(!!v)}
/>
<span>I understand the risk and want to encrypt without recovery.</span>
</Label>
</div>
)}
{pbsRecoveryStatus?.has_recovery && pbsRecoveryChange && (
<button
type="button"
@@ -3342,11 +3322,6 @@ function ManualBackupDialog({
// passphrase if one is already saved — only show the inputs when
// there's no escrow yet OR the operator explicitly asks to change.
const [pbsRecoveryChange, setPbsRecoveryChange] = useState<boolean>(false)
// Explicit acknowledgement to proceed with encryption but WITHOUT a
// recovery passphrase. Mirrors the shell's 3-way gate: without this
// flag (or a filled passphrase pair), submit is blocked when the
// operator ticks "Encrypt".
const [pbsAcceptedNoRecovery, setPbsAcceptedNoRecovery] = useState<boolean>(false)
// Whether the host already has an escrow blob configured. When
// present, the passphrase input becomes optional ("leave blank to
// keep saved"). Refreshed after a successful setup call.
@@ -3406,7 +3381,6 @@ function ManualBackupDialog({
setPbsRecoveryPass("")
setPbsRecoveryPass2("")
setPbsRecoveryChange(false)
setPbsAcceptedNoRecovery(false)
setLocalDestDir("")
setBorgRepoSelected("")
setBorgPassphrase("")
@@ -3444,15 +3418,16 @@ function ManualBackupDialog({
// Borg destination carries its own passphrase + encryption.
// No need to gate on local state — the wizard no longer asks.
: !!borgRepoSelected
// Recovery gate for PBS encryption. When "Encrypt" is ticked, either
// a matching passphrase pair OR an explicit accept-risk checkbox is
// required — otherwise submit stays blocked. Mirrors the shell 3-way
// gate so the operator can never silently create an encrypted backup
// whose keyfile only lives on this host.
// Recovery gate for PBS encryption. Choosing "Encrypt" makes the
// recovery passphrase mandatory — same as the CLI. The "Run backup"
// button stays disabled until a matching passphrase pair is entered
// (or an already-saved escrow is reused). No accept-risk escape:
// encrypting without recovery would leave the keyfile only on this
// host, and a reinstall would render every encrypted backup
// unrecoverable.
const pbsRecoveryOk = !(backend === "pbs" && pbsEncrypt) ||
(pbsRecoveryStatus?.has_recovery && !pbsRecoveryChange) ||
(pbsRecoveryPass !== "" && pbsRecoveryPass === pbsRecoveryPass2) ||
pbsAcceptedNoRecovery
(pbsRecoveryPass !== "" && pbsRecoveryPass === pbsRecoveryPass2)
const canSubmit = canAdvanceFrom1 && backendValid && pbsRecoveryOk
async function handleRun() {
@@ -3768,24 +3743,6 @@ function ManualBackupDialog({
Cancel change — keep the saved passphrase
</button>
)}
{!pbsRecoveryPass && !pbsRecoveryPass2 && (
<div className="mt-2 rounded-md border border-red-500/40 bg-red-500/10 p-2.5 space-y-1.5">
<div className="flex items-start gap-1.5 text-[11px] text-red-300">
<AlertTriangle className="h-3.5 w-3.5 shrink-0 mt-0.5" />
<div>
<span className="font-medium">Without a recovery passphrase, the keyfile lives ONLY on this host.</span> If this host is lost or reinstalled, every encrypted backup becomes unrecoverable.
</div>
</div>
<Label className="flex items-center gap-2 text-[11px] cursor-pointer">
<Checkbox
id="pbsManualAcceptNoRec"
checked={pbsAcceptedNoRecovery}
onCheckedChange={(v) => setPbsAcceptedNoRecovery(!!v)}
/>
<span>I understand the risk and want to encrypt without recovery.</span>
</Label>
</div>
)}
</>
)}
</div>