fix(api): simplify XLVask Selvvask surface by removing AI autopilot pipeline (#367)
## Summary Removes the XLVask autopilot / automation / MiniMax / OpenAI pipeline and the related module config, CLI, cron, and migration scaffolding. The Selvvask view (Superuser -> Fakturaer -> Periode -> Selvvask) is reduced to a single read-only listing of usage logs plus operator-driven ignore / unignore / accept / reject endpoints gated on the `review_xlvask_usage_order` permission. See `inventory/self-serve-inventory.md` for the full surface map. ## Test plan - [x] `vendor/bin/pest --testsuite=Unit` -> **1266 passed**, 1 unrelated pre-existing failure (`BirdControlPlaneActivationTest`, needs `PLENO_REPO_ROOT_FOR_TESTS`). - [x] `php -l` on every modified PHP file -> no syntax errors. - [x] Grep validation -> zero production-code references to removed surfaces (`xlvask_autopilot_service`, `xlvask_automation_service`, `xlvask_automation_policy_service`, `EnsureXLVaskAutomationSchema`, `runScheduledAutomationIfReady`, `processAutopilotQueue`, `MiniMax`, `minimax`, ...). - [ ] Qodana + Tests workflows green on this PR. Co-authored-by: openhands <openhands@all-hands.dev> --------- Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace miniMax\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class miniMax_api_key_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'miniMax',
|
||||
'api_key',
|
||||
'string',
|
||||
false,
|
||||
null,
|
||||
'The secret API key for MiniMax (M3). Obtain from the MiniMax Portal dashboard; the operator can rotate or remove it from the superuser XL Vask module settings.',
|
||||
'1',
|
||||
true,
|
||||
''
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace miniMax\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class miniMax_enabled_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'miniMax',
|
||||
'enabled',
|
||||
'bool',
|
||||
true,
|
||||
null,
|
||||
'Whether the MiniMax integration is enabled for XL Vask autopilot and other AI-driven features.',
|
||||
'1',
|
||||
false,
|
||||
'false'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace miniMax;
|
||||
require_once WD . '/modules/miniMax/config/miniMax_enabled_c.php';
|
||||
require_once WD . '/modules/miniMax/config/miniMax_api_key_c.php';
|
||||
|
||||
use miniMax\config\miniMax_api_key_c;
|
||||
use miniMax\config\miniMax_enabled_c;
|
||||
use traits\module_config_t;
|
||||
|
||||
class miniMax_c
|
||||
{
|
||||
use module_config_t;
|
||||
|
||||
public miniMax_enabled_c $enabled;
|
||||
public miniMax_api_key_c $api_key;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setupConfig('miniMax');
|
||||
$this->allowUpdate([
|
||||
miniMax_enabled_c::class,
|
||||
miniMax_api_key_c::class,
|
||||
]);
|
||||
$this->enabled = new miniMax_enabled_c();
|
||||
$this->api_key = new miniMax_api_key_c();
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
# XL Vask AI automation runbook
|
||||
|
||||
This runbook is an operator procedure. None of its gates are applied by deployment, HTTP GETs, constructors, or workers. Every production-changing step requires a human approval tied to the exact deployed backend and frontend SHAs.
|
||||
|
||||
## 0. Deploy-order and rollback invariant
|
||||
|
||||
The legacy attachment/creation config values are kill switches, but an old backend treats them as direct enable switches. Old code cannot interpret the new policy stages, calibration identity, rolling caps, action latches, or canary soak. Therefore old-backend traffic is forbidden whenever either legacy switch is true, including during a new-policy canary.
|
||||
|
||||
Use this exact forward sequence:
|
||||
|
||||
1. While the old backend is still serving, set both legacy automatic-order switches to false through the approved config procedure and verify the persisted values from every serving instance.
|
||||
2. Stop/disable old XL Vask automation workers and verify there is no active automatic run. Ordinary XL Vask synchronization may continue.
|
||||
3. Deploy the new backend with policy effectively `off`; verify ordinary synchronization still completes and scheduled automation no-ops while schema readiness is false.
|
||||
4. Run read-only migration preflight, then the separately approved explicit additive migration. If it is partial or fails, keep the new backend deployed, policy `off`, both legacy switches false, and workers no-op; repair or complete the migration before continuing. Never route old code as a partial-migration workaround.
|
||||
5. Verify migration readiness and the new backend SHA, then deploy/verify the compatible frontend. Only after that generate advisory evidence and use preview-bound policy transitions.
|
||||
|
||||
Use this exact rollback sequence before any old-code traffic:
|
||||
|
||||
1. Keep all traffic on the new backend, call the dedicated halt endpoint, and verify policy `halted` plus both persisted legacy switches false.
|
||||
2. Stop new-backend automation workers, wait for or safely reconcile the active run, and verify no financial mutation is in flight.
|
||||
3. Roll back the frontend if required, then deploy the old backend with both legacy switches still false. Verify ordinary sync only.
|
||||
4. Do not re-enable either legacy switch on old code. Recovery of automatic actions requires redeploying the new policy-aware backend and repeating readiness, advisory calibration, canary, and soak.
|
||||
|
||||
## 1. Read-only preflight
|
||||
|
||||
1. Record the backend/frontend SHAs, environment, operator, invoice period, and scanner-hall scope.
|
||||
2. Call the scoped capabilities and admin-readiness GETs with `dateFrom` and `dateTo`.
|
||||
3. Confirm `migration.ready`, `missing_tables`, `missing_columns`, `missing_indexes`, `preflight_conflicts`, `worker_healthy`, WashId uniqueness, planner identity, resolved model, active run, scoped eligible counts, rolling budgets, and reviewed soak counts.
|
||||
4. Stop if dates are invalid, hall scope is empty, an execute run is active, identity changed, a latch is halted, or any readiness field fails closed.
|
||||
|
||||
## 2. Explicit schema migration
|
||||
|
||||
Use the controlled database migration procedure to invoke only
|
||||
`migration_20260804_xlvask_ai_auto_policy_v2::apply()`. First retain its read-only
|
||||
`preflight()` output. Review the additive SQL and backup/restore point, approve the exact SHA, run it once, retain the returned status, and rerun readiness. Do not invoke `applyExplicitMigration()` from a request, worker, cron task, or application startup.
|
||||
If preflight reports multiple legacy execute runs in `queued`, `running`, or `retry_wait`, stop. Reconcile those runs through a separately approved operational procedure; the migration never auto-resolves or modifies the conflicting run records.
|
||||
|
||||
### 2a. Operator entry points
|
||||
|
||||
There are two equivalent ways to apply the migration from a privileged
|
||||
container with the configured DB credentials. Both call the same gated
|
||||
`migration_20260804_xlvask_ai_auto_policy_v2::apply()` entry point and
|
||||
produce identical status output. Pick whichever fits the workflow.
|
||||
|
||||
```
|
||||
# Option A — standalone script (mirrors scripts/account-deletion-schema.php)
|
||||
php scripts/xlvask-automation-migrate.php check # read-only preflight
|
||||
php scripts/xlvask-automation-migrate.php apply --yes # apply, gated by --yes
|
||||
|
||||
# Option B — CLI dispatcher inside index.php (defines WD + composes bootstrap)
|
||||
php index.php run xlvask-automation-migrate # preflight, applies if !ready
|
||||
```
|
||||
|
||||
Both exit 0 when `ready=true` and 1 otherwise. Always retain the JSON
|
||||
status artifact for the audit log and rerun `check` to confirm the
|
||||
postflight is green.
|
||||
|
||||
## 3. WashId uniqueness
|
||||
|
||||
Inspect normalized duplicate WashIds. Resolve conflicts through an independently approved data procedure. Only then use the guarded uniqueness activation with the exact typed phrase. Recheck the generated normalized column and unique index before any automatic action.
|
||||
|
||||
## 4. Advisory evidence and calibration
|
||||
|
||||
Keep policy at `advisory`. Run explicit `dry_run` requests to import and persist plans, or `replay` for cache-only read-only evaluation. Review suggestions in hall scope. Label exact OpenAI attach/create suggestions; model identity, prompt hash, schema hash, policy version, resolved model, and chronological label snapshot are part of the artifact identity. Generate inactive backtests, independently review qualification thresholds and contradictions, then activate the exact artifact hash with its typed phrase.
|
||||
|
||||
## 5. Staged policy transitions
|
||||
|
||||
Every transition uses a bounded human reason, server-generated policy preview, exact confirmation phrase, and apply-time revalidation. The reason is bound into the preview hash and retained in the immutable policy event:
|
||||
|
||||
`off` -> `advisory` -> `ai_attach_canary` -> `ai_attach_verified` -> `ai_create_canary` -> `verified_capped`
|
||||
|
||||
Stages may not be skipped. An active execute run, stale preview, changed policy version, changed model/planner identity, missing exact calibration, incomplete reviewed soak, invalid period scope, or exhausted readiness gate blocks promotion.
|
||||
|
||||
## 6. Reviewed soak and caps
|
||||
|
||||
Volume alone never completes soak. Every auto-accepted action must be adjudicated. Only explicit `correct` outcomes from the current action canary activation epoch count: 200 correct reviewed links before attach verification/create eligibility and 50 correct reviewed creates before `verified_capped`. `incorrect`, `duplicate`, `cross_hall`, or `unaudited` persistently halts the relevant action latch, invalidates the active action calibration in the same transaction, and requires investigation. Re-entering that canary creates a fresh soak epoch after a new qualifying calibration is activated.
|
||||
|
||||
Caps are atomic rolling 24-hour limits: 100 links globally and 10 per hall; 20 creates globally and 3 per hall. Cap exhaustion is a normal policy stop: the suggestion remains reviewable and the execute run pauses without recording a permanent action failure. Cap reservation, policy/model/calibration revalidation, current-candidate requery, financial locks, mutation, and audit commit in one transaction.
|
||||
|
||||
List responses intentionally use only persisted revision/hash eligibility and do not reconstruct same-day candidates per row. This avoids an unbounded N+1 query path. Candidate existence, uniqueness, customer/department/registration/lane/date/items/totals, and financial locks are authoritatively rebuilt during preview/apply and again inside the mutation transaction. Treat a preview/apply stale-candidate rejection as a normal fail-closed refresh signal; monitor list latency and preview rejection rates during advisory/canary.
|
||||
|
||||
## 7. Halt, recovery, and rollback
|
||||
|
||||
Use the dedicated halt endpoint immediately on any unexplained result, duplicate, cross-hall action, missing audit, model mismatch, financial invariant, worker lease failure, or upstream revision anomaly. Halt disables legacy compatibility switches and preserves the reason. Generic config may disable a switch but cannot enable it.
|
||||
|
||||
Rollback means: follow the exact sequence in section 0; halt; stop new execute runs; retain audit/action/review evidence; reconcile affected orders and invoice collections; restore data only through a separately approved, previewed procedure; fix and redeploy; repeat advisory calibration and staged previews. Recovery from `halted` starts at `off` or `advisory` and requires new exact-SHA human approval. Never infer activation, soak completion, or production safety from green CI alone.
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace xlvask\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class xlvask_automatic_order_attachment_enabled_c
|
||||
{
|
||||
use module_config_variable {
|
||||
setVariableValue as private setVariableValueInternal;
|
||||
}
|
||||
|
||||
private static bool $policyWrite = false;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'xlvask',
|
||||
'automatic_order_attachment_enabled',
|
||||
'bool',
|
||||
true,
|
||||
null,
|
||||
'Whether XL Vask usage logs may automatically be attached to existing same-day employee orders.',
|
||||
'0',
|
||||
false,
|
||||
'false'
|
||||
);
|
||||
}
|
||||
|
||||
/** Generic module config may kill automation but cannot activate it. */
|
||||
public function setVariableValue(mixed $value): void
|
||||
{
|
||||
if (!self::$policyWrite && self::inputToBool($value)) {
|
||||
throw new Exception('Automatic XL Vask attachment can only be enabled through the policy preview/apply flow.');
|
||||
}
|
||||
$this->setVariableValueInternal($value);
|
||||
}
|
||||
|
||||
public function setFromAutomationPolicy(bool $enabled): void
|
||||
{
|
||||
self::$policyWrite = true;
|
||||
try {
|
||||
$this->setVariableValueInternal($enabled);
|
||||
} finally {
|
||||
self::$policyWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace xlvask\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class xlvask_automatic_order_creation_enabled_c
|
||||
{
|
||||
use module_config_variable {
|
||||
setVariableValue as private setVariableValueInternal;
|
||||
}
|
||||
|
||||
private static bool $policyWrite = false;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'xlvask',
|
||||
'automatic_order_creation_enabled',
|
||||
'bool',
|
||||
true,
|
||||
null,
|
||||
'Whether XL Vask usage logs may automatically create orders when no same-day order can be attached.',
|
||||
'0',
|
||||
false,
|
||||
'false'
|
||||
);
|
||||
}
|
||||
|
||||
/** Generic module config may kill automation but cannot activate it. */
|
||||
public function setVariableValue(mixed $value): void
|
||||
{
|
||||
if (!self::$policyWrite && self::inputToBool($value)) {
|
||||
throw new Exception('Automatic XL Vask creation can only be enabled through the policy preview/apply flow.');
|
||||
}
|
||||
$this->setVariableValueInternal($value);
|
||||
}
|
||||
|
||||
public function setFromAutomationPolicy(bool $enabled): void
|
||||
{
|
||||
self::$policyWrite = true;
|
||||
try {
|
||||
$this->setVariableValueInternal($enabled);
|
||||
} finally {
|
||||
self::$policyWrite = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace xlvask\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class xlvask_minimax_integration_enabled_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'xlvask',
|
||||
'minimax_integration_enabled',
|
||||
'bool',
|
||||
true,
|
||||
null,
|
||||
'Whether XL Vask automation may ask MiniMax (M3) for attachment or creation suggestions. Replaces the OpenAI integration.',
|
||||
'0',
|
||||
false,
|
||||
'false'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace xlvask\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class xlvask_openai_integration_enabled_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'xlvask',
|
||||
'openai_integration_enabled',
|
||||
'bool',
|
||||
true,
|
||||
null,
|
||||
'Whether XL Vask automation may ask OpenAI for attachment or creation suggestions.',
|
||||
'0',
|
||||
false,
|
||||
'false'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
[
|
||||
'id' => 'xlvask.autopilot_queue',
|
||||
'legacy_name' => 'ProcessXLVaskAutopilotQueueCron',
|
||||
'name' => 'Process XL Vask autopilot queue',
|
||||
'description' => 'Claims and processes a bounded batch of queued XL Vask autopilot runs.',
|
||||
'module' => 'xlvask',
|
||||
'handler' => 'ProcessXLVaskAutopilotQueueCron',
|
||||
'schedule' => ['type' => 'interval', 'seconds' => 60],
|
||||
'timeout_seconds' => 300,
|
||||
'estimated_duration_ms' => 5000,
|
||||
'priority' => 40,
|
||||
],
|
||||
[
|
||||
'id' => 'xlvask.sync_module',
|
||||
'legacy_name' => 'SyncXLVaskModuleCron',
|
||||
'name' => 'Sync XL Vask module',
|
||||
'description' => 'Runs scheduled XL Vask synchronization tasks when the module is enabled.',
|
||||
'module' => 'xlvask',
|
||||
'handler' => 'SyncXLVaskModuleCron',
|
||||
'schedule' => ['type' => 'interval', 'seconds' => 3600],
|
||||
'timeout_seconds' => 900,
|
||||
'estimated_duration_ms' => 10000,
|
||||
'priority' => 95,
|
||||
],
|
||||
];
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace helpers;
|
||||
|
||||
require_once WD . '/classes/xlvask_autopilot_service.php';
|
||||
|
||||
use classes\xlvask_autopilot_service;
|
||||
use Exception;
|
||||
use objects\orders_o;
|
||||
use objects\plate_scanners_o;
|
||||
@@ -46,9 +43,6 @@ class xlvask_tasks
|
||||
$this->runSyncUsage();
|
||||
$this->runSyncVehicles();
|
||||
$this->runCleanupTasks();
|
||||
// Automation is an optional final phase. A pending migration or an
|
||||
// off/advisory policy must never interrupt the ordinary XL Vask sync.
|
||||
$this->runScheduledAutomationIfReady();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -76,47 +70,6 @@ class xlvask_tasks
|
||||
};
|
||||
}
|
||||
|
||||
/** Enqueue automatic work only after explicit migration and policy activation. */
|
||||
public function runScheduledAutomationIfReady(): array
|
||||
{
|
||||
try {
|
||||
$migrationStatus = \classes\xlvask_usage_logs_schema_bootstrap::migrationStatus();
|
||||
if (!(bool)($migrationStatus['ready'] ?? false)) {
|
||||
return [];
|
||||
}
|
||||
$hallIds = $this->configuredHallIds();
|
||||
if ($hallIds === []) {
|
||||
return [];
|
||||
}
|
||||
$autopilot = new xlvask_autopilot_service();
|
||||
$capabilities = (new \classes\xlvask_automation_policy_service())->capabilitiesReadOnly(null, null, $hallIds);
|
||||
if (!xlvask_autopilot_service::scheduledExecutionAllowed($migrationStatus, $capabilities)) {
|
||||
return [];
|
||||
}
|
||||
$autopilot->createRun(['mode' => 'execute'], null, $hallIds);
|
||||
return $autopilot->processQueuedRuns(3);
|
||||
} catch (\Throwable) {
|
||||
// Fail closed for automation while preserving the completed ordinary sync.
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** Drain the durable autopilot queue without running the hourly upstream synchronization. */
|
||||
public function processAutopilotQueue(int $limit = 3): array
|
||||
{
|
||||
$xlvask = new \classes\xlvask();
|
||||
$xlvask->requireModuleEnabled();
|
||||
if (!$xlvask->config->synchronization_enabled->isTrue()) {
|
||||
return [];
|
||||
}
|
||||
if (!(bool)(\classes\xlvask_usage_logs_schema_bootstrap::migrationStatus()['ready'] ?? false)) {
|
||||
return [];
|
||||
}
|
||||
// Off/advisory cannot contain execute runs because createRun is server-gated.
|
||||
// Explicit dry-run/replay evidence may still drain in advisory mode.
|
||||
return (new xlvask_autopilot_service())->processQueuedRuns($limit);
|
||||
}
|
||||
|
||||
/** Hall GUIDs are configuration, not derived from already-imported usage rows. */
|
||||
private function configuredHallIds(): array
|
||||
{
|
||||
@@ -328,10 +281,8 @@ class xlvask_tasks
|
||||
{
|
||||
global $db;
|
||||
$xlvask = new \classes\xlvask();
|
||||
$orders_o = new orders_o();
|
||||
$matches = new xlvask_potential_order_matches_o();
|
||||
$linked = 0;
|
||||
$ordersCreated = 0;
|
||||
|
||||
$dateFromSql = $dateFrom !== null && $dateFrom !== ''
|
||||
? "'" . $db->escape_string(xlvask_usage_logs_o::formatImportDateFrom($dateFrom)) . "'"
|
||||
@@ -352,8 +303,6 @@ class xlvask_tasks
|
||||
}
|
||||
$rows = $db->fetch_all($result);
|
||||
|
||||
$createEnabled = $xlvask->config->automatic_order_creation_enabled->isTrue();
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$log = (new $xlvask->helpers->xlvask_usage_log())->setProperties($row);
|
||||
$washId = (string)$log->WashId;
|
||||
@@ -374,25 +323,10 @@ class xlvask_tasks
|
||||
(int)$log->getDepartment()->id,
|
||||
);
|
||||
$linked++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// No matching order — try to create one if automatic creation is on.
|
||||
if (!$createEnabled || !$log->isEligibleForAutomaticContinuance(false)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$customer = $log->getCustomer();
|
||||
$order = (new self())->createOrderFromWash($log, $customer);
|
||||
if ($order !== null) {
|
||||
$ordersCreated++;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log('[xlvask-tasks] auto-create order failed for wash ' . $washId . ': ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return ['linked' => $linked, 'orders_created' => $ordersCreated];
|
||||
return ['linked' => $linked, 'orders_created' => 0];
|
||||
}
|
||||
|
||||
private static function formatUsageLogs(array $getUsageLog): array
|
||||
@@ -502,9 +436,5 @@ class xlvask_tasks
|
||||
$xlvask = new \classes\xlvask();
|
||||
// Require the module to be enabled
|
||||
$xlvask->requireModuleEnabled();
|
||||
if (!(bool)(\classes\xlvask_usage_logs_schema_bootstrap::migrationStatus()['ready'] ?? false)) {
|
||||
return;
|
||||
}
|
||||
(new xlvask_autopilot_service())->pruneExpiredData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace xlvask\migrations;
|
||||
|
||||
require_once WD . '/classes/xlvask_usage_logs_schema_bootstrap.php';
|
||||
|
||||
use classes\xlvask_usage_logs_schema_bootstrap;
|
||||
|
||||
/**
|
||||
* Versioned, operator-invoked XL Vask AI auto-action migration.
|
||||
*
|
||||
* Preflight is read-only. apply() is intentionally not wired to HTTP routes, cron, constructors,
|
||||
* readiness, or normal run processing. Operators must execute it through the controlled database
|
||||
* migration procedure and retain the returned status artifact.
|
||||
*/
|
||||
final class migration_20260804_xlvask_ai_auto_policy_v2
|
||||
{
|
||||
public static function preflight(): array
|
||||
{
|
||||
return xlvask_usage_logs_schema_bootstrap::migrationStatus();
|
||||
}
|
||||
|
||||
public static function apply(): array
|
||||
{
|
||||
return xlvask_usage_logs_schema_bootstrap::applyExplicitMigration();
|
||||
}
|
||||
}
|
||||
@@ -3,19 +3,11 @@
|
||||
namespace xlvask;
|
||||
require_once WD . '/modules/xlvask/config/xlvask_enabled_c.php';
|
||||
require_once WD . '/modules/xlvask/config/xlvask_synchronization_enabled_c.php';
|
||||
require_once WD . '/modules/xlvask/config/xlvask_automatic_order_attachment_enabled_c.php';
|
||||
require_once WD . '/modules/xlvask/config/xlvask_automatic_order_creation_enabled_c.php';
|
||||
require_once WD . '/modules/xlvask/config/xlvask_minimax_integration_enabled_c.php';
|
||||
require_once WD . '/modules/xlvask/config/xlvask_openai_integration_enabled_c.php';
|
||||
require_once WD . '/modules/xlvask/config/xlvask_username_c.php';
|
||||
require_once WD . '/modules/xlvask/config/xlvask_password_c.php';
|
||||
|
||||
use traits\module_config_t;
|
||||
use xlvask\config\xlvask_automatic_order_attachment_enabled_c;
|
||||
use xlvask\config\xlvask_automatic_order_creation_enabled_c;
|
||||
use xlvask\config\xlvask_enabled_c;
|
||||
use xlvask\config\xlvask_minimax_integration_enabled_c;
|
||||
use xlvask\config\xlvask_openai_integration_enabled_c;
|
||||
use xlvask\config\xlvask_password_c;
|
||||
use xlvask\config\xlvask_synchronization_enabled_c;
|
||||
use xlvask\config\xlvask_username_c;
|
||||
@@ -39,22 +31,6 @@ class xlvask_c
|
||||
* @var xlvask_synchronization_enabled_c $synchronization_enabled
|
||||
*/
|
||||
public xlvask_synchronization_enabled_c $synchronization_enabled;
|
||||
/**
|
||||
* @var xlvask_automatic_order_attachment_enabled_c $automatic_order_attachment_enabled
|
||||
*/
|
||||
public xlvask_automatic_order_attachment_enabled_c $automatic_order_attachment_enabled;
|
||||
/**
|
||||
* @var xlvask_automatic_order_creation_enabled_c $automatic_order_creation_enabled
|
||||
*/
|
||||
public xlvask_automatic_order_creation_enabled_c $automatic_order_creation_enabled;
|
||||
/**
|
||||
* @var xlvask_minimax_integration_enabled_c $minimax_integration_enabled
|
||||
*/
|
||||
public xlvask_minimax_integration_enabled_c $minimax_integration_enabled;
|
||||
/**
|
||||
* @var xlvask_openai_integration_enabled_c $openai_integration_enabled
|
||||
*/
|
||||
public xlvask_openai_integration_enabled_c $openai_integration_enabled;
|
||||
/**
|
||||
* The username
|
||||
* @var xlvask_username_c
|
||||
@@ -77,19 +53,11 @@ class xlvask_c
|
||||
$this->allowUpdate([
|
||||
xlvask_enabled_c::class,
|
||||
xlvask_synchronization_enabled_c::class,
|
||||
xlvask_automatic_order_attachment_enabled_c::class,
|
||||
xlvask_automatic_order_creation_enabled_c::class,
|
||||
xlvask_minimax_integration_enabled_c::class,
|
||||
xlvask_openai_integration_enabled_c::class,
|
||||
xlvask_username_c::class,
|
||||
xlvask_password_c::class
|
||||
]);
|
||||
$this->enabled = new xlvask_enabled_c();
|
||||
$this->synchronization_enabled = new xlvask_synchronization_enabled_c();
|
||||
$this->automatic_order_attachment_enabled = new xlvask_automatic_order_attachment_enabled_c();
|
||||
$this->automatic_order_creation_enabled = new xlvask_automatic_order_creation_enabled_c();
|
||||
$this->minimax_integration_enabled = new xlvask_minimax_integration_enabled_c();
|
||||
$this->openai_integration_enabled = new xlvask_openai_integration_enabled_c();
|
||||
$this->username = new xlvask_username_c();
|
||||
$this->password = new xlvask_password_c();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user