diff --git a/public_html/api.php b/public_html/api.php
index 0709239..0f80723 100644
--- a/public_html/api.php
+++ b/public_html/api.php
@@ -1,6 +1,8 @@
'Unauthorized', 'code' => 401]);
@@ -39,79 +41,63 @@ if ($endpoint !== 'auth' && $endpoint !== 'agent' && $endpoint !== 'netscan') {
}
}
-if ($endpoint !== 'auth') session_write_close(); // Skip for auth so login can write session token
+if ($endpoint !== 'auth') session_write_close();
$body = file_get_contents('php://input');
$data = json_decode($body, true) ?? [];
-switch ($endpoint) {
- case 'ping':
- echo json_encode(['status' => 'online', 'time' => date('c'), 'codename' => JARVIS_CODENAME]);
- break;
- case 'auth':
- require __DIR__ . '/../api/endpoints/auth.php';
- break;
- case 'chat':
- require __DIR__ . '/../api/endpoints/chat.php';
- break;
- case 'system':
- require __DIR__ . '/../api/endpoints/system.php';
- break;
- case 'netscan':
- require __DIR__ . '/../api/endpoints/netscan.php';
- break;
- case 'network':
- require __DIR__ . '/../api/endpoints/network.php';
- break;
- case 'proxmox':
- require __DIR__ . '/../api/endpoints/proxmox.php';
- break;
- case 'ha':
- require __DIR__ . '/../api/endpoints/ha.php';
- break;
- case 'tts':
- require __DIR__ . '/../api/endpoints/tts.php';
- break;
- case 'email':
- require __DIR__ . '/../api/endpoints/email.php';
- break;
- case 'do':
- require __DIR__ . '/../api/endpoints/do_server.php';
- break;
- case 'alerts':
- require __DIR__ . '/../api/endpoints/alerts.php';
- break;
- case 'facts':
- require __DIR__ . '/../api/endpoints/facts_collector.php';
- break;
- case 'weather':
- require __DIR__ . '/../api/endpoints/weather.php';
- break;
- case 'news':
- require __DIR__ . '/../api/endpoints/news.php';
- break;
- case 'sites':
- require __DIR__ . '/../api/endpoints/sites.php';
- break;
- case "agent":
- require __DIR__ . '/../api/endpoints/agent.php';
- break;
- case "planner":
- require __DIR__ . '/../api/endpoints/planner.php';
- break;
- case "arc":
- require __DIR__ . "/../api/endpoints/arc.php";
- break;
- case "directives":
- require __DIR__ . "/../api/endpoints/directives.php";
- break;
- case "memory":
- require __DIR__ . "/../api/endpoints/memory.php";
- break;
- case "calendar":
- require __DIR__ . '/../api/endpoints/calendar_sync.php';
- break;
- default:
- http_response_code(404);
- echo json_encode(['error' => 'Unknown endpoint: ' . $endpoint]);
+// ── Fast ping (no file dispatch needed) ──────────────────────────────
+if ($endpoint === 'ping') {
+ echo json_encode(['status' => 'online', 'time' => date('c'), 'codename' => JARVIS_CODENAME]);
+ exit;
+}
+
+// ── Endpoint → file map ───────────────────────────────────────────────
+$endpoints = [
+ 'auth' => 'auth.php',
+ 'chat' => 'chat.php',
+ 'system' => 'system.php',
+ 'netscan' => 'netscan.php',
+ 'network' => 'network.php',
+ 'proxmox' => 'proxmox.php',
+ 'ha' => 'ha.php',
+ 'tts' => 'tts.php',
+ 'email' => 'email.php',
+ 'do' => 'do_server.php',
+ 'alerts' => 'alerts.php',
+ 'facts' => 'facts_collector.php',
+ 'weather' => 'weather.php',
+ 'news' => 'news.php',
+ 'sites' => 'sites.php',
+ 'agent' => 'agent.php',
+ 'planner' => 'planner.php',
+ 'arc' => 'arc.php',
+ 'directives' => 'directives.php',
+ 'memory' => 'memory.php',
+ 'calendar' => 'calendar_sync.php',
+];
+
+if (!isset($endpoints[$endpoint])) {
+ http_response_code(404);
+ echo json_encode(['error' => 'Unknown endpoint: ' . $endpoint]);
+ exit;
+}
+
+$file = __DIR__ . '/../api/endpoints/' . $endpoints[$endpoint];
+
+// ── Fault-isolated dispatch ───────────────────────────────────────────
+// ob_start() buffers any partial output so a mid-execution fatal doesn't
+// send a broken response. catch(Throwable) catches ParseError, TypeError,
+// and all other Errors + Exceptions in PHP 7+.
+ob_start();
+try {
+ require $file;
+ ob_end_flush();
+} catch (\Throwable $e) {
+ ob_end_clean();
+ http_response_code(500);
+ echo json_encode(['error' => 'Endpoint unavailable', 'endpoint' => $endpoint, 'code' => 500]);
+ error_log(sprintf('JARVIS API [%s] %s: %s in %s:%d',
+ $endpoint, get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()
+ ));
}