"storage's roundtrip answered $s: " . substr($out, 0, 160), "status" => 502]; if (!($r["listed"] ?? false)) return ["error" => "uploaded, but the file was not in the listing", "status" => 502]; // The download is a presigned B2 URL, fetched like a browser would: no assertion on it. $c = curl_init($r["download"]); curl_setopt_array($c, [CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_TIMEOUT => 30]); $back = (string)curl_exec($c); $code = (int)curl_getinfo($c, CURLINFO_HTTP_CODE); if ($code !== 200) return ["error" => "the download answered $code", "status" => 502]; $same = hash_equals(hash("sha256", $bytes), hash("sha256", $back)); return ["size" => strlen($bytes), "got" => strlen($back), "matched" => $same, "sha256" => substr(hash("sha256", $bytes), 0, 12)]; } return [ "n" => 12, "wing" => "Storage", "kind" => "self", "title" => "Your files", "promise" => "You can upload a file, see it listed, and download it again unchanged.", "block" => "storage keeps each person's files (B2-backed) behind their sign-in; an app links to it and never holds storage's keys. The check here uploads random bytes, lists them, downloads them and compares.", "show" => function (?array $me): string { $s = stored(12); $last = $s && ($s["data"]["matched"] ?? false) ? '
Last roundtrip, ' . ago((int)$s["at"]) . ': ' . (int)$s["data"]["size"] . ' bytes uploaded, listed and downloaded again: matched
' : 'No matching roundtrip recorded yet.
'; return $last . 'Open storage, upload something, and download it again.
'; }, "api" => function (string $do, ?array $me, array $in, bool $post): ?array { if ($do !== "roundtrip" || !$post) return null; if (!$me) return ["error" => "sign in first", "status" => 401]; return roundtrip_once(); }, // The robot asks the zoo to run the roundtrip as it (so the assertion names the robot). "check" => function (): array { require_once ZOO_ROOT . "/lib/robot.php"; [$code, , $j] = robot_at_zoo()->post("https://" . env("RC_HOST") . "/api/12/roundtrip"); if ($code !== 200 || !is_array($j)) return [false, "the roundtrip failed ($code): " . (is_array($j) ? ($j["error"] ?? "") : substr((string)$j, 0, 120))]; if (!$j["matched"]) return [false, "the downloaded copy differs from what was uploaded ({$j['size']} bytes up, {$j['got']} down)", $j]; return [true, "uploaded {$j['size']} random bytes, listed them, downloaded them again: matched (sha256 {$j['sha256']})", $j]; }, ];