- backup:restore:full refuses on an installation with more than one user
and asks before it starts (--force skips both, also to rerun after a
failure halfway), and warns when the snapshot's database dump was not
one consistent transaction.
- backup:user:restore --mode=replace asks before deleting an existing
account; non-interactive use needs --force.
- The recovery kit file is created owner-only and never over an existing
file or symlink; backup:key:import shows the deletion delay it read from
the kit.
- Adding a location through the web API needs password confirmation, like
removing one.
- Key derivation parameters from a kit or repository config are bounded,
and a stalled network stream no longer spins at full CPU.
- Floating-point columns are dumped exactly instead of with 14 digits.
RepositoryImportSource::copyToFolder() called putContent() on the generic
return type of Node::get(), which doesn't declare that method -- only
File does. Existing-file overwrite during a per-user restore would have
fatally errored at runtime; added an instanceof check and a resource leak
fix (finally-close) while there. Also guarded getFileAsStream() against
fopen() returning false.
Everything else Psalm (strict level) currently flags is mechanical
(missing `final` on leaf classes -- applied everywhere safe) or pre-existing
array-shape/type gaps, captured in psalm-baseline.xml so CI fails only on
new issues from here on, not the whole backlog at once.
- notifications to administrators for failed backup/restore runs and
locations without a successful backup for two days (once a day)
- setup check in the admin overview: error when the key/kit is not set
up, warning for missing, old or failed backups
- security events (recovery kit downloaded, location removed,
append-only turned off, retention changed, snapshots forgotten) go to
the audit log and are announced to all administrators, from the web
and from occ; the scheduled weekly cleanup is logged only
- fix: the recovery-kit download link failed the CSRF check (412); it
now requires a recent password confirmation instead, like creating the
key, removing a location and restoring
- migration: ngb_targets, ngb_runs, ngb_snapshots
- KeyService: master key stored encrypted with the instance secret
(unattended backups), passphrase-wrapped copy in every repository and
in the recovery kit, recorded admin confirmation per key fingerprint
- TargetService: locations built from files_external backends without a
mount; files_external is loaded through IAppManager::loadApp() and its
enabled state is left alone; credentials encrypted with ICrypto;
existing repositories are adopted only if made with this key, and a
repository cannot be registered twice
- Repository: initWithKey/openWithKey with an encrypted key check
- occ: backup:key:init|kit|confirm, backup:target:backends|add|list|remove