SIMON Master Console Rebuild
True command center for SIMON + WEB360
This rebuild gives you a cleaner production spine: interactive tree, live viewer, guarded editor, dynamic graphics, architecture map, and note storage. It is designed to sit beside your existing
console.php
and become the stronger replacement path.
Dashboard
Tree
Viewer
System Map
File Registry
Notes
Files
15,026
Folders
377
Scanned Size
3.79 GB
PHP Files
791
Editable Text Files
12,310
File viewer
guarded to /htdocs
/api/_inc/simon_event_bus.php
<?php declare(strict_types=1); if (!function_exists('simon_phase2_config')) { function simon_phase2_config(): array { static $config = null; if ($config === null) { $loaded = require __DIR__ . '/simon_phase2_config.php'; $config = is_array($loaded) ? $loaded : []; } return $config; } } if (!function_exists('simon_phase2_db')) { function simon_phase2_db(): ?PDO { static $pdo = false; if ($pdo instanceof PDO) { return $pdo; } if ($pdo === null) { return null; } try { if (function_exists('simon_database_connection')) { $candidate = simon_database_connection('simon'); if ($candidate instanceof PDO) { $candidate->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $candidate->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $pdo = $candidate; return $pdo; } } if (defined('DB_DSN') && defined('DB_USER') && defined('DB_PASS')) { $candidate = new PDO((string) DB_DSN, (string) DB_USER, (string) DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]); $pdo = $candidate; return $pdo; } } catch (Throwable $e) { error_log('SIMON Phase 2 DB connection failed: ' . $e->getMessage()); } $pdo = null; return null; } } if (!function_exists('simon_phase2_uuid')) { function simon_phase2_uuid(): string { $bytes = random_bytes(16); $bytes[6] = chr((ord($bytes[6]) & 0x0f) | 0x40); $bytes[8] = chr((ord($bytes[8]) & 0x3f) | 0x80); $hex = bin2hex($bytes); return substr($hex, 0, 8) . '-' . substr($hex, 8, 4) . '-' . substr($hex, 12, 4) . '-' . substr($hex, 16, 4) . '-' . substr($hex, 20); } } if (!function_exists('simon_phase2_json')) { function simon_phase2_json(mixed $value): string { $json = json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE); return $json === false ? '{}' : $json; } } if (!function_exists('simon_phase2_request_context')) { function simon_phase2_request_context(): array { return [ 'method' => (string) ($_SERVER['REQUEST_METHOD'] ?? 'CLI'), 'uri' => (string) ($_SERVER['REQUEST_URI'] ?? ''), 'ip' => (string) ($_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? ''), 'user_agent' => (string) ($_SERVER['HTTP_USER_AGENT'] ?? ''), 'referer' => (string) ($_SERVER['HTTP_REFERER'] ?? ''), 'session_id' => session_status() === PHP_SESSION_ACTIVE ? session_id() : '', ]; } } if (!function_exists('simon_phase2_emit')) { /** * Emit a normalized 5W1H event. Database first, NDJSON fallback always retained. */ function simon_phase2_emit(string $eventType, array $data = [], ?PDO $pdo = null): array { $config = simon_phase2_config(); $eventUuid = (string) ($data['event_uuid'] ?? simon_phase2_uuid()); $scanUuid = trim((string) ($data['scan_uuid'] ?? '')); $projectId = isset($data['project_id']) && is_numeric($data['project_id']) ? (int) $data['project_id'] : null; $when = (string) ($data['when_event'] ?? (new DateTimeImmutable('now'))->format('Y-m-d H:i:s.u')); $who = is_array($data['who'] ?? null) ? $data['who'] : []; $what = is_array($data['what'] ?? null) ? $data['what'] : []; $where = is_array($data['where'] ?? null) ? $data['where'] : []; $why = is_array($data['why'] ?? null) ? $data['why'] : []; $how = is_array($data['how'] ?? null) ? $data['how'] : []; $health = is_array($data['health'] ?? null) ? $data['health'] : []; $truth = is_array($data['truth'] ?? null) ? $data['truth'] : []; $meta = is_array($data['meta'] ?? null) ? $data['meta'] : []; $meta['request'] = $meta['request'] ?? simon_phase2_request_context(); $meta['phase2_version'] = (string) ($config['version'] ?? '13.0.0'); $record = [ 'event_uuid' => $eventUuid, 'scan_uuid' => $scanUuid !== '' ? $scanUuid : null, 'project_id' => $projectId, 'event_type' => $eventType, 'who_type' => (string) ($who['type'] ?? 'system'), 'who_id' => (string) ($who['id'] ?? ''), 'who_name' => (string) ($who['name'] ?? ''), 'what_action' => (string) ($what['action'] ?? $eventType), 'what_entity_type' => (string) ($what['entity_type'] ?? ''), 'what_entity_id' => (string) ($what['entity_id'] ?? ''), 'what_entity_name' => (string) ($what['entity_name'] ?? ''), 'what_result' => (string) ($what['result'] ?? ''), 'when_event' => $when, 'where_host' => (string) ($where['host'] ?? ($_SERVER['HTTP_HOST'] ?? '')), 'where_root_path' => (string) ($where['root_path'] ?? ''), 'where_relative_path' => (string) ($where['relative_path'] ?? ''), 'where_url' => (string) ($where['url'] ?? ($_SERVER['REQUEST_URI'] ?? '')), 'why_reason' => (string) ($why['reason'] ?? ''), 'why_trigger' => (string) ($why['trigger'] ?? ''), 'how_method' => (string) ($how['method'] ?? ''), 'how_tool' => (string) ($how['tool'] ?? 'SIMON Phase 2'), 'how_version' => (string) ($how['version'] ?? ($config['version'] ?? '13.0.0')), 'health_status' => (string) ($health['status'] ?? 'ok'), 'health_score' => isset($health['score']) && is_numeric($health['score']) ? (float) $health['score'] : null, 'truth_status' => (string) ($truth['status'] ?? 'observed'), 'truth_confidence' => isset($truth['confidence']) && is_numeric($truth['confidence']) ? (float) $truth['confidence'] : null, 'meta' => simon_phase2_json($meta), ]; $result = ['event_uuid' => $eventUuid, 'database' => false, 'ndjson' => false, 'error' => null]; $pdo = $pdo ?? simon_phase2_db(); if ($pdo instanceof PDO) { try { $sql = 'INSERT INTO `' . str_replace('`', '', (string) ($config['event_table'] ?? 'simon_5w1h_events')) . '` ( event_uuid, scan_uuid, project_id, event_type, who_type, who_id, who_name, what_action, what_entity_type, what_entity_id, what_entity_name, what_result, when_event, where_host, where_root_path, where_relative_path, where_url, why_reason, why_trigger, how_method, how_tool, how_version, health_status, health_score, truth_status, truth_confidence, meta ) VALUES ( :event_uuid, :scan_uuid, :project_id, :event_type, :who_type, :who_id, :who_name, :what_action, :what_entity_type, :what_entity_id, :what_entity_name, :what_result, :when_event, :where_host, :where_root_path, :where_relative_path, :where_url, :why_reason, :why_trigger, :how_method, :how_tool, :how_version, :health_status, :health_score, :truth_status, :truth_confidence, :meta ) ON DUPLICATE KEY UPDATE what_result = VALUES(what_result), health_status = VALUES(health_status), health_score = VALUES(health_score), truth_status = VALUES(truth_status), truth_confidence = VALUES(truth_confidence), meta = VALUES(meta)'; $stmt = $pdo->prepare($sql); $stmt->execute($record); $result['database'] = true; } catch (Throwable $e) { $result['error'] = $e->getMessage(); error_log('SIMON Phase 2 event DB write failed: ' . $e->getMessage()); } } $fallbackDir = dirname(__DIR__) . '/_data/simon_phase2_events'; if (!is_dir($fallbackDir)) { @mkdir($fallbackDir, 0750, true); } $fallback = $fallbackDir . '/' . gmdate('Y-m-d') . '.ndjson'; $line = simon_phase2_json(array_merge($record, ['meta' => $meta])) . PHP_EOL; $result['ndjson'] = @file_put_contents($fallback, $line, FILE_APPEND | LOCK_EX) !== false; return $result; } }
Save file
Quick jump
open a path
Open