Retention (RetentionManager and the plugin's hourly cleanup) only ever
deleted local files; remote archives grew unbounded. Add an idempotent
delete() to RemoteUploaderInterface + all four uploaders and have
RetentionManager remove each pruned archive from the profile's enabled
remotes (best-effort; failures logged). The shared restore.php is left
in place since every backup overwrites it. (#229)
Consolidate duplicated plumbing (#230):
- New RemoteUploaderFactory replaces the createUploaderFromParams copy
duplicated in BackupEngine and SteppedBackupEngine.
- RetentionManager becomes the single retention authority (global-default
fallback + pruneOrphans()); the system plugin delegates to it and its
duplicate doCleanup()/deleteBackupRecord() logic is removed.
- Backend controller, API controller and legacy cli/mokosuitebackup.php
now run through the shared BackupRunner instead of BackupEngine directly.
Refs #229#230
Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
Renames all sub-extensions from mokojoombackup to mokosuitebackup
(package, component, 7 plugins, language files, manifests).
Adds [HOME] placeholder to BackupDirectory and PlaceholderResolver
so users can set backup_dir to [HOME]/backups (outside web root).
Fixes folder browser "access denied" on PHP-FPM shared hosting
where getenv('HOME') returns empty by adding POSIX and JPATH_ROOT
fallback detection.