What's New
Product Changelog
Every update across every Bodholdt Labs plugin, newest first. We ship often, and we write it all down.
Subscribe via RSS
Bodholdt Backup for OneDrive
v5.34.1
- Scheduled database backups no longer fail when a security plugin rebuilds its temporary table mid backup. Some security tools create and then drop a temporary scratch table while your site is running. If that happened partway through the database export, the backup stopped with a "table definition has changed" message and only finished on the next scheduled run, so you saw a failure followed by a success. That scratch table holds nothing worth restoring, so it is now left out of the backup entirely, and any brief database hiccup during a backup now retries on its own up to three times instead of ending the run. Nothing for you to change.
Bodholdt Backup for OneDrive
v5.34.0
- Clearer restore confirmation before anything is overwritten. The restore warning now says plainly that the automatic safety copy covers your database only and there is no one-click undo, replacing wording that implied a restore could simply be undone. It also adds a heads-up that your site briefly shows a maintenance page while a restore runs and reopens on its own within about ten minutes if the restore is interrupted, so you are not left wondering. The confirmation checkbox and modal are unchanged. No change to how restore itself works.
Bodholdt Backup for OneDrive
v5.33.0
- Backups now restore on sites running both Bodholdt backup plugins. If you have both the Google Drive and OneDrive backup plugins installed, every archive included the other plugin's files, and restore refused those archives outright because it is designed never to overwrite a backup plugin mid restore. The result was backups that always reported success and could never be restored. Archives taken from this version on restore normally. If you run both plugins, please take a fresh backup after updating so you have an archive that restores.
- Please take a fresh backup after updating if your site runs MySQL 8. Columns whose default is the current timestamp were being left out of the database export. Many plugin tables use these for dates like "created" and "last updated", including WooCommerce order analytics. Backups still reported success, and on restore those dates were refilled with the time of the restore rather than the original values, so the data looked plausible but was wrong. Archives created before this update are affected on MySQL 8. Sites on MariaDB were never affected. One new backup after updating replaces the gap.
- Backups no longer stop when your site contains a symbolic link. One linked theme, plugin folder, or single linked file inside uploads used to end the entire run, and the failure email suggested checking your server logs or internet connection, which had nothing to do with the real cause. Links are now skipped, the rest of your site is backed up normally, and the run tells you exactly which links were left out. This is common on managed hosting, on container based setups, and on any site using a linked child theme or a shared media mount.
- An interrupted restore can no longer leave your site stuck offline. If a restore was killed partway through, by a memory limit, a timeout, or a server restart, WordPress was left in maintenance mode permanently. Both the site and the WordPress admin returned "Briefly unavailable for scheduled maintenance" forever, and the only way out was deleting a file over SSH or FTP. A running restore still closes the site as it should, but an abandoned one now reopens on its own after ten minutes so you can get back into your admin and try again.
- A stalled restore no longer blocks every future backup with no way to clear it. The Force Unlock button only ever appeared for stalled backups, never for stalled restores, so a restore that stopped unexpectedly left backups permanently blocked with the fix hidden from view.
- Clearer, more honest failure messages. Running out of local disk space is no longer reported as your OneDrive being full, and no longer suggests deleting your backups, which would not have helped. The size estimate on the dashboard now tells you what actually went wrong instead of only "Could not calculate estimate." Internal log tags no longer appear in messages meant for you.
- File exclusions now support wildcards. Patterns like `*.log` and `wp-content/cache/*` previously matched nothing at all and gave no warning, so files you thought you had excluded were still being uploaded.
- Backup notification emails are now translatable and no longer arrive in English on a translated site. They also fall back to plain text if the HTML message cannot be delivered, and a delivery failure is recorded instead of passing silently.
- Retention problems are now visible. If old backups could not be removed from your OneDrive, the run said nothing and storage kept growing. It now tells you.
- A warning when scheduled backups cannot actually run. If WP-Cron is switched off on your host, Settings used to show an active schedule while nothing ever ran. You are now told, with instructions for setting up a real cron job.
- Also in this release. A working admin menu when the plugin is activated on a single site of a multisite network. Large downloads no longer time out on a blank page, and a download that was merely interrupted is no longer reported as a corrupt archive. The setup wizard no longer says setup is complete when the server rejected the save, and it no longer overwrites a backup time you already chose. The progress bar no longer freezes forever if a status check fails.
Bodholdt Backup for OneDrive
v5.32.12
- Clearer badges and error text (WCAG 2.1 AA). The plan badge in the header, the status badges, and the red error text in the activity log now meet AA contrast against their dark backgrounds. On some screens they could render a little too dim to read comfortably. No change to how backups or restores work.
Bodholdt Backup for OneDrive
v5.32.11
- Restore works, including full disaster recovery. Several internal checks disagreed with each other about the exact bytes of your archive, so a restore could stop before changing anything. Backups, restores, incremental restores, and fresh-site recovery (reconnect a new site to your existing OneDrive folder and restore) are now all verified working end to end. If you were unable to restore a backup on an earlier version, take a fresh backup and use that one.
- Backups keep their exact identity. The backup's stored name and the name it is signed under are now always the same string, so a cloud-side rename can no longer make an archive unrestorable.
- More accessible admin. The dashboard now meets WCAG 2.1 AA: stronger error-text and focus-outline contrast, and the optional celebration pop-ups are announced, dismissible, and pause on hover or focus.
Bodholdt Backup for OneDrive
v5.32.10
- Backups to a personal OneDrive account now work. The plugin writes an ownership marker into its backup folder and reads it back to confirm the folder is really yours. Microsoft answers that read with a redirect to a separate content host, which earlier versions treated as a failure, so the check never passed and every backup stopped before it started. The marker is now read the same way the plugin already downloads archives, so backups run normally.
- Your backups are recorded, restorable, and pruned again. Each upload is recorded in a local list that proves the plugin owns that archive. A missing field in one Microsoft request made every entry fail its ownership check and get dropped, so backups uploaded and reported success while becoming unrestorable, retention never deleted anything, and the plugin treated its own archives as if they belonged to someone else. If you have unrestorable archives from an earlier version, take a fresh backup and use that one.
Bodholdt Backup for OneDrive
v5.32.9
- Your cloud backups no longer contain your credentials on some sites. If your database table prefix has no trailing underscore, such as `wp` instead of `wp_`, the filter that keeps live credentials out of uploaded archives did not match your options table. Your Microsoft client secret, refresh token, license key, and WordPress security salts were written into the backup. Redaction now works with any valid prefix. If your site uses a prefix like this, please delete your existing cloud backups and create a fresh one.
- Binary and case-sensitive collations survive a restore exactly. Backups previously rewrote collations such as `utf8mb4_0900_bin` and `utf8mb4_ja_0900_as_cs` to a case-insensitive one, which silently changed sorting, uniqueness, and case-sensitive lookups on the restored site. They are now preserved exactly, in every place the plugin reads or writes a collation.
- Backups record your real database schema. Collation rewriting at backup time is now off by default, so an archive is a faithful copy of your source schema. If a restore lands on a server that cannot support one of your collations, the plugin adapts at restore time instead, where it can see what the destination actually supports. If you restore a dump by hand with the `mysql` command onto a different database engine, switch the setting back on before taking that backup.
- Backups no longer fail on valid database schemas. A site with a view or table that uses `REPLACE()`, `TRUNCATE()`, or `INSERT()` as a function was blocked from backing up at all. Those are now read as functions rather than as dangerous statements, and genuinely unsafe statements are still rejected.
- Restore no longer writes credentials to your error log. If a statement failed while a restore was rolling back, WordPress logged the whole statement, including options rows holding your live credentials. Failures are now recorded without the statement text, and errors are still detected and reported to you.
- Your license is no longer removed when you upgrade. On single-site installs a one-time migration deleted the stored license key, status, and tier, quietly dropping paid installs to the free feature set. It now does nothing outside multisite, and it can be run repeatedly without harm.
- A stuck backup can no longer leave the plugin unusable. If a backup process was killed, the operation lease stayed held, listing and restore stopped working, and after an hour the Force Unlock control disappeared, leaving no way to recover without server access. The stale-lock warning and its Force Unlock button now follow the real lock state, and the message explains what actually happened.
- The settings screen always opens. A corrupted saved option could stop the page mid-render, so the form and its save button never appeared and there was no way to repair it from the admin.
Bodholdt Backup for OneDrive
v5.32.8
- Exact OAuth continuity after restore. Encrypted credential and token rotations now preserve an existing option row's raw autoload metadata while changing only its encrypted value, avoiding a false restore failure on legacy WordPress rows.
- Self-contained Fast Backup restore. Removed an unused restore-base receipt. Fast Backup restore already downloads, authenticates, hash-links, and privately composes its exact Full base before maintenance mode or customer-data mutation.
Bodholdt Backup for OneDrive
v5.32.7
- Credential changes stay atomic. Hookable cache cleanup now happens before the final encrypted credential commit, so a throwing object-cache integration cannot leave OAuth authority partly rolled back.
- Mobile and keyboard-safe admin. The HUD wraps on narrow screens, wizard focus follows each visible step, Escape dismisses cleanly, inline restore controls remain in normal page focus, and the destructive-restore dialog restores focus to its trigger.
- Reliable downloads and copy controls. AJAX download links no longer depend on a popup, clipboard success requires a confirmed copy, and failures are reported clearly.
- Accessible, accurate setup. Credential and schedule controls have explicit labels; Microsoft authorization and expired-secret guidance now match the actual same-tab flow and dashboard/log error reporting.
- Safe Dashboard metadata. Legacy object- or array-valued log fields are ignored before the Dashboard renders them, matching the hardened Logs table.
- Signed file permissions. On POSIX hosts, new recovery points authenticate every managed file's SHA-256 digest and POSIX mode. Other hosts authenticate file bytes plus an explicit unavailable mode capability; filesystem restore stays fail-closed unless exact rollback permissions can be guaranteed. Restore proves bytes and file identity, applies authenticated file modes before directory modes where supported, and automatically rolls back if chmod or verification fails.
- Exact Fast Backup chains. Hashes, modes, and tombstones compose in lockstep. A base without exact POSIX mode authority forces a self-contained Full backup instead of creating a mixed-fidelity chain.
- Honest older/platform restores. On POSIX destinations, older authenticated archives preserve existing target modes, use restrictive modes for recreated files, and leave destination-only files in place because degraded archives cannot authorize exact scope deletion; source-mode-unavailable archives show a separate warning while bytes, type, and single-link identity remain verified. Filesystem restore on a non-POSIX destination is refused because exact automatic permission rollback cannot be guaranteed; database-only restore remains available.
- Bound required recovery authority. The caller-validated database dump and finalized recovery manifest must match their exact size and SHA-256 records inside the signed archive inventory. Stable bounded manifest reads, archive-identity continuity, and strict unique-key OneDrive ownership markers stop source swaps, oversized records, and duplicate-key authority collapse.
- No partial failed exports. An aborted, truncated, empty, or storage-failed database export removes its incomplete SQL image before reporting the failure, preventing stale recovery data from being reused accidentally.
- Client Secrets stay out of page HTML. Wizard and Settings password fields remain blank after a secret is saved and show only that a stored value exists. Leaving the field blank keeps the saved secret; changing credentials still requires a complete matching pair.
Bodholdt Backup for OneDrive
v5.32.6
- Safe partial legacy log rows. Older metadata that contains only a backup size or file count now renders with a harmless placeholder instead of a PHP warning; nonscalar display fields are ignored safely.
Bodholdt Backup for OneDrive
v5.32.5
- Clean legacy Logs screens on modern PHP. Older log rows with empty or malformed metadata are displayed safely without PHP 8.5 deprecation notices on the Dashboard or Logs tab.
Bodholdt Backup for OneDrive
v5.32.4
- Correct database recovery guidance. A nontransactional material table now always produces the InnoDB conversion advice in logs, webhooks, and email, even when its table name contains words such as token, quota, space, zip, or disk.
Bodholdt Backup for OneDrive
v5.32.3
- Accurate settings confirmation. The green settings-saved feedback now appears only after WordPress verifies the complete settings transaction. Invalid input, a busy backup or restore, and failed writes or rollbacks no longer show a contradictory success message.
Bodholdt Backup for OneDrive
v5.32.2
- Wordfence no longer blocks safe backups. The rebuildable `wp_wfls_role_counts` MEMORY cache is preserved as an empty InnoDB table for Wordfence to repopulate; any other non-transactional material table still stops the backup clearly.
- Multisite recovery boundaries are explicit. Every primary-site table must have one unambiguous owner, and a Network backup records the one network and all of its sites. Ambiguous tables, multi-network databases, and older archives without the new signed recovery authority are refused before anything is changed.
- Action after upgrading: Create a new Full backup in Network mode before relying on multisite restore; older network recovery points do not contain the authority required by this release.
- Cleaner safe uninstall. Successful removal clears the legacy uploads staging folder, while an uninstall attempted during active or queued recovery leaves that evidence untouched.
- Safer setup and connections. Settings and setup-wizard changes now commit and verify as one transaction or roll back exactly. Concurrent administrators can connect safely, stale OAuth callbacks are bounded and invalidated, and legacy credentials, tokens, and licenses cannot overwrite a newer valid change during upgrade.
- Restore rollback and storage protection. Pre-restore snapshots bind exact no-follow file copies to content digests, reject filesystem drift and link/type swaps, verify the complete private rollback image before mutation, and preserve a 64 MiB emergency disk reserve.
- Restore progress reconnects safely. A temporary maintenance-mode response no longer turns the progress screen red or stops polling. The page reconnects automatically, and final health failures expose only safe diagnostic codes rather than site or provider details.
- Recoverable database exports on MySQL and MariaDB. Dumps preserve the disk reserve, create dependent views in a safe global order, reject incomplete or ambiguous view graphs, and stop clearly when triggers, routines, or events cannot be represented instead of silently omitting them.
- Hardened packages, Free edition, cleanup, and privacy. Release builds reject unsafe source/ZIP content before atomic publication, and the Free build retains its required restore helper instead of fatalling on first load. Uninstall removes only OneDrive-owned state, operator notices require the backup capability, and diagnostics omit provider/customer identifiers and paths.
Bodholdt Backup for OneDrive
v5.32.1
- Database recovery points are trustworthy again. Literal percent signs and serialized data round-trip byte-for-byte. Exports use one isolated InnoDB consistent snapshot, and non-transactional tables or metadata omissions stop the backup clearly.
- Migration and restore fail safely. Imports require usable schema and data, multisite domain/path mappings are preserved, generated configuration is verified, and SQL/manifest secrets live in a protected key-bound hidden directory. Large ZIP members receive streamed size/CRC and path/type checks.
- Operations and settings are honest. Owner-token leases survive options-table restore, mandatory members and requested files are verified before upload, all webhook triggers can be disabled, weekly schedules retain their weekday, multisite reset is complete, and uninstall removes plugin transients plus OneDrive rows from every legacy subsite log table without removing Google Drive rows. Missing subsite arcade tables are skipped without database errors.
Bodholdt Backup for OneDrive
v5.32.0
- Restores you can trust, right on the screen. Restoring an incremental backup over your existing site no longer reports a false "nothing was restored", and any compatibility caution now appears on the restore screen itself, not only in the log.
- Migrations that finish the job. Moving a multisite network keeps every subsite on its correct address, saved nested settings survive a domain change, and backups taken on newer MySQL versions restore cleanly onto older database servers.
- Protected recovery evidence. A successful migration removes its database file and manifest. A failed migration retains them for retry and diagnosis; 5.32.1 moves them into a protected random directory from extraction onward. Removing the plugin from a large multisite network now cleans every site, not just the first hundred.
- Notifications and scheduling polish. The "Send Test" button now tests the webhook address you just typed, "Reset to Defaults" truly resets everything, a weekly schedule no longer triggers a daily false "backups are stale" alert, and your backup keeps its chosen time through daylight saving changes. Plus a long list of smaller reliability, safety, and translation fixes. Nothing about how your everyday backups run changes.
Bodholdt Backup for OneDrive
v5.31.0
- Migrations you can trust on any host. Moving a site to a new server now keeps every table even when your host uses a custom database prefix (common on managed hosting), so a migration no longer lands on a blank WordPress setup screen. Multisite network settings carry across too, and the one click site mover deletes its database file the moment it finishes instead of leaving it in your web root.
- Backups and restores that tell the truth. A backup now stops and warns you if the database export was cut short, instead of quietly saving an incomplete copy. A restore that had nothing to put back tells you which parts were empty rather than showing a cheerful "all done". And an incremental backup is clearly labeled, so restoring one on its own can never rebuild a broken site by surprise.
- Settings you can save any time. You can now save your schedule and other settings before you connect OneDrive, and saving before you enter a license no longer clears your Slack or Discord alert choices. Activating a valid key while our server is briefly unreachable now says exactly that, rather than claiming your key is wrong, and a slow licensing server no longer makes your Plugins screen hang.
- Calmer by default, and much more. The arcade now has its own settings and confetti is off unless you turn it on, the nightly watchdog reliably warns you if backups go stale, and there is a long list of smaller fixes and tidy ups. Nothing about how your everyday backups run changes.
Bodholdt Backup for OneDrive
v5.30.0
- Reliability and safety hardening (QA round). Saving Settings now reliably persists every change, restores report their status honestly, the database export stops rather than truncating on an error, and automatic backups re arm correctly after the plugin is switched off and on. Plus a range of smaller migration, retention, and cleanup fixes. No change to how your everyday backups run.
Bodholdt Backup for OneDrive
v5.29.0
- Restore you can trust. Restores now tell you the truth: if any part of the database or files could not be applied, you get a clear "finished with problems" message that points you to the pre-restore snapshot, instead of a false "Restore complete!". Cross-version moves are smoother too, so a backup taken on a newer MySQL restores cleanly onto an older MySQL or MariaDB.
- More reliable migrations. The standalone migration installer now works correctly on modern PHP (8.1 and newer), keeps your real site configuration and table prefix (custom prefixes and multisite restore properly now), and imports stored procedures and triggers without dropping them.
- Backups that hold up on big sites. Long backups on large sites no longer risk colliding with another run, generated columns and special column types (BIT, spatial) back up and restore correctly, and every row is captured even in unusual tables.
- Clearer and safer everywhere else. Honest schedule status on a fresh install, an accurate description of per-site multisite mode, important warnings now visible to multisite network admins, saved credentials no longer loaded on every page, a cleaner reconnect prompt when OneDrive access expires, tidier file-exclusion matching, and a range of smaller polish and cleanup fixes.
Bodholdt Backup for OneDrive
v5.28.3
- Backup safety and robustness hardening. Backups and restores can no longer run at the same moment, so a scheduled backup, a manual backup, and a restore never overlap and leave you with an inconsistent archive. We also tightened how backup file names are shown in your Backups list, made the Settings save shrug off unusual form input instead of erroring, finished the cleanup of network settings when you remove the plugin from a multisite network, and made activation safer around an old backup folder. No change to how your backups run day to day.
Bodholdt Backup for OneDrive
v5.28.2
- Security and cleanup hardening. Tightened the Slack/Discord webhook so notifications only ever reach real Slack and Discord addresses. Hardened the bundled one-click migration installer so its dormant copy can never run in place. Removing the plugin now fully cleans up after itself: settings, stats, gamification data, and scheduled tasks all clear. Also quieted a repeated staging-folder log line on some hosts, corrected a few translation labels so the whole interface localizes, and refreshed some onboarding wording. No change to how your backups run.
Bodholdt Backup for OneDrive
v5.28.1
- Arcade engine polish (shared). Protection XP now counts correctly when several events land at the same moment, the on-screen HUD labels are fully translatable, and celebration cards always stay within the screen. No change to how your backups run.
Bodholdt Backup for OneDrive
v5.28.0
- The Vault Watch. Your backups now earn their keep. A calm HUD shows your protection level and an Unbroken Watch streak that grows every night a scheduled backup runs clean, with a live Shield gauge for how protected you are right now. Trophies mark the milestones. It stays quiet by design: sound is off, the mood is steady rather than loud, and one switch turns it off. Nothing about how your backups run changes.
Bodholdt Backup for OneDrive
v5.27.0
- Connection card leads with status. Once connected, Settings shows your connection status first, with Test Connection and Disconnect beside it; the credentials tuck behind "Change credentials".
- Backup Size Estimate is now a table with a proportion bar per component and a totals row, instead of a plain text list.
- Your Backups rows now lead with the date and size, with the file name below plus a one-click Copy. Restore is styled distinctly from Download so the two are easy to tell apart.
- Activity log filters are one-click chips (All, Success, Errors) with live counts, and long paths get a Copy button.
- Reset to Defaults moved into a clearly marked danger zone. Accessibility and contrast improvements throughout, and emoji removed from admin messages.
Bodholdt Backup for OneDrive
v5.25.2
- Privacy & transparency. Added an "External services" section to this readme, and self-hosted the admin font so no request is sent to Google Fonts.
- Renewal UX. If a license lapses, the Plugins screen now shows a "renew to install this update" note instead of a failed update.
- Brand-string cleanup (author/URI, translation template). No functional or backup-behaviour change.
Bodholdt Backup for OneDrive
v5.25.1
- Corrected support and upgrade links. The catch-all backup-failure hint and the contextual-help "Email Support" link now point to [email protected], and the in-admin upgrade prompts link to the product page instead of the account portal.
- Accurate tier copy. Upgrade hints and the readme now match what each tier actually includes: retention is unlimited on every tier, including Free, and selective restore is a Solo feature (not Pro). Documentation and labelling only, with no functional or backup-behaviour change.
Bodholdt Backup for OneDrive
v5.25.0
- More cyan polish. "Start Backup Now" cloud icon is now pure white; the "Your Backups" table (column headers, file/Download/Restore icons, row hover) now uses the OneDrive blue instead of grey/purple; in-app "Upgrade to Pro" notices and the troubleshooting path now use the blue accent.
- Logs toolbar. The "Apply" filter button is now a gradient button (Clear History was already red).
Bodholdt Backup for OneDrive
v5.24.0
- Admin polish. Dashboard "Success" and "Connected" status pills now use the OneDrive blue (matching the theme); "Calculate Size", "Test Connection", "Send Test Email", and "Send Test Notification" are now gradient buttons; and "Reset to Defaults" is now clearly marked red as a destructive action.
Bodholdt Backup for OneDrive
v5.23.0
- Distinct cyan admin + consistent buttons. The OneDrive admin is now explicitly themed in its signature cyan (matching its product page, so it reads as distinct from the green Google Drive admin), and the "Start Backup Now" button uses the same gradient as "Save Settings."
Bodholdt Backup for OneDrive
v5.22.0
- Admin styling now sourced from the shared Bodholdt Labs design system. The admin UI consumes the canonical `bod-admin.css` (the same dark-admin stylesheet shipped across Bodholdt Labs plugins) instead of a plugin-local copy, so the look stays consistent and future polish lands everywhere at once. Visually unchanged save for one accessibility fix (purple text colour bumped to a WCAG-AA contrast). No functional or behavioural change.
Bodholdt Backup for OneDrive
v5.21.0
- Pro edition with licensed auto-updates. This is the paid, off-directory build of Bodholdt Backup for OneDrive, distributed by Bodholdt Labs. It enables in-dashboard automatic updates delivered from the Bodholdt Labs licensing server when a valid license key is active (license key + site URL + product identifier only; never site content or backup data).
- Selective restore available on every paid tier, including Solo. Pick exactly which components (database, system files, themes, plugins, uploads) to restore. Retention is uncapped on all tiers (bounded only by a per-install sanity limit).
- Slack/Discord webhook notifications for backup success/failure, restore-initiated, and stale-backup watchdog events (Pro and Bundle tiers).
- Hardening (parity with the directory edition): first-party download streaming now uses the WordPress HTTP API; admin-notice scripts moved to `wp_add_inline_script`; staging/uninstall paths resolved via `wp_get_upload_dir()`; installer CSRF/lockfiles relocated to the system temp directory with a table-prefix validation guard; all request inputs run through `wp_unslash()` before sanitization.
- Added an "External services" section to this readme documenting the Microsoft Graph / Microsoft OAuth endpoints, the Bodholdt Labs licensing/update server, and the WordPress.org secret-key (salt) request used during cross-server migration.
Bodholdt Backup for OneDrive
v5.20.1
- Fixed: footer line missing on installs that run third-party plugins which globally blank the WP admin footer. Some plugins (e.g. Taxonomy CSV Import/Export) register `__return_empty_string` against `admin_footer_text` at priority 11 across every admin page, which silently wiped our v5.20.0 footer line (Bodholdt Backup for OneDrive v5.X.X · Documentation · Support). Our filter now runs at priority 99, so it executes last and the footer renders as designed regardless of any other plugin's behavior.
Bodholdt Backup for OneDrive
v5.20.0
- UI: version moved out of the page title. The big "BODHOLDT BACKUP FOR ONEDRIVE V5.X.X" plugin-page heading is now just the product name + the tier badge ("FREE" / "Pro" / etc.). The version still appears, but now in the WordPress admin footer alongside Documentation and Support links, discreet and out of the way. Aligned with how WordPress core and most established plugins handle this.
Bodholdt Backup for OneDrive
v5.19.2
- Brand consistency follow-up. Two leftover short-form "Bodholdt OneDrive" labels weren't updated during the v5.19.0 rebrand: the WP admin sidebar menu entry, and the License sub-page heading. Both now read "Bodholdt Backup for OneDrive" to match the rest of the plugin. No behavior change.
Bodholdt Backup for OneDrive
v5.19.1
- Fixed: Setup Wizard never appeared on fresh installs. A function-scope bug in the dashboard renderer left the wizard's display gate (`$show_wizard`) undefined, which PHP 8+ surfaces as a Warning and silently coerces to null, so on a fresh install the wizard quietly didn't render, leaving new users with no guided onboarding (just an empty dashboard asking them to enter OAuth credentials with no setup hand-holding). The wizard now renders correctly as designed.
Bodholdt Backup for OneDrive
v5.19.0
- Renamed to "Bodholdt Backup for OneDrive." Adopts the trademark-safe "for [destination]" naming pattern across all customer-facing surfaces (plugin header, admin menus, dashboard, email subjects, logs). Functionally identical, with no settings or backups affected.
- Setup wizard: improved "Testing on a local site?" callout. The advisory now recommends Local's "Live Link" feature (HTTPS public URL) as a fallback if Microsoft still rejects a `.local` redirect URI after enabling HTTPS, so testers have a clear path forward.
- Tested up to: WordPress 7.0. Verified compatibility with the current stable release.
- Honest claims. Softened a few storefront descriptions to be evergreen rather than time-specific ("accessibility-minded" rather than a literal compliance grade; "security-audited each release" rather than a specific score) so they stay accurate without periodic updates.
- wp.org Contributors handle updated to `bodholdtlabs` in preparation for wp.org plugin directory submission.
Bodholdt Backup for OneDrive
v5.18.0
- Per-site backup folders. Each site now backs up to its own uniquely-named folder in your OneDrive (identified by a per-site ID), so multiple WordPress sites sharing one Microsoft account no longer write into the same folder. If a shared folder from an earlier version is detected, the plugin moves this site to its own folder and shows a one-time notice. Nothing is deleted and your existing backups stay untouched.
Bodholdt Backup for OneDrive
v5.17.2
- Licensing fix + brand consolidation. License activation, validation, and auto-updates now point at the correct server (bodholdtlabs.com), so license keys validate reliably (the previous host redirected and dropped the request). Author byline, support email, and account links updated to Bodholdt Labs / bodholdtlabs.com.
Bodholdt Backup for OneDrive
v5.17.1
- Retention tier fix. Solo and Agency licenses now get their correct backup-retention limits (Solo 50, Agency unlimited up to the system maximum), and Agency now includes selective restore and Slack/Discord notifications. Previously these tiers fell back to the Free 10-backup limit because the entry tier is issued as "default" and the top tier as "agency". Both are now recognized. Pro and Bundle are unchanged.
Bodholdt Backup for OneDrive
v5.17.0
- Fun + accessibility pass. Small delight and polish touches, matched to the Bodholdt Backup for Google Drive sibling.
- New: A running "backups protected" tally. The Backup Health card now shows how many backups you've made and the total size kept safe (e.g. "47 backups protected · 182 GB kept safe"). This counts off dedicated counters, so clearing your on-screen log history doesn't reset it.
- New: First-backup moment. Your very first successful backup now gets a bigger one-time celebration and a "Your first backup is done. Your site is officially protected!" message.
- New: Restore celebration. Finishing a restore now greets you with a gentle celebration and a "Site restored. Welcome back." message.
- Accessibility: Celebrations respect "reduced motion." All confetti animations now honor your operating system's "reduce motion" setting (the JS canvas confetti previously ignored it).
- Clearer destructive confirms. The "Disconnect OneDrive" and "Delete all backup log history" confirmations now spell out exactly what happens and what is NOT affected (your cloud backups are never touched).
- Warmer copy on the empty "Your Backups" state and the backup-complete message.
Bodholdt Backup for OneDrive
v5.16.1
- Cross-plugin parity follow-ups.
- "Reset to Defaults" now restores a sensible Daily 3:00 AM backup (was previously "Manual only"; both backup plugins now reset to the same default). And a scheduled backup on a site that hasn't connected OneDrive yet now skips quietly, instead of emailing a daily "backup failed" alert.
- Internal consistency: the default backup schedule is now Daily for fresh installs (matching Bodholdt Backup for Google Drive). The one-click backup flow is unchanged.
Bodholdt Backup for OneDrive
v5.16.0
- Steve Jobs / Grandma Test Pass, Rounds 2-5 (error states, settings parity, micro-interactions, visual polish). Brings the plugin to full feature/UX parity with Bodholdt Backup for Google Drive. Bundles three internal batches:
- *Error handling (R2):* clearer test-connection and restore-failure messages; the failed-backup notice now links straight to Settings and Logs; "Disconnect" now tells you how to fully revoke this site's access in your Microsoft account; a mistyped notification email is no longer saved silently; cancelling at Microsoft's consent screen is handled gracefully; backup-download errors are now friendly with a back link.
- *Settings (R3):* added an Hourly-schedule performance warning, hid the time picker when scheduling is set to Manual, added a server-side "Settings saved" confirmation, and clearer "Backups to Keep" / "Migration Tools" / file-exclusion copy.
- *Polish (R4/R5):* reliable copy-to-clipboard (with fallback), a proper "Refreshing…" working state on the size estimate, and all admin brand colors moved onto the shared design-token system (so the warning color is now consistent across both backup plugins). Build pipeline excludes editor/OS cruft from the distributed zip.
Bodholdt Backup for OneDrive
v5.15.0
- Fixed: Staging directory now has a graceful fallback when `/var/lib/bodholdt-staging/` isn't writable. Pre-v5.15.0 the plugin defaulted `BODHOLDT_OD_DIR` to `/var/lib/bodholdt-staging/onedrive/<random-suffix>/` with no fallback, a path that only exists on operator-prepared hosts. On any host without root access (most managed WordPress hosts, every local development environment, every WP.org reviewer install), the `mkdir()` call returned false, the next `fopen()` failed silently, and the backup or restore died mid-flight with the AJAX progress indicator simply disappearing at "Fetching Download link…", with no error to the user. v5.15.0 adds a three-tier fallback hierarchy resolved at plugin-load time: (1) `/var/lib/bodholdt-staging/onedrive/<suffix>/` if writable (preserves the post-2026-05-05 security model on operator-prepared hosts), (2) `sys_get_temp_dir() . '/bodholdt-staging-onedrive/<suffix>/'` if `/var/lib/` isn't writable (system temp, ephemeral but still isolated from the web document root), (3) `wp-content/uploads/.bodholdt-staging-onedrive/<suffix>/` as a last resort with three hardening layers (an `.htaccess` deny-all rule for Apache, an `index.php` returning HTTP 403 as defense-in-depth, and a docs-recommended nginx `location` deny rule in the FAQ). Each fallback transition is logged via `error_log()` so operators on hardened hosts can see why the plugin moved off the primary. Override via `define('BODHOLDT_OD_DIR', __DIR__ . '/your/custom/path/')` in wp-config.php to bypass the resolution entirely. Symmetric fix to the Bodholdt Backup for Google Drive plugin's v6.15.0 change (also shipped today). Plan §4.5.13.
Bodholdt Backup for OneDrive
v5.14.2
- Fixed: Restore engine was silently dropping `wp-content/mu-plugins/`, `wp-content/languages/`, and WordPress drop-ins (object-cache.php / advanced-cache.php / db.php / maintenance.php). OneDrive's backup engine already picked up mu-plugins via the wider `core` scope walk (no v5.14.1 backup-side hotfix needed), but the restore engine only copied `themes/`, `plugins/`, and `uploads/` from the extracted backup to the destination's `wp-content/`. Result: any disaster-recovery restore landed a site without its must-use plugins (custom auth handlers, debug-log filters, multisite-shared utilities, etc.) and without its drop-ins (Redis object cache, full-page cache, custom DB layer, maintenance-mode override). The restore engine now treats `mu-plugins/` and `languages/` like the database, always copied with no user-facing scope toggle, and copies the four standard wp-content drop-ins when they're present in the backup. Surfaced 2026-05-17 night during the §4.5.10 GDrive end-to-end retest, applied symmetrically to OneDrive. Plan §4.5.15. (v5.14.1 was never shipped. The version number was reserved as the GDrive companion to this fix's mirror; v5.14.2 is the first shipped restore-side fix on the OneDrive side.)
- Fixed: Restore engine no longer unconditionally drops your other Bodholdt backup plugin. Prior versions hard-skipped both `bodholdt-onedrive-backup` AND `bodholdt-google-drive-backup` directories during restore. The self-skip is necessary (a plugin can't safely overwrite itself mid-execution), but the sibling-skip meant customers running both plugins as belt-and-suspenders backup would lose one on every restore. The restore engine now skips the sibling only when it's currently network-active (i.e. running and could collide); installed-but-inactive siblings are restored normally. Plan §4.5.18.
Bodholdt Backup for OneDrive
v5.14.0
- New: Unified 4-step setup wizard. The setup wizard has been rebuilt to a 4-step shape that mirrors the Bodholdt Backup for Google Drive wizard exactly: Welcome → Connect OneDrive (credentials inline, with a collapsible "How do I get these?" guide) → Schedule → Run Your First Backup with size estimate. The previous 3-step wizard ended on a "go elsewhere" link to the Settings tab. New users routinely got lost there. The new wizard keeps everything in one flow, with the full 5-step OAuth setup guide reachable from the credentials step via a `<details>` panel. State persists across the OAuth round-trip (a new `bodholdt_od_wizard_step` option), so refreshing the page or returning from Microsoft mid-flow picks up where the user left off. Closes Steve Jobs pass Round 1. P1-C.
- New: Wizard returns to the dashboard after OAuth. Previously OneDrive's OAuth success redirected to the Settings tab, which meant the user had to find their way back to the dashboard before the wizard could continue. Now, when a user is mid-wizard, the OAuth callback redirects directly to the dashboard tab so the wizard resumes at the Schedule step automatically.
- New: New AJAX endpoint `bodholdt_od_wizard_save_creds`. Saves Client ID + Client Secret from the wizard's Step 2 and returns the Microsoft authorization URL with a CSRF state nonce. Byte-for-byte compatible with the existing "Authorize OneDrive Access" button on the Settings tab.
Bodholdt Backup for OneDrive
v5.13.0
- New: "Set up" link on the Plugins page. After activating, a "Set up" / "Backups" quick-link now appears next to Activate/Deactivate in the WordPress Plugins list, giving you one-click access to the dashboard. Standard WP pattern; we should have shipped this in v3. Steve Jobs pass Round 1, P1-A.
- New: Friendlier setup-guide language. Wizard welcome copy and the OAuth Setup Guide on Settings have been rewritten to drop "Microsoft Azure app" / "app registration" jargon in favor of consumer-friendly framing ("free Microsoft developer account", "Microsoft Developer Portal"). Technical terms ("Client ID", "Client Secret", "Redirect URI") stay where they're necessary, but the welcome copy no longer reads like enterprise IT. P1-D.
- New: OAuth Setup Guide Step 5 is split into Save + Authorize. The old single Step 5 packed three actions ("copy, paste+save, authorize") into one line, and new users routinely missed the second click. Now Step 5 saves the credentials and Step 6 authorizes the connection. P2-D.
- New: Backup destination renders as a breadcrumb. The Settings tab's "Backup Destination" line now shows `Your OneDrive → Apps → Bodholdt Backup → <site>` instead of the raw `/Apps/Bodholdt Backup/<site>/` path. Easier for non-developers to map to their OneDrive web UI. P2-F.
- New: Backup Size Estimate auto-loads on dashboard. Mirror of GDrive's behavior: the estimate card now populates on dashboard visit instead of waiting for a manual "Calculate Size" click. P2-E.
Bodholdt Backup for OneDrive
v5.12.0
- Fixed: Multisite retention manifest + retention setting were per-blog (architectural). The retention manifest (`bodholdt_od_backup_ids`) and the configured backup-retention count (`bodholdt_od_retention`) were stored as per-blog WordPress options, but the OneDrive folder they track is per-account, shared across every blog in the network. On multisite installs, a customer who activated the plugin from a non-main blog would hit a manifest scoped to that blog only; subsequent backup runs under a different blog context (e.g., from network admin, or scheduled cron under blog 1) saw an empty manifest, skipped the cap enforcement, and let the cloud grow silently past the configured retention. Both values are now stored as network-wide `site_option`s, mirroring the v5.8.0 license-storage migration. A one-time on-upgrade helper merges every existing blog's manifest into a single network manifest (de-duped by Graph item ID, so no data loss) and promotes the main blog's retention setting to network scope. Customer impact: multisite users will see retention enforce correctly on the next scheduled backup; single-site users are unaffected (`site_option` transparently falls back to `option` there). Plan §4.2 v5.12.
- Fixed: Manifest seed could only run once per install (Bug C). The function that reconciles the manifest against the actual cloud folder was gated by `if ( ! empty( manifest_get() ) ) return;`, which meant seed only ran ONCE in the install's lifetime, the first time the manifest was empty. After that, no source of cloud↔manifest desync (lookup_item_id silent skip after upload, manual operator file ops, pre-v5.1.1 backups inherited at upgrade time, etc.) could ever self-heal. The function is now a reconciliation pass that runs every enforcer call: it lists the folder once, diffs against the known manifest, and appends only previously-unknown canonical-named cloud files. Healthy installs pay zero option writes per pass; leaky installs self-recover on the next backup. Plan §0a 2026-05-16 evening.
- Improved: Uninstall now cleans up the network-scoped options + transients introduced in v5.8 (license keys) and v5.12 (manifest + retention). Previously these were left behind on plugin uninstall on multisite, harmless but untidy.
Bodholdt Backup for OneDrive
v5.11.1
- Fixed: Retention seed-migration silently broken since v5.1.1. The `bodholdt_od_manifest_seed_from_folder()` function used `$orderby=createdDateTime` in its Microsoft Graph query, which Graph rejects on the `:/children` endpoint with HTTP 400 "Operation not supported." The function silently fell through and returned with an empty manifest, so installs with desynced manifests (caused by occasional `lookup_item_id` failures after upload) never self-recovered, and cloud backup counts could grow unbounded past the user-configured retention. Removed the unsupported `$orderby` parameter; the enforcer already sorts the manifest in PHP. Customer impact: customers whose backup count had drifted above their configured retention will see the cap re-enforce on the next scheduled backup run.
- New: HTTP-status logging in the manifest seed. Non-2xx Graph responses (token expired, throttled, unsupported parameter, etc.) are now logged to `error_log()` so future Graph-side regressions surface in WP_DEBUG instead of vanishing silently.
Bodholdt Backup for OneDrive
v5.11.0
- New: Cross-engine collation portability. Backups taken on MariaDB 10.10+ (which defaults to the `utf8mb4_uca1400_*` collation family) now restore cleanly on MySQL 5.7 / 8.x and older MariaDB. The dump rewrites every `*_uca1400_*` collation to the closest portable equivalent (`utf8mb4_unicode_520_ci`, `utf8mb3_unicode_ci`, etc.) at emit time across CREATE TABLE / VIEW / TRIGGER / PROCEDURE / FUNCTION / EVENT statements. Set option `bodholdt_od_translate_collations` to 0 if you need byte-for-byte fidelity (e.g., restoring back to the same MariaDB version).
- New: Progress bar resumes on page reload. Refresh the WP admin tab while a backup is mid-run and the progress UI now picks up where it was. Bar, status text, and poll loop all re-attach automatically from the server-side job-status transient. No more "did my backup die?" anxiety.
- New: Default-exclusion patterns for dev artifacts. `apply-bodholdt-*-v*.py`, `__pycache__/`, `*.pyc`, and `*.source.php` are now excluded by default. Pairs with the v5.10.0 readability probe. The probe defends against batch-poisoning regardless, but pre-excluding keeps the manifest tidy and the zip leaner.
Bodholdt Backup for OneDrive
v5.10.0
- Fixed: Backup-engine drops Bodholdt-prefixed plugins/theme on symlinked-deploy patterns. Common deploy pattern (a separate clone of in-house plugins symlinked into `wp-content/plugins/`) used to silently drop those plugins from backup zips. Three independent root causes contributed; all three close in this release. Plan §4.5.6.
- 1. The relpath calc used `getRealPath()` + `substr($path, strlen(ABSPATH))`, which on symlinked subtrees returned paths outside ABSPATH and produced corrupted relpath entries (e.g., `oldt/bodholdt-wordpress/plugins/...`). Replaced with `RecursiveIteratorIterator::getSubPathname()` (iteration-depth-tracked, symlink-safe) plus a per-scope `relpath_prefix` (`wp-content/plugins/` etc.).
- 2. PHP's `RecursiveDirectoryIterator::hasChildren()` defaults to `$allowLinks = false`, so the iterator emits symlinked DIR entries but never descends into them, so the entire symlinked subtree gets skipped silently. Fixed via a small RDI subclass (`Bodholdt_OD_FollowSymlink_RDI`) that overrides `hasChildren()` to pass `$allowLinks=true`. File-level symlinks (e.g. mu-plugins) were always picked up correctly because `isDir()` returns false for them.
- 3. `ZipArchive::close()` silently drops the entire ~500-file staged batch when even one staged file is unreadable (e.g., owner-only 0600 perms; `close()` returns false with a `Permission denied` warning, but PHP discards every legitimate sibling file in the batch alongside the bad one). Pre-validate readability with `@fopen($path, 'rb')` + `fclose()` before `addFile()`; unreadable files are skipped cleanly with optional `WP_DEBUG` logging. `addFile()` and `close()` return values are also checked + logged.
- Fixed: File-collector path corruption for files reached through symlinks. Same root cause as the symlink-relpath bug above. Files reached via a symlinked subtree (e.g., `wp-content/mu-plugins/bodholdt-*.php` on the same deploy pattern) landed in the zip at `oldt/bodholdt-wordpress/mu-plugins/` instead of the canonical `wp-content/mu-plugins/`. The `getSubPathname()` approach produces correct canonical paths regardless of symlink chains. Plan §4.5.7.
- Fixed: VIEW emission order regression in multisite-network mode. v5.9.0 emitted each blog's views at the end of that blog's iteration, BEFORE the network-shared group ran. Views that JOIN `wp_users` (network-shared) failed at CREATE time on restore because wp_users hadn't been created yet. All non-table schema objects (views, triggers) are now deferred to the absolute tail of the dump, after every CREATE TABLE across every blog + the network-shared group. Plan §4.5.8.
- New: Proper self-exclusion. The backup zip no longer includes the Bodholdt Backup for OneDrive plugin's own directory (Russian-doll prevention). Sibling Bodholdt plugins and the bodholdt-labs theme are deliberately INCLUDED so customers with multiple Bodholdt plugins get a complete backup. Self-exclusion uses canonical-relpath equality, not name-prefix substring matching.
- New: mu-plugins and other non-scoped wp-content children are now backed up. Previously the "core" scan-and-skip rule excluded everything under wp-content. Relaxed so only the three scope-mapped subtrees (`wp-content/plugins/`, `wp-content/themes/`, `wp-content/uploads/`) are skipped during the core scan; `wp-content/mu-plugins/`, `wp-content/languages/`, etc. now land in the backup at their canonical paths and restore to where they belong.
- New: Unreadable files are skipped cleanly instead of poisoning a 500-file batch. Previously, ZipArchive's deferred-read behavior meant a single 0600/0700 file (e.g., a forgotten dev artifact) could silently drop dozens of unrelated legitimate backups. The pre-`addFile` readability probe defends against this regardless of what's on disk.
Bodholdt Backup for OneDrive
v5.9.0
- New: Multisite-network backup mode (Free-tier-included). The backup engine now auto-detects single-site vs multisite and defaults to a complete-network backup on multisite installs. Network mode walks every blog via `switch_to_blog()`, dumps each blog's content tables, then dumps the network-shared tables (`wp_users`, `wp_usermeta`, `wp_blogs`, `wp_blogmeta`, `wp_site`, `wp_sitemeta`, `wp_registration_log`, `wp_signups`) exactly once. Restoring such a backup recreates the full multisite layout.
- New: Per-blog mode (opt-in). Multisite admins who want per-customer subsite isolation can switch to per-blog mode in the network admin's Settings tab. Per-blog backups contain only that blog's content tables, with no shared tables and no other blogs.
- New: Backup manifest (`bodholdt-manifest.json`). Every zip now includes a manifest at the zip root describing mode, plugin version, WP version, blog topology, tables dumped, and shared-table inclusion. The restore engine reads it first to verify compatibility.
- New: Restore-side mode compatibility check. The engine refuses to restore a multisite backup onto a single-site install (the wp_N_* tables don't belong) and warns when a single-site backup is being restored onto a multisite (data lands on current blog only).
- Single-site installs continue to behave exactly as before, with no UI changes, no feature flag, and no migration required.
- Database export entry function now accepts an optional `$mode` parameter for callers that want to force a specific mode regardless of saved settings.
Bodholdt Backup for OneDrive
v5.8.0
- New: Multisite-network compatible. License state (key, tier, status, last-seen-valid timestamp) is now stored as a network-wide site option. A customer who activates a Solo license on blog 1 of a multisite network has the license recognized automatically on every other blog. One-time migration runs on upgrade. Existing per-blog license data is copied to network scope.
- Single-site installs are unaffected (site_option falls back to option there).
Bodholdt Backup for OneDrive
v5.7.0
- New: Slack and Discord webhook notifications (Pro+). One URL field, auto-detected provider. Per-event toggles for backup success, backup failure, restore initiated, and watchdog stale-alert. Send-Test-Notification button in Settings.
- New: Helper `bodholdt_od_notifications_allowed()` returns true only for Pro/Bundle. Filterable via `apply_filters( 'bodholdt_od_notifications_allowed', $allowed, $tier )` for one-off overrides.
- Failure notifications include the same auto-diagnosis hint as the email notification (token / quota / disk / network).
Bodholdt Backup for OneDrive
v5.6.0
- New: Free tier is now the default experience. No license required for full backup + restore at the Free cap (10 retained).
- New: Tier badge inline in the plugin header (Free / Solo / Pro / Bundle).
- New: Lapse banner. When a previously-active license becomes invalid, a dismissible banner reminds you to renew while backups continue at Free-tier limits.
- New: Soft-degrade on lapse. Backups keep running even with an invalid license. Retention auto-clamps to 10; selective restore disables. Manual + scheduled backups continue.
- Removed: Three hard-locks that previously blocked the admin UI, manual backups, and scheduled backups on non-valid licenses.
Bodholdt Backup for OneDrive
v5.4.0
- New: Tier-gated selective restore. Pro and Bundle customers can choose what to restore (database, plugins, themes, uploads). Free + Solo restore everything.
- New: Inline "Upgrade to Pro" hint shown next to disabled scope chooser on Free + Solo.
- Server-side defense: restore handler coerces submitted scope to full on tiers without selective access.
Bodholdt Backup for OneDrive
v5.3.0
- New: Tier-aware retention cap helper (`bodholdt_od_retention_cap`). Free=10 / Solo=50 / Pro=100 / Bundle=100. Save handler clamps; settings input cap is dynamic.
- New: Over-cap inline notice when a previously-saved retention value exceeds the current tier cap (e.g., after a downgrade).
- New: Pre-flight `force_refresh()` before retention enforcement so tier downgrades take effect within one backup, not 12 hours later.
- Licensing client now captures `tier_key` from server responses.
Bodholdt Backup for OneDrive
v5.1.1
- Fixed: Rename-bypass in the retention enforcer. Previous folder-listing + regex enforcer let a renamed backup file slip past the cap entirely. Replaced with an ID-manifest written at upload time, so renames can no longer bypass retention.
- New: One-time seed migration on upgrade.
Bodholdt Backup for OneDrive
v5.1.0
- Last-success-timestamp watchdog with stale-alert.
- Out-of-web-root staging directory (fixes a 2026-05 SQL-dump exposure risk).
Bodholdt Backup for OneDrive
v5.0.0
- Retention pagination + ordering fix. Folders with more than 200 backups now prune correctly.
Bodholdt Backup for OneDrive
v4.14.1
- Settings save reliability fix.
Bodholdt Backup for OneDrive
v4.14.0
- Email-delivery failure detection. Plain-text email fallback. Migration key now included in success emails.
Bodholdt Backup for OneDrive
v4.0.0
- Setup wizard, selective restore, pre-restore snapshot, ZIP integrity verification, atomic locking, contextual help tabs.
Bodholdt Backup for OneDrive
v3.0.0
- Initial Bodholdt-Engine rewrite. OAuth 2.0. Resumable Graph API uploads. AES-256-CBC + Sodium encryption. Migration installer.
Bodholdt Backup for Google Drive
v6.35.1
- Scheduled database backups no longer fail when a security plugin rebuilds its temporary table mid backup. Some security tools create and then drop a temporary scratch table while your site is running. If that happened partway through the database export, the backup stopped with a "table definition has changed" message and only finished on the next scheduled run, so you saw a failure followed by a success. That scratch table holds nothing worth restoring, so it is now left out of the backup entirely, and any brief database hiccup during a backup now retries on its own up to three times instead of ending the run. Nothing for you to change.
Bodholdt Backup for Google Drive
v6.35.0
- Clearer restore confirmation before anything is overwritten. The restore panel now says plainly that restoring replaces your current files and database, that the automatic safety copy covers your database only and there is no one-click undo, and that your site briefly shows a maintenance page while a restore runs. If a restore is interrupted, the panel reminds you the site reopens on its own within about ten minutes, so you are not left wondering. Starting a restore now asks you to tick "I understand this will overwrite my current site" before the final button turns on, matching the OneDrive backup plugin. No change to how restore itself works.
Bodholdt Backup for Google Drive
v6.34.0
- Backups now restore on sites running both Bodholdt backup plugins. If you have both the Google Drive and OneDrive backup plugins installed, every archive included the other plugin's files, and restore refused those archives outright because it is designed never to overwrite a backup plugin mid restore. The result was backups that always reported success and could never be restored. Archives taken from this version on restore normally. If you run both plugins, please take a fresh backup after updating so you have an archive that restores.
- Please take a fresh backup after updating if your site runs MySQL 8. Columns whose default is the current timestamp were being left out of the database export. Many plugin tables use these for dates like "created" and "last updated", including WooCommerce order analytics. Backups still reported success, and on restore those dates were refilled with the time of the restore rather than the original values, so the data looked plausible but was wrong. Archives created before this update are affected on MySQL 8. Sites on MariaDB were never affected. One new backup after updating replaces the gap.
- Backups no longer stop when your site contains a symbolic link. One linked theme, plugin folder, or single linked file inside uploads used to end the entire run, and the failure email suggested checking your server logs or internet connection, which had nothing to do with the real cause. Links are now skipped, the rest of your site is backed up normally, and the run tells you exactly which links were left out. This is common on managed hosting, on container based setups, and on any site using a linked child theme or a shared media mount.
- An interrupted restore can no longer leave your site stuck offline. If a restore was killed partway through, by a memory limit, a timeout, or a server restart, WordPress was left in maintenance mode permanently. Both the site and the WordPress admin returned "Briefly unavailable for scheduled maintenance" forever, and the only way out was deleting a file over SSH or FTP. A running restore still closes the site as it should, but an abandoned one now reopens on its own after ten minutes so you can get back into your admin and try again.
- A stalled restore no longer blocks every future backup with no way to clear it. The Force Unlock button only ever appeared for stalled backups, never for stalled restores, so a restore that stopped unexpectedly left backups permanently blocked with the fix hidden from view.
- Clearer, more honest failure messages. Running out of local disk space is no longer reported as your Google Drive being full, and no longer suggests deleting your backups, which would not have helped. The size estimate on the dashboard now tells you what actually went wrong instead of only "Could not calculate estimate." Internal log tags no longer appear in messages meant for you.
- File exclusions now support wildcards. Patterns like `*.log` and `wp-content/cache/*` previously matched nothing at all and gave no warning, so files you thought you had excluded were still being uploaded.
- Backup notification emails are now translatable and no longer arrive in English on a translated site. They also fall back to plain text if the HTML message cannot be delivered, and a delivery failure is recorded instead of passing silently.
- Retention problems are now visible. If old backups could not be removed from your Drive, the run said nothing and storage kept growing. It now tells you.
- Also in this release. A warning when the ZIP extension your host needs is missing, rather than a silent failure. A working admin menu when the plugin is activated on a single site of a multisite network. Large downloads no longer time out on a blank page, and a download that was merely interrupted is no longer reported as a corrupt archive. The setup wizard no longer says setup is complete when the server rejected the save.
Bodholdt Backup for Google Drive
v6.33.11
- Sharper error text in the activity log. Error status labels and their suggested fixes now meet WCAG 2.1 AA contrast against the dark log rows, so they are easy to read at a glance. No change to how backups or restores work.
Bodholdt Backup for Google Drive
v6.33.10
- More accessible admin. The dashboard now meets WCAG 2.1 AA: error text and the button focus outline have stronger contrast, and the optional celebration pop-ups are announced to screen readers, can be dismissed, and pause when you hover or focus them. No change to how backups or restores work.
Bodholdt Backup for Google Drive
v6.33.9
- Your cloud backups no longer contain your credentials on some sites. If your database table prefix has no trailing underscore, such as `wp` instead of `wp_`, the filter that keeps live credentials out of uploaded archives did not match your options table. Your Google client secret, refresh token, license key, and WordPress security salts were written into the backup. Redaction now works with any valid prefix. If your site uses a prefix like this, please delete your existing cloud backups and create a fresh one.
- Binary and case-sensitive collations survive a restore exactly. Backups previously rewrote collations such as `utf8mb4_0900_bin` and `utf8mb4_ja_0900_as_cs` to a case-insensitive one, which silently changed sorting, uniqueness, and case-sensitive lookups on the restored site. They are now preserved exactly, in every place the plugin reads or writes a collation.
- Backups record your real database schema. Collation rewriting at backup time is now off by default, so an archive is a faithful copy of your source schema. If a restore lands on a server that cannot support one of your collations, the plugin adapts at restore time instead, where it can see what the destination actually supports. If you restore a dump by hand with the `mysql` command onto a different database engine, switch the setting back on before taking that backup.
- Backups no longer fail on valid database schemas. A site with a view or table that uses `REPLACE()`, `TRUNCATE()`, or `INSERT()` as a function was blocked from backing up at all. Those are now read as functions rather than as dangerous statements, and genuinely unsafe statements are still rejected.
- Restore no longer writes credentials to your error log. If a statement failed while a restore was rolling back, WordPress logged the whole statement, including options rows holding your live credentials. Failures are now recorded without the statement text, and errors are still detected and reported to you.
- Your license is no longer removed when you upgrade. On single-site installs a one-time migration deleted the stored license key, status, and tier, quietly dropping paid installs to the free feature set. It now does nothing outside multisite, and it can be run repeatedly without harm.
- A stuck backup can no longer leave the plugin unusable. If a backup process was killed, the operation lease stayed held, listing and restore stopped working, and after an hour the Force Unlock control disappeared, leaving no way to recover without server access. The stale-lock warning and its Force Unlock button now follow the real lock state, and the message explains what actually happened.
- The settings screen always opens. A corrupted saved option could stop the page mid-render, so the form and its save button never appeared and there was no way to repair it from the admin.
- A site with no schedule stays unscheduled. Google Drive treated a missing schedule as daily and armed an automatic backup even when the saved setting was "none".
Bodholdt Backup for Google Drive
v6.33.8
- Exact OAuth continuity after restore. Access-token refresh now preserves an existing option row's raw autoload metadata while changing only its encrypted value, avoiding a false restore failure on legacy WordPress rows.
- Self-contained Fast Backup restore. Removed an obsolete post-restore base marker. Fast Backup restore already downloads, authenticates, hash-links, and privately composes its exact Full base before maintenance mode or customer-data mutation.
Bodholdt Backup for Google Drive
v6.33.7
- Mobile and keyboard-safe admin. The Sentinel HUD no longer overflows narrow screens; wizard step focus stays inside the visible modal, and Escape persists dismissal while restoring scrolling and focus.
- Correct page behavior. Visiting License no longer runs the Dashboard size estimate or locks page scrolling, and inline restore controls no longer trap keyboard focus.
- Honest copy and setup actions. Clipboard success appears only after a confirmed copy, failures are reported, setup and schedule controls have explicit labels, and OAuth/connection-expiry guidance matches the real same-tab and visible-error behavior.
- No partial SQL after a failed export. Snapshot, storage, truncation, empty-export, and rejected nontransactional-table failures now remove the incomplete local database file before returning an error.
- Safe Dashboard metadata. Legacy object- or array-valued log fields are ignored before the Dashboard renders them, matching the hardened Logs table.
- Signed file permissions and exact rollback. On POSIX backup hosts, new backups authenticate every managed regular-file mode alongside its bytes, including mode-only Fast Backup changes and deletions. Other hosts authenticate that exact mode authority is unavailable and cannot provide an exact-mode Fast Backup base. Restore and automatic rollback re-prove the exact regular-file inode and bytes around permission application, then finalize directory modes.
- Safe compatibility behavior. On a POSIX restore host, older authenticated backups use a clearly labeled, non-deleting overlay that preserves existing modes and gives new files owner-only permissions. On a non-POSIX host, filesystem restore stops before mutation because exact permission rollback cannot be guaranteed; database-only restore remains available. Fast Backup switches to Full when its verified cloud base lacks exact permission authority and records the reason in Logs.
- Unambiguous recovery records. Recovery, rollback, operation-lease, and cloud-folder JSON rejects duplicate decoded object keys, including escaped aliases, before PHP can collapse them into a different authority.
- Action after upgrading: Create a new Full backup before relying on Fast Backup or exact file-permission recovery. Older recovery points remain available through the degraded compatibility path.
Bodholdt Backup for Google Drive
v6.33.6
- Safe partial legacy log rows. Older metadata that contains only a backup size or file count now renders with a harmless placeholder instead of a PHP warning; nonscalar display fields are ignored safely.
Bodholdt Backup for Google Drive
v6.33.5
- Clean legacy Logs screens on modern PHP. Older log rows with empty or malformed metadata are displayed safely without PHP 8.5 deprecation notices on the Dashboard or Logs tab.
Bodholdt Backup for Google Drive
v6.33.4
- Database consistency cannot be weakened by another plugin. Only InnoDB/XtraDB tables and the exact rebuildable Wordfence role-count cache are accepted. Other MEMORY/MyISAM material tables stop safely, and every customer-facing suggestion correctly names the InnoDB remedy even when the table name contains words such as token, quota, zip, or disk.
Bodholdt Backup for Google Drive
v6.33.3
- Settings save before connection. A fresh site can save its schedule, retention, scope, and exclusions with blank Google OAuth fields. Credentials are validated only when you actually enter or change them, and failed credential changes still roll back safely.
- Stricter restore connection verification. A legitimate Google access-token refresh can update only the encrypted token value and clear a stale auth warning; unexpected autoload or unrelated provider, licensing, destination, schedule, or multisite changes still stop the restore safely.
Bodholdt Backup for Google Drive
v6.33.2
- Wordfence no longer blocks safe backups. The rebuildable `wp_wfls_role_counts` MEMORY cache is preserved as an empty InnoDB table for Wordfence to repopulate; any other non-transactional material table still stops the backup clearly.
- Multisite recovery boundaries are explicit. Every primary-site table must have one unambiguous owner, and a Network backup records the one network and all of its sites. Ambiguous tables, multi-network databases, and older archives without the new signed recovery authority are refused before anything is changed.
- Action after upgrading: Create a new Full backup in Network mode before relying on multisite restore; older network recovery points do not contain the authority required by this release.
- Full/core restore safety snapshot fixed. Canonical WordPress core directories are now captured and verified correctly before restoration, so a valid full restore no longer stops at the rollback-snapshot gate.
- Safer setup and connections. Settings and setup-wizard changes now commit and verify as one transaction or roll back exactly. Concurrent administrators can connect safely, stale OAuth callbacks are bounded and invalidated, and legacy credentials, tokens, and licenses cannot overwrite a newer valid change during upgrade.
- Restore rollback and storage protection. Pre-restore snapshots bind exact no-follow file copies to content digests, reject filesystem drift and link/type swaps, verify the complete private rollback image before mutation, and preserve a 64 MiB emergency disk reserve.
- Exact rollback and Google connection continuity. If restore health checks fail, rollback now reinstates root-level, empty, and Unicode-named files exactly and removes restore-only files. A verified Google token refresh no longer makes an otherwise healthy restore look failed, while every unrelated continuity check stays fail-closed.
- Restore progress reconnects safely. A temporary maintenance-mode response no longer turns the progress screen red or stops polling. The page reconnects automatically, and final health failures expose only safe diagnostic codes rather than site or provider details.
- Recoverable database exports on MySQL and MariaDB. Dumps preserve the disk reserve, create dependent views in a safe global order, reject incomplete or ambiguous view graphs, and stop clearly when triggers, routines, or events cannot be represented instead of silently omitting them.
- Hardened packages, cleanup, and privacy. Release builds reject unsafe source/ZIP content before atomic publication. Uninstall removes only Google-owned state, operator notices require the backup capability, and diagnostics no longer expose cloud-account identifiers, response bodies, provider URLs, or customer filesystem paths.
Bodholdt Backup for Google Drive
v6.33.1
- Database recovery points are trustworthy again. Literal percent signs, percent-encoded URLs, CSS, SQL patterns, and serialized data now round-trip byte-for-byte. Every export uses one isolated InnoDB consistent snapshot; non-transactional tables and metadata omissions stop the backup with an actionable error instead of producing a mixed or incomplete recovery point.
- Migrations fail safely and finish accurately. Empty or failed imports cannot show green success, same-host multisite moves preserve every blog's domain and path, serialized objects stay opaque, and the generated `wp-config.php` must pass exact semantic verification. SQL and manifest files live in a protected, key-bound hidden directory from extraction onward.
- Archives and operations are integrity checked. Owner-token leases survive an options-table restore, large ZIP members extract in heartbeat-sized chunks with size/CRC checks, unsafe paths and special entries are rejected, and missing requested files or mandatory recovery members fail before upload.
- Settings and cleanup match the UI. All webhook triggers can be disabled, weekly schedules keep their weekday through DST, multisite defaults reset fully, deliberately blank webhook tests are rejected, and uninstall removes plugin-specific transients plus Google Drive rows from every legacy subsite log table without removing OneDrive rows. Missing subsite arcade tables are skipped without database errors.
Bodholdt Backup for Google Drive
v6.33.0
- Restores you can trust, right on the screen. A restore that could not write your core WordPress files now says so instead of showing "Restore complete", and restoring an incremental backup over your existing site no longer reports a false "nothing was restored". Any compatibility caution now appears on the restore screen itself, not only in the log.
- Migrations that finish the job. Moving a multisite network keeps every subsite on its correct address, saved nested settings survive a domain change, and backups taken on newer MySQL versions restore cleanly onto older database servers.
- Protected recovery evidence. A successful migration removes its database file and manifest. A failed migration retains them for retry and diagnosis; 6.33.1 moves them into a protected random directory from extraction onward. Removing the plugin from a large multisite network now cleans every site, not just the first hundred.
- Notifications and scheduling polish. The "Send Test" button now tests the webhook address you just typed, "Reset to Defaults" truly resets everything, a weekly schedule no longer triggers a daily false "backups are stale" alert, and your backup keeps its chosen time through daylight saving changes. Plus a long list of smaller reliability, safety, and translation fixes. Nothing about how your everyday backups run changes.
Bodholdt Backup for Google Drive
v6.32.0
- Migrations you can trust on any host. Moving a site to a new server now keeps every table even when your host uses a custom database prefix (common on managed hosting), so a migration no longer lands on a blank WordPress setup screen. Multisite network settings carry across too, and the one click site mover deletes its database file the moment it finishes instead of leaving it in your web root.
- Backups and restores that tell the truth. A backup now stops and warns you if the database export was cut short, instead of quietly saving an incomplete copy. A restore that had nothing to put back tells you which parts were empty rather than showing a cheerful "all done". And an incremental backup is clearly labeled, so restoring one on its own can never rebuild a broken site by surprise.
- Notifications and licensing polish. Saving your settings before you enter a license no longer clears your Slack or Discord alert choices. Activating a valid key while our server is briefly unreachable now says exactly that, rather than claiming your key is wrong, and a slow licensing server no longer makes your Plugins screen hang.
- Calmer by default, and much more. The Sentinel arcade now has its own settings and confetti is off unless you turn it on, the nightly watchdog reliably warns you if backups go stale, and there is a long list of smaller fixes and tidy ups. Nothing about how your everyday backups run changes.
Bodholdt Backup for Google Drive
v6.31.0
- Reliability and safety hardening (QA round). Saving Settings now reliably persists every change, restores report their status honestly, the database export stops rather than truncating on an error, and automatic backups re arm correctly after the plugin is switched off and on. Plus a range of smaller migration, retention, and cleanup fixes. No change to how your everyday backups run.
Bodholdt Backup for Google Drive
v6.30.0
- Restore you can trust. Restores now tell you the truth: if any part of the database or files could not be applied, you get a clear "finished with problems" message that points you to the pre-restore snapshot, instead of a false "Restore complete!". Cross-version moves are smoother too, so a backup taken on a newer MySQL restores cleanly onto an older MySQL or MariaDB.
- More reliable migrations. The standalone migration installer now works correctly on modern PHP (8.1 and newer), keeps your real site configuration and table prefix (custom prefixes and multisite restore properly now), and imports stored procedures and triggers without dropping them.
- Backups that hold up on big sites. Long backups on large sites no longer risk colliding with another run, generated columns and special column types (BIT, spatial) back up and restore correctly, and every row is captured even in unusual tables.
- Clearer and safer everywhere else. Honest schedule status on a fresh install, an accurate description of per-site multisite mode, important warnings now visible to multisite network admins, saved credentials no longer loaded on every page, a cleaner reconnect prompt when Google access expires, tidier file-exclusion matching, and a range of smaller polish and cleanup fixes.
Bodholdt Backup for Google Drive
v6.29.3
- Backup safety and robustness hardening. Backups are now guarded against overlapping runs, so a scheduled backup and a manual backup or restore can never run at the same moment and leave you with an inconsistent archive. We also tightened how backup file names are shown in your Backups list, made the Settings save shrug off unusual form input instead of erroring, finished the cleanup of network settings when you remove the plugin from a multisite network, and made activation safer around an old backup folder. No change to how your backups run day to day.
Bodholdt Backup for Google Drive
v6.29.2
- Security and cleanup hardening. Tightened the Slack/Discord webhook so notifications only ever reach real Slack and Discord addresses. Hardened the bundled one-click migration installer so its dormant copy can never run in place. Removing the plugin now fully cleans up after itself: settings, stats, gamification data, and scheduled tasks all clear. Also quieted a repeated staging-folder log line on some hosts, corrected a few translation labels so the whole interface localizes, and refreshed some onboarding wording. No change to how your backups run.
Bodholdt Backup for Google Drive
v6.29.1
- Arcade engine polish (shared). Protection XP now counts correctly when several events land at the same moment, the on-screen HUD labels are fully translatable, and celebration cards always stay within the screen. No change to how your backups run.
Bodholdt Backup for Google Drive
v6.29.0
- Sentinel: The Night Watch. Your backups now earn their keep. A calm HUD shows your protection level and an Unbroken Watch streak that grows every night a scheduled backup runs clean, with a live Shield gauge for how protected you are right now. Trophies mark the milestones. It stays quiet by design: sound is off, the mood is steady rather than loud, and one switch turns it off. Nothing about how your backups run changes.
Bodholdt Backup for Google Drive
v6.28.0
- Connection card leads with status. Once connected, Settings shows your connection status first, with Test Connection and Disconnect beside it; the credentials tuck behind "Change credentials".
- Backup Size Estimate is now a table with a proportion bar per component and a totals row, instead of a plain text list.
- Your Backups rows now lead with the date and size, with the file name below plus a one-click Copy. Restore is styled distinctly from Download so the two are easy to tell apart.
- Activity log filters are one-click chips (All, Success, Errors) with live counts, and long paths get a Copy button.
- Reset to Defaults moved into a clearly marked danger zone. Accessibility and contrast improvements throughout, and emoji removed from admin messages.
Bodholdt Backup for Google Drive
v6.26.2
- Privacy & transparency. Added an "External services" section to this readme, and self-hosted the admin font so no request is sent to Google Fonts.
- Renewal UX. If a license lapses, the Plugins screen now shows a "renew to install this update" note instead of a failed update.
- Brand-string cleanup (author/URI, translation template). No functional or backup-behaviour change.
Bodholdt Backup for Google Drive
v6.26.1
- Corrected support and upgrade links. The contextual-help "Email Support" link now points to [email protected], and the in-admin upgrade prompts link to the product page instead of the account portal.
- Accurate tier copy. Upgrade hints and the readme now match what each tier actually includes: retention is unlimited on every tier, including Free, and selective restore is a Solo feature (not Pro). Documentation and labelling only. No functional or backup-behaviour change.
Bodholdt Backup for Google Drive
v6.26.0
- More emerald polish. "Start Backup Now" cloud icon is now pure white; the "Your Backups" table (column headers, file/Download/Restore icons, row hover) is now emerald instead of cyan/purple; in-app "Upgrade to Pro" notices and the troubleshooting path now use the emerald accent.
- Logs toolbar. The "Apply" filter button is now a gradient button and "Clear History" is clearly marked red as a destructive action.
Bodholdt Backup for Google Drive
v6.25.0
- Admin polish. Dashboard "Success" and "Connected" status pills now use the emerald theme accent; "Refresh Estimate", "Test Connection", "Send Test Email", and "Send Test Notification" are now gradient buttons; and "Reset to Defaults" is now clearly marked red as a destructive action.
- Fixed "Your Backups" showing empty. The plugin could read a stray duplicate "Bodholdt Backups" folder in Google Drive and report no backups even when backups existed. It now reliably resolves the original folder (oldest match) and will no longer create a duplicate folder if a Drive lookup briefly fails.
Bodholdt Backup for Google Drive
v6.24.0
- Consistent buttons. The "Start Backup Now" button now uses the same green gradient as the "Save Settings" button, so the primary actions match across the admin.
Bodholdt Backup for Google Drive
v6.23.0
- Green admin theme. The Google Drive admin now uses an emerald-green accent that matches its product page, so it reads as distinct from the cyan Bodholdt Backup for OneDrive admin at a glance. Same layout and dark canvas; accent colour only.
Bodholdt Backup for Google Drive
v6.22.0
- Admin styling now sourced from the shared Bodholdt Labs design system. The admin UI consumes the canonical `bod-admin.css` (the same dark-admin stylesheet shipped across Bodholdt Labs plugins) instead of a plugin-local copy, so the look stays consistent and future polish lands everywhere at once. This release brings the Google Drive admin up to full parity with the OneDrive edition: entrance animations on cards/modals/toasts, standardized title/progress gradients, a tooltip layering fix, the upsell/locked-feature polish, and an accessible purple text colour. No functional or behavioural change.
Bodholdt Backup for Google Drive
v6.21.0
- Pro edition with licensed auto-updates. This is the paid, off-directory build of Bodholdt Backup for Google Drive, distributed by Bodholdt Labs. It enables in-dashboard automatic updates delivered from the Bodholdt Labs licensing server when a valid license key is active (license key + site URL + product identifier only; never site content or backup data).
- Selective restore available on every paid tier, including Solo. Pick exactly which components (database, system files, themes, plugins, uploads) to restore. Retention is uncapped on all tiers (bounded only by a per-install sanity limit).
- Slack/Discord webhook notifications for backup success/failure, restore-initiated, and stale-backup watchdog events (Pro and Bundle tiers).
- Hardening (parity with the directory edition): first-party download streaming now uses the WordPress HTTP API; admin-notice scripts moved to `wp_add_inline_script`; staging/uninstall paths resolved via `wp_get_upload_dir()`; installer CSRF/lockfiles relocated to the system temp directory with a table-prefix validation guard; all request inputs run through `wp_unslash()` before sanitization.
- Added an "External services" section to this readme documenting the Google Drive / Google OAuth endpoints, the Bodholdt Labs licensing/update server, and the WordPress.org secret-key (salt) request used during cross-server migration.
Bodholdt Backup for Google Drive
v6.20.2
- Fixed: Duration column in the Logs view showed a stray trailing "s" (e.g. "2 minutess" instead of "2 minutes"). The duration string from `human_time_diff()` already includes the unit word, but the Logs table cell appended an extra `'s'`, a leftover from when duration was rendered as a numeric-seconds value. The cell now renders the duration string as-is. Cosmetic only. No data, scheduling, or backup behavior changes.
Bodholdt Backup for Google Drive
v6.20.1
- Fixed: footer line missing on installs that run third-party plugins which globally blank the WP admin footer. Some plugins (e.g. Taxonomy CSV Import/Export) register `__return_empty_string` against `admin_footer_text` at priority 11 across every admin page, which silently wiped our v6.20.0 footer line (Bodholdt Backup for Google Drive v6.X.X · Documentation · Support). Our filter now runs at priority 99, so it executes last and the footer renders as designed regardless of any other plugin's behavior.
Bodholdt Backup for Google Drive
v6.20.0
- UI: version moved out of the page title. The big "BODHOLDT BACKUP FOR GOOGLE DRIVE V6.X.X" plugin-page heading is now just the product name + the tier badge ("FREE" / "Pro" / etc.). The version still appears, but now in the WordPress admin footer alongside Documentation and Support links, discreet and out of the way. Aligned with how WordPress core and most established plugins handle this.
Bodholdt Backup for Google Drive
v6.19.1
- Brand consistency follow-up. The License sub-page heading still showed the short-form "Bodholdt G-Drive" label after the v6.19.0 rebrand. Now reads "Bodholdt Backup for Google Drive: License" to match the rest of the plugin. No behavior change.
Bodholdt Backup for Google Drive
v6.19.0
- Renamed to "Bodholdt Backup for Google Drive." Adopts the trademark-safe "for [destination]" naming pattern across all customer-facing surfaces (plugin header, admin menus, dashboard, email subjects, logs). Functionally identical. No settings or backups affected.
- Setup wizard: inline OAuth setup guide. Step 2 of the first-run wizard now spells out exactly how to create the OAuth Client ID and Client Secret in Google Cloud Console, including the redirect URI you need to paste, inline with a copy-to-clipboard helper. Previously this guidance lived only in the Settings tab, and the wizard alone left first-time users without enough information to complete the connection.
- Setup wizard: improved "Testing on a local site?" callout. The advisory now correctly explains Google's policy that redirect URIs must be either `http://localhost` or HTTPS at a public TLD (`.com`, `.org`, etc.), so `.local` development sites (Local by Flywheel, MAMP) are rejected even with HTTPS enabled. Recommends using Local's "Live Link" feature for an HTTPS public URL when testing.
- Tested up to: WordPress 7.0. Verified compatibility with the current stable release.
- Honest claims. Softened a few storefront descriptions to be evergreen rather than time-specific ("accessibility-minded" rather than a literal compliance grade; "security-audited each release" rather than a specific score) so they stay accurate without periodic updates.
- wp.org Contributors handle updated to `bodholdtlabs` in preparation for wp.org plugin directory submission.
Bodholdt Backup for Google Drive
v6.18.0
- Per-site backup folders. Each site now backs up to its own uniquely-named folder in your Google Drive (identified by a per-site ID), so multiple WordPress sites sharing one Google account no longer write into the same folder. If a shared folder from an earlier version is detected, the plugin moves this site to its own folder and shows a one-time notice. Nothing is deleted and your existing backups stay untouched.
Bodholdt Backup for Google Drive
v6.17.2
- Licensing fix + brand consolidation. License activation, validation, and auto-updates now point at the correct server (bodholdtlabs.com) and use the correct product reference, so license keys validate reliably (a mismatch previously prevented validation). Author byline, support email, and account links updated to Bodholdt Labs / bodholdtlabs.com.
Bodholdt Backup for Google Drive
v6.17.1
- Retention tier fix. Solo and Agency licenses now get their correct backup-retention limits (Solo 50, Agency unlimited up to the system maximum), and Agency now includes selective restore and Slack/Discord notifications. Previously these tiers fell back to the Free 10-backup limit because the entry tier is issued as "default" and the top tier as "agency". Both are now recognized. Pro and Bundle are unchanged.
Bodholdt Backup for Google Drive
v6.17.0
- Fun + accessibility + consistency pass. Brings the celebration moments, accessibility, and copy up to full parity with Bodholdt Backup for OneDrive, plus a few new-for-both delights.
- New: cumulative "backups protected" stat. The Backup Health card now shows a running total ("N backups protected · X GB kept safe"), counted from a dedicated counter so it survives clearing your activity log.
- New: first-backup celebration. Your very first successful backup now gets a bigger one-time celebration ("Your first backup is done. Your site is officially protected!").
- New: restore-complete celebration. Finishing a restore now greets you with a gentle celebration and a "Site restored. Welcome back." confirmation.
- Richer backup-complete celebration: multi-burst branded confetti, a green-to-teal glow on the progress bar, and a success notification (matching Bodholdt Backup for OneDrive).
- Accessibility: confetti now respects "reduce motion." All celebration animations are skipped when your system requests reduced motion. Tab navigation also gained proper ARIA tablist semantics for screen readers.
- Friendlier first-run guidance: the connect-success banner is now warmly themed with a "Run First Backup →" button; the Start Backup button is disabled with a "Connect your Google Drive first, then open Settings" prompt until you've connected; and a "Your site stays online during the backup." reassurance now sits under the button.
- Clearer empty states + copy: the activity log empty state is now two reassuring lines; health-card placeholders read "Ready to start" / "Awaiting first backup"; and destructive confirmations now state exactly what happens and what's reversible.
- Help sidebar now links to the plugin homepage and email support. Page heading standardized to "Bodholdt Backup for Google Drive."
Bodholdt Backup for Google Drive
v6.16.1
- Cross-plugin parity follow-ups.
- "Reset to Defaults" now restores a sensible Daily 3:00 AM backup (both backup plugins now reset to the same default). And a scheduled backup on a site that hasn't connected its cloud account yet now skips quietly, instead of emailing a daily "backup failed" alert.
- Removed the extra pre-backup confirmation dialog: clicking "Start Backup Now" begins immediately, matching Bodholdt Backup for OneDrive's one-click flow. The "Force Full Backup" option is still right there as an inline checkbox above the button.
Bodholdt Backup for Google Drive
v6.16.0
- Steve Jobs / Grandma Test Pass, Rounds 2-5 (error states, settings parity, micro-interactions, visual polish). Brings the plugin to full feature/UX parity with Bodholdt Backup for OneDrive. Bundles three internal batches:
- *Error handling (R2):* OAuth failures now show a friendly, recoverable banner instead of a blank WordPress error page; an expired or revoked Google Drive authorization now prompts you to reconnect instead of showing "no backups yet"; a dropped network request during a backup or restore no longer freezes the progress bar silently (you get a clear error + retry path); a mistyped notification email is no longer saved silently; cancelling at Google's consent screen is handled gracefully; backup-download errors are now friendly with a back link.
- *Settings (R3):* added Notification-Email and Backup-Type help tooltips, a copy-paste real-cron helper, a friendlier Google Drive destination display, and clearer "Backups to Keep" / "Migration Tools" / file-exclusion copy.
- *Polish (R4/R5):* modern navigation guard during in-progress backups, a green "saved" confirmation, and all admin brand colors moved onto the shared design-token system (so the warning color is now consistent across both backup plugins). Build pipeline excludes editor/OS cruft from the distributed zip.
Bodholdt Backup for Google Drive
v6.15.0
- Fixed: Staging directory now has a graceful fallback when `/var/lib/bodholdt-staging/` isn't writable. Pre-v6.15.0 the plugin defaulted `BODHOLDT_GDRIVE_DIR` to `/var/lib/bodholdt-staging/gdrive/<random-suffix>/` with no fallback, a path that only exists on operator-prepared hosts. On any host without root access (most managed WordPress hosts, every local development environment, every WP.org reviewer install), the `mkdir()` call returned false, the next `fopen()` failed silently, and the backup or restore died mid-flight with the AJAX progress indicator simply disappearing at "Fetching Download link…", with no error to the user. v6.15.0 adds a three-tier fallback hierarchy resolved at plugin-load time: (1) `/var/lib/bodholdt-staging/gdrive/<suffix>/` if writable (preserves the post-2026-05-05 security model on operator-prepared hosts), (2) `sys_get_temp_dir() . '/bodholdt-staging-gdrive/<suffix>/'` if `/var/lib/` isn't writable (system temp, ephemeral but still isolated from the web document root), (3) `wp-content/uploads/.bodholdt-staging-gdrive/<suffix>/` as a last resort with three hardening layers (an `.htaccess` deny-all rule for Apache, an `index.php` returning HTTP 403 as defense-in-depth, and a docs-recommended nginx `location` deny rule in the FAQ). Each fallback transition is logged via `error_log()` so operators on hardened hosts can see why the plugin moved off the primary. Override via `define('BODHOLDT_GDRIVE_DIR', __DIR__ . '/your/custom/path/')` in wp-config.php to bypass the resolution entirely. Plan §4.5.13.
- Fixed: Backup engine was silently omitting WordPress drop-ins (`object-cache.php` / `advanced-cache.php` / `db.php` / `maintenance.php`) at the root of `wp-content/`. v6.14.1 closed the matching gap for `wp-content/mu-plugins/` and v6.14.2 closed the matching gap on the restore side for drop-ins, but the backup engine itself never added drop-ins to the zip. Its scope-dirs helper enumerates directories only, and drop-ins are single files. v6.14.2's restore-side `is_file()` guard masked the gap by degrading quietly (file missing from temp dir → no error → drop-in silently absent from the destination). v6.15.0 adds an unconditional drop-ins block to the backup engine (symmetric to v6.14.1's mu-plugins always-include treatment) with `is_file()` guards so installs without drop-ins degrade quietly. Drop-ins now ride through end-to-end on the backup/restore round-trip. Plan §4.5.19.
Bodholdt Backup for Google Drive
v6.14.2
- Fixed: Restore engine was silently dropping `wp-content/mu-plugins/`, `wp-content/languages/`, and WordPress drop-ins (object-cache.php / advanced-cache.php / db.php / maintenance.php). v6.14.1 closed the matching backup-side gap so mu-plugins now ride along inside the zip, but the restore engine still only copied `themes/`, `plugins/`, and `uploads/` from the extracted backup to the destination's `wp-content/`. Result: any disaster-recovery restore from any prior version landed a site without its must-use plugins (custom auth handlers, debug-log filters, multisite-shared utilities, etc.) and without its drop-ins (Redis object cache, full-page cache, custom DB layer, maintenance-mode override). The restore engine now treats `mu-plugins/` and `languages/` like the database (always copied, no user-facing scope toggle) and copies the four standard wp-content drop-ins when they're present in the backup. Surfaced 2026-05-17 night during the §4.5.10 GDrive end-to-end retest. Plan §4.5.15.
- Fixed: Restore engine no longer unconditionally drops your other Bodholdt backup plugin. Prior versions hard-skipped both `bodholdt-google-drive-backup` AND `bodholdt-onedrive-backup` directories during restore. The self-skip is necessary (a plugin can't safely overwrite itself mid-execution), but the sibling-skip meant customers running both plugins as belt-and-suspenders backup would lose one on every restore. The restore engine now skips the sibling only when it's currently network-active (i.e. running and could collide); installed-but-inactive siblings are restored normally. Plan §4.5.18.
Bodholdt Backup for Google Drive
v6.14.1
- Fixed: `wp-content/mu-plugins/` was silently omitted from every backup. The backup engine's scope-dirs helper enumerated four directory scopes: `core` (wp-admin + wp-includes only), `themes`, `plugins`, and `uploads`. It had no entry for mu-plugins. Result: every GDrive backup zip was missing must-use plugins entirely. Restoring from one of these backups would leave the destination site without any of its mu-plugins (custom auth handlers, debug-log filters, multisite-shared utilities, etc.), silently corrupting site behavior. Surfaced 2026-05-17 during the §4.5.5 GDrive parity retest. OneDrive's wholesale ABSPATH `core` scan picked them up as a side effect, masking the bug across plugins until this retest. Fix: mu-plugins are now treated like the database (always included, no user-facing scope toggle, no way to accidentally omit). Plan §4.5.11.
- Note on Bodholdt Backup for OneDrive: Bodholdt Backup for OneDrive v5.14.0 is not affected. Its `core` scope walks `ABSPATH` wholesale with skip-prefixes for plugins/themes/uploads, so mu-plugins were already included via the wider walk. No OneDrive hotfix is required.
Bodholdt Backup for Google Drive
v6.14.0
- New: Welcome step added to the setup wizard. The wizard now opens on a friendly Welcome screen ("Let's get your site backed up to Google Drive in just a few steps") instead of dropping the user straight into a Client ID / Client Secret form. The 3-step shape becomes 4-step: Welcome → Connect Google Drive → Schedule → Run First Backup. Mirrors the new Bodholdt Backup for OneDrive v5.14.0 wizard structure for cross-plugin consistency. Closes Steve Jobs pass Round 1. P1-B + P1-C.
- New: Wizard JS state machine refactored. Step navigation is now driven by a single `showWizardStep(n)` helper that handles step visibility, dot indicators, and the step-counter text consistently. The previous per-step JS handlers had subtle drift; this refactor unifies them.
Bodholdt Backup for Google Drive
v6.13.0
- New: "Set up" link on the Plugins page. After activating, a "Set up" / "Backups" quick-link now appears next to Activate/Deactivate in the WordPress Plugins list, giving you one-click access to the dashboard. Standard WP pattern; we should have shipped this in v4. Steve Jobs pass Round 1, P1-A.
- New: Friendlier setup-guide language. Wizard welcome copy and the OAuth Setup Guide on Settings have been rewritten to drop "Google Cloud credentials" / "Google Cloud Console" jargon in favor of consumer-friendly framing ("free Google project", "Google Cloud (free)") that explains *why* each step is needed. Technical terms ("Client ID", "Client Secret", "Redirect URI") stay where they're necessary, but the welcome copy no longer reads like enterprise IT. P1-D.
- New: OAuth consent-screen step is now correctly ordered. The Setup Guide previously listed "Configure Consent Screen (if prompted)" as Step 4, but Google requires consent-screen configuration before they'll let you create credentials at all, so it's *always* prompted on a new project, not optional. The step is now Step 3 (before Create Credentials), the "if prompted" misleading wording is gone, and the External-vs-Internal user-type choice is called out explicitly. P2-C.
- New: OAuth Setup Guide Step 5 is split into Save + Authorize. The old single step packed three actions ("paste, save, authorize") into one line, and new users routinely missed the second click. Now Step 5 saves the credentials and Step 6 authorizes the connection. P2-D.
Bodholdt Backup for Google Drive
v6.12.1
- Fixed: "Could not calculate estimate" error on the dashboard. The pre-flight size estimator's "Core Root Files" section called `new DirectoryIterator($root)` against a never-defined variable, which threw a PHP fatal on every dashboard load and the Refresh Estimate button. Vestigial reference left over from the v6.10 `getSubPathname()` refactor. Defined `$root` from `ABSPATH` the same way the scope-dirs helper does. Single-line fix, no behavior change beyond the estimate now actually rendering. OneDrive was unaffected (its core-scope walk handles root files in the main iterator).
Bodholdt Backup for Google Drive
v6.12.0
- Fixed: Multisite retention manifest + retention setting were per-blog (architectural). The retention manifest (`bodholdt_gdrive_backup_ids`) and the configured backup-retention count (`bodholdt_gdrive_retention`) were stored as per-blog WordPress options, but the Google Drive folder they track is per-account, shared across every blog in the network. On multisite installs, a customer who activated the plugin from a non-main blog would hit a manifest scoped to that blog only; subsequent backup runs under a different blog context could see an empty manifest, skip the cap enforcement, and let the cloud grow silently past the configured retention. Both values are now stored as network-wide `site_option`s, mirroring the v6.8.0 license-storage migration. A one-time on-upgrade helper merges every existing blog's manifest into a single network manifest (de-duped by Drive file ID, so no data loss) and promotes the main blog's retention setting to network scope. Single-site installs are unaffected (`site_option` transparently falls back to `option` there). Plan §4.2 v6.12.
- Fixed: Manifest seed could only run once per install (Bug C). The function that reconciles the manifest against the actual cloud folder was gated by `if ( ! empty( manifest_get() ) ) return;`, meaning seed only ran ONCE in the install's lifetime, the first time the manifest was empty. After that, no source of cloud↔manifest desync (manual operator file ops, pre-v6.1.1 backups inherited at upgrade time, etc.) could ever self-heal. Surfaced 2026-05-16 when Kyle's GDrive showed 9 files vs configured retention of 7. Seven pre-v6.1.1 backups were already in the cloud at v6.1.1 install time, the first new backup populated the manifest, the seed never ran again, and the 7 pre-existing orphans were never caught. The function is now a reconciliation pass that runs every enforcer call. Healthy installs pay zero option writes per pass. Plan §0a 2026-05-16 evening.
- Improved: HTTP-status logging in the manifest reconcile pass. Non-2xx Drive API responses are now logged to `error_log()` with the status code + body excerpt, matching the parity hardening already shipped on OneDrive in v5.11.1.
- Improved: Uninstall now cleans up the network-scoped options + transients introduced in v6.8 (license keys) and v6.12 (manifest + retention).
Bodholdt Backup for Google Drive
v6.11.0
- New: Cross-engine collation portability. Backups taken on MariaDB 10.10+ (which defaults to the `utf8mb4_uca1400_*` collation family) now restore cleanly on MySQL 5.7 / 8.x and older MariaDB. The dump rewrites every `*_uca1400_*` collation to the closest portable equivalent (`utf8mb4_unicode_520_ci`, `utf8mb3_unicode_ci`, etc.) at emit time across CREATE TABLE / VIEW / TRIGGER / PROCEDURE / FUNCTION / EVENT statements. Set option `bodholdt_gdrive_translate_collations` to 0 if you need byte-for-byte fidelity (e.g., restoring back to the same MariaDB version).
- New: Progress bar resumes on page reload. Refresh the WP admin tab while a backup is mid-run and the progress UI now picks up where it was: bar, status text, and poll loop all re-attach automatically from the server-side job-status transient. No more "did my backup die?" anxiety.
- New: Default-exclusion patterns for dev artifacts. `apply-bodholdt-*-v*.py`, `__pycache__/`, `*.pyc`, and `*.source.php` are now excluded by default. Pairs with the v6.10.0 readability probe. The probe defends against batch-poisoning regardless, but pre-excluding keeps the manifest tidy and the zip leaner.
Bodholdt Backup for Google Drive
v6.10.0
- Fixed: Backup-engine drops Bodholdt-prefixed plugins/theme on symlinked-deploy patterns. Common deploy pattern (a separate clone of in-house plugins symlinked into `wp-content/plugins/`) used to silently drop those plugins from backup zips. Three independent root causes contributed; all three close in this release. Plan §4.5.6.
- 1. The relpath calc used `getRealPath()` + `substr($path, strlen(ABSPATH))`, which on symlinked subtrees returned paths outside ABSPATH and produced corrupted relpath entries (e.g., `oldt/bodholdt-wordpress/plugins/...`). Replaced with `RecursiveIteratorIterator::getSubPathname()` (iteration-depth-tracked, symlink-safe) plus a per-scope `relpath_prefix` (`wp-content/plugins/` etc.). `bodholdt_gdrive_get_scope_dirs()` now returns each entry shaped as `[ 'path', 'relpath_prefix' ]` (back-compat-tolerant of older callers passing plain-string paths).
- 2. PHP's `RecursiveDirectoryIterator::hasChildren()` defaults to `$allowLinks = false`, so the iterator emits symlinked DIR entries but never descends into them. The entire symlinked subtree gets skipped silently. Fixed via a small RDI subclass (`Bodholdt_Gdrive_FollowSymlink_RDI`) that overrides `hasChildren()` to pass `$allowLinks=true`.
- 3. `ZipArchive::close()` silently drops the entire ~500-file staged batch when even one staged file is unreadable. Pre-validate readability with `@fopen($path, 'rb')` + `fclose()` before `addFile()`; unreadable files are skipped cleanly with optional `WP_DEBUG` logging. `addFile()` and `close()` return values are also checked + logged.
- Fixed: VIEW emission order regression in multisite-network mode. v6.9.0 emitted each blog's views at the end of that blog's iteration, BEFORE the network-shared group ran. Views that JOIN `wp_users` (network-shared) failed at CREATE time on restore because wp_users hadn't been created yet. All non-table schema objects (views, triggers) are now deferred to the absolute tail of the dump, after every CREATE TABLE across every blog + the network-shared group. Plan §4.5.8.
- New: Proper self-exclusion. The backup zip no longer includes the Bodholdt Backup for Google Drive plugin's own directory (Russian-doll prevention). Sibling Bodholdt plugins and the bodholdt-labs theme are deliberately INCLUDED so customers with multiple Bodholdt plugins get a complete backup. Self-exclusion uses canonical-relpath equality, not name-prefix substring matching.
- New: Unreadable files are skipped cleanly instead of poisoning a 500-file batch. Previously, ZipArchive's deferred-read behavior meant a single 0600/0700 file could silently drop dozens of unrelated legitimate backups. The pre-`addFile` readability probe defends against this regardless of what's on disk.
- New: Multisite-network backup mode (Free-tier-included). The backup engine now auto-detects single-site vs multisite and defaults to a complete-network backup on multisite installs. Network mode walks every blog via `switch_to_blog()`, dumps each blog's content tables, then dumps the network-shared tables (`wp_users`, `wp_usermeta`, `wp_blogs`, `wp_blogmeta`, `wp_site`, `wp_sitemeta`, `wp_registration_log`, `wp_signups`) exactly once. Restoring such a backup recreates the full multisite layout.
- New: Per-blog mode (opt-in). Multisite admins who want per-customer subsite isolation can switch to per-blog mode in the network admin's Settings tab. Per-blog backups contain only that blog's content tables.
- New: Backup manifest (`bodholdt-manifest.json`). Every zip now includes a manifest describing mode, plugin version, WP version, blog topology, tables dumped, and shared-table inclusion. The restore engine reads it first.
- New: Restore-side mode compatibility check. Refuses incompatible mode combos (multisite backup → single-site target) to prevent orphan tables.
- Single-site installs unchanged. No UI changes, no feature flag, no migration required.
- New: Multisite-network compatible. License state (key, tier, status, last-seen-valid timestamp) is now stored as a network-wide site option. A customer who activates a Solo license on blog 1 of a multisite network has the license recognized automatically on every other blog. One-time migration runs on upgrade.
- Single-site installs are unaffected.
- New: Slack and Discord webhook notifications (Pro+). One URL field, auto-detected provider. Per-event toggles for backup success, backup failure, restore initiated, and watchdog stale-alert. Send-Test-Notification button in Settings.
- New: Helper `bodholdt_gdrive_notifications_allowed()` returns true only for Pro/Bundle. Filterable for one-off overrides.
- Failure notifications include the same auto-diagnosis hint as the email notification.
- New: Free tier is now the default experience. No license required for full backup + restore at the Free cap (10 retained).
- New: Tier badge inline in the plugin header (Free / Solo / Pro / Bundle).
- New: Lapse banner: when a previously-active license becomes invalid, a dismissible banner reminds you to renew while backups continue at Free-tier limits.
- New: Soft-degrade on lapse: backups keep running even with an invalid license. Retention auto-clamps to 10; selective restore disables.
- Removed: Three hard-locks that previously blocked the admin UI, manual backups, and scheduled backups on non-valid licenses.
- Setup wizard now also surfaces to Free users for OAuth-flow guidance.
- New: Tier-gated selective restore. Pro and Bundle customers can choose what to restore (database, plugins, themes, uploads, core). Free + Solo restore everything.
- New: Inline "Upgrade to Pro" hint shown next to disabled scope chooser on Free + Solo.
- Server-side defense: restore handler coerces submitted scope to full on tiers without selective access.
- New: Tier-aware retention cap helper. Free=10 / Solo=50 / Pro=100 / Bundle=100. Save handler clamps; settings input cap is dynamic.
- New: Over-cap inline notice when a previously-saved retention value exceeds the current tier cap (e.g., after a downgrade).
- New: Pre-flight `force_refresh()` before retention enforcement so tier downgrades take effect within one backup, not 12 hours later.
- Licensing client now captures `tier_key` from server responses.
- Critical fix: added backup-filename allowlist to retention enforcement. Previously the enforcer listed every child of the backup folder; user-dropped files in `Bodholdt Backups/<site>` could have been auto-deleted. Now the enforcer uses an ID-manifest written at upload time plus a filename regex check.
- New: One-time seed migration on upgrade for existing backups.
- New: Watchdog last-success timestamp with stale-alert.
- New: Out-of-web-root staging directory.
- New: Multipart-leak fix in email rendering.
Bodholdt Backup for Google Drive
v5.12.0
- Security hardening: strict base64 decoding, WP_DEBUG-gated error logs, Windows zip-path validation, OAuth state-transient race fix, path-traversal protection in uninstall, API response structure validation, hex-format validation on directory suffix.
- GPL-2.0-or-later license file added. Languages directory added. CHANGELOG.md added.
Bodholdt Backup for Google Drive
v5.11.0
- Incremental backup mode. Selective backup scope. Setup wizard. Test email. Force unlock for stuck backup processes.
Bodholdt Backup for Google Drive
v5.10.0
- Selective restore. Sentinel-based SQL statement splitting. Pre-restore safety snapshot.
- Sodium encryption support. HMAC-authenticated AES-256-CBC. Dark cyberpunk admin theme.
- Resumable chunked upload to Google Drive. Backup retention policy with automatic cleanup. Email notifications.
- Migration installer (standalone restore tool). Custom file/folder exclusions. Scheduled backups.
- Initial release with Google Drive integration.
Bodholdt Licensing
v10.37.1
- Shared admin engine reconciliation across the Bodholdt product line.
Bodholdt Licensing
v10.36.0
- Admin dashboard: optional recurring-revenue "Compounding Vault" view added to the built-in gamification, with a Settings > Arcade switch to turn the whole layer (and its motion and sound) off.
Bodholdt Licensing
v10.35.0
- Introduced an optional, fully dismissible admin gamification layer that respects reduced-motion preferences.
Bodholdt Licensing
v10.34.0
- Admin redesign across the board: refreshed Dashboard, Activity Log, and Manage Licenses (status chips, inline expiry editing, per-row menus, and a bulk-action bar), cleaner Settings sub-tabs, a clearer "Connect a Plugin" screen, and a split list/editor for Products with safer per-product saving.
Bodholdt Licensing
v10.33.0
- Added download tracking and a Reports > Downloads section.
Bodholdt Licensing
v10.32.0
- New Sender Identity settings with a live email preview.
Bodholdt Licensing
v10.31.0
- Portable customer-reviews display you can place on any page, plus a support line in review-request emails.
Bodholdt Licensing
v10.30.0
- Automatic post-purchase review-request email.
Bodholdt Licensing
v10.29.0
- Verified customer reviews, so only real, purchase-linked customers can leave one.
Bodholdt Licensing
v10.28.0
- Pricing-page refinements and Free-card alignment on the buy-plugins page.
Bodholdt Licensing
v10.27.0
- Aligned the Atelier pricing and pitch copy.
Bodholdt Licensing
v10.26.0
- Wired the Atelier product family into the pricing page and comparison matrix.
Bodholdt Licensing
v10.25.0
- Entitlement gating for the free "Lite" builds.
Bodholdt Licensing
v10.24.0
- Self-serve free tier: the free build became a direct, no-key download (with abuse caps and Cloudflare-aware IP trust), and the marketing copy was realigned to the free-and-paid model.
- Pricing accuracy: removed the "Streaming restore (FK-safe, BLOB-safe)" line from the paid Backup tier. The free build's full restore already uses that same streaming, FK-safe, BLOB-safe engine, so it was never a paid upgrade. The genuine upgrade is selective restore, choosing what to restore, which the tier already lists.
- Documentation: backfilled the release history below (10.24 through 10.37) so the changelog reflects the full recent record.
- Pricing accuracy: the Backup Agency tier now reads "Up to 127 sites" (and 127 in the comparison table and the agency FAQ) instead of "Unlimited", matching the enforced activation limit.
- Copy polish: removed em dashes used as sentence punctuation in the Backup Bundle heading and the Licensing pitches, and demoted the pricing section heading to <h2> so each page has a single <h1>.
- Fixed: higher pricing tiers (Pro, Agency, Studio, Foundry) could not complete checkout. The payment-boundary price check compared the tier's Stripe price against the wrong product and returned a price mismatch, bouncing buyers back to the pricing page. Non-default tiers now check out correctly.
- Fixed: the "Manage Billing & Subscriptions" button on the customer subscription-management page did nothing. It now submits and emails the billing-portal access link as intended.
Bodholdt Atelier
v1.9.0
- This is a quality and safety release. Every admin section is reachable again, payments are verified more strictly, and the public forms are protected against abuse.
- Every studio section opens again. After the 1.8.0 menu tidy, opening Works, Orders, CRM, Shows, the License page, the Setup Quest, and the other sections from the in page tabs or a direct link could show "Sorry, you are not allowed to access this page." Those sections are now fully reachable while the sidebar stays calm with just Dashboard and Settings. If you were stuck on activation, you can now enter your license key and finish setup.
- Stronger PayPal verification. A returning PayPal payment is now matched to the exact order and amount it paid for, so a completed payment can never be applied to a different or more expensive order.
- Correct prices for yen and other zero decimal currencies. A price in Japanese yen now shows the same amount your customer is actually charged, instead of appearing one hundred times too high.
- Fair EU VAT for business buyers. With tax inclusive pricing, a valid EU business buyer under reverse charge, and a buyer outside the EU, now pay the net price with the embedded VAT removed instead of the full amount.
- Download limits are enforced exactly. A download link now honors its maximum download count even when several downloads start at the same moment.
- Spam protection on public forms. Newsletter signup, commission requests, and studio visit booking now have rate limiting and a hidden honeypot, so the forms cannot be used to flood your inbox or your subscriber list, and cannot be turned into a tool to email strangers.
- Certificates follow the order. A license certificate PDF now checks that its order is still paid and the license has not expired before it is shown, matching how downloads and certificates of authenticity already worked.
- Affiliate self referrals are ignored. An affiliate can no longer earn a commission on their own purchase.
- Secure connection for the Lightroom publisher. The Lightroom plugin now refuses to send your publish token unless the store URL uses https, and assumes https when you leave the scheme out.
- Cleaner uninstall. Deleting the plugin now removes its data on every site of a multisite network and clears its cached license and update records, while still leaving your storefront page untouched.
- Accurate promo end time. A Bodholdt Friday promo now ends at the moment you set in your site timezone.
- Translation ready. A translation template is now bundled so the plugin can be translated into any language.
Bodholdt Atelier
v1.8.2
- Privacy tools (GDPR export and erase). The storefront now answers data subject requests through the built-in WordPress privacy tools. Export returns a buyer's orders, licenses, commissions, subscriptions, newsletter and contact records, bookings, and affiliate record; erase deletes the newsletter, booking, and contact rows, invalidates the license download token, and anonymizes orders, commissions, subscriptions, and affiliate earnings (name, email, and shipping address removed) while keeping amounts, tax, country, VAT number, and payment references required by tax law. The provenance hash chain is left intact. Suggested privacy-policy text is added to Settings > Privacy.
- Safer subscriber export. The newsletter CSV export now neutralizes spreadsheet formula injection, so a subscriber name cannot run a formula when you open the file in Excel or Sheets.
- Cleaner release package and accurate privacy notes. Internal build and testing notes are no longer included in the plugin download, and the bundled privacy documentation now correctly states that fonts are served from your own site (no Google Fonts CDN request).
Bodholdt Atelier
v1.8.1
- Countdown icon. The limited run countdown timer on a work page was the one spot still showing an emoji hourglass. It now uses the same brand icon as the rest of your storefront.
Bodholdt Atelier
v1.8.0
- Admin UX pass. The section nav hides features you have turned off and groups the rest into Sell / People / Events, so a solo artist no longer scrolls past empty rooms. Off-state tabs can turn a feature on (and create its page) in one click. The long settings page becomes six sub-tabs, each with its own Save. Shipping zones and rates get row builders instead of a pipe-delimited textarea. Payments leads with a connection status card and masks your saved keys. The dashboard stays quiet until your first sale, then folds the "you kept 100%" comparison into your revenue. The setup quest spotlights one next step, and the CRM search filters as you type. Every emoji in the plugin, admin and storefront and emails alike, is replaced with crisp icons that match your brand. The arcade (quest, XP, trophies) is untouched.
Bodholdt Atelier
v1.7.0
- Solo edition now earns its keep. Patron subscriptions with content drip, and commissions with milestone/deposit payments (including studio-visit / appointment scheduling), are now Atelier Solo features rather than free. The complete one-off-sale loop stays free in Lite — every other work type, Stripe/PayPal/simulated checkout, orders, certificates of authenticity + provenance, per-buyer watermarking + signed expiring downloads, the collectors CRM, royalty splits, the white-label storefront, the music pipeline, EU VAT/IOSS, print-on-demand, promos/affiliates, gamification, and shows. Pro features (multi-artist Foundry, cross-artist Marketplace, Lightroom / Publish API) are unchanged. Enforcement never bricks: a feature is only hidden for a confirmed below-tier license — a server hiccup, expiry, or grace period never removes anything.
Bodholdt Atelier
v1.6.1
- Edition tiers tightened. The multi-artist Foundry, cross-artist Marketplace, and the Lightroom / Publish API are now Atelier Pro features. Solo licenses keep all core commerce — the work types, checkout, certificates, provenance, watermarking, signed downloads, commissions, patronage, EU VAT/IOSS, royalty splits, collectors CRM, and white-label appearance — unchanged. Enforcement never bricks: features are only hidden for a confirmed below-tier license; a server hiccup or grace period never removes anything.
Bodholdt Atelier
v1.6.0
- White-label storefront. Your public storefront, gallery, artist pages, and checkout now adopt *your* brand: upload your logo and set a single accent colour plus Light/Dark/Auto and a corner style in Settings → Storefront appearance (with a live preview). It ships with clean, neutral defaults instead of a fixed theme, and readable hover/contrast shades are derived automatically. Status colours (available / sold / limited) keep their meaning.
Bodholdt Atelier
v1.5.0
- Licensing & automatic updates. Atelier now activates against the Bodholdt Licensing server and delivers in-dashboard automatic updates to licensed sites (it sends only your license key, site URL, and product name — never your store, customer, or sales data). Unactivated installs keep working in community mode.
Bodholdt Atelier
v1.4.1
- Admin polish: the section tabs and view headings now use crisp monochrome icons, and admin notices/forms match the dark studio theme.
Bodholdt Atelier
v1.4.0
- Privacy: web fonts (Roboto Mono, Orbitron) are now bundled and served locally instead of loaded from Google — no visitor IP is shared with a third party on page load.
- The "Powered by Bodholdt Atelier" storefront credit is now opt-in (Settings → Studio) and hidden by default.
Bodholdt Atelier
v1.3.0
- Certificate signature: upload a signature image (Settings → Studio) and it's drawn on every Certificate of Authenticity, composited onto the dark certificate so it blends. The PDF engine now embeds JPEG images.
Bodholdt Atelier
v1.2.0
- Lossless audio downloads: offer a music release for download as MP3 320, FLAC, ALAC, or WAV (24-bit), transcoded on demand from one master upload (FFmpeg) and cached in the protected store. Buyers pick a format at checkout; the master is delivered as-is if FFmpeg isn't present.
Bodholdt Atelier
v1.1.0
- Shipping rate tables: charge by destination zone + parcel weight, not just a flat per-piece fee. Define zones (country groups + a catch-all) and weight bands in Settings → Shipping, set each Work's weight, and checkout looks up the rate (with the flat price as a safe fallback). A destination picker appears at checkout when VAT isn't collecting a country.
Bodholdt Atelier
v1.0.1
- Launch-readiness: compliance + go-live docs (docs/PAYMENTS.md, docs/PRIVACY.md with data inventory + adaptable privacy/terms starters, docs/TESTING.md for Stripe/PayPal sandbox wiring), Lightroom distribution guide + build script (a separate .lrplugin zip), and a text-only payment-trust line at checkout (nominative "powered by Stripe" / "redirected to PayPal" — no third-party logos bundled).
Bodholdt Atelier
v1.0.0
- First stable release. Every master-plan feature is in: all 13 Work types, three checkout modes (simulated / Stripe / PayPal), COAs + tamper-evident provenance, watermarked signed downloads, commissions, subscriptions + drip, EU VAT/IOSS, music/serials/PoD/AR, Foundry + marketplace, bundles + royalty splits, affiliates + promos, email + newsletter, wholesale + consignment, Maker's Proof, the buyer PWA, the publish/Lightroom API, the full CRM, a WCAG 2.1 AA pass, and the Bodholdt Licensing layer.
- Pre-1.0 QA: parallel security + correctness audits (no critical/high issues); added an SSRF guard on remote-image publishing and a named lock so the provenance chain can't fork under concurrent finalizes.
Bodholdt Atelier
v0.27.0
- Bodholdt Licensing layer: a License admin page to activate your key (domain-bound, daily re-validation), tiered features (Solo/Pro/Agency), simulated-by-default so it works without a server, and it never bricks an install.
Bodholdt Atelier
v0.26.0
- Publish API: a token-secured REST endpoint to create/update a Work from an uploaded image + metadata (re-publishing the same photo updates, not duplicates).
- Adobe Lightroom Classic publish plugin (in /lightroom) that pushes finished photos straight from your catalog into your store over that endpoint.
Bodholdt Atelier
v0.25.0
- Accessibility (WCAG 2.1 AA) pass: visible keyboard focus everywhere, an accessible AR modal (focus trap + Escape + focus restore), site-locale on portal pages, higher text/border contrast, labelled fields, and full reduced-motion support.
Bodholdt Atelier
v0.24.0
- Full artist CRM: one contact directory across buyers, patrons, subscribers and commission clients, with segments (VIP, lapsed, …), search, channel badges, a purchase-history timeline, and editable per-contact notes & tags.
Bodholdt Atelier
v0.23.0
- On-chain provenance receipts: every certificate is SHA-256 fingerprinted and chained to the previous one — a tamper-evident ledger shown on the verify page and certificate. Optional free anchoring to Bitcoin via OpenTimestamps.
Bodholdt Atelier
v0.22.0
- Wholesale / trade pricing: a private trade code unlocks wholesale prices for galleries/shops (per-Work wholesale price or a global trade discount), shown with retail struck through.
- Consignment ledger: a new admin page to track pieces placed with galleries/shops — venue, commission %, status (out/sold/returned), and your net take after commission.
Bodholdt Atelier
v0.21.0
- Maker's Proof: a per-Work human-made attestation + generative-AI disclosure, plus medium, tools, hours, process notes and work-in-progress images — rendered as a trust panel on the storefront and a line on the certificate. In an AI-flooded market, honest provenance is the differentiator.
Bodholdt Atelier
v0.20.0
- PayPal checkout (Orders v2, SDK-free): create order → approve → capture on return, with a signature-verified webhook backstop. Sandbox/live toggle; configure under Settings → Payments.
- Gateway abstraction: one helper picks the active processor (Stripe / PayPal / simulated) for the whole plugin.
Bodholdt Atelier
v0.19.0
- Buyer "My Collection" app: a private, no-login page listing every purchase with fresh download links, certificates and invoices — installable to the phone home screen as a PWA (web manifest, GD-drawn app icons, offline page via a service worker).
- The collection link is added to order receipts and the success page; enable it under Settings → Buyer app.
Bodholdt Atelier
v0.18.0
- Webcomic / Serial Work type: schedule episodes (title + page + release date); the storefront reader shows released episodes with prev/next and hides future ones behind a public release schedule.
- Per-format music inventory: define formats as "Label | price | stock"; buyers pick a format with its own price and remaining-stock count, and a limited run (e.g. vinyl) depletes on sale.
Bodholdt Atelier
v0.17.0
- Subscription content drip: posts that unlock over a patron's membership, via a tokenized patron portal.
- Sync-license tier for music (film/TV/ads) with an auto-generated sync license PDF.
Bodholdt Atelier
v0.16.0
- Pay-what-you-want everywhere: any fixed-price work can opt into name-your-price.
- Vinyl pre-orders + crowdfunding goal bar (funded % / backers / ships-when).
Bodholdt Atelier
v0.15.0
- Show/fair inventory mode: reserve Works for a show; they auto-release when it ends.
- Studio-visit booking: open-slot calendar + [bodholdt_atelier_book] form with artist/visitor emails.
Bodholdt Atelier
v0.14.0
- QR codes: a self-contained encoder (no library); scannable QR on the COA + downloadable per-Work QR for shows/merch.
Bodholdt Atelier
v0.13.0
- Collector CRM: lifetime value, tiers, and what each collector owns (from the order ledger).
- File-type variants: buyers pick a format (PSD/PNG/SVG) at checkout and get that file.
Bodholdt Atelier
v0.12.0
- Client galleries: private, password-protected photo delivery (hidden from the public catalog).
- Per-piece shipping: flat shipping price + ship-to address at checkout for physical works.
Bodholdt Atelier
v0.11.0
- Transactional email: branded order receipts (with download/COA/invoice links), artist sale notices, and commission notifications.
- Newsletter capture: ESP-agnostic double opt-in (Mailchimp/Kit/FluentCRM/CSV), checkout opt-in + [bodholdt_atelier_subscribe] shortcode, subscribers admin + export.
Bodholdt Atelier
v0.10.0
- Affiliate/referral codes: shareable ?ref=CODE links with buyer discounts + tracked referrer commission.
- Bodholdt-Friday promo mode: countdown banner, optional sitewide discount, and Foundry-fee waiver.
Bodholdt Atelier
v0.9.0
- Bundles: group Works into a discounted combo; buyers receive every item.
- Royalty splits: pay collaborators a percentage of each sale via Stripe Connect transfers.
Bodholdt Atelier
v0.8.1
- QA pass: oversell protection on the Stripe path, webhook rejects unsigned events, path-traversal guard on file delivery.
Bodholdt Atelier
v0.8.0
- Marketplace mode: a public storefront with search, type/artist filters, sort, a featured row, and an artists directory.
Bodholdt Atelier
v0.7.0
- Foundry (multi-artist) mode: run a collective/label/agency with per-artist works, profiles, XP/trophies, and a leaderboard.
- Per-artist Stripe Connect payouts (destination charges) with an optional collective fee.
- Public artist profile pages + bylines.
Bodholdt Atelier
v0.6.0
- Music: FFmpeg skip-protected 30s previews + lossless master ZIP delivery, per-track players.
- Print-on-demand routing (theprintspace, FinerWorks) with a Fulfillments admin screen.
- AR "view on your wall" room viewer (camera or room photo) with real-size scaling.
Bodholdt Atelier
v0.5.1
- Fixed VAT invoice layout (totals no longer overlap the amount) and PDF transliteration of accented characters.
Bodholdt Atelier
v0.5.0
- Built-in EU VAT/IOSS: EU-27 rate table, destination/OSS/IOSS rules, B2B reverse charge with VIES validation.
- Country + VAT-number fields at checkout with a live VAT/total preview.
- Auto-generated VAT invoice PDF per sale; admin VAT-collected-by-country report.
Bodholdt Atelier
v0.4.0
- Stripe-backed commission deposits + per-milestone payments (buyer pays from the portal).
- Recurring patronage subscriptions via Stripe (subscription Checkout, renewal revenue, cancellation).
- Patrons admin screen with active count, MRR, and one-click cancel.
Bodholdt Atelier
v0.3.0
- Per-buyer image watermarking (tiled preview + forensic delivery stamp), pure GD.
- Signed, expiring, HMAC-protected download URLs streamed through PHP with download-count + expiry enforcement.
- Real commission milestone workflow: admin control panel + tokenized buyer portal (accept quote, approve milestone gates).
Bodholdt Atelier
v0.2.0
- Live Stripe Checkout (no SDK) with idempotent finalize, webhook + signature verification.
- Auto-generated Certificate of Authenticity + license PDFs via a built-in, dependency-free PDF writer.
- Public scan-to-verify page and a basic download gate.
Bodholdt Atelier
v0.1.0
- Initial MVP foundation: Work engine + all 10 types, gamified cyberpunk admin, setup quest, storefront + simulated checkout, XP/levels/trophies.
Bodholdt Tickets
v1.5.4
- Security and reliability hardening. Support credits are now granted only for a genuine credit purchase, and repeated or simultaneous captures can no longer grant extra credits. The GDPR erase tool now fully drains customers with large ticket histories instead of stopping after the first batch. SLA due dates, breach alerts, and clutch bonuses are corrected on sites that are not set to UTC.
- Privacy and access. Internal agent notes and their attachments can no longer be reached from the customer portal. Portal actions now carry a per session token. The erase tool also clears the customer entered subject line. Uninstall now removes uploaded files, appearance settings, and gamification standings, and cleans every site on a multisite network.
- Smaller fixes. Rate limiting keys on the real client address, web push endpoints must be https and are validated before use, the stored web push key is encrypted at rest, legacy Office document uploads are accepted, the translation template was refreshed, and a queue search edge case no longer errors.
Bodholdt Tickets
v1.5.3
- Privacy tools (GDPR export and erase). The plugin now answers data subject requests through the built-in WordPress privacy tools. Export returns a customer's tickets, messages, attachments, support credits, and verified email links; erase deletes the messages, attachments, and links, anonymizes the ticket history, and anonymizes but retains paid-support purchase records where tax law requires. Suggested privacy-policy text is added to Settings → Privacy. No change to how the support desk works.
Bodholdt Tickets
v1.5.2
- Arcade engine polish (shared). XP now counts correctly when several events land at the same moment, the on-screen HUD labels are fully translatable, and celebration cards always stay within the screen. No change to how the support desk works.
Bodholdt Tickets
v1.5.1
- The Support Desk now names your rank. The desk's top-bar scoreboard shows your Response Ops rank (Rookie through Desk Legend) next to your level and XP, matching the wp-admin HUD, so your progress reads the same on both surfaces. Your stats panel shows it too.
Bodholdt Tickets
v1.5.0
- Response Ops. The support desk becomes something you want to play. A HUD in wp-admin tracks your level, rank, and XP as you work tickets, and your agents get the same on the Support Desk itself, with a celebration when a customer rates a reply or you reach a new rank. Clutch Time rewards a save landed right before an SLA runs out, scaled to how close to the buzzer you get. Trophies unlock as you go. All optional, sound stays off by default, and the desk works exactly as before.
Bodholdt Tickets
v1.1.0
- Settings redesign. The one long settings page is now a set of tabs (General, Channels, Notifications, Team, Paid Support, AI Co-pilot, Appearance), each with its own Save, so you configure one thing at a time. Every setting is exactly where it was, just grouped.
- New setup status card at the top tells you at a glance whether your desk is ready, and links straight to the step that still needs doing.
- Custom fields and credit packs now have friendly row editors instead of a type-the-syntax text box. The plain text editor is still there under "Edit as text" if you prefer it.
- The inbound webhook URL and widget embed snippet now hide their secret token until you click Reveal, and both got a one click Copy button.
- Clearer wording on the email intake and paid support options, with the fine print tucked into "how this works" expanders.
- The database table list collapses to a single "all tables ready" line unless something needs attention.
- Support Desk: every emoji is replaced with original brand icons, including the achievement badges. No functional change.
Bodholdt Tickets
v1.0.0
- 1.0 is out of beta. Bodholdt Tickets graduates to 1.0 after 30+ shipped releases. No breaking changes; this marks the product as production-stable: the same license-aware desk, AI co-pilot, four intake channels, departments and routing, SLA management, and gamification you've been running.
- Added an "External services" section to the readme (Anthropic, Web Push, licensing server) and self-hosted the admin font so no admin request is sent to Google Fonts.
- When a license is inactive, the plugin now shows a "renew to update" note on the Plugins screen instead of a failed update.
Bodholdt Tickets
v0.33.4
- Free (wp.org) edition: reworded the customer portal's "Linked emails" copy so it reads as consolidating your tickets across email addresses (no licensing/paid-support phrasing), and finished the wp.org readme (screenshots + a clean free-launch changelog). No behavior change.
Bodholdt Tickets
v0.33.3
- Code quality: annotate the custom-table database queries (the plugin owns its own `wp_bt_*` tables, which have no core API) with justified `phpcs:ignore` markers, add `wp_unslash()` to the remaining admin save paths, and trim the short description, which clears the WordPress.org Plugin Check warnings. No behavior change.
- Free (wp.org) build: regenerate the translation template for the free slug/text domain so the shipped `.pot` matches `bodholdt-support-tickets` (no stale licensing strings).
Bodholdt Tickets
v0.33.2
- Hardening: escape upgrade-nag output in the agents/plan admin views and add `wp_unslash()` + key sanitization to the Settings and Appearance save paths.
- Fix: pass bound query parameters to `$wpdb->prepare()` via argument spread in the ticket-queue query so replacement counts match (no behavior change).
- Free (wp.org) build: the slug rename now also rewrites `assets/admin.css`, so the free edition's admin styling is correctly scoped and no longer renders unstyled.
Bodholdt Tickets
v0.33.1
- Desk SPA: the agent desk now surfaces SLA state, with an "Overdue" / "At risk" badge on queue rows, an SLA quick-filter (Overdue / At risk) in the inbox, and first-response / resolution due times with their on-track / at-risk / overdue state in the ticket detail panel. (Pro; the desk shows nothing SLA-related on the free plan.)
Bodholdt Tickets
v0.33.0
- New (Pro): SLA management + automation. Set first-response and resolution targets per priority (Urgent / High / Normal / Low), define your business hours (working days, open/close, timezone, or count 24/7), and every new ticket is stamped with due dates. The desk flags tickets that are *at risk* or *breached*, and an hourly check emails the assigned agent and admin the moment a target is missed.
- New (Pro): round-robin auto-assignment. Tickets routed to a department are automatically handed to the next agent in that department.
- SLA due dates recompute automatically when a ticket's priority changes. (The basic SLA *report* remains available on the free plan.)
Bodholdt Tickets
v0.32.1
- Rebuilt the Agent Support Desk SPA and refined the in-admin help and upgrade prompts.
- Packaging: the WordPress.org free build now ships a self-contained free edition (Pro-only code physically stripped) and is available as a self-served Lite download.
Bodholdt Tickets
v0.32.0
- New, more generous Free + a clearer Pro. The plan model is now free-vs-Pro: paid tiers differ only by how many sites they cover. Free now includes up to 3 agents, unlimited tickets, the support form & block, the customer portal, custom fields, private notes, canned replies, CSAT, gamification, categories, the Claude (bring-your-own-key) AI co-pilot, the embeddable widget, and basic/aggregate reports.
- Pro (any paid plan) adds: unlimited agents, inbound email-to-ticket piping, departments & routing, advanced per-agent/per-department reporting, and license-aware customer context in the desk.
- Inbound email intake and the licensing-aware customer context are now gated to paid plans; the free plan is capped at 3 agent seats (upgrade to any paid plan for unlimited agents).
Bodholdt Tickets
v0.31.0
- In-app bug reports (authenticated channel). A new `bt/v1/app-report` endpoint lets a companion mobile app file tickets on behalf of the logged-in user. There's no typed email; identity comes from the authenticated account. Reports land in your desk on the new `app` channel and reply by email like any other ticket.
- Beta-tester allowlist. Submission is gated on a per-user Beta tester capability, toggled from the user-edit screen (Users → edit a user → the "Bodholdt Speed Test" Beta toggle). Only allowlisted accounts can file reports. The `app` channel bypasses the free-tier cap and the paid-support gate, so it stays fully decoupled from licensing.
Bodholdt Tickets
v0.30.0
- Agent email alerts. Get an email the moment a customer opens a ticket or replies, so your team is notified even when nobody has the Support Desk open. A reliable fallback to the desk's browser/desktop alerts (which require each agent to opt in per device).
- Turn it on under Tickets → Agent notifications: choose whether to alert on new tickets, new replies, or both; send to all agents or only the assigned agent/department; add extra recipients (a shared inbox or on-call alias); and send a test alert to confirm delivery. Off by default.
Bodholdt Tickets
v0.29.1
- Appearance preview fix. The settings-page brand preview now faithfully reflects light/dark mode (the admin dark styling was bleeding into the live preview's input fields). Visual-only.
Bodholdt Tickets
v0.29.0
- White-label your customer-facing surfaces. The contact form, customer portal, and floating widget now adopt *your* brand instead of Bodholdt's, driven by a single accent colour with clean, neutral defaults. Semantic ticket-status colours keep their meaning.
- New Appearance settings. Pick a brand colour, light/dark/auto mode, corner style, and font from the Tickets settings page, with a real live preview. Applies across the form, portal, and widget at once. (The agent Support Desk is intentionally left on its own dark theme.)
Bodholdt Tickets
v0.28.0
- Refreshed admin styling. The Tickets settings screen now uses the shared Bodholdt Labs dark admin design system, with clearer headings and labels, readable inputs and tables, a unified button style, and consistent focus states. No functional change.
Bodholdt Tickets
v0.27.0
- Choose your support model. New setting runs lifetime support as non-expiring credits (tokens), a fixed time window, or both.
- Build your own credit packs. Define any number of packs (credits + price + your own Stripe Payment Link) instead of a fixed single/3-pack.
- Set how many non-expiring credits each lifetime license grants, by site tier.
Bodholdt Tickets
v0.26.2
- See your support credits. The My Tickets portal now lists your available support credits with a per-product breakdown, so you always know what you have and which product each credit applies to.
Bodholdt Tickets
v0.26.1
- Renamed to Bodholdt Tickets. The product is now "Bodholdt Tickets" and the wp-admin menu reads "Tickets." No functional changes; your license, data, and settings are untouched.
Bodholdt Tickets
v0.26.0
- Product-scoped support credits. Lifetime support credits are now redeemable only for support on the product they were purchased with; manually-granted/comped credits remain universal.
Bodholdt Tickets
v0.25.0
- Custom ticket fields. Add your own fields (text, dropdown, checkbox, email, number, and more) to the support form and the new block. Values arrive attached to the ticket.
- Gutenberg support-form block. Drop the support form on any page with a block, alongside the existing [bodholdt_support_form] shortcode.
- Lifetime support credits. Lifetime license purchases now automatically receive non-expiring support credits, ADDED to any credits you already have (never overwritten).
- More desk power. File attachments on tickets (customer + agent), a canned/saved-replies picker, one-click ticket deletion, a personal "My stats" tab, and a fully responsive Support Desk.
- Accessibility, i18n, and reliability improvements throughout.
- Stripe webhooks now acknowledge checkout sessions created by other integrations on the same Stripe account, so unrelated events cannot disable the webhook endpoint.
- License activation is serialized regardless of key letter casing, so the per-license site limit cannot be bypassed by concurrent requests.
- A licensed store re-verifies from any page load when the scheduled check has not run, instead of self-locking after 30 days on hosts without wp-cron.
- Reports keep showing the last known figures when Stripe is briefly unreachable, instead of a fresh 0.
- Fixed two Settings notices that reported success when a store page slug or vault path was actually rejected.
- Messages now reach you exactly as they were typed. A link containing encoded characters used to lose part of itself on the way to you, so a pasted address could arrive broken. Quoted markup, such as a customer showing you the HTML on their page, could vanish from the message entirely. Both are fixed. Messages routed into Bodholdt Tickets are now escaped as well, so nothing a visitor sends can render as live content in your Support Desk.
- Asking for a fresh code works again. The hourly limit on codes sent to one address was exactly the number the widget itself could spend, so "start again to request a new code" was always refused. The limit now leaves room to start over, and when a visitor does have to wait, the widget says roughly how long.
- Clearer answers when something is wrong. If the plugin cannot create its database tables, the settings page and an admin notice now say so plainly instead of reporting that the widget is live. If a saved setting had to be shortened, or had formatting removed, the page now names the field that changed instead of only saying "Settings saved".
- Friendlier recovery in the widget. After too many incorrect codes the widget returns the visitor to the email step, rather than offering a Resend button that could never work. The resend countdown now follows real time, so it no longer looks stuck after someone switches to their mail app on a phone.
- Sites behind a proxy or CDN. Added a `bodholdt_contact_client_ip` filter so operators whose web server does not pass through the real visitor address can supply it. Without it, every visitor could end up sharing a single rate limit bucket. Forwarded headers are still never trusted by default.
- Smaller fixes. A three-digit colour such as #0af no longer produces invalid styling. The message box now shows its length limit before you send. The suggested privacy policy wording and the erase result describe the ticket store accurately when Bodholdt Tickets is handling messages. The Licensing note no longer contradicts the status card. Gamification labels can now be translated. A failed table creation no longer repeats a full migration on every page load, and no longer disables the activity report permanently.
- Privacy tools (GDPR export and erase). The plugin now integrates with the built-in WordPress privacy tools. Tools → Export Personal Data returns the verification records held for an email address, and Tools → Erase Personal Data deletes them, so you can answer data subject requests the standard way. The plugin also adds suggested wording to Settings → Privacy for your privacy policy. No change to how the contact form works.
- Accessible contact form (WCAG 2.1 AA). The visitor widget now passes accessibility review: readable success and error text in dark mode, visible field borders and focus outlines, autocomplete on the email and verification-code fields, a properly announced delivery confirmation, and correct focus handling on Resend. This matters if your site serves visitors in the EU, where the European Accessibility Act applies to consumer-facing forms.
- Licensing and packaging. The bundled confetti library now ships its required copyright notice, and the release archive uses correct, non-world-writable file permissions. The readme now names the database tables the plugin creates.
- Enforces Hobby, Studio, and Foundry activation and product entitlements against the canonical commercial-license ledger, including Multisite.
- Verifies replacement keys before saving, preserves a working state during transient failures, and releases activations on clear or uninstall.
- Hardens generated clients and the built-in updater so license keys stay out of URLs and are sent only to an exact matching HTTPS origin and product.
- Validates carts, canonical Stripe Prices, currencies, recurrence, products, tiers, bundles, and trial rules on the server before Checkout.
- Makes checkout fulfillment, subscription state, refunds, disputes, and email retry ordered, durable, transactional, and idempotent.
- Requires all seven documented Stripe events and proves webhook readiness before paid checkout.
- Makes the private product vault fail closed, validates exact product references on downloads, applies download throttling, and redacts operational logs.
- Hardens customer OTP, portal, review, REST, AJAX, admin, settings, product, license, and GDPR paths against replay, enumeration, injection, privilege, and data-integrity failures.
- Corrects expiry-date boundaries, domain-seat locking, manual Stripe sync, review eligibility, currency handling, plan limits, and multi-customer billing portal access.
- Removes customer email addresses from portal URLs and persistent browser cookies and applies private-cache/referrer protections to sensitive pages.
- Makes settings migration exclude credentials and environment-specific storage paths and makes uninstall/network cleanup deliberate and consistent.
- Updates first-run guidance, translation catalog, compatibility declarations, public documentation, and sanitized release screenshots.
- Stronger verification state. One-time codes and opaque flow tokens are stored as HMAC hashes in plugin-owned per-site tables. Each challenge is bound to its browser flow, expires quickly, enforces exact six-digit input and attempt/resend limits, and can authorize at most one delivered message through atomic state transitions.
- Bounded abuse handling. Atomic database-backed limits now cover source addresses, destination emails, global mail volume, widget opens, and message attempts. An hourly security task removes expired challenges and counters; a failed delivery releases the verified flow for a safe retry instead of silently consuming it.
- Precise customer recognition. Skipping the emailed code requires a signed-in WordPress account whose email exactly matches the address entered. Licensing mode additionally requires a currently active, non-expired Bodholdt license, checked again when the message is submitted. A known email address alone is never proof of identity.
- Safer request boundaries. Each public action has its own nonce, cached pages can refresh the complete nonce set, malformed non-scalar fields are rejected cleanly, and message length is validated rather than silently truncated.
- Safer delivery. A support ticket is considered delivered only after its first message is stored. If that partial write fails, direct-email fallback occurs only after the empty ticket is confirmed removed, preventing duplicate or orphaned customer conversations.
- Deliberate first run and upgrades. Fresh installations start with the widget hidden and weekly summary email off, then show a direct setup notice. Existing installations retain their prior live/hidden behavior and automatic reports even if they never opened the old settings page. In-place and automatic updates create required storage on the first request instead of waiting for an administrator visit.
- Operator controls that match the documentation. The settings page now exposes the weekly activity email and the private Fun Pass, sound, and confetti switches. Blank display copy falls back consistently in both the preview and live accessible dialog.
- Complete lifecycle support. Activation creates or upgrades per-site security storage and schedules cleanup; network activation covers existing sites and sites added later. Deactivation clears short-lived security state and scheduled tasks without deleting configuration. Uninstall removes this plugin's settings, owned tables, legacy verification remnants, scheduled tasks, and only its own rows from shared Bodholdt Arcade tables.
- Requires WordPress 6.5 or newer and PHP 8.0 or newer.
- Sturdier under odd input. The contact endpoints and the settings save now shrug off malformed requests (for example a field sent in the wrong shape) and return a normal validation response instead of erroring. This only ever affected hand crafted requests, never a real visitor or a normal save, but it keeps your error log clean.
- Precise multisite cleanup. On a multisite network, turning the plugin off on a single site now leaves the other sites' weekly report untouched; only a full network deactivation clears them all.
- Housekeeping. Trimmed a few unused entries from the "Working the Door" scoreboard so its catalog only lists rewards you can actually earn.
- Cleaner activity readout. The "last 7 days" line and the weekly email always show sensible figures now. Percentages stay between 0 and 100, the counts never read backwards, and the wording reads correctly even when a number is 1.
- Tidier multisite cleanup. On a multisite network, turning the plugin off now clears its scheduled weekly report on every site, leaving nothing behind.
- True open-rate. The activity summary now also counts how many people opened the widget, so you can see the whole funnel: opened, entered an email, and finished. It reports the overall share of opens that turned into a message, which tells you at a glance whether people are dropping off before they even start.
- See how your contact form is doing. The settings page now shows a short "last 7 days" activity line (how many people started, how many were sent a code, and how many finished after verifying), and you get an optional weekly email summary. This makes it easy to tell whether the email step is turning visitors away, so you can switch recognition mode if it is.
- Stronger proof before the code is skipped. A returning customer now skips the email code only when they are signed in to the matching account. A visitor who simply types a known customer's email address is asked to verify by code like anyone else. This closes a way someone could send you a message posing as one of your customers.
- Tougher on abuse. Verification codes are now capped per destination address as well as per sender, a valid code can be used only once even under a rapid burst of requests, and automated "bot" traffic is rate limited before it can touch anything. Together these bound spam and reduce the widget's usefulness for sending unwanted code emails to other people.
- Off means off. When you switch the widget off, its background endpoints stop responding too, not just the visible button.
- Accurate tallies. The "Working the Door" counts tick over only after a message is actually delivered, so your Door Report reflects reality even when mail is misconfigured.
- Polish. Very long messages are trimmed to a sensible length, the celebration animations stay within the screen, and the arcade labels are translatable (the shared level-up HUD badges stay in English, since a shared component cannot carry a fixed text domain).
- The code is checked the moment you enter it. When a visitor types their verification code and continues, the widget now confirms it right away, so a wrong or mistyped code is caught before they write their whole message instead of after.
- The widget keeps working on cached sites. If your pages are served from a cache and the security token in the page has gone stale, the widget quietly refreshes it and carries on, so the contact form no longer breaks with a "network error" on heavily cached sites.
- You are told when a code cannot be emailed. If your site cannot send the verification email (for example mail is not configured yet), the visitor now sees a clear "please try again in a few minutes" message instead of being stranded on a code screen with no code ever arriving. Submitted messages are handled the same way, so a message is never quietly lost.
- Clean removal. Deleting the plugin now removes its settings, its "Working the Door" tallies, and its rows in the shared arcade tables. The four shared `bod_arcade_*` tables and the `bod_arcade_db_version` option are deliberately left alone, because uninstall has no safe way to tell whether another Bodholdt plugin still needs them. If Contact was the only Bodholdt plugin on the site, those four tables stay behind empty and you can drop them yourself.
- Polish. The notification address now tells you if what you entered was not a valid email instead of silently ignoring it, the header, intro and success text show exactly what you typed, those fields gained sensible length limits, and the "Working the Door" operator text is translatable.
- The widget stays readable with any accent color. Button text and links now choose their color from the accent's real contrast, so a light accent (like a bright cyan) gets dark, legible text instead of washing out on the white card. The admin live preview reflects the same result.
- Working the Door. A calm, optional arcade for you, the operator. Because contact activity happens while you are away, the settings page now greets you with a Door Report of who you waved through, the strangers who verified, the bots you bounced, and the messages handled since your last visit, plus a rank and XP that grow as your door gets busier. It sits behind a Fun Pass switch (on by default, sound off) and stores everything in your own database.
- A clearer settings page and a preview you can walk through. The page now opens with a status card that answers "is my widget live and doing what I set up?" in plain sentences: whether it shows, where messages go, who skips verification, and the address you are notified at. The live preview steps through all three screens a visitor sees (email, then the 6-digit code, then the message and its success note), so the verification flow you configure is no longer invisible. On wide screens the form and preview sit side by side. Accent color gains curated swatches and a readability note, and the appearance and corner-style choices became tidy segmented controls.
- The verification step no longer dead-ends. If a visitor's code does not arrive or they typed the wrong address, they can now "Resend code" (with a short countdown that respects the anti-spam limit) or go back and fix their email. Running out of attempts now says so and offers a fresh code instead of failing silently. The opening line also explains why the email is asked for first.
- Added a dismissible panel on the settings page inviting you to turn contact messages into trackable Bodholdt Tickets when that plugin is not active. This mirrors the confirmation shown when it is active. Nothing about the widget changed.
- White-label appearance. The widget now offers Light, Dark, or Auto (match the visitor's system) display modes plus a corner-style choice, all derived from your single accent color with readable text and contrast shades computed automatically, so it blends into any site. The settings page got a matching refresh and the live preview reflects every change.
- WordPress.org readiness pass: added translator comments for placeholder strings, removed the manual text-domain load (WordPress loads translations automatically), and hardened a server-variable read. No change to how the widget behaves.
- Renamed the Bodholdt Tickets integration to its current name and refined the verification step layout. The email address and the "enter your code" instruction now sit on their own lines.
- Settings page now shows a live preview of the widget that updates as you change the accent color, header, and intro (§7.4 Steve Jobs pass).
- Brand consolidation: author byline + the License page's support email now use Bodholdt Labs / bodholdtlabs.com.
- Licensing + plans. Bodholdt Tickets is now a licensed product with a Free tier and paid Solo/Studio/Foundry plans. Enter your license key under Tickets → License to unlock your plan and receive automatic updates. The Free tier includes 1 agent and 25 tickets/month across email, the web form, and the customer portal. Solo adds the AI co-pilot, the embeddable cross-site widget, categories, gamification, and aggregate reports with CSV. Studio adds departments & routing plus the per-agent and per-department report breakdowns. Foundry removes all limits. Your desk keeps working if a license lapses. It falls back to Free-tier limits after a short grace period, never losing your data. (No database changes.)
- Bodholdt Tickets front-door. With a compatible Bodholdt Tickets release active, contact submissions can create a support ticket (and notify you by email) instead of a plain email, so customers can track and reply to them, and you work them in the Support Desk. If Tickets has categories, the widget shows a “What’s this about?” picker. Without a compatible Tickets API, it behaves exactly as before (emails you). All recognition + anti-spam unchanged.
- Reconfigured for distribution: renamed to Bodholdt Contact, added a multi-tenant settings page (brand name, accent color, copy, notification email, customer-recognition mode), made visitor-facing branding configurable, internationalized the interface (text domain `bodholdt-contact`), and packaged it for release. All anti-spam protections (one-time code, honeypot, rate limiting, brute-force lockout, timing-safe comparison) retained.
- Reporting & analytics. A new supervisor-only Reports view in the Support Desk surfaces what the desk already tracks: volume over time (created vs resolved + open backlog, sliced by channel, category, and department), speed & SLA (first-response and resolution times with median/avg/p90 and % within a target you choose), CSAT (average, the 1 to 5 spread, a daily trend, and breakdowns by agent and department), per-agent workload & outcomes, and the category/channel/tag mix. Pick a date range (7/30/90 days, this month, or custom) and export any report to CSV. Agents can opt out of the peer leaderboard from their stats panel (supervisors still see everyone in reports). Computed live from your data, with no setup required. (Adds reporting indexes, applied automatically on update.)
- Departments & routing. Group your agents into departments (Sales, Support, Billing…), then map each category to a department so incoming tickets auto-route to the right team. Set it all up under Tickets → Departments & routing, and tick which departments each agent belongs to. In the Support Desk, the department shows on every ticket, you can filter the queue by department (or “My departments”), and re-route a ticket by hand from the ticket header. Built to run real multi-team support out of the box; solo operators can simply leave it empty. (Adds an `assigned_group` column, applied automatically on update.)
- Categories. Define your own ticket categories (e.g. one per product, or Billing / General) under Ticketing settings; customers then pick “What’s this about?” on the front-end form and the embeddable widget, and you can filter the Support Desk queue by category. The category shows on the ticket and in the queue. (Adds a `category` column, applied automatically on update.)
- Onboarding. A new “Channels & setup” panel at the top of the Ticketing admin page. It shows a setup checklist (do you have a form page, a portal page, agents, email intake, the AI co-pilot?) and spells out every way customers can reach you: the form + portal shortcodes (with “view your page” links), pointers to the widget + email, and a one-click “Create the support pages for me” button. Makes it obvious how to put ticket entry on the front end.
- Phase 4 (polish): a customer-facing pass on the submission form, customer portal, and embeddable widget. Delightful success states (an animated checkmark + warm copy) when a request is sent or a sign-in link is on its way; the widget now has a friendly chat-bubble launcher, properly labeled fields, focus-on-open, and closes on Escape; consistent look across all three. Accessibility + micro-interaction polish; no functional change to ticket handling.
- Phase 4 (packaging): a distribution-ready build. Adds a `build.sh` that produces a clean customer/WordPress.org ZIP (ships only the compiled Support Desk bundle, never the React source or build tooling), directory-index hardening (`index.php` silence files), a translation template, and a polished readme. No behavior change for existing installs.
- Phase 3: gamification. The desk now plays like a game: agents earn XP for first responses, resolutions, and good CSAT; XP drives levels (with a progress bar), daily streaks, an all-time rank, a weekly + all-time leaderboard, and unlockable achievements. A stats chip sits in the Support Desk top bar; clicking it opens a leaderboard + achievements panel, and a satisfying “+XP” toast pops whenever you earn points. (Adds a bt_xp table, created automatically on update.)
- Phase 2.3: the embeddable cross-site widget. Paste a small snippet on ANY external website and a floating “Contact support” button appears; visitors file a ticket without leaving the page. The widget UI is isolated in a shadow DOM (host-site CSS can’t interfere), and submissions post cross-origin to a token-gated endpoint with an optional origin allowlist + honeypot + rate limit, landing on the “widget” channel. Configure + copy the snippet under Tickets → Embeddable widget.
- Phase 2.2: the customer portal. Add the [bodholdt_portal] shortcode to a page and customers can view, track, and reply to their own tickets. Works for logged-in WordPress users (uses their account email) and for customers without an account via a passwordless magic-link sign-in (enter email → receive a secure, single-use link → a 7-day session). Every view is strictly scoped to the signed-in customer’s email; internal notes and AI drafts are never shown. Magic-link requests are honeypot- and rate-limited and never reveal whether an email exists.
- Phase 2.1: the front-end submission form. Drop the [bodholdt_support_form] shortcode on any page and customers can file a ticket from your site (pre-filled for logged-in users). New tickets land in the desk on the “form” channel and flow into the same pipeline as email (auto-triage/draft if the co-pilot is on). Posts to a public REST endpoint protected by a honeypot + per-IP rate limit + validation; a clean, self-contained card that fits any theme; on-screen confirmation with the ticket reference.
- Phase 1.3: thread summarize. A “✨ Summarize” button in the ticket header gives agents a one-click internal TL;DR for picking up or handing off a conversation: what the customer needs, what’s happened, current status, and the recommended next step. Includes internal notes for full context; shown in a dismissible banner above the thread; never sent to the customer.
- Phase 1.2: the self-organizing desk. With Auto-pilot on (AI Co-pilot settings), every new ticket is analyzed by Claude the moment it arrives. In one call it sets the priority, adds topic tags, and pre-writes a reply that's waiting in the composer behind the “review before sending” ribbon when the agent opens the ticket. Tags show in the ticket header. Drafts are kept out of the visible conversation, generated at most once per ticket, and discarded once the agent sends. Analysis runs on a background job so inbound email stays fast; nothing is ever sent without a human.
- Phase 1: the AI co-pilot (BYOK Claude). Agents click “Draft with AI” in the Support Desk and Claude drafts a reply using the ticket thread, the customer’s license context, and your brand voice + knowledge base. Drafts land in the composer under a “review & edit before sending” ribbon. A human always reviews and sends; nothing goes out automatically. Bring your own Anthropic API key (stored encrypted at rest); pick the model (defaults to Claude Opus 4.7); set brand voice + a knowledge base in Tickets → AI Co-pilot, with a one-click connection test. The stable system prompt (voice + KB) is prompt-cached for speed + cost across drafts.
- Phase 0.4: email channel + configuration console (closes Phase 0). Outbound: agent replies email the customer via the site’s mail/SMTP, with a [#BT…] subject tag so their reply threads back. Inbound: a token-secured webhook endpoint (no IMAP needed) that any inbound-parse service (Postmark/Mailgun/SendGrid) or server forward can POST email to. New mail opens a ticket, replies thread by the subject tag, and quoted reply tails are trimmed. Console: a wp-admin page to set the desk name, from-name/email, enable in/out email, view + rotate the inbound webhook URL, and grant/revoke agent access. The core engine (license-aware tickets + REST API + Agent Support Desk + email + admin) is now complete; next up is the AI co-pilot.
- Phase 0.3: the Agent Support Desk. A chrome-less, full-page React app at /support-desk/ (agent-gated) where agents work tickets. Tier-colored, triage-sorted queue (Open/Mine/All/Resolved + search); a conversation thread with distinct customer / agent / internal-note styling; a reply composer (with internal notes + ⌘↵ to send); assign + status + one-click Resolve; and a license-aware customer panel showing the customer's Bodholdt Licensing tier, active licenses, sites, and renewal inline. Built with React + Vite (bundle in assets/desk/). Cyberpunk-dark, matches the Labs catalog.
- Phase 0.2: the `bt/v1` REST API (tickets list/get/create/reply, status, assign, csat, plus /me and /agents; all gated on the bt_agent capability) and the license-aware customer lookup that pulls a customer's Bodholdt Licensing tier, products, active licenses, and nearest expiry into every ticket. This is the spine the Agent Support Desk front-end (0.3) will talk to.
- Phase 0.1: the initial scaffold. Plugin bootstrap, database schema (tickets, messages, attachments, tags, canned replies, activity log), and capabilities (bt_agent / bt_supervisor / bt_admin). Not yet feature-complete; activation creates the schema and a status page in the admin.