Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ To create an installable ZIP: `cd` to the repo root and run `zip -r digitizer-si
| `Aura_Worker_Redact` | `includes/class-aura-worker-redact.php` | Agent read redaction (2.18.0, #419): detectors (`redact`, `redact_text`), audience (`is_audience`), the `rest_pre_echo_response` read seam (`filter_echo`), the `rest_request_before_callbacks` placeholder guard and unredacted-grant check (`before_callbacks`, `grant_shape`), counters, `status_fragment` |
| `Aura_Worker_Redact_Decode` | `includes/class-aura-worker-redact-decode.php` | Redaction stage 2 (2.18.2, #113), pure: `decode_layers()` (the raw run, then every pass whose result changed, up to `MAX_DECODE_PASSES` layers of HTML5 character references, `%XX` and JSON escapes — `\\`, `\/`, `\uXXXX`; null past the check pass or the `MAX_DECODE_GROWTH` bound), `decode_run()` (its last layer), `decode_pass()`, `html5_code_point()`, `utf8()` |
| `Aura_Worker_Redact_Idna` | `includes/class-aura-worker-redact-idna.php` | Redaction stage 2 view 2 (2.18.3, #116), pure, GENERATED — `map()` applies Unicode 18.0.0's UTS-46 hostname mappings and deletions with one `strtr()`; regenerate with `php bin/generate-idna-map.php` (pinned URL + SHA-256), then run the tests; to move to a new Unicode version, bump `IDNA_VERSION`, `IDNA_URL` and `IDNA_SHA256` in the script, regenerate, then update the three counts AND the MAP content pin in `RedactIdnaTest` |
| `Aura_Worker_Install_Ledger` | `includes/class-aura-worker-install-ledger.php` | The install ledger (2.22.0, Aura spec 2026-09-21 §4): observes `upgrader_package_options` (per-run token in `hook_extra`), `upgrader_pre_download` (`PHP_INT_MAX`: source + context under the token) and `upgrader_install_package_result` (the entry) for plugin/theme runs only; records and never decides. Ring of 200 entries / 90 days in `aura_worker_install_ledger` (+ `_state`), not autoloaded, network options on multisite; `report()` is `audit_agent_code`'s `installs`. `as_siteagent()` wraps the updater's four upgrader calls. `auto_update` = `doing_action( 'wp_maybe_auto_update' )`, never the skin (EMCP Pro installs with `Automatic_Upgrader_Skin`) |

### Initialization Flow

Expand Down
50 changes: 50 additions & 0 deletions digitizer-site-worker/digitizer-site-worker.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ function () {
require_once AURA_WORKER_DIR . 'includes/class-aura-worker-abilities.php';
require_once AURA_WORKER_DIR . 'includes/class-aura-worker-magic-link.php';
require_once AURA_WORKER_DIR . 'includes/class-aura-worker-unbind.php';
require_once AURA_WORKER_DIR . 'includes/class-aura-worker-install-ledger.php';

/**
* Initialize the plugin.
Expand Down Expand Up @@ -117,6 +118,11 @@ function aura_worker_maybe_upgrade() {
if ( get_option( 'aura_worker_version' ) === AURA_WORKER_VERSION ) {
return;
}
// The install ledger's coverage starts here (2.22.0, Ruling R3): once per
// version change, a fresh install included — never on every request.
if ( class_exists( 'Aura_Worker_Install_Ledger' ) ) {
Aura_Worker_Install_Ledger::ensure_started();
}
if ( class_exists( 'Aura_Worker_Rules' ) && ! Aura_Worker_Rules::backfill_from_stored_envelope() ) {
return; // the NEXT request retries; the marker stays behind on purpose
}
Expand All @@ -129,6 +135,39 @@ function aura_worker_maybe_upgrade() {
* Activation hook.
*/
function aura_worker_activate( $network_wide = false ) {
// The install ledger's coverage restarts here, once per ACTIVATION CALL —
// not once per site (Codex r1 on #139, install ledger 2.22.0): the ledger
// is a single NETWORK option even on a network-wide activation, so a call
// inside the per-site loop restarted that one shared ledger once per site,
// reporting `evicted: true` (coverage "moved") on every site after the
// first — even on a fresh network-wide install where nothing had
// happened yet. This hook fires exactly once per activation, whether
// network-wide or on a single site, which is the one moment a
// deactivate -> reactivate cycle should actually move coverage: the
// plugin observed nothing while inactive, and leaving `started` unmoved
// would have the ledger claim coverage over that gap. Guarded and
// swallowed on both sides — activation must never fail because of the
// ledger.
//
// BEFORE the per-site loop below, not after (Codex r2 on #139): the loop's
// own aura_worker_activate_site() calls aura_worker_maybe_upgrade(), which
// calls Aura_Worker_Install_Ledger::ensure_started() for a site with no
// ledger option yet. Restarting coverage AFTER the loop would then find
// that fresh ledger already sitting on disk and treat it as an existing
// ring being reactivated — marking a brand-new install `evicted: true`
// before it ever recorded anything. Running first means a genuinely fresh
// site still has no storage at all: restart_coverage() takes the
// ensure_started() path itself (`evicted: false`), and the loop's later
// ensure_started() call is then a no-op because the ledger already
// exists. A true reactivation still sees its ring already on disk and
// moves coverage to a boundary exactly as before.
if ( class_exists( 'Aura_Worker_Install_Ledger' ) ) {
try {
Aura_Worker_Install_Ledger::restart_coverage();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restart coverage before per-site activation initializes it

Although the restart was moved outside the per-site loop, it still runs after that loop. On a fresh activation, aura_worker_activate_site() calls aura_worker_maybe_upgrade(), which calls ensure_started() and creates the state and empty ring; this subsequent restart_coverage() therefore treats the fresh ledger as existing and immediately sets evicted: true. This affects both single-site and network-wide fresh activations, falsely reporting that coverage was lost before anything could have been observed.

Useful? React with 👍 / 👎.

} catch ( \Throwable $e ) {
// Activation must still complete.
}
}
aura_worker_for_each_site( 'aura_worker_activate_site', (bool) $network_wide );
}
register_activation_hook( __FILE__, 'aura_worker_activate' );
Expand Down Expand Up @@ -169,6 +208,17 @@ function aura_worker_activate_site() {
error_log( 'SiteAgent: an Aura Application Password left over from a failed deactivation could not be revoked; revoke it by hand in Users → Profile → Application Passwords.' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
}
Aura_Worker_Magic_Link::release_site( $aura_fence );
// The install ledger's coverage restart lives in aura_worker_activate()
// itself, BEFORE this function ever runs (Codex r1/r2 on #139): the
// ledger is a single NETWORK option even on a network-wide activation, so
// restarting it once PER SITE from this function restarted that one
// shared ledger once per site — reporting `evicted: true` on every site
// after the first, even on a fresh network-wide install where nothing had
// happened yet. aura_worker_maybe_upgrade() below still calls
// ensure_started(), but by the time it runs the caller has already
// restarted coverage once for this whole activation, so a fresh site's
// ensure_started() call here is a no-op and a reactivated site's ring is
// untouched.
// Through the SAME decision as a request-time upgrade (round-1 P2). A site
// updated while the plugin was inactive reaches this hook with the marker
// still behind and `plugins_loaded` already past: stamping the version
Expand Down
Loading
Loading