From 827ac3b372aaeae2b70478ae14b46543a52c65a4 Mon Sep 17 00:00:00 2001
From: Ben Kalsky
Date: Sat, 26 Sep 2026 15:30:09 +0300
Subject: [PATCH 1/4] =?UTF-8?q?release:=20SiteAgent=202.22.0=20=E2=80=94?=
=?UTF-8?q?=20the=20install=20ledger=20(P6.3=20phase=202)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-Authored-By: Claude Opus 5.5 (1M context)
---
README.md | 8 +++++++-
digitizer-site-worker/digitizer-site-worker.php | 4 ++--
digitizer-site-worker/readme.txt | 6 +++++-
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 4a43633d..b3a973b3 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@
-
+
---
@@ -239,6 +239,12 @@ These plug straight into **Aura's Fleet MCP Gateway**: read tools run on demand,
## Changelog
+### 2.22.0
+
+- **An install ledger** (Digitizers/Aura spec 2026-09-21 §4, P6.3 phase 2). New `Aura_Worker_Install_Ledger` observes the upgrader for plugin and theme runs only — a per-run token in `hook_extra`, `upgrader_pre_download` at `PHP_INT_MAX`, the entry at `upgrader_install_package_result` — and records and never decides. Each entry: when, type, action, slug, version (the main file), transport (`siteagent` for SiteAgent's own upgrader object, `wp_cli`, `auto_update` only inside core's `wp_maybe_auto_update` — never the upgrader skin, `cron`, `rest`, `wp_admin`), user id, auth, the application password's name (never its uuid), REST route, and the package source (`wporg`, `uploaded_zip`, `remote_host` + host, `local_path`, `unknown`). (#139)
+- **Storage that only under-claims.** A ring of 200 entries / 90 days in two non-autoloaded options (network options on multisite), purged physically on read and daily (`wp_scheduled_delete`); every stored row is validated; unreadable storage answers `ledger_unreadable` and is recovered behind a coverage boundary; writes are ordered and read back so an interruption can only shorten `since`. Reactivation restarts coverage; a network where SiteAgent is not network-active answers `ledger_partial_network`. (#139)
+- **`audit_agent_code` reports it as `installs`** — `{ since, entries, total, evicted }` — consumed by Aura's `agent_installed_package` grading. Uninstall removes the network rows. `user_id`, the password name and the route are personal data kept by owner decision, bounded as above. (#139)
+
### 2.21.0
- **The approval queue sees elementor-mcp writes' rule verdicts.** `tools/preview` answers a name its own registry does not know by asking elementor-mcp ≥ 1.38.0's `Elementor_MCP_Governance::declare_touches()` (Digitizers/Aura#586) — exactly the touches the fork's early rules gate judges — with `_mcpPath` removed, and returns `{success, supported: false, preview: null, touches, rule_match}`. Fail-closed: no fork, an older fork, a throw, a malformed answer or touch, or a declaration of nothing (a dry run) answer `Unknown tool` as before. (#137)
diff --git a/digitizer-site-worker/digitizer-site-worker.php b/digitizer-site-worker/digitizer-site-worker.php
index 9d0fa248..1014d65a 100644
--- a/digitizer-site-worker/digitizer-site-worker.php
+++ b/digitizer-site-worker/digitizer-site-worker.php
@@ -3,7 +3,7 @@
* Plugin Name: SiteAgent for Aura
* Plugin URI: https://my-aura.app/siteagent
* Description: Remote site management agent for Aura dashboard. Enables secure updates, health monitoring, and maintenance operations via REST API.
- * Version: 2.21.0
+ * Version: 2.22.0
* Requires at least: 6.2
* Requires PHP: 7.4
* Author: Digitizer
@@ -18,7 +18,7 @@
exit;
}
-define( 'AURA_WORKER_VERSION', '2.21.0' );
+define( 'AURA_WORKER_VERSION', '2.22.0' );
define( 'AURA_WORKER_FILE', __FILE__ );
define( 'AURA_WORKER_DIR', plugin_dir_path( __FILE__ ) );
diff --git a/digitizer-site-worker/readme.txt b/digitizer-site-worker/readme.txt
index 818c8469..62430cfc 100644
--- a/digitizer-site-worker/readme.txt
+++ b/digitizer-site-worker/readme.txt
@@ -4,7 +4,7 @@ Tags: ai, automation, maintenance, updates, wordpress management
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
-Stable tag: 2.21.0
+Stable tag: 2.22.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -253,6 +253,10 @@ Yes. SiteAgent is open source under the GPLv2 or later license. The source code
== Changelog ==
+= 2.22.0 =
+* New: an install ledger. Every plugin and theme install or update is recorded with how it arrived (wp-admin, REST, WP-CLI, cron, a WordPress auto-update, or SiteAgent itself), which user and application password, and where the package came from, so Aura can flag packages an AI agent installed. It only observes; it never blocks an install. Nothing to configure.
+* Privacy: each record keeps the user ID, the application password's name (never the password) and the REST route. Records are kept at most 90 days or 200 installs, are not autoloaded, and are deleted when the plugin is uninstalled.
+
= 2.21.0 =
* The Aura approval queue now shows whether an operator rule would block or warn about an Elementor design change made through the elementor-mcp plugin (1.38.0 or later), before anyone approves it. Nothing runs when the queue asks. No new settings.
From a42ea333b3d0fa5ada250c6e30212a7bc861fd46 Mon Sep 17 00:00:00 2001
From: Ben Kalsky
Date: Sat, 26 Sep 2026 15:33:44 +0300
Subject: [PATCH 2/4] =?UTF-8?q?release:=20Codex=20on=20#140=20=E2=80=94=20?=
=?UTF-8?q?the=2090-day=20retention=20holds=20while=20the=20plugin=20is=20?=
=?UTF-8?q?active;=20say=20so?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-Authored-By: Claude Opus 5.5 (1M context)
---
README.md | 2 +-
digitizer-site-worker/readme.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index b3a973b3..3834ebcd 100644
--- a/README.md
+++ b/README.md
@@ -243,7 +243,7 @@ These plug straight into **Aura's Fleet MCP Gateway**: read tools run on demand,
- **An install ledger** (Digitizers/Aura spec 2026-09-21 §4, P6.3 phase 2). New `Aura_Worker_Install_Ledger` observes the upgrader for plugin and theme runs only — a per-run token in `hook_extra`, `upgrader_pre_download` at `PHP_INT_MAX`, the entry at `upgrader_install_package_result` — and records and never decides. Each entry: when, type, action, slug, version (the main file), transport (`siteagent` for SiteAgent's own upgrader object, `wp_cli`, `auto_update` only inside core's `wp_maybe_auto_update` — never the upgrader skin, `cron`, `rest`, `wp_admin`), user id, auth, the application password's name (never its uuid), REST route, and the package source (`wporg`, `uploaded_zip`, `remote_host` + host, `local_path`, `unknown`). (#139)
- **Storage that only under-claims.** A ring of 200 entries / 90 days in two non-autoloaded options (network options on multisite), purged physically on read and daily (`wp_scheduled_delete`); every stored row is validated; unreadable storage answers `ledger_unreadable` and is recovered behind a coverage boundary; writes are ordered and read back so an interruption can only shorten `since`. Reactivation restarts coverage; a network where SiteAgent is not network-active answers `ledger_partial_network`. (#139)
-- **`audit_agent_code` reports it as `installs`** — `{ since, entries, total, evicted }` — consumed by Aura's `agent_installed_package` grading. Uninstall removes the network rows. `user_id`, the password name and the route are personal data kept by owner decision, bounded as above. (#139)
+- **`audit_agent_code` reports it as `installs`** — `{ since, entries, total, evicted }` — consumed by Aura's `agent_installed_package` grading. Uninstall removes the network rows. `user_id`, the password name and the route are personal data kept by owner decision, bounded as above — while the plugin is active; a deactivated SiteAgent runs no purge, so its rows stay until reactivation (which purges on the next read or daily pass) or uninstall. (#139)
### 2.21.0
diff --git a/digitizer-site-worker/readme.txt b/digitizer-site-worker/readme.txt
index 62430cfc..0eafee7e 100644
--- a/digitizer-site-worker/readme.txt
+++ b/digitizer-site-worker/readme.txt
@@ -255,7 +255,7 @@ Yes. SiteAgent is open source under the GPLv2 or later license. The source code
= 2.22.0 =
* New: an install ledger. Every plugin and theme install or update is recorded with how it arrived (wp-admin, REST, WP-CLI, cron, a WordPress auto-update, or SiteAgent itself), which user and application password, and where the package came from, so Aura can flag packages an AI agent installed. It only observes; it never blocks an install. Nothing to configure.
-* Privacy: each record keeps the user ID, the application password's name (never the password) and the REST route. Records are kept at most 90 days or 200 installs, are not autoloaded, and are deleted when the plugin is uninstalled.
+* Privacy: each record keeps the user ID, the application password's name (never the password) and the REST route. While the plugin is active, records older than 90 days (or beyond the latest 200 installs) are deleted; a deactivated plugin keeps them until it is reactivated or uninstalled. Records are not autoloaded and are deleted when the plugin is uninstalled.
= 2.21.0 =
* The Aura approval queue now shows whether an operator rule would block or warn about an Elementor design change made through the elementor-mcp plugin (1.38.0 or later), before anyone approves it. Nothing runs when the queue asks. No new settings.
From 11843d4b220598ddf61cd56eb8a57a4581e7e5ff Mon Sep 17 00:00:00 2001
From: Ben Kalsky
Date: Sat, 26 Sep 2026 15:37:37 +0300
Subject: [PATCH 3/4] =?UTF-8?q?release:=20Codex=20r2=20on=20#140=20?=
=?UTF-8?q?=E2=80=94=20old=20rows=20go=20at=20the=20first=20cleanup=20afte?=
=?UTF-8?q?r=20reactivation,=20not=20at=20reactivation?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-Authored-By: Claude Opus 5.5 (1M context)
---
README.md | 2 +-
digitizer-site-worker/readme.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 3834ebcd..f93b8ec4 100644
--- a/README.md
+++ b/README.md
@@ -243,7 +243,7 @@ These plug straight into **Aura's Fleet MCP Gateway**: read tools run on demand,
- **An install ledger** (Digitizers/Aura spec 2026-09-21 §4, P6.3 phase 2). New `Aura_Worker_Install_Ledger` observes the upgrader for plugin and theme runs only — a per-run token in `hook_extra`, `upgrader_pre_download` at `PHP_INT_MAX`, the entry at `upgrader_install_package_result` — and records and never decides. Each entry: when, type, action, slug, version (the main file), transport (`siteagent` for SiteAgent's own upgrader object, `wp_cli`, `auto_update` only inside core's `wp_maybe_auto_update` — never the upgrader skin, `cron`, `rest`, `wp_admin`), user id, auth, the application password's name (never its uuid), REST route, and the package source (`wporg`, `uploaded_zip`, `remote_host` + host, `local_path`, `unknown`). (#139)
- **Storage that only under-claims.** A ring of 200 entries / 90 days in two non-autoloaded options (network options on multisite), purged physically on read and daily (`wp_scheduled_delete`); every stored row is validated; unreadable storage answers `ledger_unreadable` and is recovered behind a coverage boundary; writes are ordered and read back so an interruption can only shorten `since`. Reactivation restarts coverage; a network where SiteAgent is not network-active answers `ledger_partial_network`. (#139)
-- **`audit_agent_code` reports it as `installs`** — `{ since, entries, total, evicted }` — consumed by Aura's `agent_installed_package` grading. Uninstall removes the network rows. `user_id`, the password name and the route are personal data kept by owner decision, bounded as above — while the plugin is active; a deactivated SiteAgent runs no purge, so its rows stay until reactivation (which purges on the next read or daily pass) or uninstall. (#139)
+- **`audit_agent_code` reports it as `installs`** — `{ since, entries, total, evicted }` — consumed by Aura's `agent_installed_package` grading. Uninstall removes the network rows. `user_id`, the password name and the route are personal data kept by owner decision, bounded as above — while the plugin is active; a deactivated SiteAgent runs no purge, so its rows stay until the first purge after reactivation (the next audit read, install or daily `wp_scheduled_delete` pass — activation itself only restarts coverage) or uninstall. (#139)
### 2.21.0
diff --git a/digitizer-site-worker/readme.txt b/digitizer-site-worker/readme.txt
index 0eafee7e..422b720a 100644
--- a/digitizer-site-worker/readme.txt
+++ b/digitizer-site-worker/readme.txt
@@ -255,7 +255,7 @@ Yes. SiteAgent is open source under the GPLv2 or later license. The source code
= 2.22.0 =
* New: an install ledger. Every plugin and theme install or update is recorded with how it arrived (wp-admin, REST, WP-CLI, cron, a WordPress auto-update, or SiteAgent itself), which user and application password, and where the package came from, so Aura can flag packages an AI agent installed. It only observes; it never blocks an install. Nothing to configure.
-* Privacy: each record keeps the user ID, the application password's name (never the password) and the REST route. While the plugin is active, records older than 90 days (or beyond the latest 200 installs) are deleted; a deactivated plugin keeps them until it is reactivated or uninstalled. Records are not autoloaded and are deleted when the plugin is uninstalled.
+* Privacy: each record keeps the user ID, the application password's name (never the password) and the REST route. While the plugin is active, records older than 90 days (or beyond the latest 200 installs) are deleted; a deactivated plugin cannot delete anything, so they stay until its first cleanup after reactivation (the daily clean-up, an audit or the next install) or until it is uninstalled. Records are not autoloaded and are deleted when the plugin is uninstalled.
= 2.21.0 =
* The Aura approval queue now shows whether an operator rule would block or warn about an Elementor design change made through the elementor-mcp plugin (1.38.0 or later), before anyone approves it. Nothing runs when the queue asks. No new settings.
From ba46c7d72c8375fab37d0a88530dfa79a65f23c1 Mon Sep 17 00:00:00 2001
From: Ben Kalsky
Date: Sat, 26 Sep 2026 15:45:59 +0300
Subject: [PATCH 4/4] =?UTF-8?q?release:=20Codex=20r4=20on=20#140=20?=
=?UTF-8?q?=E2=80=94=20the=20suggested=20privacy-policy=20text=20discloses?=
=?UTF-8?q?=20the=20install=20ledger?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-Authored-By: Claude Opus 5.5 (1M context)
---
.../includes/class-aura-worker.php | 9 ++++-
tests/unit/PrivacyPolicyContentTest.php | 38 +++++++++++++++++++
2 files changed, 46 insertions(+), 1 deletion(-)
create mode 100644 tests/unit/PrivacyPolicyContentTest.php
diff --git a/digitizer-site-worker/includes/class-aura-worker.php b/digitizer-site-worker/includes/class-aura-worker.php
index 12cc18ae..42cd9dc4 100644
--- a/digitizer-site-worker/includes/class-aura-worker.php
+++ b/digitizer-site-worker/includes/class-aura-worker.php
@@ -560,7 +560,14 @@ public function add_privacy_policy_content() {
}
wp_add_privacy_policy_content(
'SiteAgent',
- wp_kses_post( wpautop( __( 'This site uses the SiteAgent plugin to enable remote management from the Aura dashboard (my-aura.app). When connected, the Aura dashboard may access site health information including WordPress version, PHP version, installed plugins and themes, and database metadata. No personal user data is collected or transmitted by this plugin.', 'digitizer-site-worker' ) ) )
+ wp_kses_post(
+ wpautop(
+ __( 'This site uses the SiteAgent plugin to enable remote management from the Aura dashboard (my-aura.app). When connected, the Aura dashboard may access site health information including WordPress version, PHP version, installed plugins and themes, and database metadata.', 'digitizer-site-worker' )
+ . "\n\n"
+ // Since 2.22.0 the install ledger keeps personal data (Aura spec 2026-09-21 §4.2).
+ . __( 'SiteAgent also keeps a record of each plugin and theme installation or update: when it happened, how it was made (for example the dashboard, the REST API or WP-CLI), the ID of the user who made it, the name of the application password used (never the password itself) and the REST route. This record is sent to the connected Aura dashboard as part of its security audit. While the plugin is active, records older than 90 days, or beyond the latest 200 installations, are deleted; all of them are deleted when the plugin is uninstalled.', 'digitizer-site-worker' )
+ )
+ )
);
}
diff --git a/tests/unit/PrivacyPolicyContentTest.php b/tests/unit/PrivacyPolicyContentTest.php
new file mode 100644
index 00000000..ba8a5c9b
--- /dev/null
+++ b/tests/unit/PrivacyPolicyContentTest.php
@@ -0,0 +1,38 @@
+add_privacy_policy_content();
+ $text = (string) ( $GLOBALS['_sa_privacy_policy']['SiteAgent'] ?? '' );
+ $this->assertStringNotContainsString( 'No personal user data', $text );
+ foreach ( array( 'ID of the user', 'application password', 'REST route', '90 days', 'uninstalled' ) as $needle ) {
+ $this->assertStringContainsString( $needle, $text );
+ }
+ }
+}