=== SwissSuite AI ===
Contributors: swisswpsecure
Tags: security, backup, malware scanner, firewall, two-factor authentication
Requires at least: 6.2
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 2.9.30.144
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

All-in-one WordPress security plugin. Malware scanner, firewall, 2FA, site backup, migration, and AI SEO — one plugin, zero bloat.

== Description ==

SwissSuite AI is an all-in-one WordPress security plugin that bundles a malware scanner, web application firewall, two-factor authentication, scheduled site backup, site migration, and AI-powered SEO tools into a single install. One plugin. One settings screen. No add-ons to chase.

Most sites end up with five plugins doing what one plugin should do — a security plugin, a backup plugin, a migration plugin, an SEO plugin, and a cache plugin. Every extra plugin is another auto-update, another DB table, another performance hit, another attack surface. SwissSuite replaces the security, backup, migration, and SEO layer with one tightly integrated codebase.

[youtube https://www.youtube.com/watch?v=PLACEHOLDER]
<!-- TODO: Replace PLACEHOLDER with real YouTube video ID after recording -->

= Sentinel Security =
* Malware scanner with 38+ detection patterns plus optional AI deep analysis (Groq-powered)
* Web Application Firewall with SQL injection, XSS, and path traversal blocking
* IP reputation and rate limiting with admin IP safelist
* 11 one-click WordPress hardening options (XML-RPC, file editing, user enumeration, REST API, application passwords, and more)
* Two-Factor Authentication (TOTP) for every user role — works with Google Authenticator, Authy, 1Password
* Geo-blocking with country-level allow and deny rules
* Real-time email alerts and daily security report
* Vulnerability lookups via WPScan and Patchstack (bring your own API key)

= Backup Fortress =
* Full WordPress backup (files + database) with hybrid zip engine — pure PHP, no shell exec
* Scheduled site backup with rolling retention and auto-prune
* Cloud destinations: Google Drive, AWS S3, Backblaze B2, Dropbox
* One-click restore with serialized-string-safe domain replacement
* Optional AES-256 encryption-at-rest for backup archives
* Adaptive health check that adjusts to slow shared hosts instead of killing in-progress jobs

= Sync Teleport =
* Two-way content sync between WordPress sites (staging ↔ production)
* HMAC-signed encrypted transport — no plaintext credentials cross the wire
* Smart diff comparison before any change is written
* Selective push: posts, products, media, FSE templates

= Migration Station =
* Mode A: plugin-to-plugin migration when both sites have SwissSuite installed
* Mode B: standalone receiver script for migrating to an empty or broken destination
* Serialization-safe domain replacement (handles serialized arrays and JSON-in-meta)
* Chunked transfer tuned for shared hosting (Hostinger, SiteGround, IONOS)
* Post-migration verification step that confirms site URL, theme, and plugin count

= AI SEO & Content =
* Bulk meta title and description generation
* AI content rewriting and tone control
* Vision AI for automatic image alt text
* XML sitemap generator with custom post type support
* On-page SEO audit and score
* llms.txt generator so AI crawlers can find your authoritative content

= Why SwissSuite? =

**vs Wordfence:** Wordfence is security-only. You still need a separate backup plugin (UpdraftPlus, BlogVault), a separate migration plugin (Duplicator, All-in-One WP Migration), and a separate SEO plugin (Yoast, RankMath). That's four plugins, four update channels, four monthly costs. SwissSuite covers all four layers in one install.

**vs UpdraftPlus:** UpdraftPlus is backup-only. It does not scan for malware, does not provide a firewall, does not handle 2FA, and has no SEO tools. SwissSuite includes a full backup engine plus everything UpdraftPlus does not.

**vs Yoast / RankMath:** Yoast and RankMath are SEO-only. They cannot detect a hacked site, cannot back up your content before an algorithm penalty, and cannot block a brute-force attack on your admin login. SwissSuite includes AI-powered SEO plus the security layer that protects your rankings.

= Perfect for =

* **Freelancers** managing 5-50 client sites who do not want to install and configure five plugins per site
* **Agencies** that need a single security and backup standard across an entire portfolio
* **WooCommerce stores** that need PCI-friendly security plus reliable nightly backups
* **High-traffic blogs** that cannot afford downtime from a hack or a botched plugin update
* **Site owners** who would rather pay for one plugin than five

= Privacy & Data =

SwissSuite does not phone home on install. No background telemetry. External services are contacted only when you explicitly enable them (cloud backup, AI analysis, vulnerability lookup, geo-blocking). Every external service is disclosed below.

== Installation ==

1. In WordPress Admin, go to Plugins → Add New → Upload Plugin.
2. Upload the SwissSuite AI zip and click Install Now.
3. Activate the plugin.
4. Open the SwissSuite menu in the WordPress sidebar.
5. Click "Get Free License" on the License tab — enter your email and the plugin auto-provisions a free license locked to your domain.
6. Run your first malware scan from the Security Hub → Scan tab.

= Minimum Requirements =

* WordPress 5.6 or higher
* PHP 7.4 or higher
* HTTPS recommended for two-factor authentication

== Frequently Asked Questions ==

= Is SwissSuite AI free? =

Yes. The free tier includes daily malware scans, the web application firewall, 5 hardening options, two-factor authentication, and the on-page SEO audit. You do not need a credit card to get started. Paid tiers unlock advanced features like cloud backup, site migration, AI content rewriting, and the deep AI security audit.

= How do I block countries in WordPress? =

Open SwissSuite → Security Hub → Geo-Blocking. Pick "Block list" mode and select the countries you want to deny. The list is enforced at the firewall layer before WordPress loads, so blocked countries cannot brute-force your login page or hit your REST API. You can also use "Allow list" mode to restrict access to a single country (useful for staging sites).

= What is the best WordPress 2FA plugin? =

If you already use SwissSuite for security, the built-in TOTP two-factor authentication is the simplest answer — no extra plugin to install, no compatibility risk between the WAF and the 2FA layer. It works with Google Authenticator, Authy, 1Password, Bitwarden, and any other TOTP app. Enable it from Security Hub → Two-Factor Authentication and scan the QR code with your authenticator.

= How do I scan my WordPress site for malware? =

Open SwissSuite → Security Hub → Scan tab. You have three scan types: Quick Scan (local signature check, fast, free), AI Security Audit (configuration and integrity audit, daily auto-scan, free), and Deep Malware Scan with AI (file hashes checked against MalwareBazaar plus AI analysis, Pro tier). The first scan typically takes 30-90 seconds depending on site size.

= Does this replace Wordfence? =

Yes. SwissSuite includes everything Wordfence does — malware scanner, firewall, login protection, two-factor authentication, country blocking — and adds backup, migration, and SEO that Wordfence does not have. If you are running Wordfence and a separate backup plugin and a separate SEO plugin, SwissSuite is a one-for-three swap.

= How do I back up my WordPress site automatically? =

Open Settings → Backup → Schedule. Pick a frequency (hourly, daily, weekly) and a retention count. Optionally connect a cloud destination (Google Drive, S3, B2, or Dropbox) under Settings → Backup → Cloud. The backup cron runs unattended; you can check the last completion time on the Dashboard.

= Can I migrate my WordPress site without manual SQL edits? =

Yes. SwissSuite handles serialized string replacement automatically — no need to run wp-cli search-replace or hand-edit the SQL dump. Use Mode A if the destination site already has SwissSuite installed. Use Mode B if the destination is empty or broken: the plugin generates a standalone receiver script you upload to the destination, then push the migration.

= What AI features are included in the free version? =

The AI Security Audit runs daily on the free tier at zero token cost (Layer 1 is signature-based, not AI). The on-page SEO audit and XML sitemap generator are free. AI-powered features that consume tokens — deep malware analysis, bulk SEO meta generation, content rewriting, image alt text — are gated to paid tiers. Free accounts include 50,000 tokens per month for occasional AI use.

= Is SwissSuite compatible with WooCommerce? =

Yes. The firewall has an explicit allowlist for WooCommerce REST routes (wc/v3, wc/store/v1, wc/store/v2, wc-analytics/v1, wc-admin/v1, wc-auth/v1) so cart, checkout, and the Store API work normally even with hardening enabled. The backup engine handles WooCommerce-specific tables (orders, customers, sessions) and the sync layer pushes products between staging and production.

= How many sites can I use one license on? =

Each license key is locked to one domain. For multi-site management, contact support — agency tiers are available with discounted per-site pricing. The free license is also domain-locked, so you can run a free install on every site you manage at no cost.

== Screenshots ==

1. Security Hub dashboard — threat count, scan status, and hardening score at a glance.
2. Malware scan results — file list with threat classifications and inline AI analysis.
3. Hardening options — 11 one-click security toggles, most enabled.
4. Backup Fortress — backup list with Google Drive and S3 cloud status indicators.
5. AI SEO tools — bulk meta optimisation table with AI-generated suggestions.

== External Services ==

This plugin connects to the following external services. No data is transmitted unless you initiate an action that requires it.

= SwissSuite Command Center (api.swisswpsecure.com) =
Used for: License key validation, AI request proxying, token balance sync, and Deep Malware Scan hash lookups.
Data sent: Your license key and AI scan request payloads. Your site domain is sent in an X-Domain header on every request to api.swisswpsecure.com for license verification (the server uses it to confirm the key is active for your domain). During the Deep Malware Scan (Pro license required), SHA-256 hashes of PHP files on your site are sent to api.swisswpsecure.com/v1/scan/batch to check them against a malware signature database (sources: URLhaus, MalwareBazaar). File contents are never transmitted, and hashes are not logged per-site.
This service is only contacted after you enter a license key — the plugin does not phone home on a fresh install with no key.
Privacy Policy: https://swisswpsuite.com/privacy-policy
Terms of Service: https://swisswpsuite.com/terms-of-service

= Groq AI API (proxied via swisswpsecure.com) =
Used for: Malware pattern analysis, AI content enhancement, vision AI for automatic alt text generation.
Data sent: File content snippets, URLs, or post content — only when you explicitly trigger an AI-powered action (e.g. "Analyze with AI", bulk SEO meta generation, alt text generation).
No background data collection or tracking.
Groq Privacy Policy: https://groq.com/privacy-policy

= Google Drive / Google OAuth =
Host: googleapis.com, accounts.google.com, oauth2.googleapis.com, www.googleapis.com
Used for: Optional Google Drive backup destination (upload/download/list backup archives) and OAuth 2.0 authorization.
Data sent: Backup archive contents (your site files + database export, only when you click "Upload to Google Drive"), OAuth refresh/access tokens, file metadata (name, size).
When contacted: Only after you connect a Google account under Settings → Backup → Cloud → Google Drive and trigger or schedule a backup upload. Not contacted on a fresh install or if Google Drive is not configured.
Privacy Policy: https://policies.google.com/privacy
Terms of Service: https://policies.google.com/terms

= Backblaze B2 Cloud Storage =
Host: api.backblazeb2.com (and per-bucket upload hosts returned by the B2 API, e.g. *.backblazeb2.com)
Used for: Optional Backblaze B2 backup destination (upload/download/list backup archives).
Data sent: Backup archive contents (your site files + database export, only when uploading), B2 application key ID + application key (sent in the authorization request only), bucket/file metadata.
When contacted: Only after you enter B2 credentials under Settings → Backup → Cloud → Backblaze B2 and trigger or schedule a backup upload. Not contacted on a fresh install or if B2 is not configured.
Privacy Policy: https://www.backblaze.com/company/policies.html
Terms of Service: https://www.backblaze.com/company/policies.html

= Dropbox =
Host: api.dropboxapi.com, content.dropboxapi.com
Used for: Optional Dropbox backup destination (upload/download/list backup archives).
Data sent: Backup archive contents (your site files + database export, only when uploading), Dropbox OAuth access token, file metadata.
When contacted: Only after you connect a Dropbox account under Settings → Backup → Cloud → Dropbox and trigger or schedule a backup upload. Not contacted on a fresh install or if Dropbox is not configured.
Privacy Policy: https://www.dropbox.com/privacy
Terms of Service: https://www.dropbox.com/terms

= Amazon S3 / S3-compatible storage =
Host: s3.amazonaws.com, regional AWS S3 endpoints, or a custom S3-compatible endpoint you configure.
Used for: Optional Amazon S3 (or S3-compatible) backup destination (upload/download/list backup archives).
Data sent: Backup archive contents (your site files + database export, only when uploading), your S3 access key ID + secret key (used to sign requests), and bucket/object metadata.
When contacted: Only after you enter S3 credentials under Settings → Backup → Cloud → Amazon S3 and trigger or schedule a backup upload. Not contacted on a fresh install or if S3 is not configured.
Privacy Policy: https://aws.amazon.com/privacy/
Terms of Service: https://aws.amazon.com/service-terms/

= FTP / SFTP backup destination (user-specified server) =
Host: The remote server address you provide. This is not a fixed third-party service — the destination is entirely under your control.
Used for: Optional upload of backup archives to a remote FTP/SFTP server whose address and credentials you provide.
Data sent: Backup archive contents (your site files + database export) to the host you specify, only when a backup upload runs.
When contacted: Only after you enter FTP/SFTP details under Settings → Backup → Cloud and trigger or schedule an upload. Not contacted on a fresh install or if no FTP/SFTP destination is configured.

= WPScan Vulnerability Database API =
Host: wpscan.com (https://wpscan.com/api/v3/)
Used for: Optional vulnerability lookup of installed plugin/theme slugs + versions during deep malware scans.
Data sent: Plugin/theme slugs and version numbers of components installed on your site (no file contents, no PII), and the WPScan API key you provided.
When contacted: Only when you provide a WPScan API key under Settings → Security → Vulnerability Feeds AND a deep scan or vulnerability sweep runs. Not contacted if no API key is configured.
Privacy Policy: https://wpscan.com/privacy/
Terms of Service: https://wpscan.com/terms-of-service

= Patchstack Vulnerability Database API =
Host: api.patchstack.com (https://api.patchstack.com/)
Used for: Optional vulnerability lookup of installed plugin/theme slugs + versions during deep malware scans.
Data sent: Plugin/theme slugs and version numbers of components installed on your site (no file contents, no PII), and the Patchstack API key you provided.
When contacted: Only when you provide a Patchstack API key under Settings → Security → Vulnerability Feeds AND a deep scan or vulnerability sweep runs. Not contacted if no API key is configured.
Privacy Policy: https://patchstack.com/privacy-policy/
Terms of Service: https://patchstack.com/terms-of-service/

= ipwho.is (IP geolocation) =
Host: ipwho.is (https://ipwho.is/)
Used for: Determining the country of a visitor's IP address for the optional Geo-Blocking security feature, and only as a fallback when a Cloudflare country header is not already present.
Data sent: The visitor's IP address (sent to resolve its country). No other data, no site content, no API key. The resolved country code is cached locally on your site for 7 days; the IP itself is not stored by us or retained per-request.
When contacted: Only when Geo-Blocking is enabled AND the visitor's country is not already supplied by Cloudflare AND the result is not already cached. Private/reserved IPs are never sent. Not contacted if Geo-Blocking is disabled.
Legal basis (EU/UK/CH site owners): legitimate interest in network and information security (GDPR Art. 6(1)(f), Recital 49).
Privacy Policy: https://ipwho.is/ (review the provider's terms before enabling)

= WordPress.org APIs =
Host: api.wordpress.org
Used for: Core file checksum verification (to detect modified or infected WordPress core files) and plugin/theme metadata lookups during vulnerability scans.
Data sent: WordPress version number (for checksum requests), plugin/theme slugs and version numbers (for metadata lookups). No personal data or site content is sent.
When contacted: Only when you run a security scan that includes core file integrity checking. Not contacted on page load or without a user-initiated scan.
Privacy Policy: https://wordpress.org/about/privacy/

For full details on what data is transmitted and your rights, see our Privacy Policy linked above.

== Upgrade Notice ==

= 2.9.30.93 =
Critical fix: archive scan was restarting from scratch on every recovery tick instead of resuming from where it stopped. Sites with 50K+ files on overloaded shared hosting would burn all 5 scan attempts and circuit-break. Mandatory update for users experiencing repeated scan failures on large sites.

= 2.9.30.92 =
Critical fix: backup was re-archiving its own previous backup zips on every run, causing exponential size growth. Mandatory update for all users.

= 2.9.30.91 =
Major backup engine reliability update. The engine now self-tunes to your hosting environment: detects host tier on first run, adapts files-per-tick and tick budget after each job, and handles overloaded shared servers automatically. Recommended for all users.

= 2.9.30.90 =
Restores scheduled backup cron after a regression that silently stopped automated backups, and corrects the "last backup" time display for UTC+ timezones. Recommended for all users with backup automation enabled.

== Changelog ==

= 2.9.30.144 =
* Fixed: The Plugin URI and Author URI in the plugin header were identical; the Plugin URI now points to the plugin's own resource page so the two are distinct (clears the WordPress.org "Plugin and author URIs are the same" upload error).

= 2.9.30.143 =
* Fixed: Corrected two remaining text strings that used the plugin's old text domain, so all translations now resolve under the current `swisssuite-ai` domain (clears the last WordPress.org Plugin Check errors).
* Compliance: The Privacy & Data summary now lists Geo-Blocking alongside the other features that may contact an external service, matching the detailed External Services disclosure.

= 2.9.30.142 =
* Compliance: Disclosed three additional external services in the External Services section — ipwho.is (IP geolocation used by Geo-Blocking as a Cloudflare fallback), Amazon S3 / S3-compatible storage, and FTP/SFTP backup destinations — for full WordPress.org and GDPR transparency.
* Privacy/Fixed: Removed a Google Fonts hotlink that shipped inside an unused build template file. Fonts were never actually loaded at runtime, but the reference is now stripped from the distributed package so no visitor IP can reach Google Fonts.
* Housekeeping: Internal developer documentation is no longer bundled in the distributed plugin zip.

= 2.9.30.141 =
* Fixed: SEO title and meta tags now reliably appear on your live pages. The plugin's SEO output now runs late enough to win over a theme's own hardcoded title, using the highest hook priority.
* Added: Automatic SEO plugin conflict handling. If you run a dedicated SEO plugin (Yoast, Rank Math, All in One SEO, SEOPress, The SEO Framework), SwissSuite AI now steps aside to avoid duplicate tags and shows a notice explaining why. Generic SEO tags injected by host-bundled plugins (e.g. Hostinger AI Assistant) are automatically overridden so your optimized tags take precedence.

= 2.9.30.140 =
* Fixed: The "Manage Billing" link on the License screen was broken for every customer — it now opens a real Stripe billing portal session instead of a dead link.
* Added: The plugin now recognizes whether a license was purchased through Stripe or issued manually (e.g. a support-granted license), and only shows Stripe billing actions when they will actually work — manually-issued licenses see a "contact support" notice instead of a broken button.

= 2.9.30.139 =
* Improved: License actions (change renewal type, cancel/resume auto-renewal) now always show a clear, plain-English result — either a success confirmation or a specific error message — instead of ever failing silently.

= 2.9.30.138 =
* Fixed: Restoring a backup no longer removes your license. Backup restore now preserves and re-applies your license key, status, and site identity, so a restored site keeps its plan and AI tokens instead of dropping to the free tier.
* Fixed: The License screen now updates your token balance, per-feature bars, and license status as soon as it loads — no page refresh needed.
* Changed: "Tokens Used" now counts every AI operation this billing period (including Sentinel deep scans and batch jobs), and is relabeled "Tokens Used (This Period)".

= 2.9.30.137 =
* Fixed: WAF threat logging now self-heals when the security_logs database table is missing (e.g., after a messy reinstall or manual cleanup). Previously the WAF blocked requests correctly (returning 403) but silently failed to record them — the Threats Blocked counter stayed at zero. The table is now recreated automatically on the first blocked request, and any future insert failure is logged to the plugin diagnostics.

= 2.9.30.136 =
* Added: Per-feature token balances — à-la-carte licenses now show each feature's own token balance (Security / SEO / Content) beneath its renewal date, so you can see exactly what's left per feature.
* Fixed: Full-suite (SwissSuite) licenses now show their included features (Backup, Security, SEO, Content) sharing one token pool, instead of an empty Feature Subscriptions section.
* Changed: The "Upgrade to Annual" button is now clearly labeled (was a confusing "↑ Annual").

= 2.9.30.135 =
* Fixed: Removed the cross-domain "Total Across Licenses" pooled token display. A license bound to a different site could appear in this site's token total, which was misleading because tokens are spent per-site. The License screen now shows only this site's balance.

= 2.9.30.134 =
* Changed: Groundwork for per-feature token tracking — AI and security-scan requests now record which feature they belong to (Security, SEO, Content, Backup) so usage and limits can be tracked per feature. How tokens are spent is unchanged until the matching server update is live.
* Added: Clearer messages when a specific feature runs out of tokens, plus a prompt to update the plugin if the server expects a newer version.

= 2.9.30.133 =
* Fixed (critical security): The firewall (WAF) could silently stop protecting your site after the plugin loaded with geo-blocking available. A startup ordering bug caused the security module to abort before the firewall switched on — with no visible error — so attacks were no longer blocked or logged. The firewall, geo-blocking, hardening and other protections now initialise reliably on every request.

= 2.9.30.132 =
* Added: Cancel auto-renewal — each feature subscription on the License screen now has a "Cancel renewal" button. Your access continues until the paid period ends; it just won't renew. A "Resume" button turns auto-renewal back on.
* Added: Shared-subscription safety — if several features are billed on one subscription, cancelling shows exactly which features will be affected and asks you to confirm before stopping them all.
* Added: Expiry badges — feature subscriptions now show a "days left" badge (yellow within 14 days, red within 3) and read "Cancels on {date}" instead of "Renews on {date}" once auto-renewal is off.

= 2.9.30.131 =
* Changed: When you hold more than one license, the main token counter now shows your combined (pooled) balance across all licenses, with the per-site spendable balance shown as a secondary line.
* Fixed (billing): A single feature's failed or cancelled payment no longer downgrades the other features on the same license; each feature now renews and expires independently.
* Fixed (admin): The management dashboard now shows each license's owner name/email and a per-feature breakdown (status, expiry, token limit).

= 2.9.30.130 =
* Added: "Total available tokens" view — the license screen now shows your combined token balance across all licenses on your account (shown when you hold more than one license).
* Fixed: A refunded or cancelled license could be silently re-activated on a new site; revoked licenses are now correctly rejected.
* Fixed: Refund processing failed silently for some purchases; refunds now correctly mark the affected license.

= 2.9.30.129 =
* Fixed: Amazon S3 (and S3-compatible) cloud backups of files larger than 10 MB failed with a "SignatureDoesNotMatch" error. The multipart upload signature is now AWS Signature V4 compliant, restoring large-file S3 backups.

= 2.9.30.128 =
* Fixed: Google Drive / Dropbox cloud backup connection failed with "Sorry, you are not allowed to access this page" after authorizing — the post-consent redirect now targets the current admin menu slug.
* Changed: extended the cloud-OAuth nonce lifetime from 30 to 60 minutes so slower consent flows no longer expire mid-authorization.
* Changed: removed an unused legacy OAuth callback handler (dead code cleanup; no user-facing behavior change).

For the full version history (every release from v2.9.0 to current), see CHANGELOG.md in the plugin folder or visit https://github.com/Gfellerman/SwisswpSuite_Public/blob/main/CHANGELOG.md
