pages/code.php
Snapshot 2026.09.17-a2894de (current) · 147 lines · 14,856 bytes · tree · plain text
SHA-256
f777036a4c1aa44d1b66c8183ba7069d5ab872a2fffa0c6f6d6ddb303392f387Functions: code_rate_limit L14-L21 · code_versions L22-L26 · code_lines L27-L43 · code_ver_link L44-L147
| 1 | <?php |
| 2 | /* WEB-001: the Code tab. A read-only view of the snapshot that inc/code-snapshot.php |
| 3 | writes at deploy: file tree, file view with line anchors, search, version stamp, |
| 4 | per-file SHA-256 and the manifest. GET only; the request selects a manifest |
| 5 | entry, never a filesystem path. Installed to pages/code.php by the AI platform's |
| 6 | deploy hook; source deploy/research/code.php in districthive/ai. */ |
| 7 | require_once __DIR__.'/../inc/layout.php'; |
| 8 | if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'GET') { http_response_code(405); exit; } |
| 9 | |
| 10 | const CODE_MAX_LINES = 1500; // a file view is paged beyond this |
| 11 | const CODE_MAX_HITS = 200; |
| 12 | const CODE_STATEMENT = 'Source shown for scrutiny of the research platform. All rights reserved. Not offered as installable software.'; |
| 13 | |
| 14 | function code_rate_limit(): void { |
| 15 | $dir = sys_get_temp_dir().'/dh-research-code-rl'; if (!is_dir($dir)) { @mkdir($dir, 0700); } |
| 16 | $now = time(); $f = $dir.'/'.hash('sha256', (string)($_SERVER['REMOTE_ADDR'] ?? '0')); |
| 17 | $hits = is_file($f) ? array_filter(array_map('intval', explode(',', (string)file_get_contents($f))), fn($t) => $t > $now - 600) : []; |
| 18 | if (count($hits) >= 150) { http_response_code(429); header('Retry-After: 600'); exit('Too many requests; please try again in a few minutes.'); } |
| 19 | $hits[] = $now; @file_put_contents($f, implode(',', $hits)); |
| 20 | if (random_int(1, 25) === 1) { foreach (glob($dir.'/*') ?: [] as $g) { if (@filemtime($g) < $now - 900) { @unlink($g); } } } |
| 21 | } |
| 22 | function code_versions(string $root): array { |
| 23 | $v = []; foreach (glob($root.'/*', GLOB_ONLYDIR) ?: [] as $d) { $b = basename($d); if (preg_match('/^\d{4}\.\d{2}\.\d{2}-[0-9a-f]{7}$/', $b) && is_file("$d/code-manifest.json")) { $v[] = $b; } } |
| 24 | rsort($v); return $v; |
| 25 | } |
| 26 | /* highlight_string output split into lines, with a span that crosses a line break reopened on the next line */ |
| 27 | function code_lines(string $src, string $ext): array { |
| 28 | if ($ext !== 'php') { return array_map(fn($l) => h(rtrim($l, "\r")), explode("\n", $src)); } |
| 29 | foreach (['highlight.comment' => '#7d8590', 'highlight.default' => '#e6edf3', 'highlight.html' => '#a5d6ff', 'highlight.keyword' => '#ff7b72', 'highlight.string' => '#a5d6ff'] as $k => $c) { ini_set($k, $c); } |
| 30 | $html = highlight_string($src, true); |
| 31 | $html = preg_replace('/^<pre><code style="color: #[0-9a-fA-F]{6}">/', '', $html); $html = preg_replace('/<\/code><\/pre>$/', '', $html); |
| 32 | $html = str_replace('<br />', "\n", $html); |
| 33 | $out = []; $open = null; |
| 34 | foreach (explode("\n", $html) as $line) { |
| 35 | $line = rtrim($line, "\r"); |
| 36 | $pre = $open !== null ? '<span style="color: '.$open.'">' : ''; |
| 37 | $count = preg_match_all('/<span style="color: (#[0-9a-fA-F]{6})">/', $line, $m, PREG_OFFSET_CAPTURE); $closes = substr_count($line, '</span>'); |
| 38 | if ($count > $closes) { $open = $m[1][$count - 1][0]; $line .= '</span>'; } |
| 39 | elseif ($count < $closes) { $open = null; } |
| 40 | $out[] = $pre.$line; |
| 41 | } |
| 42 | return $out; |
| 43 | } |
| 44 | function code_ver_link(string $v, string $f = '', array $extra = []): string { |
| 45 | $q = ['p' => 'code', 'v' => $v]; if ($f !== '') { $q['f'] = $f; } return 'index.php?'.http_build_query($q + $extra); |
| 46 | } |
| 47 | |
| 48 | code_rate_limit(); |
| 49 | $snapRoot = __DIR__.'/../inc/snapshots'; |
| 50 | $versions = code_versions($snapRoot); |
| 51 | $current = is_file("$snapRoot/current.json") ? (json_decode((string)file_get_contents("$snapRoot/current.json"), true) ?: []) : []; |
| 52 | $v = (string)($_GET['v'] ?? ''); |
| 53 | if ($v !== '' && !in_array($v, $versions, true)) { http_response_code(404); page_header('Code', 'code'); echo '<h1>Code</h1><p class="lede">No such version. <a href="index.php?p=code">Current snapshot</a>.</p>'; page_footer(); exit; } |
| 54 | if ($v === '') { $v = (string)($current['version'] ?? ($versions[0] ?? '')); } |
| 55 | if ($v === '') { page_header('Code', 'code'); echo '<h1>Code</h1><p class="lede">No snapshot has been written yet; the next deploy writes the first one.</p><p class="note">'.CODE_STATEMENT.'</p>'; page_footer(); exit; } |
| 56 | $manifest = json_decode((string)file_get_contents("$snapRoot/$v/code-manifest.json"), true) ?: ['files' => []]; |
| 57 | $byPath = []; foreach ($manifest['files'] as $e) { $byPath[$e['path']] = $e; } |
| 58 | $isCurrent = $v === ($current['version'] ?? ''); |
| 59 | |
| 60 | /* the manifest itself */ |
| 61 | if (!empty($_GET['manifest'])) { |
| 62 | header('Content-Type: application/json; charset=utf-8'); header('Content-Disposition: attachment; filename="code-manifest-'.$v.'.json"'); header('X-Content-Type-Options: nosniff'); |
| 63 | readfile("$snapRoot/$v/code-manifest.json"); exit; |
| 64 | } |
| 65 | |
| 66 | /* one file */ |
| 67 | $f = (string)($_GET['f'] ?? ''); |
| 68 | if ($f !== '') { |
| 69 | if (!isset($byPath[$f])) { http_response_code(404); page_header('Code', 'code'); echo '<h1>Code</h1><p class="lede">No such file in snapshot '.h($v).'. <a href="'.h(code_ver_link($v)).'">Back to the tree</a>.</p>'; page_footer(); exit; } |
| 70 | $e = $byPath[$f]; |
| 71 | $fn = (string)($_GET['fn'] ?? ''); |
| 72 | if ($fn !== '') { |
| 73 | if (isset($e['functions'][$fn])) { [$a, $b] = $e['functions'][$fn]; header('Location: '.code_ver_link($v, $f, ['from' => max(1, intdiv($a - 1, CODE_MAX_LINES) * CODE_MAX_LINES + 1)]).'#L'.$a.'-L'.$b); exit; } |
| 74 | header('Location: '.code_ver_link($v, $f)); exit; |
| 75 | } |
| 76 | $src = (string)file_get_contents("$snapRoot/$v/$f"); |
| 77 | if (!empty($_GET['raw'])) { header('Content-Type: text/plain; charset=utf-8'); header('X-Content-Type-Options: nosniff'); header('Content-Disposition: inline; filename="'.basename($f).'.txt"'); echo $src; exit; } |
| 78 | $lines = code_lines($src, strtolower(pathinfo($f, PATHINFO_EXTENSION))); |
| 79 | $total = count($lines); |
| 80 | $from = max(1, (int)($_GET['from'] ?? 1)); $from = min($from, $total); $to = min($total, $from + CODE_MAX_LINES - 1); |
| 81 | page_header('Code · '.$f, 'code'); |
| 82 | echo '<h1>'.h($f).'</h1><p class="lede">Snapshot <b>'.h($v).'</b>'.($isCurrent ? ' (current)' : ' (an earlier version; <a href="index.php?p=code&f='.rawurlencode($f).'">current</a>)').' · '.(int)$e['lines'].' lines · '.number_format((int)$e['bytes']).' bytes · <a href="'.h(code_ver_link($v)).'">tree</a> · <a href="'.h(code_ver_link($v, $f, ['raw' => 1])).'">plain text</a></p>'; |
| 83 | echo '<div class="kv code-sha">SHA-256 <code>'.h($e['sha256']).'</code></div>'; |
| 84 | if (!empty($e['functions'])) { echo '<div class="kv code-fns">Functions: '; $i = 0; foreach ($e['functions'] as $name => [$a, $b]) { echo ($i++ ? ' · ' : '').'<a href="'.h(code_ver_link($v, $f, ['fn' => $name])).'">'.h($name).'</a> <span class="mono">L'.$a.'-L'.$b.'</span>'; } echo '</div>'; } |
| 85 | if ($total > CODE_MAX_LINES) { |
| 86 | echo '<div class="kv code-pages">Pages: '; |
| 87 | for ($s = 1; $s <= $total; $s += CODE_MAX_LINES) { echo '<a href="'.h(code_ver_link($v, $f, ['from' => $s])).'"'.($s === $from ? ' aria-current="page"' : '').'>L'.$s.'-L'.min($total, $s + CODE_MAX_LINES - 1).'</a> '; } |
| 88 | echo '</div>'; |
| 89 | } |
| 90 | echo '<div class="card code-view"><table><tbody>'; |
| 91 | for ($n = $from; $n <= $to; $n++) { echo '<tr id="L'.$n.'"><td class="ln"><a href="#L'.$n.'">'.$n.'</a></td><td class="lc"><code>'.($lines[$n - 1] === '' ? ' ' : $lines[$n - 1]).'</code></td></tr>'; } |
| 92 | echo '</tbody></table></div>'; |
| 93 | echo '<p class="note">Lines can be cited as <span class="mono">'.h($f).' L120-L140, platform code '.h($v).'</span>; add <span class="mono">#L120-L140</span> to this page\'s address to highlight them. '.CODE_STATEMENT.'</p>'; |
| 94 | echo '<script>(function(){var m=location.hash.match(/^#L(\d+)(?:-L(\d+))?$/);if(!m)return;var a=+m[1],b=m[2]?+m[2]:a,first=null;for(var i=a;i<=b;i++){var r=document.getElementById("L"+i);if(r){r.classList.add("hl");first=first||r;}}if(first)first.scrollIntoView({block:"center"});})();</script>'; |
| 95 | page_footer(); exit; |
| 96 | } |
| 97 | |
| 98 | /* search */ |
| 99 | $q = trim((string)($_GET['q'] ?? '')); |
| 100 | if ($q !== '') { |
| 101 | page_header('Code · search', 'code'); |
| 102 | echo '<h1>Search the code</h1>'; |
| 103 | echo '<form class="controls" method="get"><input type="hidden" name="p" value="code"><input type="hidden" name="v" value="'.h($v).'"><div><label>TEXT</label><input type="text" name="q" value="'.h($q).'" maxlength="80" minlength="3"></div><button>Search</button></form>'; |
| 104 | if (mb_strlen($q) < 3) { echo '<p class="note">Three characters at least.</p>'; page_footer(); exit; } |
| 105 | $hits = 0; $needle = mb_strtolower(mb_substr($q, 0, 80)); |
| 106 | echo '<p class="lede">Snapshot <b>'.h($v).'</b>, file names and contents, case-insensitive.</p><table class="data"><tr><th>File</th><th>Line</th><th>Text</th></tr>'; |
| 107 | foreach ($byPath as $path => $e) { |
| 108 | if (mb_strpos(mb_strtolower($path), $needle) !== false) { echo '<tr><td><a href="'.h(code_ver_link($v, $path)).'">'.h($path).'</a></td><td></td><td class="kv">file name</td></tr>'; if (++$hits >= CODE_MAX_HITS) { break; } } |
| 109 | foreach (explode("\n", (string)file_get_contents("$snapRoot/$v/$path")) as $i => $line) { |
| 110 | if (mb_strpos(mb_strtolower($line), $needle) === false) { continue; } |
| 111 | $n = $i + 1; $snip = trim($line); if (mb_strlen($snip) > 160) { $pos = max(0, mb_strpos(mb_strtolower($snip), $needle) - 60); $snip = ($pos ? '…' : '').mb_substr($snip, $pos, 160).'…'; } |
| 112 | echo '<tr><td><a href="'.h(code_ver_link($v, $path, ['from' => max(1, intdiv($n - 1, CODE_MAX_LINES) * CODE_MAX_LINES + 1)])).'#L'.$n.'">'.h($path).'</a></td><td class="mono">'.$n.'</td><td><code class="code-snip">'.h($snip).'</code></td></tr>'; |
| 113 | if (++$hits >= CODE_MAX_HITS) { break 2; } |
| 114 | } |
| 115 | } |
| 116 | echo '</table><p class="note">'.($hits === 0 ? 'Nothing found.' : ($hits >= CODE_MAX_HITS ? 'The first '.CODE_MAX_HITS.' matches are shown; narrow the search for the rest.' : $hits.' match'.($hits === 1 ? '' : 'es').'.')).'</p>'; |
| 117 | page_footer(); exit; |
| 118 | } |
| 119 | |
| 120 | /* the tree */ |
| 121 | page_header('Code', 'code'); |
| 122 | echo '<h1>Code</h1><p class="lede">The Research Labs platform as it runs, shown for scrutiny: every file that reads an instrument, computes a stream, aggregates, checks provenance or renders a page, with a checksum per file. A reader of any published number can open the code that produced it.</p>'; |
| 123 | echo '<div class="card code-stamp"><h3>Version stamp</h3><div class="big">'.h($v).'</div><div class="kv">'.($isCurrent ? 'current snapshot' : 'an earlier version; <a href="index.php?p=code">current</a>').' · written '.h(str_replace('T', ' ', substr((string)($manifest['generated_at'] ?? ''), 0, 19))).' UTC · '.count($byPath).' files · commit: '.h((string)($manifest['commit'] ?? 'not from git')).'</div>'; |
| 124 | echo '<div class="kv">tree SHA-256 <code>'.h((string)($manifest['tree_sha256'] ?? '')).'</code></div><div class="kv">manifest SHA-256 <code>'.h((string)($manifest['manifest_sha256'] ?? '')).'</code> · <a href="'.h(code_ver_link($v, '', ['manifest' => 1])).'">code-manifest.json</a> (also printed on the <a href="index.php?p=vault">Raw Vault</a>)</div>'; |
| 125 | echo '<div class="kv">redaction: '.(!empty($manifest['redaction']['ran']) ? 'ran, '.(int)($manifest['redaction']['emails_redacted'] ?? 0).' e-mail address'.((int)($manifest['redaction']['emails_redacted'] ?? 0) === 1 ? '' : 'es').' redacted, secret scan '.h((string)($manifest['redaction']['secret_scan'] ?? '')) : 'not recorded').'</div>'; |
| 126 | if (count($versions) > 1) { echo '<div class="kv">Versions: '; foreach ($versions as $ov) { echo '<a href="'.h(code_ver_link($ov)).'"'.($ov === $v ? ' aria-current="page"' : '').'>'.h($ov).'</a> '; } echo '</div>'; } |
| 127 | echo '</div>'; |
| 128 | echo '<form class="controls" method="get"><input type="hidden" name="p" value="code"><input type="hidden" name="v" value="'.h($v).'"><div><label>SEARCH THE TREE</label><input type="text" name="q" maxlength="80" minlength="3" placeholder="function name, stream code, table"></div><button>Search</button></form>'; |
| 129 | |
| 130 | echo '<details class="card code-how" open><summary><b>How this platform is built</b></summary>'; |
| 131 | echo '<p><b>Stack.</b> PHP 8 and MySQL 8 behind Apache, written for this platform without a framework. Charts are dependency-free SVG drawn by assets/app.js. No third-party library is part of the tree; the one outside service is the Anthropic API, called from inc/ai.php for the Ask Grímnir page with a key held in the excluded configuration file.</p>'; |
| 132 | echo '<p><b>From instrument to published table.</b> cron/poll_all.php runs on a schedule and calls one client per instrument family under cron/clients/ (weather station, water-quality sonde, aquifer logger, sky quality meter, footfall counters, acoustic recorders). Each pull is stored as a raw file, checksummed and listed in files_raw (the Raw Vault), then parsed into readings rows: stream, timestamp, value, and a placeholder flag. Every stream starts in placeholder mode and flips to live with its first real reading; cron/health_check.php watches freshness and completeness. Pages under pages/ render the readings through inc/streampage.php and inc/helpers.php (series, latest, mode badges); api.php serves the same readings to keyed clients. schema.sql defines the tables.</p>'; |
| 133 | echo '<p><b>Excluded, and why.</b> config.php and its template (credentials); data/ (raw files, uploads, media); logs; admin/ (the write path, no part of how a published number is produced); diagnose.php (server layout); the snapshots themselves. Paths are shown relative to the application root. E-mail addresses other than the company\'s are redacted at snapshot time, and a scan for secret-like strings refuses to publish a snapshot that contains one; the allowlist and the snapshot script are in the tree (inc/code-allowlist.php, inc/code-snapshot.php).</p>'; |
| 134 | echo '<p><b>Versions.</b> A snapshot is written at each deploy. The version is the UTC date plus seven characters of the tree\'s SHA-256, so an unchanged tree keeps its version and a changed one cannot hide. Every version stays reachable by its stamp, every page footer prints the version that rendered it, and a citation reads: file, lines, platform code version.</p>'; |
| 135 | echo '<p class="kv">'.CODE_STATEMENT.'</p></details>'; |
| 136 | |
| 137 | $groups = []; |
| 138 | foreach ($byPath as $path => $e) { $dir = str_contains($path, '/') ? dirname($path) : '.'; $groups[$dir][] = $e; } |
| 139 | uksort($groups, fn($a, $b) => $a === '.' ? -1 : ($b === '.' ? 1 : strcmp($a, $b))); |
| 140 | foreach ($groups as $dir => $list) { |
| 141 | echo '<div class="card code-dir"><h3>'.h($dir === '.' ? 'application root' : $dir.'/').'</h3><table class="data"><tr><th>File</th><th>Lines</th><th>Bytes</th><th>SHA-256</th></tr>'; |
| 142 | foreach ($list as $e) { echo '<tr><td><a href="'.h(code_ver_link($v, $e['path'])).'">'.h(basename($e['path'])).'</a>'.(!empty($e['functions']) ? ' <span class="kv">'.count($e['functions']).' function'.(count($e['functions']) === 1 ? '' : 's').'</span>' : '').'</td><td class="mono">'.(int)$e['lines'].'</td><td class="mono">'.number_format((int)$e['bytes']).'</td><td class="mono code-hash" title="'.h($e['sha256']).'">'.h(substr($e['sha256'], 0, 16)).'…</td></tr>'; } |
| 143 | echo '</table></div>'; |
| 144 | } |
| 145 | echo '<p class="note">'.CODE_STATEMENT.' To verify a file: download it as plain text, compute its SHA-256, compare with the manifest.</p>'; |
| 146 | page_footer(); |
| 147 | |
Lines can be cited as pages/code.php L120-L140, platform code 2026.09.17-a2894de; add #L120-L140 to this page's address to highlight them. Source shown for scrutiny of the research platform. All rights reserved. Not offered as installable software.