'','faces'=>[],'complete'=>false];
if (!is_file($path) || is_link($path)) return $out;
$raw = @file_get_contents($path);
if (!is_string($raw) || $raw === '' || strlen($raw) > 262144) return $out;
if (preg_match('/^EMPIRE_FINGERPRINT\s+([0-9a-f]{64})\s*$/mi', $raw, $m)) $out['fingerprint'] = strtolower($m[1]);
if (preg_match_all('/^([0-9a-f]{64})\s+nosignup\.(com|org|net|trade|chat|work|market|date|fun|info)\s*$/mi', $raw, $mm, PREG_SET_ORDER)) {
foreach ($mm as $x) $out['faces']['nosignup.'.strtolower($x[2])] = strtolower($x[1]);
}
$need = ['nosignup.com','nosignup.org','nosignup.net','nosignup.trade','nosignup.chat','nosignup.work','nosignup.market','nosignup.date','nosignup.fun','nosignup.info'];
$out['complete'] = ($out['fingerprint'] !== '');
foreach ($need as $k) if (!isset($out['faces'][$k])) { $out['complete']=false; break; }
return $out;
}
function nsu_mirror_hello_payload(): array {
$mf = nsu_mirror_manifest_state();
$actual = strtolower((string)@hash_file('sha256', __FILE__));
$keys = ['nosignup.chat'];
$expected = '';
foreach ($keys as $k) { if (isset($mf['faces'][$k])) { $expected=(string)$mf['faces'][$k]; break; } }
$faceMatch = ($actual !== '' && $expected !== '' && hash_equals($expected, $actual));
$manual = ((string)getenv('NSU_MIRROR_OVERLOAD') === '1') || is_file(__DIR__ . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'mirror.pause');
$loadRatio = null; $over = $manual;
if (function_exists('sys_getloadavg')) {
$la = @sys_getloadavg();
if (is_array($la) && isset($la[0])) {
$cpus = 1;
if (is_file('/proc/cpuinfo')) { $c=@file_get_contents('/proc/cpuinfo'); if (is_string($c)) { $n=preg_match_all('/^processor\s*:/m',$c); if ($n>0) $cpus=$n; } }
$loadRatio = round(((float)$la[0]) / max(1,$cpus), 3);
$mx = (float)(getenv('NSU_MIRROR_LOAD_RATIO_MAX') ?: 1.50);
if ($mx > 0 && $loadRatio >= $mx) $over = true;
}
}
$compatible = !empty($mf['complete']) && $faceMatch;
return [
'ok'=>true,'schema'=>'nsu-mirror-hello-v1','node_kind'=>'mirror','face'=>NSU_MIRROR_FACE,
'face_hash'=>$actual,'empire_fingerprint'=>(string)$mf['fingerprint'],
'complete_organism'=>(bool)$mf['complete'],'manifest_face_match'=>$faceMatch,
'compatible_for_service'=>$compatible,'accepting_traffic'=>$compatible && !$over,
'overloaded'=>$over,'load_ratio'=>$loadRatio,
'economy_mesh'=>false,
'economy_note'=>'Service mirror only. Decentralized NSU consensus is not claimed by this build.',
'capacity_authority'=>false,
];
}
if ((string)($_GET['api'] ?? '') === 'mirror_hello') {
if (PHP_SAPI !== 'cli') {
header('Content-Type: application/json; charset=UTF-8');
header('Cache-Control: no-store, max-age=0');
header('Access-Control-Allow-Origin: *');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: no-referrer');
}
echo json_encode(nsu_mirror_hello_payload(), JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE); exit;
}
/* === /NSU V8 MIRROR SERVICE SUBSTRATE ===================================== */
/**
* FINAL-PACK MAINTENANCE CHARTER -- DO NOT DELETE.
* This is the durable operating soul for the standalone PHP. Fix evidence, not
* product fantasy.
*
* UNIVERSAL LAW: one stock-PHP file; no composer/npm/database dependency; no
* visitor signup, recovery account, tracking profile, shared bank, SSO, or
* paywall on basic use. Keep ?src=1 and ?download=1 auditable. This host owns
* only its own data, vault, and operator panel. A panel is never a visitor
* identity. Public status must never disclose vault/filesystem detail, and
* admin passwords belong in POST bodies, never URLs.
*
* SOUL: a minimal, honest peer-chat switch with dual left/right panes. HTML
* mode is the safer default (HTML local preview matches the outgoing JPEG cell); HD is optional and visibly hazardous. Try Peer
* and PeerID are invitations to try a peer path, never promises of a match.
* KEEP WORKING: entry disclaimer, dual panes, Try Peer/PeerID flow, clear
* leave/next behavior, protocol contract deeper in this file, source/download,
* and the local compose guide as advisory-only text.
* NEVER BECOME: Omegle theater, a central matching/moderation service, account
* system, chat-gems/second currency, paid match queue, hidden identity graph,
* fake reliability claim, protocol rewrite, or external AI authority.
* CHANGE BOUNDARY: preserve wire/protocol shapes and the two-pane product.
* Change engines only for a reproduced protocol failure with before/after
* evidence; a local guide may warn but must never silently block a send.
* PROOF: PHP lint; numbered/pack parity; protocol bookends and entry smoke;
* use a real two-browser note before claiming peer/match behavior works; then
* verify live source parity.
*/
/**
* DO NOT DELETE - NOSIGNUP.CHAT FILE HEADER + PROTOCOL (see full PROTOCOL CONTRACT below)
* SPIRIT: Peer chat — empire REFERENCE entrance-modal DNA.
*
* ORIGINAL LAYOUT DNA (conform loosely — edit > invent):
* - Dual L/R panels (Try Peer / PeerID / Send) after ENTER; sprite-sheet media panes.
* - Default HTML mode (safer, pixelated); HD opt-in with honest risk.
* - DNA line: CHAT · sprite green. Empire entrance is #nsGate:
* Options · Mirrors · Donate + feature rows + I AGREE ENTER (template for other crops).
* - Debug/stragglers live on Options (not corner-only primary chrome).
* - Full protocol MUST/MUST NOT block lives deeper in this file — keep it.
*/
/**
* FALLBACK / TOR (amended 2026-08-27).
* ALL: HTML face always serves. Telemetry, rate, KYC, counters, sprites, listings, chain writes SKIP
* (never 500, never invent a third root, never write KYC to durable disk just because RAM died).
* Loud banners required. An onion address may expose this face; a complete mirror is the full ten-face spore. No signup, no remint, no cookie-as-account.
* CHAT: dual panes + enter still work. No RAM: sprites do not persist; do not pretend they stored. No disk: id mill skips (no remint). KYC stays fail-off / RAM-only.
*/
/**
* LORD rent credit placeholder (ledger units) if rent/claim is ever wired for this crop.
* Chat has no visitor ledger / mint this ship — define only (com-style utility crop).
* Not a faucet; not visitor wallet; no chat-gems. Money/buy on nosignup.trade.
*/
const LORD_RENT_CREDIT = 10000;
/* ---- SITE-LOCAL CONTROL PANEL (renter key; not OS root) ---- */
function nsp_vault_dir(): string {
/* Sibling vault is optional; one public_html is enough. Local fallback is ./vault. */
$sib = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vault';
$loc = __DIR__ . DIRECTORY_SEPARATOR . 'vault';
foreach ([$sib, $loc] as $d) {
if (is_dir($d) || @mkdir($d, 0700, true)) {
if (is_dir($d) && is_writable($d)) return $d;
}
}
return $sib;
}
function nsp_data_dir(): string {
/* Disk fallback is ./data. Sibling vault is optional; one public_html is enough. */
$d = __DIR__ . DIRECTORY_SEPARATOR . 'data';
if (!is_dir($d)) @mkdir($d, 0755, true);
$ht = $d . DIRECTORY_SEPARATOR . '.htaccess';
if (!is_file($ht)) @file_put_contents($ht, "Require all denied\nDeny from all\n");
return $d;
}
/** Deny /data/ or /vault/ if a request path already hit this php file. No rewrite required. */
function nsp_reject_private_http_path(): void {
if (PHP_SAPI === 'cli') return;
$uri = (string)($_SERVER['REQUEST_URI'] ?? '');
$path = (string)(@parse_url($uri, PHP_URL_PATH) ?? '');
for ($i = 0; $i < 2; $i++) {
$decoded = rawurldecode($path);
if ($decoded === $path) break;
$path = $decoded;
}
$path = str_replace('\\', '/', $path);
if (strpos($path, "\0") !== false || preg_match('~(?:^|/)(?:vault|data)(?:/|$)~i', $path)) {
http_response_code(404);
header('Content-Type: text/plain; charset=UTF-8');
header('Cache-Control: private, no-store, max-age=0, must-revalidate');
echo "Not found\n";
exit;
}
}
nsp_reject_private_http_path();
function nsp_hash_file(): string { return nsp_data_dir() . DIRECTORY_SEPARATOR . 'admin.pass.hash'; }
function nsp_seed_file(): string { return nsp_data_dir() . DIRECTORY_SEPARATOR . 'site.seed'; }
function nsp_norm_seed(string $s): string {
return strtolower(trim(preg_replace('/\s+/', ' ', $s) ?? ''));
}
/** Identity surface only (same scheme as trade); chat has no visitor spend ledger.
* LEFT IN PLACE — economy+identity telomere IDENTITY slot points here (owner panel, not visitor mill). */
function nsp_addr_from_seed(string $seed): string {
return hash('sha256', 'nsu-addr-v1|' . nsp_norm_seed($seed));
}
/**
* 12-word site seed (not BIP39). CSPRNG into fixed word pool.
* Panel unlock for THIS crop only — not a faucet mint (chat has no visitor wallet / chat-gems).
*/
function nsp_generate_site_seed(): string {
static $wl = [
'able','acid','aged','also','aqua','arch','area','army','atom','aunt','auto','avoid',
'axis','baby','band','bank','bare','barn','base','bean','bear','belt','bike','bind',
'bird','bite','blue','boat','body','bold','bolt','bone','book','boot','born','bowl',
'brass','brave','bread','brick','brief','bring','broad','broke','brown','brush','build','bulk',
'burn','burst','bush','busy','cable','cage','cake','calm','camp','cane','cape','card',
'care','cart','case','cash','cast','cave','cell','cent','chat','chef','chin','chip',
'city','clap','clay','clip','club','coal','coat','code','coil','coin','cold','come',
'cook','cool','cope','copy','cord','core','corn','cost','cove','crab','crew','crop',
'crow','cube','cult','curb','cure','curl','dark','dart','dash','data','dawn','deal',
'dear','deck','deep','deer','desk','dial','dice','diet','dine','dirt','disc','dock',
'dome','done','door','dose','down','draw','drip','drop','drum','dual','duck','dune',
'dusk','dust','duty','each','earn','east','easy','echo','edge','edit','else','emit',
'epic','even','ever','evil','exit','face','fact','fade','fail','fair','fall','fame',
'farm','fast','fate','fear','feed','feel','fern','file','fill','film','find','fine',
'fire','firm','fish','flag','flat','flee','flip','flow','foam','foil','fold','font',
'food','fool','foot','ford','fork','form','fort','foul','four','free','frog','from',
'fuel','full','fund','fuse','gain','game','gate','gear','gene','gift','girl','give',
'glad','glow','glue','goal','goat','gold','golf','good','grab','grad','gram','gray',
'grid','grim','grin','grip','grow','gulf','guru','hail','hair','half','hall','hand',
'hang','hard','harm','harp','hate','have','hawk','haze','head','heal','heap','heat',
'heed','heel','held','help','herb','here','hero','hide','high','hill','hint','hire',
'hold','hole','home','hood','hook','hope','horn','host','hour','huge','hull','hung',
'hunt','hurt','icon','idea','idle','inch','info','into','iron','item','jade','jail',
'jazz','join','joke','jump','june','jury','just','keen','keep','kept','kick','kind',
'king','kite','knee','knew','knit','knot','know','lace','lack','lady','lake','lamp',
'land','lane','last','late','lava','lawn','lead','leaf','lean','left','lend','lens',
];
$n = count($wl);
$bytes = random_bytes(12);
$out = [];
for ($i = 0; $i < 12; $i++) {
$out[] = $wl[ord($bytes[$i]) % $n];
}
return implode(' ', $out);
}
/** Owner-only vault note: site seed = panel unlock for THIS crop. Never to renters/visitors. */
function nsp_vault_site_seed_note(string $seed): void {
$d = nsp_vault_dir();
if (!is_dir($d) && !@mkdir($d, 0700, true)) {
return;
}
@chmod($d, 0700);
$body = "NOSIGNUP.CHAT SITE WALLET SEED (OWNER ONLY)\n"
. "This seed unlocks /controlpanel for THIS crop only.\n"
. "Chat has no visitor ledger, faucet mint, or chat-gems on this crop. Money/buy: nosignup.trade.\n"
. "NO RECOVERY. Renters must NOT receive this secret (LORD seed is issued offline per epoch).\n"
. "Generated: " . gmdate('c') . "\n\n"
. trim($seed) . "\n";
@file_put_contents($d . DIRECTORY_SEPARATOR . 'SITE_WALLET_SEED.txt', $body, LOCK_EX);
@chmod($d . DIRECTORY_SEPARATOR . 'SITE_WALLET_SEED.txt', 0600);
}
/** True if $seed matches data/site.seed (normalized). */
function nsp_panel_seed_ok(string $seed): bool {
$seed = nsp_norm_seed($seed);
if ($seed === '') {
return false;
}
$path = nsp_seed_file();
if (!is_file($path)) {
return false;
}
$have = nsp_norm_seed((string)@file_get_contents($path));
if ($have === '') {
return false;
}
return hash_equals($have, $seed);
}
/**
* Ensure data/site.seed exists; mirror to vault SITE_WALLET_SEED.txt on first write.
* Idempotent. Call before admin API so setup is never land-grabable.
* NOT a treasury faucet mint — chat has no visitor ledger this crop.
*/
function nsp_ensure_site_seed(): void {
nsp_pass_burn();
$path = nsp_seed_file();
if (is_file($path) && nsp_norm_seed((string)@file_get_contents($path)) !== '') {
$vd = nsp_vault_dir();
$note = $vd . DIRECTORY_SEPARATOR . 'SITE_WALLET_SEED.txt';
if (!is_file($note) || trim((string)@file_get_contents($note)) === '') {
nsp_vault_site_seed_note(nsp_norm_seed((string)@file_get_contents($path)));
}
return;
}
$seed = nsp_generate_site_seed();
if (@file_put_contents($path, $seed . "\n", LOCK_EX) === false) return;
@chmod($path, 0600);
nsp_vault_site_seed_note($seed);
}
function nsp_json(array $x, int $c = 200): void {
http_response_code($c);
header('Content-Type: application/json; charset=UTF-8');
header('Cache-Control: no-store');
echo json_encode($x, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
function nsp_pass_burn(): void {
$paths = [
nsp_hash_file(),
nsp_data_dir() . DIRECTORY_SEPARATOR . 'admin.pass.txt',
nsp_vault_dir() . DIRECTORY_SEPARATOR . 'ADMIN_PASSWORD.txt',
];
foreach ($paths as $p) {
if (is_string($p) && $p !== '' && is_file($p) && !is_link($p)) {
@unlink($p);
}
}
}
function nsp_require(): void {
// POST body only — never accept seed from query (URL/access logs/Referer).
nsp_pass_burn();
$seed = (string)($_POST['seed'] ?? '');
if ($seed !== '' && nsp_panel_seed_ok($seed)) {
return;
}
nsp_json(['ok' => false, 'err' => 'admin auth'], 401);
}
function nsp_handle_admin_api(string $api): bool {
if (!str_starts_with($api, 'admin_')) return false;
nsp_ensure_site_seed();
if ($api === 'admin_status') {
// Soft-verify: site + version only. No filesystem vault path to strangers.
nsp_json(['ok' => true, 'site' => 'chat', 'version' => 'chat']);
}
if ($api === 'admin_login' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
nsp_json(['ok' => true, 'msg' => 'ok', 'site' => 'chat', 'vault_hint' => nsp_vault_dir(), 'version' => 'chat']);
}
/* LORD SOVEREIGNTY — rotate this crop's panel seed.
*
* Until this existed a lord could not become independent of the king. The
* ten panel seeds are minted by genesis and every one of them is printed in
* the king's GENESIS-INFO.txt, so the key to a rented crop was issued by the
* landlord and the landlord kept a copy. admin_change_pass rotates only the
* legacy PASSWORD, which changes nothing: nsp_require() accepts the seed
* directly, so the seed is the real door and it could never be changed.
*
* That is fine for a staff position and wrong for a tenancy - and the rent
* system (admin_rent_claim, operator_addr, NST_RENT_NSU_PER_DAY) says
* tenancy is the intent. A tenant whose landlord holds a key to the safe is
* not a tenant.
*
* CONFIRMATION IS REQUIRED AND CASE-SENSITIVE, matching the WIPE prompt in
* Deploy.bat. Re-keying is irreversible with no recovery desk, so it must be
* un-runnable by accident rather than merely documented as dangerous.
*
* THE ADDRESS CHANGES, AND THAT HAS CONSEQUENCES THE CALLER MUST SEE.
* Addresses derive from seeds, so a new seed is a new wallet:
* - the crop's existing NSU stays at the OLD address, which the old seed
* still opens; move it deliberately, it is not swept
* - trade pays this crop's emission share to the address in its on-chain
* crop registry, which still names the OLD one until a successor is
* anchored there
* Both are reported in the response rather than left to be discovered.
*/
if ($api === 'admin_rekey' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
if ((string)($_POST['confirm'] ?? '') !== 'REKEY') {
nsp_json([
'ok' => false,
'err' => 'Re-keying replaces this crop\'s panel seed permanently. There is no '
. 'recovery desk. POST confirm=REKEY to proceed.',
'confirm_required' => 'REKEY',
], 400);
}
$oldSeed = nsp_norm_seed((string)@file_get_contents(nsp_seed_file()));
$oldAddr = $oldSeed !== '' ? nsp_addr_from_seed($oldSeed) : '';
$new = nsp_generate_site_seed();
$newAddr = nsp_addr_from_seed($new);
if ($new === '' || $newAddr === '' || $newAddr === $oldAddr) {
nsp_json(['ok' => false, 'err' => 'seed generation failed'], 500);
}
/* Vault note first: it is the operator's offline copy, so if the second
* write fails the seed still exists somewhere other than this response.
* The old seed keeps working until site.seed itself is replaced, so a
* half-finished rotation locks nobody out. */
nsp_vault_site_seed_note($new);
if (@file_put_contents(nsp_seed_file(), $new . "\n", LOCK_EX) === false) {
nsp_json(['ok' => false, 'err' => 'could not write site.seed - crop unchanged, old seed still valid'], 500);
}
@chmod(nsp_seed_file(), 0600);
/* Read back before claiming success. Reporting a rotation that did not
* land would strand the lord with a seed the crop does not accept. */
$check = nsp_norm_seed((string)@file_get_contents(nsp_seed_file()));
if ($check !== nsp_norm_seed($new)) {
nsp_json(['ok' => false, 'err' => 'readback mismatch - rotation not confirmed'], 500);
}
nsp_json([
'ok' => true,
'seed' => $new,
'seed_shown_once' => true,
'old_addr' => $oldAddr,
'new_addr' => $newAddr,
'vault' => 'SITE_WALLET_SEED.txt',
'next_steps' => [
'SAVE THIS SEED OFFLINE NOW. It is shown once and there is no recovery desk.',
'The king\'s copy of the previous seed no longer opens this crop.',
'Your NSU is still at the OLD address - the old seed opens that wallet. '
. 'Transfer it to the new address deliberately; nothing is swept for you.',
'Trade still pays this crop\'s emission to the OLD address until a successor '
. 'is anchored in its on-chain crop registry.',
],
'msg' => 'Panel seed rotated. This crop is now yours alone.',
]);
}
if ($api === 'admin_get_source' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
$raw = (string)file_get_contents(__FILE__);
nsp_json(['ok' => true, 'bytes' => strlen($raw), 'sha256' => hash('sha256', $raw), 'source' => $raw]);
}
if ($api === 'admin_put_source' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
$src = (string)($_POST['source'] ?? '');
if (strlen($src) < 100 || strpos($src, ' false, 'err' => 'bad source'], 400);
$bak = __FILE__ . '.bak.' . time();
@copy(__FILE__, $bak);
if (file_put_contents(__FILE__, $src, LOCK_EX) === false) nsp_json(['ok' => false, 'err' => 'write failed'], 500);
nsp_json(['ok' => true, 'msg' => 'replaced', 'backup' => basename($bak), 'sha256' => hash('sha256', $src)]);
}
nsp_json(['ok' => false, 'err' => 'unknown admin api'], 404);
return true;
}
function nsp_render_controlpanel(): void {
header('Content-Type: text/html; charset=UTF-8');
header('Cache-Control: no-store');
$site = 'Nosignup.Chat';
echo '
Site-local renter key for THIS crop. '
. 'Paste this crop\'s site wallet seed (vault SITE_WALLET_SEED.txt / data/site.seed). '
. 'UTTER control of THIS index.php (incl. replace). Not OS root. Independent vault. '
. 'Rent until yearly reset — no refunds. Yearly wipe clears visitor data; site wallet seed is not rotated by wipe (rotate seed yourself if leaked). '
. 'This peer-chat crop has no visitor wallet, faucet mint, or chat-gems. '
. 'Money/buy lives on nosignup.trade. Panel door is site seed only. Leftover admin password files are unlinked.
';
echo '
';
echo '';
echo '';
echo '';
echo '';
echo '
Owner: seed auto-generated at first boot into data/site.seed + vault SITE_WALLET_SEED.txt (root pull). Paste seed → unlock. No password product path. No recovery desk. Chat is not a mint. Not a visitor account.
';
exit;
}
// --- controlpanel early gate (before any HTML) ---
// Site seed genesis BEFORE any admin API / controlpanel (no land-grab window).
$_nsp_api = (string)($_GET['api'] ?? $_POST['api'] ?? '');
$_nsp_panel = isset($_GET['controlpanel']) || (isset($_SERVER['REQUEST_URI']) && preg_match('#/controlpanel/?(\?|$)#', (string)$_SERVER['REQUEST_URI']));
if (($_nsp_api !== '' && str_starts_with($_nsp_api, 'admin_')) || ($_nsp_panel && $_nsp_api === '')) {
nsp_ensure_site_seed();
}
if ($_nsp_api !== '' && str_starts_with($_nsp_api, 'admin_')) { nsp_handle_admin_api($_nsp_api); }
if ($_nsp_panel && $_nsp_api === '') { nsp_render_controlpanel(); }
/**
* DO NOT DELETE/REMOVE THIS BLOCK - NOSIGNUP.CHAT PROTOCOL CONTRACT.
* AUTHORITATIVE. Change code to satisfy this; MUST/MUST NOT/MAY/SHOULD bind.
*
* 0 PRIME: no signup/install/account/cookie. One readable index.php over ordinary
* HTTP for cheap hosts/hostile networks. PHP is a dumb switchboard; browser owns
* robustness, identity, payments, mirrors, UI. Prefer small; do not grow
* (amended 2026-08-27 — live file is already over 200KB; do not strip trainer/chat to hit 150KB).
* Mirrors are disposable; swarm regrows through browser gossip plus
* RAM-only reminders. Parity proves source bytes, not host behavior. No central
* server, obfuscation, mirror-side entitlements, or server trust/moderation.
*
* 1 BOUNDARIES: MUST NOT use WebSocket, SSE, STUN, TURN, long-poll, sessions,
* cookies, accounts, or server media decode. Single deployable file; runtime
* files only as sec 4 permits. One upload pass and one fetch pass per active
* panel/tick. Server routes by filename + size + mtime + tail only.
*
* 2 WIRE: [4 vLen BE][JPEG 3x3 sheet, cell 20x15->80x60 over 20s from first link; viewer uses sheet/3][4 aLen BE][G.711 u-law][UTF-8 tail].
* Host-only RTC after visible media MAY send vLen=0/aLen=0 maintenance blobs.
* 9 frames x 256ms=2304ms, center crop .85, JPEG_Q=.50. Audio ON: 9 x 256ms
* mono u-law at 12kHz (~30KB/s); OFF sends aLen=0. Non-8kHz audio MUST carry sr.
* Exhaustive tail keys: head, sid, sr, msg, msg_ts, bridge_target, px_hit, rtc.
* Adding keys is a protocol change. MUST NOT add seq.
*
* 3 IDENTITY: public ticket is a sequential integer (1, 2, 3...). First visit
* to ANY of the ten faces with no stored ID assigns that ticket and a wallet
* to this browser/device instance (chat: POST ?api=id; PHP flock-increments
* the shared mill data/id.counter, or nosignup.shared/id.counter with trade,
* and returns the next number). Store in localStorage nosignup_device_id.
* Same browser, same stored ticket (two tabs are one person). Incognito or
* another device is another person. NEVER lock identity to IP — the same
* address must not open someone else's wallet. Bind to the stored ticket /
* seed, not the network address. Same key and same mill as trade — the
* number IS the wallet receipt. Gossip the ticket across the ten so a
* return restores the profile with no signup. All ten keep one .txt per
* user (userID + userinfo + wallet) in an aa folder-of-folders like
* sprite/{aa}/ and trade keys/{aa}/; NOT sharded by IP. Never remint on
* refresh or remint seeds. Digits only for new IDs. Badge shows the number
* so it can be read aloud. Leftover 16-hex or 8-char in this browser are
* exchanged for a mill number on next load. Seeds are not reminted. The
* badge is the integer. MUST NOT put raw IP in JS,
* HTML, localStorage, or the copied ticket. Override hook: setOverrideId /
* claimIdIfFree (trade may later sell a free number; chat does not buy).
* Engine still publishes {id}_{L|R} and {id}_H_{L|R}; seekers append _S.
* Public ticket extracted from that name MUST be the plain number (or
* leftover 8/16-char legacy), NEVER 109_H: strip _H_(L|R) first, then
* _(L|R), then _S. Linked/log copy shows that public ticket, not a slice
* of the engine name. No visitor ledger, cookie, or signup. Optional KYC
* grouping still uses a separate HMAC tag; metadata stores neither raw IP
* nor a visitor account. Money still lives on trade. The wallet is the
* seed. The public ticket is the receipt name.
*
* 4 STORAGE: RAM: /dev/shm/nosignup/sprite/{peerId}.bin and
* /dev/shm/nosignup/mirrors.txt. One RAM blob/user, two while bridging; newest
* replaces old; flat dir; routing in filename. mirrors.txt is untrusted URL+ts
* gossip only, cap 64, lazy/TTL, torn reads OK. Optional verification metadata:
* /dev/shm/nosignup/kyc/metadata.log with a volatile .salt; enable only when
* /dev/shm is tmpfs/ramfs and host swap is off. Cap the whole log at 64KiB;
* inactive data expires after 30d or sooner at host reboot/shutdown.
* Store ts + client tag + peer/session ids + act only; no sample.jpg/raw IP.
* Sprite writes SHOULD be direct final replacement; clients drop torn/invalid/
* truncated/decode-failed blobs as no-fresh-frame. Seek uses fresh _S only.
*
* 5 UPLOAD: active panel prep blob -> fire POST without await -> base pass at
* UPLOAD_MS - prep; if ACK is still pending then retry at the ACK cutoff, not
* another full grid. Cadence=max(prep,UPLOAD_MS), not prep+post. Exactly one POST;
* _postInflight skips prep+POST while prior POST is out. ACK cutoff below
* UPLOAD_MS. Idle uploads nothing. Instrument prep_ms/post_ms/queue/code. JPEG
* encode SHOULD use Worker; fallback explicit synchronous toDataURL, never
* main-thread toBlob callback. Mic SHOULD use AudioWorklet; ScriptProcessor is
* fallback. api=encworker/api=micworklet are startup-only same-file scripts.
* MUST NOT vary chunks, frame rate, upload cadence, or JPEG_Q to chase bytes.
*
* 6 FETCH/LIVENESS: fetch target peerId on 1024ms grid, one GET in flight/panel.
* Manual stop/reset is authoritative; stale async callbacks MUST NOT revive old
* epochs. Fresh decoded head > high-water is alive. Same/older head, 404/204,
* fetch error, invalid blob, decode failure -> same no-fresh-frame path. Match
* may echo _S sid/head; client rejects sid mismatch or far-out first head. After
* match briefly publish own _S; exact remote BASE fetch MAY serve fresh remote _S.
* Disconnect budgets are wall-clock: orphan 6s, established 6s. Silence=black/silence.
*
* 7 PLAYBACK: cursor advances 1 frame/256ms by wall clock. Blobs lay absolute
* rails: firstAbs=head-8; wantAbs=anchor.abs+floor((now-anchor.time)/256). Draw
* newest blob covering wantAbs; audio same abs, play once. Arrival order irrelevant.
* Re-anchor only on first blob/underrun/runaway/sender swap; skip forward to
* newestAbs-PLAY_RUNWAY. Exhaustion blanks. No hold, loop, catch-up speed, or back replay.
*
* 8 SENDER/BRIDGE: head > high-water alive; head <= high-water within
* SWAP_GAP_FRAMES drop; larger drop means sender swap -> re-anchor. Bridge only
* after both panels have same-mirror remote IDs. Bridge is HTTP-mode only; WebRTC/HD
* disables Bridge UI/state. Bridge sets bridge_target={peerId}; /sprite
* reads only that key, emits X-Bridge-Target, streams target if fresh.
* Clients accept SID changes only under that header.
*
* 9 ADD-ONS: PIXEL px_hit best-effort; click/draw mapping MUST use displayed
* bitmap rect; one-shot on upload ACK. A tail hit is not authority: the other
* browser can ignore or forge it. Holes live on the shooter's playback of the
* remote sheet (pixelAcks), not on the victim's encoder or res cap.
* px_hit MUST carry w,h. HELP NETWORK ?src=1 MUST expose normalized parity CORS;
* browser MUST hash source before mirror use. PHP MAY remember untrusted mirror
* URLs only in RAM mirrors.txt; MUST NOT fetch/probe/score/relay mirrors. DONATION
* vanity is browser self-rename only; PHP MUST NOT check ledgers, trust proofs,
* store names, edit KYC, reserve IDs, refund, recover, or be name authority.
* AUDIO RAIL is local visualization only. SPECIFIC-ID is browser-owned; explicit
* ID/substr plus optional mirror hint resolves via fresh base/_S sprite filenames;
* no directory/inbox/caller queue/mailbox. Cross-mirror lookup MAY probe same-parity staged mirrors by CORS
* sprite reads; remote mirror URL stays browser-local; PHP MUST NOT relay. TRUSTED
* mirrors are user-staged/browser-held; PHP stores URL hints only, never trust/rank/vote.
*
* 9A AUDIO/ADULT: audio media only: sr=12000 when ON, aLen=0 when OFF, no match
* split. Adult section publishes {deviceId}_H_{L|R}; normal publishes {deviceId}_{L|R};
* random/partial/explicit same-mirror matches MUST NOT cross namespace. `_H`
* reserved; PHP enforces by filename/fromPeerId. HTML Mode default. WebRTC Mode
* explicit opt-in: host-only, iceServers=[], signaling via rtc tail, PHP blind,
* peer IP may be exposed, strict NAT falls back to HTTP. UI MUST warn in large
* direct-IP language before enabling HD; no moderation/warranty/recovery/recourse.
* HD tooltip states current mode; toggle retunes own cam.
* Once RTC visible, HTTP SHOULD become no-media head/sid/rtc/chat/px maintenance.
*
* 10 DIAGNOSTICS: trace/overlay opt-in and MUST NOT alter protocol. Trace DOM
* and debug-only state MUST be bounded. Judge production with trace/debug OFF.
* Key metric: jitter-buffer lead vs PLAY_RUNWAY.
*
* 11 LANDMINES: no background-send uploads; no await-held prep guard; no rAF
* capture/playback; no unbounded/awaited upload cadence or skip grids; no seq;
* no held/looped underrun frame; no unmeasured timing cuts; no per-event DOM trace;
* no temp files/locks/validation for sprite races; no masking gaps by raising
* runway; no ACK wait past next slot; no jitter re-anchor; no main-thread toBlob;
* no ScriptProcessor-only mic.
* DO NOT DELETE/REMOVE THIS BLOCK - NOSIGNUP.CHAT PROTOCOL CONTRACT.
*/
// ===== FILE MAP (sections in physical order) =====
// ABOVE (do not reorder): charter/soul header; vault+admin API+controlpanel;
// PROTOCOL CONTRACT (bookends — immutable); then this map.
// BLOCK 1 PHP config + /dev/shm storage + helpers (mirrors, sprites, pid_*)
// API encworker · micworklet · mirror gossip · upload · sprite fetch · seek/match/bridge
// SRC ?src=1 / ?download=1 source/parity stream
// HTML/CSS dual L/R shell · entry #nsGate · Options/Mirrors/Donate/HD
// BLOCK 2 JS config + state · deviceId / API helper
// TICK payload builders · normalizePeerId / normalizePeerQuery
// BLOCK 3–9 utilities · forensic trace · capture · media · audio · pack · debug
// BLOCK 10–12 upload loop · fetch loop · playback timeline
// BLOCK 13–14 device switchers · bindings + disclaimer enter flow
// TAIL donate modal · network/mirror staging · empire DBG (opt-in)
// TELOMERE economy+identity: IDENTITY pointers (mill/JS left in place) + ECONOMY ask-trade
// =================================================
// ===== BLOCK 1: PHP CONFIG + STORAGE DIRS =====
error_reporting(0); ini_set('display_errors', 0); ini_set('log_errors', 1);
$SPRITE_DIR = '/dev/shm/nosignup/sprite';
$MIRROR_FILE = '/dev/shm/nosignup/mirrors.txt';
/* WORKTABLES: one RAM root. Keep /dev/shm/nosignup. Fallback mkdir only if shm missing. KYC stays at $KYC_BASE and fail-off. */
if (DIRECTORY_SEPARATOR !== '/' || !is_dir('/dev/shm') || !is_writable('/dev/shm')) {
$fb = nsp_data_dir() . DIRECTORY_SEPARATOR . 'ephemeral';
@mkdir($fb . DIRECTORY_SEPARATOR . 'sprite', 0755, true);
if (is_dir($fb . DIRECTORY_SEPARATOR . 'sprite') && is_writable($fb . DIRECTORY_SEPARATOR . 'sprite')) {
$SPRITE_DIR = $fb . DIRECTORY_SEPARATOR . 'sprite';
$MIRROR_FILE = $fb . DIRECTORY_SEPARATOR . 'mirrors.txt';
}
}
/** In-file pepper for one-way visitor IP token. NOT the 12-word owner seed. */
const NSC_ID_PEPPER = 'nsc-id-v1:68c8d3f0b10c095594d99b7c1be915d7f22acab5e4a08da2815097b760334f90';
/** One-way token of REMOTE_ADDR. Never echo raw IP into JS/HTML/storage. */
function nsc_ip_token(): string {
$ip = (string)($_SERVER['REMOTE_ADDR'] ?? '');
return hash('sha256', NSC_ID_PEPPER . "\x1e" . $ip);
}
/** Public ticket from a published peerId. Strip _H_(L|R) first, then _(L|R), then _S. Plain number or leftover 8/16-char legacy; never 109_H. */
function nsc_public_ticket(string $pid): string {
$pid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $pid) ?? '';
$pid = preg_replace('/_H_(L|R)/', '', $pid) ?? '';
$pid = preg_replace('/_(L|R)/', '', $pid) ?? '';
$pid = preg_replace('/_S$/', '', $pid) ?? '';
return $pid;
}
/** First 2 hex of public ticket (or sha256) — 256 fan-out. Groups L/R/H/S of same id. */
function nsc_sprite_aa(string $pid): string {
$ticket = nsc_public_ticket($pid);
$hex = preg_replace('/[^a-f0-9]/', '', strtolower($ticket)) ?? '';
if (strlen($hex) >= 2) return substr($hex, 0, 2);
return substr(hash('sha256', $ticket !== '' ? $ticket : $pid), 0, 2);
}
/** Prefer shard sprite/{aa}/$pid.bin; read legacy flat sprite/$pid.bin. */
function nsc_sprite_path(string $pid, bool $create = false): ?string {
global $SPRITE_DIR;
$pid = preg_replace('/[^a-zA-Z0-9_\-]/', '', $pid) ?? '';
if (strlen($pid) < 3 && !preg_match('/^[1-9][0-9]*$/', $pid)) return null;
$aa = nsc_sprite_aa($pid);
$shard = $SPRITE_DIR . DIRECTORY_SEPARATOR . $aa;
$p = $shard . DIRECTORY_SEPARATOR . $pid . '.bin';
if ($create) {
if (!is_dir($SPRITE_DIR) && !@mkdir($SPRITE_DIR, 0755, true) && !is_dir($SPRITE_DIR)) return null;
if (!is_dir($shard) && !@mkdir($shard, 0755, true) && !is_dir($shard)) return null;
return $p;
}
if (is_file($p)) return $p;
$flat = $SPRITE_DIR . DIRECTORY_SEPARATOR . $pid . '.bin';
return is_file($flat) ? $flat : null;
}
function nsc_sprite_glob(string $pattern = '*.bin'): array {
global $SPRITE_DIR;
$out = [];
foreach (glob($SPRITE_DIR . DIRECTORY_SEPARATOR . '*' . DIRECTORY_SEPARATOR . $pattern) ?: [] as $f) {
if (is_file($f)) $out[] = $f;
}
foreach (glob($SPRITE_DIR . DIRECTORY_SEPARATOR . $pattern) ?: [] as $f) {
if (is_file($f)) $out[] = $f;
}
return $out;
}
/** Atomic integer mill. One counter file; trade uses the same mill. Not a signup.
* LEFT IN PLACE — economy+identity telomere IDENTITY slot points here (functions sit next to top-level $KYC_*). */
function nsc_ticket_read_counter(string $path): int {
if (!is_file($path) || !is_readable($path)) return 0;
$raw = trim((string)@file_get_contents($path));
return preg_match('/^[0-9]{1,18}$/', $raw) ? (int)$raw : 0;
}
function nsc_ticket_seed_counter(string $path, int $max): bool {
$dir = dirname($path);
if (!is_dir($dir)) {
if (!@mkdir($dir, 0775, true) && !is_dir($dir)) return false;
}
if (!is_writable($dir)) return false;
$fh = @fopen($path, 'c+');
if (!is_resource($fh)) return false;
if (!@flock($fh, LOCK_EX)) { @fclose($fh); return false; }
$raw = stream_get_contents($fh);
$now = (is_string($raw) && preg_match('/^[0-9]{1,18}$/', trim($raw))) ? (int)trim($raw) : 0;
$write = max($now, $max);
if ($write !== $now || $raw === '' || $raw === false) {
rewind($fh);
ftruncate($fh, 0);
fwrite($fh, (string)$write);
fflush($fh);
}
@flock($fh, LOCK_UN);
@fclose($fh);
@chmod($path, 0600);
return true;
}
/**
* Live: /var/www/nosignup.{chat,trade}/html → nosignup.shared/id.counter
* (else the sibling crop's existing file). Desktop/NSU stays on local
* data/id.counter — both faces already share that folder. Never lowers
* an existing counter, so old chat numbers stay valid.
*/
function nsc_ticket_mill_path(): string {
$localDir = nsp_data_dir();
$local = $localDir . DIRECTORY_SEPARATOR . 'id.counter';
$siteRoot = dirname(__DIR__);
$www = dirname($siteRoot);
$site = strtolower(basename($siteRoot));
if (!preg_match('/^nosignup\.(chat|trade)$/', $site)) {
return $local;
}
$sharedDir = $www . DIRECTORY_SEPARATOR . 'nosignup.shared';
$shared = $sharedDir . DIRECTORY_SEPARATOR . 'id.counter';
$chatC = $www . DIRECTORY_SEPARATOR . 'nosignup.chat' . DIRECTORY_SEPARATOR . 'html' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'id.counter';
$tradeC = $www . DIRECTORY_SEPARATOR . 'nosignup.trade' . DIRECTORY_SEPARATOR . 'html' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'id.counter';
$max = max(
nsc_ticket_read_counter($local),
nsc_ticket_read_counter($shared),
nsc_ticket_read_counter($chatC),
nsc_ticket_read_counter($tradeC)
);
/* Do not create /var/www/nosignup.shared. Sibling vault is optional; one public_html is enough. */
if (is_dir($sharedDir) && nsc_ticket_seed_counter($shared, $max)) return $shared;
if (nsc_ticket_seed_counter($chatC, $max)) return $chatC;
if (nsc_ticket_seed_counter($tradeC, $max)) return $tradeC;
nsc_ticket_seed_counter($local, $max);
return $local;
}
function nsc_id_counter_file(): string {
return nsc_ticket_mill_path();
}
function nsc_mint_next_id(): ?string {
$path = nsc_id_counter_file();
$fh = @fopen($path, 'c+');
if (!is_resource($fh)) {
return null;
}
$lockExtra = null;
if (!@flock($fh, LOCK_EX)) {
/* flock failed: local lock file, then skip mill (fail-closed; never remint) */
$lockPath = dirname($path) . DIRECTORY_SEPARATOR . 'id.counter.lock';
$lockExtra = @fopen($lockPath, 'c+');
if (!is_resource($lockExtra) || !@flock($lockExtra, LOCK_EX)) {
if (is_resource($lockExtra)) @fclose($lockExtra);
@fclose($fh);
return null;
}
}
$raw = stream_get_contents($fh);
$cur = (is_string($raw) && preg_match('/^[0-9]{1,18}$/', trim($raw))) ? trim($raw) : '0';
$next = (string)((int)$cur + 1);
if ($next === '0' || strlen($next) > 18) {
@flock($fh, LOCK_UN);
@fclose($fh);
if (is_resource($lockExtra)) { @flock($lockExtra, LOCK_UN); @fclose($lockExtra); }
return null;
}
rewind($fh);
ftruncate($fh, 0);
fwrite($fh, $next);
fflush($fh);
@flock($fh, LOCK_UN);
@fclose($fh);
if (is_resource($lockExtra)) { @flock($lockExtra, LOCK_UN); @fclose($lockExtra); }
@chmod($path, 0600);
return $next;
}
$KYC_BASE = '/dev/shm/nosignup/kyc';
$KYC_LOG_MAX_BYTES = 65536;
$SEEK_MATCH_FRESH_MS = 3000;
$SPRITE_FRESH_SEC = 5;
$SPRITE_MAX_BYTES = 262144; // 256KiB. Wire is 3x3 JPEG (cell 20x15->80x60) + ~2.3s u-law, not nginx 32m.
$MIRROR_FRESH_SEC = 86400 * 30;
$MIRROR_CAP = 64;
const MIRROR_JSON_BODY_MAX = 4096;
/* Optional KYC enable: /dev/shm is tmpfs|ramfs and /proc/swaps has no active swap. */
$_kyc_sw = @file('/proc/swaps', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$KYC_VOLATILE = (bool)preg_match('#^\S+\s+/dev/shm\s+(?:tmpfs|ramfs)\s#mi', (string)@file_get_contents('/proc/mounts'))
&& is_array($_kyc_sw) && count($_kyc_sw) === 1;
unset($_kyc_sw);
if (!$KYC_VOLATILE && is_dir($KYC_BASE) && !is_link($KYC_BASE)) {
@unlink($KYC_BASE . '/metadata.log'); @unlink($KYC_BASE . '/.salt'); @rmdir($KYC_BASE);
}
function ns_real_ram_root(): string {
return '/dev/shm/nosignup';
}
function ns_real_ram_ok(): bool {
/* REAL RAM only. Disk fallback may still run; the RAM banner still shows. */
if (DIRECTORY_SEPARATOR !== '/' || !is_dir('/dev/shm') || !@is_writable('/dev/shm')) return false;
$d = ns_real_ram_root();
if (!is_dir($d)) @mkdir($d, 0700, true);
return is_dir($d) && @is_writable($d);
}
/** Worktable health. REAL /dev/shm root and ./data independently. Fail-open. Loud banners. */
function ns_worktable_problems(): array {
$disk = nsp_data_dir();
if ($disk !== '' && !is_dir($disk)) @mkdir($disk, 0755, true);
$out = [];
if (!ns_real_ram_ok()) $out[] = ['kind' => 'ram', 'msg' => 'No RAM folder. This host has no memory worktable.', 'path' => ns_real_ram_root()];
if (!ns_worktable_folder_ok($disk)) $out[] = ['kind' => 'disk', 'msg' => 'No disk folder. This host cannot save.', 'path' => $disk];
return $out;
}
function ns_worktable_folder_ok(string $d): bool {
return $d !== '' && is_dir($d) && @is_writable($d);
}
function ns_worktable_banner(bool $public = true): string {
$probs = ns_worktable_problems();
if (!$probs) return '';
$lines = '';
foreach ($probs as $p) {
$extra = '';
if (!$public && !empty($p['path'])) {
$extra = ' ' . htmlspecialchars((string)$p['path'], ENT_QUOTES) . '';
}
$lines .= '
Peer chat · no signupTwo panes. Try a peer or paste an ID.No match promised.
HTML default · HD optionalDefault HTML mode is pixelated and safer.HD is clearer and may expose your IP to the peer.
Volatile framesFrames are volatile where the service uses RAM-only transport.Normal host/network logs may still exist. No recovery account.
Shared NSU walletOpen Wallet for economy continuity — CHAT does not settle trades.Money/buy/trade lives on nosignup.trade · optional donate.
Risk acknowledgment · not an account. Unmoderated · 18+ · enter at your own risk.Strangers can transmit arbitrary content. No moderation or recovery guarantee.
Donating does not buy moderation, priority, identity, access, ranking, or control over another user's chat.
+
Mirrors / Donate
FACE MIRROR — a compatible alternate host for this CHAT face. SPORE — a complete configured ten-face organism. EMPIRE — the lineage/economy a Genesis spore creates or a clone-Mirror joins.
Stage a face-mirror URL. Browser checks build fingerprint + exact face before use. A CHAT face mirror is not by itself a sovereign economy.
Confirmed = exact build + face. Learned URLs are hints until confirmed. Operators may log normal requests.
Change wallet
Seed is the password. Write it down. By continuing, you agree your seed is the password. CHAT does not settle trades — sending/trading/buying lives on Trade.
Current wallet
New wallet
Generate a new random wallet on this browser.
Open a different wallet
Paste its 12-word seed to use that wallet on this device.
';
}
return '';
}
/** Chat-only: one stretch cell for a remote pane (not the 49-tile board). */
function nsu_ad_slot_html_one(string $pane = 'L'): string {
$t = nsu_crop_tld();
if ($t === '' || !in_array($t, nsu_ad_sites(), true)) return '';
$url = nsu_ad_slot_url($t);
if ($url === '') return '';
$pane = ($pane === 'R') ? 'R' : 'L';
$cell = '';
return '';
}
/**
* Where a visitor's "report ad" goes. Reports surface to the King and to
* this crop's lord; they never auto-pull a paying ad, because the lord is
* paid by the advertiser and should not be the only reviewer.
*/
function nsu_report_endpoint(): string {
$t = nsu_crop_tld();
if ($t === '') return '';
return nsu_trade_origin() . '/?api=ad_report&crop=' . urlencode($t);
}
/* ===================== END ECONOMY+IDENTITY TELOMERE ================== */