<?php
declare(strict_types=1);

// DEFAULT DENY for business HTTP, DB cleanup and token audit until reviewed SHA approval.
$phase = (string)($argv[1] ?? '');
$lane = (string)($argv[2] ?? '');
$marker = (string)($argv[3] ?? '');
if (!in_array($phase, ['--preflight', '--run', '--audit-token',
        '--cleanup', '--audit', '--recover-probe'], true)
    || !in_array($lane, ['B', 'C'], true)
    || !preg_match('/^CDXSVC[0-9A-F]{12}$/', $marker)) {
    fwrite(STDERR, "DENIED: exact phase/lane/marker required\n");
    exit(78);
}
if (!in_array($phase, ['--preflight', '--recover-probe'], true)) {
    $reviewed = (string)getenv('CDX_SERVICE_W3_REVIEWED_SHA256');
    if ((string)getenv('CDX_SERVICE_W3_APPROVAL') !== 'OWNED_SERVICE_WRITE3_V1'
        || !preg_match('/^[0-9a-f]{64}$/', $reviewed)
        || ($lane === 'B' && hash_file('sha256', __FILE__) !== $reviewed)
        || ($lane === 'C' && (string)getenv('CDX_SERVICE_W3_SOURCE_CHECKED') !== '1')) {
        fwrite(STDERR, "DENIED: exact reviewed SHA/write gate required\n");
        exit(78);
    }
}
$stage = 'start';
set_exception_handler(static function (Throwable $e) use (&$stage): void {
    fwrite(STDERR, 'SERVICE_W3_STOP stage=' . $stage
        . ' class=' . get_class($e) . "\n");
    exit(3);
});
$root = $lane === 'B' ? '/private/tmp/zhct-http-ai-macos.x2CCZX'
    : '/tmp/zhct-ai-http-20260929.3XDj3w';
$pid = $lane === 'B' ? 13127 : 53772;
$port = $lane === 'B' ? 18101 : 18102;
$base = 'http://127.0.0.1:' . $port;
$sourceSha = [
    'app\\store\\controller\\goods\\Service' => '319b8e191f6f126979d6d5a6b77d4dba4dda2c8b39c0fff403f00b0c24b9b15d',
    'app\\store\\model\\goods\\Service' => '7449f17affe3bf7b477cefa010c5911e17b52edcd42f3839572a6f46fe67d3a7',
    'app\\store\\model\\goods\\ServiceRel' => '3696cd8dc95d3a16050db2dc5b37ca7241f8d46fa77c8489f9d2b0a5ebd8d920',
    'app\\common\\model\\goods\\Service' => 'd6e3a9291a6b887f4700343b97ac33d55853e65339ca67140415553b2898929e',
];
if ($lane === 'B') {
    $cfg = parse_ini_file('/Users/wiscourper/Documents/workspace/zhct/zhctproject/ai_api/.env.local', true, INI_SCANNER_RAW)['DATABASE'] ?? null;
    $ps = (string)shell_exec('/bin/ps eww -p ' . $pid . ' -o command=');
    $owner = trim((string)shell_exec('/usr/sbin/lsof -nP -t -iTCP:' . $port . ' -sTCP:LISTEN 2>/dev/null'));
    if (!is_array($cfg) || strtolower((string)($cfg['TYPE'] ?? '')) !== 'mysql'
        || (string)($cfg['HOSTPORT'] ?? '') !== '3306' || $owner !== (string)$pid
        || strpos($ps, 'POC_DIALECT=mysql') === false
        || strpos($ps, 'POC_EXTERNAL_STUBS=1') === false) {
        throw new RuntimeException('B worker/config drift');
    }
    foreach (['HOSTNAME' => 'HOST', 'HOSTPORT' => 'PORT', 'DATABASE' => 'SCHEMA',
              'USERNAME' => 'USER', 'PASSWORD' => 'PASSWORD'] as $from => $to) {
        $v = (string)($cfg[$from] ?? '');
        if ($v === '' || strpos($ps, 'POC_AI_' . $to . '=' . $v) === false) {
            throw new RuntimeException('B worker differs from code local config');
        }
    }
    $connect = static function () use ($cfg): PDO {
        return new PDO('mysql:host=' . $cfg['HOSTNAME'] . ';port=' . $cfg['HOSTPORT']
            . ';dbname=' . $cfg['DATABASE'] . ';charset=utf8', $cfg['USERNAME'], $cfg['PASSWORD'],
            [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_CASE => PDO::CASE_LOWER]);
    };
    $envName = 'local';
} else {
    $env = [];
    foreach (explode("\0", (string)file_get_contents('/proc/' . $pid . '/environ')) as $item) {
        $pair = explode('=', $item, 2);
        if (count($pair) === 2) $env[$pair[0]] = $pair[1];
    }
    if (($env['POC_TARGET_ROOT'] ?? '') !== $root
        || ($env['POC_BASE_URL'] ?? '') !== $base
        || ($env['POC_DIALECT'] ?? '') !== 'dm'
        || ($env['POC_EXTERNAL_STUBS'] ?? '') !== '1'
        || ($env['POC_AI_HOST'] ?? '') !== '127.0.0.1'
        || ($env['POC_AI_PORT'] ?? '') !== '5238'
        || ($env['POC_AI_SCHEMA'] ?? '') !== 'AIZHCT_APP'
        || ($env['POC_AI_USER'] ?? '') !== 'AIZHCT_APP'
        || !in_array('dm', PDO::getAvailableDrivers(), true)) {
        throw new RuntimeException('C worker/config drift');
    }
    $connect = static function () use ($env): PDO {
        $d = new PDO('dm:host=127.0.0.1;port=5238;schema=AIZHCT_APP',
            $env['POC_AI_USER'], $env['POC_AI_PASSWORD'],
            [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_CASE => PDO::CASE_LOWER]);
        if ($d->query("SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL")->fetchColumn() !== 'AIZHCT_APP') {
            throw new RuntimeException('C schema drift');
        }
        return $d;
    };
    $envName = 'poc';
}
$loader = require $root . '/vendor/autoload.php';
if (!is_object($loader) || !method_exists($loader, 'findFile')) {
    throw new RuntimeException('Composer loader absent');
}
foreach ($sourceSha as $class => $sha) {
    $file = $loader->findFile($class);
    $real = is_string($file) ? realpath($file) : false;
    if (!is_string($real) || !is_file($real)
        || hash_file('sha256', $real) !== $sha) {
        throw new RuntimeException('Actual Composer source drift');
    }
}
$table = $lane === 'B' ? 'yoshop_goods_service' : 'YOSHOP_GOODS_SERVICE';
$rel = $lane === 'B' ? 'yoshop_goods_service_rel' : 'YOSHOP_GOODS_SERVICE_REL';
$db = $connect();
$count = static function (PDO $d, string $sql, array $args = []): int {
    $s = $d->prepare($sql);
    $s->execute($args);
    return (int)$s->fetchColumn();
};
$query = static function (PDO $d, string $sql, array $args = []): array {
    $s = $d->prepare($sql);
    $s->execute($args);
    return $s->fetchAll(PDO::FETCH_ASSOC);
};
$refsSql = $lane === 'B'
    ? "SELECT TABLE_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME LIKE 'yoshop_%' AND UPPER(COLUMN_NAME)='SERVICE_ID'"
    : "SELECT TABLE_NAME,COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME LIKE 'YOSHOP_%' AND COLUMN_NAME='SERVICE_ID'";
$refs = $query($db, $refsSql);
$seen = [];
foreach ($refs as $r) {
    $name = strtoupper((string)$r['table_name']);
    $col = strtoupper((string)$r['column_name']);
    if (!preg_match('/^[A-Z_][A-Z0-9_]*$/', $name)
        || !preg_match('/^[A-Z_][A-Z0-9_]*$/', $col)) {
        throw new RuntimeException('Unsafe reference metadata');
    }
    $seen[] = $name . '.' . $col;
}
sort($seen);
if ($seen !== ['YOSHOP_GOODS_SERVICE.SERVICE_ID',
        'YOSHOP_GOODS_SERVICE_REL.SERVICE_ID']) {
    throw new RuntimeException('Service reference inventory drift');
}
if ($lane === 'B') {
    $triggers = $count($db, 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_SCHEMA=DATABASE() AND EVENT_OBJECT_TABLE IN (?,?)', [$table, $rel]);
    $fks = $count($db, 'SELECT COUNT(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA=DATABASE() AND REFERENCED_TABLE_NAME IS NOT NULL AND (TABLE_NAME IN (?,?) OR REFERENCED_TABLE_NAME IN (?,?))', [$table, $rel, $table, $rel]);
    $identity = $count($db, "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? AND COLUMN_NAME='service_id' AND EXTRA LIKE '%auto_increment%'", [$table]) === 1;
} else {
    $triggers = $count($db, "SELECT COUNT(*) FROM USER_TRIGGERS WHERE TABLE_NAME IN ('YOSHOP_GOODS_SERVICE','YOSHOP_GOODS_SERVICE_REL')");
    $fks = $count($db, "SELECT COUNT(*) FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE='R' AND (TABLE_NAME IN ('YOSHOP_GOODS_SERVICE','YOSHOP_GOODS_SERVICE_REL') OR R_CONSTRAINT_NAME IN (SELECT CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME IN ('YOSHOP_GOODS_SERVICE','YOSHOP_GOODS_SERVICE_REL')))");
    $s = $db->prepare('CALL SP_TABLEDEF(?, ?)');
    $s->execute(['AIZHCT_APP', $table]);
    $ddl = $s->fetchColumn();
    if (is_resource($ddl)) $ddl = stream_get_contents($ddl);
    $identity = is_string($ddl)
        && preg_match('/"SERVICE_ID"\s+[A-Z0-9_]+\s+(?:AUTO_INCREMENT|IDENTITY)/i', $ddl) === 1;
}
if ($triggers !== 0 || $fks !== 0 || !$identity) {
    throw new RuntimeException('Schema/side-effect gate drift');
}
$natural = static function (PDO $d, int $excludedId = 0) use ($table, $rel): array {
    $out = [];
    foreach (['service' => [$table, 'SERVICE_ID'], 'relation' => [$rel, 'ID']] as $logical => [$name, $pk]) {
        $s = $d->query('SELECT * FROM ' . $name
            . ' WHERE STORE_ID=10001 ORDER BY ' . $pk);
        $h = hash_init('sha256');
        $n = 0;
        while (($row = $s->fetch(PDO::FETCH_ASSOC)) !== false) {
            if ($logical === 'service' && $excludedId > 0
                && (int)$row['service_id'] === $excludedId) continue;
            hash_update($h, serialize(array_values($row)));
            if (++$n > 30000) throw new RuntimeException('Natural source cap exceeded');
        }
        $out[$logical] = ['count' => $n, 'sha256' => hash_final($h)];
    }
    return $out;
};
$own = static function (PDO $d, int $id) use ($query, $table, $marker): array {
    $found = $query($d, 'SELECT * FROM ' . $table
        . ' WHERE SERVICE_ID=? AND NAME=? AND STORE_ID=10001', [$id, $marker]);
    if (count($found) !== 1) throw new RuntimeException('Owned service row absent/ambiguous');
    $row = $found[0];
    if ((int)$row['is_default'] !== 0 || (int)$row['status'] !== 0) {
        throw new RuntimeException('Owned service became visible/default');
    }
    return $row;
};
$journalDir = sys_get_temp_dir() . '/cdx-service-w3-'
    . strtolower($lane) . '-' . strtolower($marker);
$journalPath = $journalDir . '/journal.json';
$tokenDir = sys_get_temp_dir() . '/cdx-service-w3-token-'
    . strtolower($lane) . '-' . strtolower($marker);
$tokenPath = $tokenDir . '/journal.json';
$save = static function (string $path, array $value): void {
    $body = json_encode($value, JSON_UNESCAPED_SLASHES);
    $tmp = $path . '.tmp';
    if (!is_string($body) || file_put_contents($tmp, $body, LOCK_EX) !== strlen($body)
        || !chmod($tmp, 0600) || !rename($tmp, $path)) {
        throw new RuntimeException('Private journal write failed');
    }
};
$markCount = $count($db, 'SELECT COUNT(*) FROM ' . $table
    . ' WHERE NAME=? AND STORE_ID=10001', [$marker]);
if ($phase === '--preflight') {
    echo json_encode(['lane' => $lane, 'phase' => $phase,
        'marker' => $marker, 'marker_count' => $markCount,
        'natural_source' => $natural($db), 'source_sha256' => $sourceSha,
        'service_id_reference_columns' => $seen,
        'triggers' => 0, 'foreign_keys' => 0, 'identity' => true,
        'journal_absent' => !file_exists($journalDir) && !file_exists($tokenDir),
        'business_http' => 0, 'business_dml' => 0], JSON_UNESCAPED_SLASHES), "\n";
    exit($markCount === 0 && !file_exists($journalDir)
        && !file_exists($tokenDir) ? 0 : 3);
}
$journal = is_file($journalPath)
    ? json_decode((string)file_get_contents($journalPath), true) : null;
if (is_array($journal) && (($journal['lane'] ?? '') !== $lane
    || ($journal['marker'] ?? '') !== $marker)) {
    throw new RuntimeException('Exact journal identity mismatch');
}
if ($phase === '--recover-probe') {
    echo json_encode(['lane' => $lane, 'phase' => $phase,
        'marker_count' => $markCount,
        'journal_phase' => is_array($journal) ? ($journal['phase'] ?? 'invalid') : 'absent',
        'journal_id' => is_array($journal) ? ($journal['id'] ?? 0) : 0,
        'token_journal_present' => is_file($tokenPath),
        'business_http' => 0, 'business_dml' => 0], JSON_UNESCAPED_SLASHES), "\n";
    exit(0);
}
define('TP_ENV', $envName);
define('BUSINESS', 'aizhct');
define('ENTERPRISE_NO', '10001');
(new \think\App($root))->setEnvName($envName)->initialize();
if (config('cache.default') !== 'file') throw new RuntimeException('Private File cache absent');
if ($phase === '--audit-token') {
    if (!is_array($journal) || !is_file($tokenPath)) {
        throw new RuntimeException('Token/owned journal absent');
    }
    $tokenJ = json_decode((string)file_get_contents($tokenPath), true);
    if (!is_array($tokenJ) || ($tokenJ['lane'] ?? '') !== $lane
        || ($tokenJ['marker'] ?? '') !== $marker
        || !preg_match('/^CDXSVCTOKEN[0-9A-F]{32}$/', (string)($tokenJ['token'] ?? ''))) {
        throw new RuntimeException('Token journal identity invalid');
    }
    $boundary = @fopen($base . '/__poc_boundary', 'rb', false,
        stream_context_create(['http' => ['timeout' => 5,
            'ignore_errors' => true, 'follow_location' => 0]]));
    if ($boundary === false) throw new RuntimeException('Worker completion boundary absent');
    $raw = stream_get_contents($boundary, 8193);
    $meta = stream_get_meta_data($boundary);
    $eof = feof($boundary);
    fclose($boundary);
    $boundaryJson = is_string($raw) ? json_decode($raw, true) : null;
    if (!is_string($raw) || strlen($raw) > 8192 || !$eof
        || ($meta['timed_out'] ?? false)
        || ($lane === 'C' && (!is_array($boundaryJson)
            || empty($boundaryJson['external_stubs'])))) {
        throw new RuntimeException('Worker completion boundary uncertain');
    }
    if (\think\facade\Cache::has($tokenJ['token'])) {
        throw new RuntimeException('Temporary File token still live');
    }
    $recoveryRequired = ($journal['phase'] ?? '') !== 'completed';
    if (!$recoveryRequired) {
        $id = (int)($journal['id'] ?? 0);
        if ($id <= 0 || hash('sha256', serialize($own($connect(), $id)))
            !== (string)($journal['own_sha256'] ?? '')
            || $natural($connect(), $id) !== ($journal['source_before'] ?? null)) {
            throw new RuntimeException('Independent owned/source token audit failed');
        }
    }
    if (!unlink($tokenPath) || !rmdir($tokenDir)
        || file_exists($tokenPath) || is_dir($tokenDir)) {
        throw new RuntimeException('Exact token journal removal failed');
    }
    echo json_encode(['lane' => $lane, 'phase' => $phase,
        'token_zero' => true, 'journal_absent' => true,
        'worker_boundary_confirmed' => true,
        'recovery_required' => $recoveryRequired,
        'business_http' => 0, 'business_dml' => 0], JSON_UNESCAPED_SLASHES), "\n";
    exit(0);
}
if ($phase === '--audit') {
    if (!is_array($journal) || !is_array($journal['source_before'] ?? null)
        || (int)($journal['id'] ?? 0) <= 0 || file_exists($tokenDir)
        || !in_array($journal['phase'] ?? '',
            ['cleanup_committed', 'completed'], true)) {
        throw new RuntimeException('Independent audit journal state invalid');
    }
    $verify = $connect();
    $id = (int)$journal['id'];
    $zero = $count($verify, 'SELECT COUNT(*) FROM ' . $table
        . ' WHERE SERVICE_ID=?', [$id]) === 0
        && $count($verify, 'SELECT COUNT(*) FROM ' . $rel
            . ' WHERE SERVICE_ID=?', [$id]) === 0
        && $count($verify, 'SELECT COUNT(*) FROM ' . $table
            . ' WHERE NAME=? AND STORE_ID=10001', [$marker]) === 0;
    if (!$zero || $natural($verify) !== $journal['source_before']) {
        throw new RuntimeException('Independent zero/source audit failed');
    }
    if (!unlink($journalPath) || !rmdir($journalDir)
        || file_exists($journalPath) || is_dir($journalDir)) {
        throw new RuntimeException('Verified journal removal failed');
    }
    echo json_encode(['lane' => $lane, 'phase' => $phase,
        'owned_service_and_refs_zero' => true,
        'two_table_natural_sha_unchanged' => true,
        'journal_absent' => true, 'business_http' => 0,
        'business_dml' => 0], JSON_UNESCAPED_SLASHES), "\n";
    exit(0);
}
if ($phase === '--cleanup') {
    if (!is_array($journal) || ($journal['phase'] ?? '') !== 'completed'
        || (int)($journal['id'] ?? 0) <= 0 || file_exists($tokenDir)) {
        throw new RuntimeException('Completed fixture/token audit absent');
    }
    $id = (int)$journal['id'];
    $row = $own($db, $id);
    if ((int)$row['is_delete'] !== 1
        || (int)$row['sort'] !== 9998
        || (string)$row['summary'] !== $marker . ' EDIT'
        || hash('sha256', serialize($row)) !== (string)($journal['own_sha256'] ?? '')
        || $count($db, 'SELECT COUNT(*) FROM ' . $rel
            . ' WHERE SERVICE_ID=?', [$id]) !== 0
        || $natural($db, $id) !== ($journal['source_before'] ?? null)) {
        throw new RuntimeException('Owned row/ref/natural drift; cleanup refused');
    }
    $db->beginTransaction();
    try {
        $s = $db->prepare('DELETE FROM ' . $table
            . ' WHERE SERVICE_ID=? AND NAME=? AND STORE_ID=10001'
            . ' AND IS_DELETE=1 AND STATUS=0 AND IS_DEFAULT=0');
        $s->execute([$id, $marker]);
        if ($s->rowCount() !== 1) throw new RuntimeException('Exact delete affected-row mismatch');
        $db->commit();
    } catch (Throwable $e) {
        if ($db->inTransaction()) $db->rollBack();
        throw $e;
    }
    $journal['phase'] = 'cleanup_committed';
    $save($journalPath, $journal);
    echo json_encode(['lane' => $lane, 'phase' => $phase,
        'deleted_exact_owned_row' => 1,
        'independent_audit_required' => true], JSON_UNESCAPED_SLASHES), "\n";
    exit(0);
}
if ($phase !== '--run' || $markCount !== 0
    || file_exists($journalDir) || file_exists($tokenDir)) {
    throw new RuntimeException('Run state/marker not pristine');
}
$sourceBefore = $natural($db);
if (!mkdir($journalDir, 0700) || !chmod($journalDir, 0700)) {
    throw new RuntimeException('Private journal creation failed');
}
$journal = ['lane' => $lane, 'marker' => $marker,
    'phase' => 'before_http', 'source_before' => $sourceBefore,
    'id' => 0, 'created_at' => time()];
$save($journalPath, $journal);
if (!mkdir($tokenDir, 0700) || !chmod($tokenDir, 0700)) {
    throw new RuntimeException('Private token journal creation failed');
}
$token = 'CDXSVCTOKEN' . strtoupper(bin2hex(random_bytes(16)));
$tokenJ = ['lane' => $lane, 'marker' => $marker,
    'token' => $token, 'phase' => 'before_token'];
$save($tokenPath, $tokenJ);
$shape = null;
$shape = static function ($v) use (&$shape) {
    if (is_array($v)) {
        if (array_values($v) === $v) {
            return ['@array' => count($v), '@items' => array_map($shape, $v)];
        }
        $out = [];
        foreach ($v as $key => $value) $out[(string)$key] = $shape($value);
        ksort($out);
        return $out;
    }
    return gettype($v);
};
$request = static function (string $action, array $data, string $auth) use ($base): array {
    $url = $base . '/index.php?s=/store/goods.Service/' . $action;
    $body = json_encode($data, JSON_UNESCAPED_SLASHES);
    $ctx = stream_context_create(['http' => ['method' => 'POST',
        'header' => 'Access-Token: ' . $auth . "\r\n"
            . "Content-Type: application/json\r\n",
        'content' => $body, 'timeout' => 20,
        'ignore_errors' => true, 'follow_location' => 0]]);
    $start = microtime(true);
    $h = @fopen($url, 'rb', false, $ctx);
    if ($h === false) return ['complete' => false, 'http' => 0, 'json' => null];
    $raw = stream_get_contents($h, 1048577);
    $meta = stream_get_meta_data($h);
    $eof = feof($h);
    fclose($h);
    $lines = $meta['wrapper_data'] ?? [];
    preg_match('/^HTTP\/\S+\s+(\d{3})(?:\s|$)/', (string)($lines[0] ?? ''), $m);
    $http = isset($m[1]) ? (int)$m[1] : 0;
    $lengthOk = true;
    foreach ($lines as $line) {
        if (preg_match('/^Content-Length:\s*(\d+)\s*$/i', (string)$line, $n)) {
            $lengthOk = is_string($raw) && strlen($raw) === (int)$n[1];
        }
    }
    $json = is_string($raw) && strlen($raw) <= 1048576 ? json_decode($raw, true) : null;
    $complete = $http > 0 && is_string($raw) && strlen($raw) <= 1048576
        && $eof && !($meta['timed_out'] ?? false) && $lengthOk
        && is_array($json) && json_last_error() === JSON_ERROR_NONE;
    return ['complete' => $complete, 'http' => $http,
        'json' => $complete ? $json : null,
        'elapsed_ms' => (int)round((microtime(true) - $start) * 1000)];
};
$out = ['lane' => $lane, 'phase' => $phase,
    'marker' => $marker, 'routes' => [],
    'token_deleted' => false, 'business_dml_only_http' => true];
$issued = false;
try {
    $stage = 'token';
    if (!\think\facade\Cache::set($token, ['user' => [
            'store_user_id' => 2147480012, 'store_id' => 10001,
            'user_name' => $marker, 'real_name' => $marker,
            'is_super' => 1], 'store_id' => 10001,
            'is_login' => true], 300)
        || !\think\facade\Cache::has($token)) {
        throw new RuntimeException('Short File token unavailable');
    }
    $issued = true;
    $tokenJ['phase'] = 'token_issued'; $save($tokenPath, $tokenJ);
    $stage = 'add';
    $add = $request('add', ['form' => [
        'name' => $marker, 'summary' => $marker . ' NEW',
        'is_default' => 0, 'status' => 0, 'sort' => 9999]], $token);
    if (!$add['complete'] || $add['http'] !== 200
        || (int)($add['json']['status'] ?? -1) !== 200) {
        throw new RuntimeException('Add HTTP result failed/uncertain');
    }
    $rows = $query($connect(), 'SELECT SERVICE_ID FROM ' . $table
        . ' WHERE NAME=? AND STORE_ID=10001', [$marker]);
    if (count($rows) !== 1 || (int)$rows[0]['service_id'] <= 0) {
        throw new RuntimeException('Added service identity unresolved');
    }
    $id = (int)$rows[0]['service_id'];
    $journal['id'] = $id;
    $journal['phase'] = 'added'; $save($journalPath, $journal);
    $row = $own($connect(), $id);
    if ((int)$row['is_delete'] !== 0 || (int)$row['sort'] !== 9999
        || (string)$row['summary'] !== $marker . ' NEW') {
        throw new RuntimeException('Added row fields mismatch');
    }
    $out['routes']['add'] = ['http' => 200, 'status' => 200,
        'source_id' => $id, 'source_fields_match' => true,
        'elapsed_ms' => $add['elapsed_ms'],
        'full_json_key_type_shape' => $shape($add['json'])];
    $stage = 'edit';
    $edit = $request('edit', ['serviceId' => $id, 'form' => [
        'name' => $marker, 'summary' => $marker . ' EDIT',
        'is_default' => 0, 'status' => 0, 'sort' => 9998]], $token);
    if (!$edit['complete'] || $edit['http'] !== 200
        || (int)($edit['json']['status'] ?? -1) !== 200) {
        throw new RuntimeException('Edit HTTP result failed/uncertain');
    }
    $row = $own($connect(), $id);
    if ((int)$row['is_delete'] !== 0 || (int)$row['sort'] !== 9998
        || (string)$row['summary'] !== $marker . ' EDIT') {
        throw new RuntimeException('Edited row fields mismatch');
    }
    $journal['phase'] = 'edited'; $save($journalPath, $journal);
    $out['routes']['edit'] = ['http' => 200, 'status' => 200,
        'source_id' => $id, 'source_fields_match' => true,
        'elapsed_ms' => $edit['elapsed_ms'],
        'full_json_key_type_shape' => $shape($edit['json'])];
    if ($count($connect(), 'SELECT COUNT(*) FROM ' . $rel
        . ' WHERE SERVICE_ID=?', [$id]) !== 0) {
        throw new RuntimeException('External relation appeared; delete refused');
    }
    $stage = 'delete';
    $delete = $request('delete', ['serviceId' => $id], $token);
    if (!$delete['complete'] || $delete['http'] !== 200
        || (int)($delete['json']['status'] ?? -1) !== 200) {
        throw new RuntimeException('Delete HTTP result failed/uncertain');
    }
    $row = $own($connect(), $id);
    if ((int)$row['is_delete'] !== 1 || (int)$row['sort'] !== 9998
        || (string)$row['summary'] !== $marker . ' EDIT') {
        throw new RuntimeException('Soft-deleted row mismatch');
    }
    if ($count($connect(), 'SELECT COUNT(*) FROM ' . $rel
        . ' WHERE SERVICE_ID=?', [$id]) !== 0
        || $natural($connect(), $id) !== $sourceBefore) {
        throw new RuntimeException('Natural source/relation changed during HTTP');
    }
    $journal['phase'] = 'completed';
    $journal['own_sha256'] = hash('sha256', serialize($row));
    $save($journalPath, $journal);
    $out['routes']['delete'] = ['http' => 200, 'status' => 200,
        'source_id' => $id, 'source_is_delete' => 1,
        'elapsed_ms' => $delete['elapsed_ms'],
        'full_json_key_type_shape' => $shape($delete['json'])];
} catch (Throwable $e) {
    $out['failure_stage'] = $stage;
    $out['failure_class'] = get_class($e);
} finally {
    if ($issued) {
        \think\facade\Cache::delete($token);
        $out['token_deleted'] = !\think\facade\Cache::has($token);
    }
}
$out['pass'] = !isset($out['failure_class'])
    && $out['token_deleted'] && count($out['routes']) === 3;
echo json_encode($out, JSON_UNESCAPED_SLASHES), "\n";
exit($out['pass'] ? 0 : 3);
