Repository navigation
v1.7.3
Security
- Bump
guzzlehttp/guzzleto^7.15.2to clear two fresh advisories (reported 2026-08-03): CVE-2026-69246 (high — a noncanonical host can bypass host-based checks; directly relevant to the agent's trusted-status-URL origin guard) and CVE-2026-69245 (medium — a noncanonical cookie domain keeps subdomain scope). No code changes.
Fixed
- A Laravel 12 client install can no longer resolve an incompatible
nesbot/carbon. Laravel 12.62'sIlluminate\Support\Carbon::plus()override is fatally incompatible with carbon3.12+(which added a?bool $overflowparameter), and the protective pin lived only in this repository's CI matrix — so CI stayed green while a client site runningcomposer updateon Laravel 12 could pull carbon 3.12 and crash on boot. The pin is now a composerconflict(nesbot/carbon >= 3.12.0), so every install resolves carbon 3.11.x until Laravel 12 ships a fix. Laravel 13 accepts carbon^3.8.4, so Laravel 13 installs keep working — they are merely held back from 3.12+ until the conflict is lifted. - Concurrent backup runs can no longer clobber each other's archive. Every backup wrote
backup-<timestamp>.zipintostorage/app/privatewith one-second resolution, and concurrent runs are real: a database and a storage backup may run at once (the trigger lock is per type), and a scheduled command can meet a trigger-driven run of the same type (the command path takes no lock). The CLI zip creator deletes a pre-existing target as "stale", so a same-second neighbour could delete or overwrite an archive mid-run. Archive names now carry a type prefix and a random per-run suffix (backup-database-<timestamp>-<random>.zip/backup-storage-…), so no two runs can ever share a path; the database dump and its ZIP also share one timestamp instead of taking two. - Trigger-driven backups now stamp the heartbeat timestamps. The
last_database_backup_at/last_storage_backup_atsuccess stamp was written only by the artisan commands, so a backup started via the inbound trigger (sync or queued) shipped fine but the heartbeat manifest kept reporting the old timestamp — the control plane could alarm on backups that were in fact running nightly. The stamp now lives in the upload services, at the one point every successful upload passes through, covering the command, sync-trigger and queued paths alike. - A queued backup job re-checks the environment before running.
ProcessBackupJobran without any environment validation — the trigger route's middleware checks it, but a job dispatched directly from host code (or an env change between dispatch and a queued run) could produce an unencrypted database upload whenNOTIFIER_BACKUP_PASSWORDwas missing. The job now fails fast with the missing variable names, matching the command path's refusal to run. - An effectively-empty storage backup skips cleanly instead of failing against the server. A site whose
storage/app/publicholds only a placeholder (.gitkeep) produced a ~200 B archive: the agent's own "nothing to back up" floor was just 100 B, so the archive shipped — and the control plane rejected it with "Backup too small (< 102 400 B)", turning every scheduled run into a hard failure. The agent floor is now configurable (NOTIFIER_MIN_STORAGE_BACKUP_BYTES) and defaults to the server's 102 400 B, so a sub-threshold archive is treated like an empty source: warn + skip (exit 0), no upload, no heartbeat stamp..gitkeepalso joined.gitignorein the default storage exclusions, so a placeholder-only directory is recognized as empty outright. Database backups are unaffected — a database dump is never legitimately empty, so it always ships. - CHANGELOG footer links repaired. The
[1.7.1]and[1.7.2]sections had no link definitions and[Unreleased]still compared fromv1.7.0.
What's Changed
- fix: collision-proof backup archives, heartbeat stamps on every path, carbon/guzzle guards by @ludwigtomas in #26
Full Changelog: v1.7.2...v1.7.3