false, 'error' => 'not_authenticated'], 401); } } function read_json_file(string $path): array { if (!file_exists($path)) return []; $raw = file_get_contents($path); if ($raw === false || trim($raw) === '') return []; $data = json_decode($raw, true); return is_array($data) ? $data : []; } function write_json_file_atomic(string $path, string $json): bool { // Ensure directory exists $dir = dirname($path); if (!is_dir($dir)) { if (!mkdir($dir, 0750, true)) return false; } $fp = fopen($path, 'c+'); if ($fp === false) return false; $ok = false; if (flock($fp, LOCK_EX)) { ftruncate($fp, 0); rewind($fp); $bytes = fwrite($fp, $json); fflush($fp); flock($fp, LOCK_UN); $ok = ($bytes !== false); } fclose($fp); return $ok; }