fix(2meet-data-optimizer): alter an existing flat table in one process at a time; keep a deferred group native until its drift fix

- security review H1: anonymous /wp-cron.php requests pass ddl_allowed(),
  and dbDelta on an existing table had no lock, so concurrent requests each
  ran the ALTER on a large table. The upgrade now runs under the same MySQL
  GET_LOCK as the index DDL (skipped when another process holds it) and
  re-checks the stored hash once locked; this covers aeav_only too. The table
  build moves unchanged to write_table(); lock()/unlock() are shared
- security review M1: after a deferred upgrade the group stays native until
  tmdo_drift_resync has rebuilt the rows written meanwhile
  (TMDO_Schema_Manager::resynced() from run_scheduled_fix()); with no flat
  writes (disabled) it is released at once
- Verify: SchemaUpgradeDeferralTest (lock held elsewhere, resync release),
  integration 585, unit 702, phpcs, stan
- PR: PR-111 (2.3 acceptance security review)
This commit is contained in:
2026-09-27 17:22:57 +08:00
parent 0aec4b9bb6
commit 29adb05567
4 changed files with 149 additions and 20 deletions
@@ -237,6 +237,7 @@ final class TMDO_Drift_Check {
public static function run_scheduled_fix( string $entity_type ): void {
try {
$result = self::fix( $entity_type );
TMDO_Schema_Manager::resynced( $entity_type ); // Groups upgraded while deferred use the flat table again.
TMDO_Logger::info( 'drift_resync', array( 'entity' => $entity_type ) + $result['fixed'] );
} catch ( InvalidArgumentException | RuntimeException $e ) {
TMDO_Logger::info(