invent):
* - Tile/map browse shell + post forms for jobs/resumes; floating category filters.
* - Cards show Contact: email/phone on the listing (not an account wall).
* - Empty boards: honest CTAs (Post a Job / Leave a Resume). ~32 day expiry.
* - DNA line: WORK · board blue. Empire entrance (chat DNA): Options · Mirrors · Donate + ENTER.
* - No site-local visitor wallet UI — money/buy on nosignup.trade.
*/
/**
* FILE MAP (cells/work.php — physical order; comments only, not a second spec):
* charter + WORK CONTRACT ......... law / keep-working / never-become (above)
* vault / panel / admin ........... nsp_vault_* · site.seed · nsp_handle_admin_api · controlpanel
* constants + MLP ................. NSW_* · NSW_MLP_BLOB (FROZEN)
* data paths + storage ............ nsw_base · shards · rate · store · mirrors
* optional seeder ................. seed.conf · terms.txt/demand.txt · JobPosting import · CLI/web ticks
* public API router ............... ?api=jobs|resumes|post_*|capacity|demand|mirror|model|vote
* ?src=1 / ?download .............. auditable source stream
* main HTML/CSS ................... board shell · forms · cards · category filters
* entry gate CSS .................. .ns-entry base (head) + designer absolute-% block
* entry / home DOM ................ gate · four paths · browse/post panels · map
* client JS ....................... browse · post · fmtContact(+copy/mailto) · mirrors · entry boot
* Edit this cell only; sync-pack writes root/pack 6.php. Do not hand-edit pack.
*/
/**
* LEGACY flat rent placeholder only — NEVER implement / wire / mint on work.
* Trade retired flat 10k as LORD_RENT_CREDIT_LEGACY; live LORD grants are
* market-value formula on nosignup.trade (KING faucet → LORD), not a local const.
* Work has no visitor ledger, no site-local treasury, no rent_claim, no mint.
* Money/buy on nosignup.trade. Do not re-introduce live LORD_RENT_CREDIT.
*/
const LORD_RENT_CREDIT_LEGACY = 10000; // retired flat placeholder (whole unit) — never mint here
/* ---- SITE-LOCAL CONTROL PANEL (renter key; not OS root) ---- */
function nsp_vault_dir(): string {
$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 {
$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;
}
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); work has no visitor spend ledger. */
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 (work has no visitor wallet).
* Distinct from nsw_seed_* JobPosting seeder (jobs import).
*/
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.WORK SITE WALLET SEED (OWNER ONLY)\n"
. "This seed unlocks /controlpanel for THIS crop only.\n"
. "Work has no visitor ledger or mint 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 — work 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();
file_put_contents($path, $seed . "\n", LOCK_EX);
@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' => 'work', 'version' => 'work']);
}
if ($api === 'admin_login' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
nsp_require();
nsp_json(['ok' => true, 'msg' => 'ok', 'site' => 'work', 'vault_hint' => nsp_vault_dir(), 'version' => 'work']);
}
/* 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' => 'Could not save to the server — try again in a moment'], 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.Work';
echo '
';
echo '' . htmlspecialchars($site) . ' Control
';
echo '
DNA · WORK · board blue
';
echo '
' . htmlspecialchars($site) . ' · Control Panel ';
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. '
. 'This board has no visitor wallet or ads — listings expire on the ~32d board clock. '
. 'Money/buy lives on nosignup.trade. Panel door is site seed only. Leftover admin password files are unlinked.
';
echo '
';
echo '
Site wallet seed (12 words) ';
echo '
';
echo '
Unlock with site seed ';
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. Work is not a mint. Not a visitor account.
';
echo '
Vault: -
';
echo '
Source (utter control) Load Save ';
echo '
';
echo '
← back
';
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(); }
/* EMPIRE SETUP GATE → trade console until filled */
if ($_nsp_api === '' && !$_nsp_panel && !isset($_GET['empire_setup']) && !isset($_GET['setup']) && !isset($_GET['src']) && !isset($_GET['download'])) {
$uri = (string)($_SERVER['REQUEST_URI'] ?? '');
if (!preg_match('#/(controlpanel|setup)/?(\?|$)#', $uri)) {
$dataDir = __DIR__ . DIRECTORY_SEPARATOR . 'data';
$ok = false;
$local = $dataDir . DIRECTORY_SEPARATOR . 'empire_setup.json';
if (is_file($local)) {
$lj = json_decode((string)@file_get_contents($local), true);
$ok = is_array($lj) && !empty($lj['filled']);
}
$cache = $dataDir . DIRECTORY_SEPARATOR . 'empire_setup_status_cache.json';
if (!$ok && is_file($cache)) {
$c = json_decode((string)@file_get_contents($cache), true);
if (is_array($c) && isset($c['ts'], $c['filled']) && (time() - (int)$c['ts']) < 60 && !empty($c['filled'])) {
$ok = true;
}
}
if (!$ok) {
$ctx = stream_context_create(['http' => ['timeout' => 2.5, 'ignore_errors' => true]]);
$httpsOn = (!empty($_SERVER['HTTPS']) && strtolower((string)$_SERVER['HTTPS']) !== 'off') || ((int)($_SERVER['SERVER_PORT'] ?? 0) === 443) || (strtolower((string)($_SERVER['REQUEST_SCHEME'] ?? '')) === 'https') || (strtolower((string)($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '')) === 'https');
$scheme = $httpsOn ? 'https' : 'http';
$rawS = @file_get_contents($scheme . '://nosignup.trade/?api=empire_setup_status', false, $ctx);
$httpsHit = false;
if (is_string($rawS) && $rawS !== '') {
$j = json_decode($rawS, true);
if (is_array($j) && array_key_exists('filled', $j)) {
$httpsHit = true;
$ok = !empty($j['filled']);
if (!is_dir($dataDir)) {
@mkdir($dataDir, 0755, true);
}
@file_put_contents($cache, json_encode(['ts' => time(), 'filled' => $ok]) . "\n", LOCK_EX);
}
}
if (!$httpsHit && !$ok && is_file($cache)) {
$c = json_decode((string)@file_get_contents($cache), true);
if (is_array($c) && !empty($c['filled'])) {
$ok = true;
}
}
}
if (!$ok) {
header('Cache-Control: no-store');
header('Location: //nosignup.trade/?empire_setup=1', true, 302);
exit;
}
}
}
define('NSW_RATE_WINDOW',300);define('NSW_MAX_IDS_PER_IP',10);define('NSW_BROWSE_MAX',8);define('NSW_BROWSE_MIN',1);define('NSW_DOWNVOTE_MIN',5);define('NSW_DOWNVOTE_SCALE',200000);define('NSW_VOTE_MAX',30);/* community removal: (down−up) ≥ max(MIN, today's KYC-log bytes / SCALE); NSW_VOTE_MAX caps votes/IP/window *//* browse cap per IP per window, scaled to spare power: idle→MAX, loaded→MIN *//* per browser-id: 1 post per type per 5 min (trips on submit). per IP: at most NSW_MAX_IDS_PER_IP DISTINCT ids per type per 5 min, so several people on one shared/library/office IP each get a slot, but a client that clears its id to rotate just burns into the per-IP cap. Tune NSW_MAX_IDS_PER_IP up for mobile/CGNAT (many real users per IP), down for stricter anti-spam. */define('NSW_EXPIRY_DAYS',32);define('NSW_EXPIRY_SEC',NSW_EXPIRY_DAYS*86400);define('NSW_REMOTE_TILE','_remote');define('NSW_MIRROR_JSON_BODY_MAX',4096);
/* FROZEN spam MLP (zlib+b64 bag→16→8→sigmoid): post-only AFTER rate limit; fail-open; frozen for parity. */
define('NSW_MLP_THRESHOLD',0.95);
define('NSW_MLP_BLOB','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');
function nsw_mlp_tokens($text){$text=function_exists('mb_substr')?mb_substr((string)$text,0,8000,'UTF-8'):substr((string)$text,0,8000);/* bag-of-words over a ~240-word vocab: capping the scanned text bounds the work and changes no verdict */$t=function_exists('mb_strtolower')?mb_strtolower($text,'UTF-8'):strtolower($text);return preg_split('/[^\p{L}\p{N}]+/u',$t,-1,PREG_SPLIT_NO_EMPTY)?:[];}
function nsw_nn_score_mlp($text){static$m=null,$loaded=false;if(!$loaded){$loaded=true;$j=@gzuncompress(base64_decode(NSW_MLP_BLOB));if($j!==false){$d=json_decode($j,true);if(is_array($d)&&isset($d['vocab'],$d['w1'],$d['b1'],$d['w2'],$d['b2'],$d['w3'],$d['b3']))$m=$d;}}if($m===null)return 0.0;$vocab=$m['vocab'];$H1=count($m['b1']);$H2=count($m['b2']);$x=[];foreach(nsw_mlp_tokens($text)as$w){if(isset($vocab[$w]))$x[$vocab[$w]]=1.0;}$h1=$m['b1'];foreach($x as$j=>$xv){$row=$m['w1'][$j];for($i=0;$i<$H1;$i++)$h1[$i]+=$xv*$row[$i];}for($i=0;$i<$H1;$i++)if($h1[$i]<0)$h1[$i]=0.0;$h2=$m['b2'];for($i=0;$i<$H1;$i++){$hi=$h1[$i];if($hi==0.0)continue;$row=$m['w2'][$i];for($k=0;$k<$H2;$k++)$h2[$k]+=$hi*$row[$k];}for($k=0;$k<$H2;$k++)if($h2[$k]<0)$h2[$k]=0.0;$z=$m['b3'][0];for($k=0;$k<$H2;$k++)$z+=$h2[$k]*$m['w3'][$k];return 1.0/(1.0+exp(-$z));}
/* ── DATA DIR & PATHS (one base dir; .htaccess-guarded) ── */
function nsw_base(){static$b=null;if($b!==null)return$b;$c=[];if(getenv('NSW_DATA_DIR'))$c[]=rtrim(getenv('NSW_DATA_DIR'),"/\\");$c[]='/var/lib/nosignup/work';$c[]=__DIR__.DIRECTORY_SEPARATOR.'.nsw-data';$c[]=rtrim(sys_get_temp_dir(),"/\\").DIRECTORY_SEPARATOR.'nsw-data';/* sys_get_temp_dir() = the universal NO-PERMISSION fallback: PHP guarantees a writable temp on every host */foreach($c as$d){if($d===''||(!is_dir($d)&&!@mkdir($d,0755,true)&&!is_dir($d)))continue;$h=$d.DIRECTORY_SEPARATOR.'.htaccess';if((file_exists($h)&&is_writable($d))||@file_put_contents($h,"Require all denied\nDeny from all\n")!==false){$b=$d;return$b;}/* the .htaccess write doubles as the real writability probe */}$b=sys_get_temp_dir();return$b;/* last-ditch: raw temp, which always exists */}
function nsw_shards(){return nsw_base().DIRECTORY_SEPARATOR.'shards';}
/* PUBLIC static dump nsw.txt + optional CORS .htaccess (bot-walled hosts stay readable cross-origin). */
/* PUBLIC static dump: build full body then atomic rename; skip full shard-glob when freshness stamp ≤30s (shared dirty/freshness flag for page tick + on-post). */
function nsw_static_fresh(){$f=__DIR__.DIRECTORY_SEPARATOR.'nsw.txt';return is_file($f)&&(time()-(int)@filemtime($f))<=30;}
function nsw_write_static($force=false){if(!$force&&nsw_static_fresh())return;/* dirty-flag: no re-glob while stamp fresh */$dir=__DIR__;$jobs=array();$res=array();
foreach(glob(nsw_shards().DIRECTORY_SEPARATOR.'*'.DIRECTORY_SEPARATOR.'*.job.txt')?:array() as$f){$c=trim((string)@file_get_contents($f));if($c!=='')$jobs[]=$c;}
foreach(glob(nsw_shards().DIRECTORY_SEPARATOR.'*'.DIRECTORY_SEPARATOR.'*.resume.txt')?:array() as$f){$c=trim((string)@file_get_contents($f));if($c!=='')$res[]=$c;}
$body='{"jobs":['.implode(',',$jobs).'],"resumes":['.implode(',',$res).'],"ts":'.time().'}';$dst=$dir.DIRECTORY_SEPARATOR.'nsw.txt';$tmp=$dir.DIRECTORY_SEPARATOR.'nsw.txt.'.getmypid().'.'.mt_rand(1000,9999).'.tmp';
if(@file_put_contents($tmp,$body,LOCK_EX)!==false){if(DIRECTORY_SEPARATOR==='\\'&&is_file($dst))@unlink($dst);if(!@rename($tmp,$dst)){@file_put_contents($dst,$body,LOCK_EX);@unlink($tmp);}}/* atomic rename when OS allows; never leave a half-written public file from this writer */
$ht=$dir.DIRECTORY_SEPARATOR.'.htaccess';$cur=is_file($ht)?(string)@file_get_contents($ht):'';
if(strpos($cur,'# nsw-cors')===false)@file_put_contents($ht,$cur."\n# nsw-cors (lets any browser read the PUBLIC static dump cross-origin; a static file can't set its own header)\n\n\nHeader set Access-Control-Allow-Origin \"*\"\n \n \n",LOCK_EX);}
function nsw_static_tick(){nsw_write_static(false);}/* throttled via freshness stamp inside nsw_write_static */
function nsw_ratedir(){if(DIRECTORY_SEPARATOR==='/'&&is_dir('/dev/shm')&&is_writable('/dev/shm')){$d='/dev/shm/nosignup_work_ip';if((is_dir($d)||@mkdir($d,0700,true))&&is_writable($d))return$d;}return nsw_base().DIRECTORY_SEPARATOR.'ip_posts';}
/* ── REQUEST HELPERS (json out · parity hash · sanitize · tiles) ── */
function nsw_json_out($d,$c=200){http_response_code($c);header('Content-Type: application/json; charset=utf-8');header('X-NSW-Backend: file-shard');echo json_encode($d);exit;}
/* PARITY: sha256 of this file normalized (BOM strip, CRLF→LF, trim line WS, one final LF). Peer re-hashes. */
function nsw_norm_hash(){$s=(string)@file_get_contents(__FILE__);if(substr($s,0,3)==="\xEF\xBB\xBF")$s=substr($s,3);$s=str_replace(["\r\n","\r"],"\n",$s);$s=preg_replace('/[ \t]+\n/',"\n",$s);$s=rtrim($s,"\n")."\n";return hash('sha256',$s);}
/* STORAGE sanitize: trim + length cap only (raw). Client must esc() on render. */
function nsw_san($s,$m=2000){$s=trim((string)($s??''));return function_exists('mb_substr')?mb_substr($s,0,$m,'UTF-8'):substr($s,0,$m);}
function nsw_tile_ok($t){return$t&&preg_match('/^-?\d{1,3}(?:\.5)?_-?\d{1,3}(?:\.5)?$/',$t);}
/* CANONICAL 0.5° CELL STRING - every node (and the JS in fmtHalf) MUST format a half-degree value
identically or shard dir names / cross-node dedup drift: whole → "40", half → "40.5", "-73.5". */
function nsw_half($v){$v=floor((float)$v*2)/2;return $v==(int)$v?(string)(int)$v:(string)$v;}
/* Cells are 0.5° (~55.5km). The slider notch (1-7) is in DEGREES (~111km each), so one notch =
TWO sub-tiles: expand ±2·notch cells, stepping 0.5°. (4·notch+1)² cells - cheap is_dir() stats. */
function nsw_tiles($tile,$r){$p=explode('_',$tile);$lat=(float)$p[0];$lon=(float)$p[1];$n=2*(int)$r;$out=[];for($dy=-$n;$dy<=$n;$dy++)for($dx=-$n;$dx<=$n;$dx++)$out[]=nsw_half($lat+$dy*0.5).'_'.nsw_half($lon+$dx*0.5);return$out;}
/* ── RATE LIMIT (per browser-id, capped per IP) ── */
/* shared rate-file RMW helper (rate/browse/vote/vp) — behavior-preserving; still LOCK_EX on write. */
function nsw_priv_salt(){$d=nsw_logdir();$f=$d.DIRECTORY_SEPARATOR.'.salt';if(is_file($f)){$s=trim((string)@file_get_contents($f));if($s!=='')return$s;}try{$s=bin2hex(random_bytes(32));}catch(Exception$e){$s=hash('sha256',uniqid('',true).mt_rand());}if(@file_put_contents($f,$s,LOCK_EX)!==false)@chmod($f,0600);return$s;}
function nsw_client_tag($ip,$extra=''){return substr(hash_hmac('sha256',(string)$ip.'|'.$extra,nsw_priv_salt()),0,24);}
function nsw_rate_file($ip){$dir=nsw_ratedir();if(!is_dir($dir))@mkdir($dir,0700,true);return[$dir,$dir.DIRECTORY_SEPARATOR.nsw_client_tag($ip,'rate').'.txt'];}
function nsw_rate_read($f){$all=is_file($f)?(json_decode(@file_get_contents($f),true)?:[]):[];return is_array($all)?$all:[];}
function nsw_rate_write($f,$all){@file_put_contents($f,json_encode($all),LOCK_EX);}
/* per-IP rate file (uid map per type): soon=uid cooldown, busy=too many ids on IP. */
function nsw_rate_check($ip,$type,$uid){list($dir,$f)=nsw_rate_file($ip);$now=time();if(mt_rand(1,20)===1)foreach(glob($dir.DIRECTORY_SEPARATOR.'*.txt')?:[]as$g)if(@filemtime($g)<$now-NSW_RATE_WINDOW)@unlink($g);/* GC: a rate file untouched for one full window is stale */$all=nsw_rate_read($f);$m=(isset($all[$type])&&is_array($all[$type]))?$all[$type]:[];foreach($m as$k=>$ts){if(!is_int($ts)||$now-$ts>=NSW_RATE_WINDOW)unset($m[$k]);}/* drop ids whose 5-min window lapsed */$r=['wait'=>0,'reason'=>''];if(isset($m[$uid]))$r=['wait'=>max(1,($m[$uid]+NSW_RATE_WINDOW)-$now),'reason'=>'soon'];/* this browser-id already posted this type */elseif(count($m)>=NSW_MAX_IDS_PER_IP)$r=['wait'=>max(1,(min($m)+NSW_RATE_WINDOW)-$now),'reason'=>'busy'];/* too many distinct ids from this IP */else{$m[$uid]=$now;$all[$type]=$m;nsw_rate_write($f,$all);}/* persist ONLY when recording - a blocked hit changes nothing worth writing (no write-amplification on a flood) */return $r;}
/* ADAPTIVE browse throttle: per-IP cap scales with loadavg (lenient if unavailable). */
function nsw_load_factor(){if(!function_exists('sys_getloadavg'))return -1.0;$l=@sys_getloadavg();if(!is_array($l)||!isset($l[0]))return -1.0;$n=1;$ci=@file_get_contents('/proc/cpuinfo');if($ci!==false){$c=substr_count($ci,'processor');if($c>0)$n=$c;}return $l[0]/$n;/* 1-min load per core: 0 idle, ~1 fully busy */}
function nsw_browse_check($ip){list($dir,$f)=nsw_rate_file($ip);$now=time();if(mt_rand(1,30)===1)foreach(glob($dir.DIRECTORY_SEPARATOR.'*.txt')?:[]as$g)if(@filemtime($g)<$now-NSW_RATE_WINDOW)@unlink($g);$all=nsw_rate_read($f);$b=array_values(array_filter((isset($all['browse'])&&is_array($all['browse']))?$all['browse']:[],fn($t)=>is_int($t)&&$now-$t=$cap){sort($b);$wait=($b[0]+NSW_RATE_WINDOW)-$now;return $wait>0?$wait:1;}$b[]=$now;$all['browse']=$b;nsw_rate_write($f,$all);return 0;}
/* ── STORAGE (ids · region shards) ── */
function nsw_new_id($ip){return time().'_'.substr(nsw_client_tag($ip,microtime(true)),0,10);}
function nsw_mkdir($p){if(!is_dir($p))@mkdir($p,0755,true);return is_dir($p);}
/* one file per posting, type IN the name: shards/{tile}/{id}.job.txt | {id}.resume.txt
so a browse can pull the right type by filename glob without reading every file. */
function nsw_store($type,$tile,$id,$data){$s=rtrim($type,'s');$p=nsw_shards()."/$tile/";if(!nsw_mkdir($p))return false;$j=json_encode($data,JSON_INVALID_UTF8_SUBSTITUTE);/* malformed bytes → U+FFFD instead of false: a record must never silently store empty and vanish */if($j===false)return false;$ok=@file_put_contents($p.$id.'.u0.d0.'.$s.'.txt',$j,LOCK_EX)!==false;if($ok&&!empty($data['remote'])){$a=nsw_shards().'/'.NSW_REMOTE_TILE.'/';if(nsw_mkdir($a))@file_put_contents($a.$id.'.u0.d0.'.$s.'.txt',$j,LOCK_EX);}return$ok;}
/* ── ACCESS LOG (append-only privacy telemetry · salted HMAC shard fan-out) ── */
function nsw_logdir(){$d=nsw_base().DIRECTORY_SEPARATOR.'kyc';if(!is_dir($d))@mkdir($d,0700,true);return$d;}
function nsw_kyc_ipdir($ip=null){$ip=($ip===null||$ip==='')?(string)($_SERVER['REMOTE_ADDR']??'0.0.0.0'):(string)$ip;$d=nsw_logdir().DIRECTORY_SEPARATOR.nsw_client_tag($ip,'log');if(!is_dir($d))@mkdir($d,0700,true);return$d;}/* kyc/{salted HMAC}/ day logs — dirent fan-out, not RAM */
/* ── COMMUNITY VOTES (downvotes remove a post - up/down counts live IN the shard filename; a vote is an atomic rename; per-IP-per-post dedup in the RAM rate file) ── */
function nsw_downvote_threshold(){$dir=nsw_logdir();$day=date('Y-m-d');$b=0;foreach(glob($dir.DIRECTORY_SEPARATOR.'*',GLOB_ONLYDIR)?:[]as$ipd){foreach(glob($ipd.DIRECTORY_SEPARATOR.$day.'*.log.txt')?:[]as$f)$b+=(int)@filesize($f);}return max(NSW_DOWNVOTE_MIN,(int)floor($b/NSW_DOWNVOTE_SCALE));}/* scales with the day's activity via KYC-log bytes across HMAC client-tag shards (filesize stat, no read) */
function nsw_vote_check($ip){list($dir,$f)=nsw_rate_file($ip);$now=time();$all=nsw_rate_read($f);$b=array_values(array_filter((isset($all['vote'])&&is_array($all['vote']))?$all['vote']:[],fn($t)=>is_int($t)&&$now-$t=NSW_VOTE_MAX)return false;$b[]=$now;$all['vote']=$b;nsw_rate_write($f,$all);return true;}
function nsw_vote_same_site(){$host=strtolower((string)($_SERVER['HTTP_HOST']??$_SERVER['SERVER_NAME']??''));if(strpos($host,':')!==false)$host=preg_replace('/:\d+$/','',$host)??$host;if($host==='')return false;$origin=trim((string)($_SERVER['HTTP_ORIGIN']??''));if($origin!==''){$oh=strtolower((string)(parse_url($origin,PHP_URL_HOST)?:''));return $oh!==''&&strcasecmp($oh,$host)===0;}$ref=trim((string)($_SERVER['HTTP_REFERER']??''));if($ref!==''){$rh=strtolower((string)(parse_url($ref,PHP_URL_HOST)?:''));return $rh!==''&&strcasecmp($rh,$host)===0;}return true;}
/* MIRROR GOSSIP: ephemeral peer URLs in rate dir (prefer /dev/shm); only esc() data crosses. */
function nsw_mirrorfile(){return nsw_ratedir().DIRECTORY_SEPARATOR.'mirrors.txt';}
/* RR345 + night-redline: RFC2606/private/CGNAT/mapped/octal ban (date/chat parity). */
function nsw_mirror_embedded_v4($ip){$ip=strtolower(trim((string)$ip," \t[]"));$bin=@inet_pton($ip);if($bin===false||strlen($bin)!==16)return null;if(strncmp($bin,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff",12)!==0)return null;return ord($bin[12]).'.'.ord($bin[13]).'.'.ord($bin[14]).'.'.ord($bin[15]);}
function nsw_mirror_is_cgnat_v4($ip){$ip=strtolower((string)$ip);if(preg_match('/^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./',$ip))return true;$emb=nsw_mirror_embedded_v4($ip);return($emb!==null&&preg_match('/^100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\./',$emb));}
function nsw_mirror_is_private_v4_dotted($ip){$ip=strtolower(trim((string)$ip));if(!filter_var($ip,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4))return false;if(nsw_mirror_is_cgnat_v4($ip))return true;if(!filter_var($ip,FILTER_VALIDATE_IP,FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE))return true;$long=ip2long($ip);if($long===false)return true;$u=sprintf('%u',$long);if($u<16777216)return true;if($u>=2130706432&&$u<=2147483647)return true;return false;}
function nsw_mirror_is_obfuscated_ip_host($host){$host=strtolower(trim((string)$host," \t[]"));if($host===''||strpos($host,'.')===false)return false;if(!preg_match('/^([0-9a-fx]+)(\.([0-9a-fx]+)){3}$/i',$host))return false;if(filter_var($host,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4))return false;if(preg_match('/(^|\.)0[0-9]+/',$host))return true;if(preg_match('/0x/i',$host))return true;if(preg_match('/^[0-9]+(\.[0-9]+){3}$/',$host))return true;return false;}
function nsw_mirror_host_ok($h){$h=strtolower(trim((string)$h," \t[]"));if($h==='')return false;if(preg_match('/[=\s\/\\\\@\[\]]/',$h))return false;if(filter_var($h,FILTER_VALIDATE_IP)){if(nsw_mirror_is_cgnat_v4($h))return false;$emb=nsw_mirror_embedded_v4($h);if($emb!==null&&nsw_mirror_is_private_v4_dotted($emb))return false;if(!filter_var($h,FILTER_VALIDATE_IP,FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE))return false;return true;}if(preg_match('/^(localhost|127\.|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|0\.|169\.254\.|100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.|::1)/i',$h))return false;if(nsw_mirror_is_obfuscated_ip_host($h))return false;if(preg_match('/\.(example|invalid|test|localhost)$/i',$h))return false;if(preg_match('/^(example|invalid|test|localhost)$/i',$h))return false;if(preg_match('/(^|\.)example\.(com|net|org|edu)$/i',$h))return false;if(strpos($h,'.')===false)return false;return true;}
function nsw_mirror_ok($u){$u=trim((string)$u);if($u==='')return null;/* P1-WORK-MIRROR-ENCODED-HOST-KEY: never strip host=/m=/url= into a hostname — encoded key syntax is reject, not promote */$u=rawurldecode(trim($u));if($u==='')return null;if(preg_match('/^(https?:\/\/)?(host|m|url|mirror)=/i',$u))return null;if(!preg_match('#^https?://#i',$u))$u='https://'.$u;if(strlen($u)>200)return null;if(preg_match('#^https?://https?%3a%2f%2f#i',$u)||preg_match('#^https?://https?://#i',$u))return null;/* unbracketed multi-colon authority is ambiguous */if(preg_match('~^https?://([^/?#]+)~i',$u,$am)){$auth=$am[1];if(strpos($auth,'@')!==false)$auth=substr($auth,strrpos($auth,'@')+1);if($auth!==''&&$auth[0]!=='['&&substr_count($auth,':')>=2)return null;}$p=@parse_url($u);if(!$p||empty($p['host']))return null;$scheme=strtolower($p['scheme']??'https');if($scheme!=='http'&&$scheme!=='https')return null;$h=strtolower(trim(rawurldecode($p['host'])," \t[]"));if(strpos($h,'%')!==false)return null;if(!nsw_mirror_host_ok($h))return null;$rest=($p['path']??'').(isset($p['query'])?'?'.$p['query']:'');if(preg_match('#https?://#i',$rest)||preg_match('#https?%3a%2f%2f#i',$rest))return null;$port=isset($p['port'])?(':'.(int)$p['port']):'';$path=$p['path']??'';$hostOut=(filter_var($h,FILTER_VALIDATE_IP,FILTER_FLAG_IPV6)!==false)?('['.$h.']'):$h;return rtrim($scheme.'://'.$hostOut.$port.$path,'/');}
function nsw_mirrors_read(){$f=nsw_mirrorfile();if(!is_file($f))return[];$o=[];$now=time();foreach(file($f,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[]as$l){$p=explode("\t",$l);$u=nsw_mirror_ok($p[0]??'');$t=(int)($p[1]??0);if($u&&($t===0||$now-$t32)break;$u=nsw_mirror_ok($raw);if($u===null){$rej++;continue;}$cur[$u]=$now;$ch=true;$acc++;}if($ch){if(count($cur)>64)$cur=array_slice($cur,-64,null,true);$out='';foreach($cur as$u=>$t)$out.=$u."\t".$t."\n";@file_put_contents(nsw_mirrorfile(),$out,LOCK_EX);}return['accepted'=>$acc,'rejected'=>$rej,'changed'=>$ch];}
function nsw_mirror_field_cap($s){$s=(string)$s;if(strlen($s)>NSW_MIRROR_JSON_BODY_MAX){header('Access-Control-Allow-Origin: *');nsw_json_out(['ok'=>false,'err'=>'Body too large'],413);}return$s;}
/* CHAT-2: fail-closed mirror ingest (9.php fun_json_body_read / 4.php nst_device_wallet_read_json_body). Never substr partial JSON. */
function nsw_mirror_body_read(){$declared=trim((string)($_SERVER['CONTENT_LENGTH']??''));if($declared!==''){if(!ctype_digit($declared)||strlen($declared)>9||(int)$declared>NSW_MIRROR_JSON_BODY_MAX){header('Access-Control-Allow-Origin: *');nsw_json_out(['ok'=>false,'err'=>'Body too large'],413);}}$fh=@fopen('php://input','rb');if(!is_resource($fh))return'';$raw=@stream_get_contents($fh,NSW_MIRROR_JSON_BODY_MAX+1);@fclose($fh);if(!is_string($raw))return'';if(strlen($raw)>NSW_MIRROR_JSON_BODY_MAX){header('Access-Control-Allow-Origin: *');nsw_json_out(['ok'=>false,'err'=>'Body too large'],413);}return$raw;}
function nsw_mirrors_sample($n){$u=array_keys(nsw_mirrors_read());if(!$u)return[];shuffle($u);return array_slice($u,0,$n);}
/* append-only KYC/access log - ONE json line per post/browse/src; new dated file past 50KB. */
function nsw_log($act,$loc){$ip=(string)($_SERVER['REMOTE_ADDR']??'0.0.0.0');$dir=nsw_kyc_ipdir($ip);$now=time();if(mt_rand(1,50)===1)foreach(glob($dir.DIRECTORY_SEPARATOR.'*.log.txt')?:[]as$g)if(@filemtime($g)<$now-NSW_EXPIRY_SEC)@unlink($g);/* GC own pseudonymous shard; interactions deleted after 32 days */$day=date('Y-m-d');$f=$dir.DIRECTORY_SEPARATOR.$day.'.log.txt';if(is_file($f)&&@filesize($f)>=51200){$n=2;do{$f=$dir.DIRECTORY_SEPARATOR.$day.'_'.$n.'.log.txt';$n++;}while(is_file($f)&&@filesize($f)>=51200);}$line=json_encode(['ts'=>time(),'client'=>nsw_client_tag($ip,'event'),'act'=>$act,'loc'=>$loc],JSON_UNESCAPED_SLASHES)."\n";if(@file_put_contents($f,$line,FILE_APPEND|LOCK_EX)!==false)@chmod($f,0600);}
/* ── REGION DUMP (dumb switchboard) ── */
/* DUMB SWITCHBOARD: region raw files, dedup by id, lazy 32d expiry, newest-first; no rank/filter. */
function nsw_listings($type,$tile,$radius,$with_remote){
$s=rtrim($type,'s');$now=time();$byId=[];$cp=explode('_',$tile);$clat=(float)$cp[0];$clon=(float)$cp[1];
/* (1) everything inside the CHOSEN radius (non-remote) */
foreach(nsw_tiles($tile,$radius) as$t){$dir=nsw_shards()."/$t/";if(!is_dir($dir))continue;
foreach(glob($dir.'*.'.$s.'.txt')?:[]as$f){
if(@filemtime($f)<$now-NSW_EXPIRY_SEC){@unlink($f);continue;}
$b=basename($f);$dot=strpos($b,'.');$id=$dot!==false?substr($b,0,$dot):$b;
if(!isset($byId[$id]))$byId[$id]=$f;}}
/* (2) sparse region → expand with NO distance bound to back-fill the nearest 10 ("best we've got").
Scan only POPULATED tiles (a dir exists only where someone posted), nearest-first, read until 10. */
if(count($byId)<10){$dirs=[];
foreach(glob(nsw_shards().'/*',GLOB_ONLYDIR)?:[]as$d){$n=basename($d);
if($n===NSW_REMOTE_TILE||!preg_match('/^-?\d+(?:\.5)?_-?\d+(?:\.5)?$/',$n))continue;
$np=explode('_',$n);$tl=(float)$np[0];$tn=(float)$np[1];$ch=max(abs($tl-$clat),abs($tn-$clon));
if($ch<=$radius)continue;$dirs[]=[$ch,$d];}
usort($dirs,fn($a,$b)=>$a[0]<=>$b[0]);
foreach($dirs as$dd){if(count($byId)>=10)break;
foreach(glob($dd[1].'/*.'.$s.'.txt')?:[]as$f){
if(@filemtime($f)<$now-NSW_EXPIRY_SEC){@unlink($f);continue;}
$b=basename($f);$dot=strpos($b,'.');$id=$dot!==false?substr($b,0,$dot):$b;
if(!isset($byId[$id])){$byId[$id]=$f;if(count($byId)>=10)break;}}}}
/* (3) remote (location-independent) listings - always included when asked, never counted toward the 10 */
if($with_remote){$dir=nsw_shards().'/'.NSW_REMOTE_TILE.'/';if(is_dir($dir))
foreach(glob($dir.'*.'.$s.'.txt')?:[]as$f){
if(@filemtime($f)<$now-NSW_EXPIRY_SEC){@unlink($f);continue;}
$b=basename($f);$dot=strpos($b,'.');$id=$dot!==false?substr($b,0,$dot):$b;
if(!isset($byId[$id]))$byId[$id]=$f;}}
krsort($byId); // id = "_" → newest first; the browser sorts by distance
$parts=[];foreach($byId as$f){$c=trim((string)@file_get_contents($f));if($c!==''&&$c[0]==='{'&&substr($c,-1)==='}')$parts[]=$c;}
return $parts;}
/* ── ROUTER (?api=jobs|resumes|post_job|post_resume · ?src=1) ── */
/* OPTIONAL seeder: piggyback idle web ticks; schema.org JobPosting; demand-driven; external seed/* config. */
function nsw_seed_dir(){$d=nsw_base().DIRECTORY_SEPARATOR.'seed';if(!is_dir($d))@mkdir($d,0700,true);return$d;}/* no own .htaccess - the data-dir root deny-all already covers it recursively (Apache) */
function nsw_seed_lines($f){$p=nsw_seed_dir().DIRECTORY_SEPARATOR.$f;if(!is_file($p))return[];$o=[];foreach(file($p,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[] as$l){$l=trim($l);if($l!==''&&$l[0]!=='#')$o[]=$l;}return$o;}
function nsw_seed_conf($k,$d){foreach(nsw_seed_lines('seed.conf') as$l){$p=explode('=',$l,2);if(count($p)===2&&trim($p[0])===$k)return trim($p[1]);}return$d;}
function nsw_seed_busy(){$n=0;$day=date('Y-m-d');foreach(glob(nsw_logdir().DIRECTORY_SEPARATOR.'*',GLOB_ONLYDIR)?:[]as$ipd){foreach(glob($ipd.DIRECTORY_SEPARATOR.$day.'*.log.txt')?:[]as$f){$m=@filemtime($f);if($m>$n)$n=$m;}}if($n&&(time()-$n)<(int)nsw_seed_conf('idle_secs',45))return true;$lf=nsw_load_factor();return($lf>=0&&$lf>(float)nsw_seed_conf('max_load',0.75));}
/* dependence-less fetch: curl → allow_url_fopen → raw fsockopen. If ALL outbound is blocked → null (this host
can't crawl; it stays a pure mirror - the one hard floor no code can fix). */
function nsw_seed_get($url,$ua){
if(function_exists('curl_init')){$ch=curl_init($url);curl_setopt_array($ch,[CURLOPT_RETURNTRANSFER=>true,CURLOPT_FOLLOWLOCATION=>true,CURLOPT_MAXREDIRS=>4,CURLOPT_TIMEOUT=>12,CURLOPT_USERAGENT=>$ua,CURLOPT_ENCODING=>'']);$b=curl_exec($ch);$c=(int)curl_getinfo($ch,CURLINFO_HTTP_CODE);curl_close($ch);if($b!==false&&$c<400)return substr($b,0,600000);}
if(ini_get('allow_url_fopen')){$ctx=stream_context_create(['http'=>['method'=>'GET','header'=>"User-Agent: $ua\r\nAccept-Encoding: identity\r\n",'timeout'=>12,'follow_location'=>1,'max_redirects'=>4,'ignore_errors'=>true],'ssl'=>['verify_peer'=>false,'verify_peer_name'=>false]]);$b=@file_get_contents($url,false,$ctx);if($b!==false&&$b!=='')return substr($b,0,600000);}
return nsw_seed_sock($url,$ua);
}
function nsw_seed_sock($url,$ua){if(!function_exists('fsockopen'))return null;$p=parse_url($url);if(!$p||!isset($p['host']))return null;$host=$p['host'];$https=(($p['scheme']??'http')==='https');$port=$p['port']??($https?443:80);$path=($p['path']??'/').(isset($p['query'])?'?'.$p['query']:'');$fp=@fsockopen(($https?'ssl://':'').$host,$port,$e,$es,12);if(!$fp)return null;@stream_set_timeout($fp,12);@fwrite($fp,"GET $path HTTP/1.0\r\nHost: $host\r\nUser-Agent: $ua\r\nAccept-Encoding: identity\r\nConnection: close\r\n\r\n");$r='';while(!feof($fp)){$r.=fread($fp,8192);if(strlen($r)>1000000)break;}fclose($fp);$pos=strpos($r,"\r\n\r\n");if($pos===false)return null;if(preg_match('#^HTTP/\d\.\d\s+(\d+)#',$r,$m)&&(int)$m[1]>=400)return null;return substr($r,$pos+4,600000);}
function nsw_seed_robots($url,$ua){static$c=[];$p=parse_url($url);if(!$p||!isset($p['scheme'],$p['host']))return false;$host=$p['scheme'].'://'.$p['host'];$path=$p['path']??'/';if(!array_key_exists($host,$c)){$rb=nsw_seed_get($host.'/robots.txt',$ua);$dis=[];if($rb!==null){$apply=false;foreach(preg_split('/\r?\n/',$rb) as$ln){$ln=trim($ln);if($ln===''||$ln[0]==='#')continue;$kv=explode(':',$ln,2);if(count($kv)<2)continue;$k=strtolower(trim($kv[0]));$v=trim($kv[1]);if($k==='user-agent')$apply=($v==='*');elseif($k==='disallow'&&$apply&&$v!=='')$dis[]=$v;}}$c[$host]=$dis;}foreach($c[$host] as$d)if(strpos($path,$d)===0)return false;return true;}
function nsw_seed_absurl($h,$base){if(preg_match('#^https?://#i',$h))return$h;$p=parse_url($base);if(!$p||!isset($p['scheme'],$p['host']))return null;$r=$p['scheme'].'://'.$p['host'].(isset($p['port'])?':'.$p['port']:'');if(substr($h,0,2)==='//')return$p['scheme'].':'.$h;if($h!==''&&$h[0]==='/')return$r.$h;return$r.'/'.ltrim($h,'/');}
function nsw_seed_links($html,$base){if(!preg_match_all('~]*href=([\'"])([^\'"#\s]+)~i',$html,$m))return[];$o=[];foreach($m[2] as$h){$u=nsw_seed_absurl(html_entity_decode($h,ENT_QUOTES,'UTF-8'),$base);if($u&&preg_match('/[?&]uddg=([^&]+)/',$u,$dm))$u=urldecode($dm[1]);/* DuckDuckGo HTML wraps results in /l/?uddg= - unwrap it */if($u&&preg_match('#^https?://#i',$u))$o[$u]=1;}return array_keys($o);}
function nsw_seed_jsonld($html){if(!preg_match_all('##is',$html,$m))return[];$out=[];foreach($m[1] as$blob){$d=json_decode(trim($blob),true);if(!is_array($d))continue;$items=isset($d[0])?$d:((isset($d['@graph'])&&is_array($d['@graph']))?$d['@graph']:[$d]);foreach($items as$it)if(is_array($it))$out[]=$it;}return$out;}
function nsw_seed_category($t){$t=' '.strtolower($t).' ';$map=['construction_trades'=>'carpenter|plumber|electrician|welder|mason|roofer|hvac|construction|labou?r|trades?','healthcare'=>'nurse|caregiver|medical|dental|therapist|healthcare|pharmac|clinic|hospital','engineering_technology'=>'engineer|developer|software|programmer|technician|devops|sysadmin|data scien','education_training'=>'teacher|tutor|instructor|professor|educat|trainer','logistics_transportation'=>'driver|warehouse|logistic|delivery|courier|forklift|truck|shipping','marketing_sales'=>'sales|marketing|advertis|retail|cashier','business_finance'=>'account|finance|bookkeep|analyst|banker','administration'=>'admin|assistant|clerk|reception|secretary','legal_government'=>'lawyer|legal|paralegal|attorney|government','arts'=>'artist|music|photograph|design|video|actor|writer'];foreach($map as$c=>$re)if(preg_match('#'.$re.'#',$t))return$c;return'miscellaneous';}
function nsw_seed_have($hex){return(bool)glob(nsw_shards().DIRECTORY_SEPARATOR.'*'.DIRECTORY_SEPARATOR.'*_'.$hex.'*.job.txt');}
function nsw_seed_clamp($s,$n){$s=trim((string)$s);return function_exists('mb_substr')?mb_substr($s,0,$n,'UTF-8'):substr($s,0,$n);}
function nsw_seed_tile($loc,$remote){return($remote||$loc[1]===null||$loc[2]===null)?NSW_REMOTE_TILE:(nsw_half($loc[1]).'_'.nsw_half($loc[2]));}
function nsw_seed_put($f,$url,$loc,$remote){$cats=['business_finance','administration','marketing_sales','engineering_technology','healthcare','education_training','construction_trades','arts','logistics_transportation','legal_government','miscellaneous'];$pts=['remote_bounty','remote_hourly','inperson_bounty','inperson_hourly','no_pay',''];$hex=substr(sha1($url),0,8);if(nsw_seed_have($hex))return'dup';$tile=nsw_seed_tile($loc,$remote);$id=((!empty($f['posted'])&&$f['posted']>0)?(int)$f['posted']:time()).'_'.$hex;/* id timestamp = the job's datePosted when known → SAME id on every node → cross-node dedup */$desc="\xF0\x9F\xA4\x96 Auto-imported \xC2\xB7 Apply: $url\n\n".nsw_seed_clamp($f['description']??'',1900);$rec=['id'=>$id,'tile'=>$tile,'title'=>nsw_seed_clamp($f['title']??'',120),'category'=>in_array($f['category']??'',$cats,true)?$f['category']:'miscellaneous','pay_type'=>in_array($f['pay_type']??'',$pts,true)?$f['pay_type']:'','pay_amount'=>nsw_seed_clamp($f['pay_amount']??'',80),'description'=>nsw_seed_clamp($desc,2000),'contact_email'=>'','contact_phone'=>'','remote'=>(bool)$remote,'timestamp'=>time()];return nsw_store('job',$tile,$id,$rec)?'wrote':'err';}
function nsw_seed_extract($html){foreach(nsw_seed_jsonld($html) as$it){$ty=$it['@type']??'';if(is_array($ty))$ty=implode(',',$ty);if(stripos((string)$ty,'JobPosting')===false)continue;$title=trim((string)($it['title']??''));$desc=trim(preg_replace('/\s+/',' ',html_entity_decode(strip_tags((string)($it['description']??'')),ENT_QUOTES|ENT_HTML5,'UTF-8')));if($title===''||$desc==='')continue;$remote=stripos((string)($it['jobLocationType']??''),'TELECOMMUTE')!==false;$amt='';$hourly=false;$bs=$it['baseSalary']??null;if(is_array($bs)){$cur=(string)($bs['currency']??'');$v=$bs['value']??null;if(is_array($v)){$val=$v['value']??($v['minValue']??'');$unit=(string)($v['unitText']??'');}else{$val=$v;$unit='';}if($val!==null&&$val!==''){$amt=trim(($cur?$cur.' ':'').$val.($unit?' / '.strtolower($unit):''));$hourly=stripos($unit,'HOUR')!==false;}}$pt=$amt===''?'':(($remote?'remote_':'inperson_').($hourly?'hourly':'bounty'));$ex=((function_exists('mb_strlen')?mb_strlen($desc,'UTF-8'):strlen($desc))>200)?nsw_seed_clamp($desc,200)."\xE2\x80\xA6":$desc;/* store only a short EXCERPT + apply link, never the full text (copyright/ToS) */$posted=strtotime((string)($it['datePosted']??''));$lat=$lon=null;$jl=$it['jobLocation']??null;if(is_array($jl)){$j0=isset($jl[0])?$jl[0]:$jl;if(is_array($j0)&&isset($j0['geo'])&&is_array($j0['geo'])){if(is_numeric($j0['geo']['latitude']??null))$lat=(float)$j0['geo']['latitude'];if(is_numeric($j0['geo']['longitude']??null))$lon=(float)$j0['geo']['longitude'];}}return['job'=>true,'title'=>$title,'description'=>$ex,'pay_type'=>$pt,'pay_amount'=>$amt,'category'=>nsw_seed_category($title.' '.$desc),'remote'=>$remote,'posted'=>($posted?:0),'lat'=>$lat,'lon'=>$lon];}return['job'=>false];}
/* SELF-CONFIG seeder inputs: terms.txt ∪ demand.txt; optional seed.conf. */
function nsw_seed_inputs(){$terms=array_values(array_unique(array_merge(nsw_seed_lines('terms.txt'),nsw_seed_lines('demand.txt'))));return[$terms,nsw_seed_conf('search','https://html.duckduckgo.com/html/?q={q}'),nsw_seed_conf('ua','nsw-seed/1.0 (+nosignup.work; respectful job indexer)'),(int)nsw_seed_conf('links_per',12)];}
function nsw_seed_enabled(){if(!function_exists('curl_init')&&!ini_get('allow_url_fopen')&&!function_exists('fsockopen'))return false;if(nsw_seed_conf('enabled','0')==='0')return false;list($terms)=nsw_seed_inputs();return!empty($terms);}/* dual footgun: default OFF unless seed.conf enabled=1 AND terms present (polymer W-SEED-FOOT) */
function nsw_seed_step($deadline){list($terms,$search,$ua,$lp)=nsw_seed_inputs();if(!$terms)return;$q=$terms[(int)floor(time()/120)%count($terms)];/* which term to search is DERIVED FROM THE CLOCK (~1 per 2 min) - no cursor file, sweeps over time, forgettable */$surl=str_replace('{q}',rawurlencode($q.' jobs'),$search);$html=nsw_seed_get($surl,$ua);if($html===null)return;foreach(array_slice(nsw_seed_links($html,$surl),0,$lp) as$url){if(time()>=$deadline)break;$hex=substr(sha1($url),0,8);if(nsw_seed_have($hex))continue;if(!nsw_seed_robots($url,$ua))continue;$page=nsw_seed_get($url,$ua);if($page===null)continue;$f=nsw_seed_extract($page);if(!is_array($f)||empty($f['job'])||trim($f['title']??'')===''||trim($f['description']??'')==='')continue;$remote=!empty($f['remote'])||!isset($f['lat'])||$f['lat']===null||$f['lon']===null;nsw_seed_put($f,$url,['',$f['lat']??null,$f['lon']??null],$remote);}}
function nsw_seed_tick(){if(mt_rand(1,max(1,(int)nsw_seed_conf('odds',12)))!==1)return;if(!nsw_seed_enabled())return;if(nsw_seed_busy())return;$fin=function_exists('fastcgi_finish_request');if($fin)@fastcgi_finish_request();@ignore_user_abort(true);@set_time_limit($fin?40:10);nsw_seed_step(time()+($fin?25:6));/* NO lock file: the idle-gate (kyc mtime) already serializes ticks, and the file_exists dedup makes a rare double-run harmless (just redundant fetches) */}
function nsw_seed_run($selftest){if($selftest){fwrite(STDOUT,'selftest: '.nsw_seed_put(['title'=>'SELFTEST seeded carpenter','description'=>'Synthetic seeder self-test job - safe to ignore; it auto-expires.','category'=>'construction_trades','pay_type'=>'inperson_hourly','pay_amount'=>'$20/hr'],'https://selftest.local/job/'.microtime(true),['Test City',30,-97],false)."\n");return;}while(true){if(nsw_seed_busy()){sleep(3);continue;}if(!nsw_seed_enabled()){fwrite(STDERR,"seeder idle - no demand yet (no users have searched) and no seed/terms.txt; outbound: ".((function_exists('curl_init')||ini_get('allow_url_fopen')||function_exists('fsockopen'))?'ok':'BLOCKED')."\n");sleep(10);continue;}nsw_seed_step(time()+25);sleep(2);}}
/* CLI entry - `php index.php seed` (or seed-selftest). DORMANT on the web (PHP_SAPI is never 'cli' there). */
if(PHP_SAPI==='cli'){$cmd=$argv[1]??'';if($cmd==='seed')nsw_seed_run(false);elseif($cmd==='seed-selftest')nsw_seed_run(true);else fwrite(STDERR,"nosignup.work seeder - usage: php index.php seed | seed-selftest\n");exit;}
/* WEB seed piggyback: occasional idle post-response step; no cron. */
register_shutdown_function('nsw_seed_tick');
if(isset($_GET['api'])){
$api=$_GET['api'];
/* WIRING-PARITY: public selfhash (trade-shape; no auth) */
if($api==='selfhash'){header('Access-Control-Allow-Origin: *');nsw_json_out(['ok'=>true,'version'=>'work','sha256'=>@hash_file('sha256',__FILE__)?:null,'file'=>basename(__FILE__)]);}
if($api==='jobs'||$api==='resumes'){
/* RR318 P1-WORK-TILE-ERR-PLAIN: map tile missing/invalid is plain English (not "bad tile"). */
/* RR357 P1-WORK-POST-ERR-SCHEMA: ok:false + err alongside error (face still reads error) */
$tile=$_GET['tile']??'';if(!nsw_tile_ok($tile))nsw_json_out(['ok'=>false,'err'=>'Pick a map tile (location) before loading jobs or résumés','error'=>'Pick a map tile (location) before loading jobs or résumés'],400);
$radius=max(1,min(7,(int)($_GET['radius']??1)));$remote=!empty($_GET['remote'])&&$_GET['remote']!=='0';
/* GET list is a read: no rate write, no KYC log, no salt mint. */
$parts=nsw_listings($api,$tile,$radius,$remote);
/* one efficient response: raw region files concatenated into a JSON array (no per-record
re-encode) + gzip if the client supports it. The browser counts/sorts/filters it all. */
@ob_start('ob_gzhandler');
header('Content-Type: application/json; charset=utf-8');header('X-NSW-Backend: file-shard');header('Access-Control-Allow-Origin: *');/* public region dump - allow a browser on another node to read it cross-origin so it can mirror the network */
echo '{"total":'.count($parts).',"listings":['.implode(',',$parts).'],"mirrors":'.json_encode(nsw_mirrors_sample(6)).'}';exit;}
if($api==='post_job'){
if($_SERVER['REQUEST_METHOD']!=='POST')nsw_json_out(['ok'=>false,'err'=>'POST only','error'=>'POST only'],405);
$ip=$_SERVER['REMOTE_ADDR']??'0.0.0.0';
/* RR318: post_job tile gate plain English · RR357 schema ok:false+err */
$tile=$_POST['tile']??'';if(!nsw_tile_ok($tile))nsw_json_out(['ok'=>false,'err'=>'Pick a map tile (location) before posting a job','error'=>'Pick a map tile (location) before posting a job'],400);
$cats=['business_finance','administration','marketing_sales','engineering_technology','healthcare','education_training','construction_trades','arts','logistics_transportation','legal_government','miscellaneous'];
$pay_types=['remote_bounty','remote_hourly','inperson_bounty','inperson_hourly','no_pay'];
/* RR354 P1-WORK-JOB-CAT-PAY-PLAIN: non-empty unknown category/pay_type must not soft-accept as empty */
$rawCat=trim((string)($_POST['category']??''));
if($rawCat!==''&&!in_array($rawCat,$cats,true))nsw_json_out(['ok'=>false,'err'=>'Pick a job category from the list (or omit)','error'=>'Pick a job category from the list (or omit)','category'=>$rawCat],400);
$rawPay=trim((string)($_POST['pay_type']??''));
if($rawPay!==''&&!in_array($rawPay,$pay_types,true))nsw_json_out(['ok'=>false,'err'=>'Pick a pay type: remote_bounty, remote_hourly, inperson_bounty, inperson_hourly, or no_pay','error'=>'Pick a pay type: remote_bounty, remote_hourly, inperson_bounty, inperson_hourly, or no_pay','pay_type'=>$rawPay],400);
$cat=in_array($rawCat,$cats,true)?$rawCat:'';
$pay_type=in_array($rawPay,$pay_types,true)?$rawPay:'';
$pay_amount=trim((string)($_POST['pay_amount']??''));
/* pay amount is required EXCEPT when the poster picked "No Pay" (volunteer/unpaid gigs) */
if(empty($_POST['title'])||empty($_POST['details'])||($pay_type!=='no_pay'&&$pay_amount===''))
nsw_json_out(['ok'=>false,'err'=>'Need a title, job details, and pay (or choose No Pay).','error'=>'Need a title, job details, and pay (or choose No Pay).'],400);
if(trim((string)($_POST['email']??''))===''&&trim((string)($_POST['phone']??''))==='')
nsw_json_out(['ok'=>false,'err'=>'Missing contact: put an email or phone on the listing so people can reach you (no account).','error'=>'Missing contact: put an email or phone on the listing so people can reach you (no account).'],400);
$uid=preg_replace('/[^a-zA-Z0-9_-]/','',(string)($_POST['uid']??''));if(strlen($uid)<8||strlen($uid)>64)$uid='ip';/* no/garbage id => share one strict per-IP slot */
$rl=nsw_rate_check($ip,'jobs',$uid);if($rl['wait']>0)nsw_json_out(['ok'=>false,'err'=>'Too many requests from your network — wait a moment and try again','error'=>'rate_limited','retry_after'=>$rl['wait'],'reason'=>$rl['reason']],429);/* AFTER validation (a typo mustn't burn a slot); per-id cooldown + per-IP id cap, trips on submit */
/* frozen spam/malice node - AFTER the rate limit so a flood can't spin the classifier; the slot is already spent, which is the point (processing spam must cost the spammer their turn) */
$mlpJob=nsw_nn_score_mlp(($_POST['title']??'').' '.($_POST['details']??'').' '.($_POST['pay_amount']??'').' '.($_POST['category']??''));
/* RR344 P1-WORK-CONTENT-FLAGGED-PLAIN: keep error code for face JS; err/msg plain for API strangers */
if($mlpJob>=NSW_MLP_THRESHOLD){nsw_log('post_job_flagged','tile='.$tile);nsw_json_out(['ok'=>false,'error'=>'content_flagged','err'=>'That job looks like spam and was not posted — rewrite the title/details and try again','msg'=>'That job looks like spam and was not posted — rewrite the title/details and try again','brains'=>['spam_mlp'=>['brain'=>'spam_mlp','score'=>round($mlpJob,4),'flag'=>true,'threshold'=>NSW_MLP_THRESHOLD]]],422);}
$id=nsw_new_id($ip);$remote=(!empty($_POST['remote'])&&$_POST['remote']!=='0')||strpos($pay_type,'remote')===0;
$data=['id'=>$id,'tile'=>$tile,'title'=>nsw_san($_POST['title'],120),'category'=>$cat,'pay_type'=>$pay_type,'pay_amount'=>nsw_san($pay_amount,80),'description'=>nsw_san($_POST['details'],2000),'contact_email'=>nsw_san($_POST['email']??'',200),'contact_phone'=>nsw_san($_POST['phone']??'',40),'remote'=>$remote,'timestamp'=>time()];
if($mlpJob>=0.55)$data['spam_mlp']=['brain'=>'spam_mlp','score'=>round($mlpJob,4),'flag'=>true];
/* RR364 P1-WORK-STORAGE-PLAIN: storage fail → visitor plain English */
if(!nsw_store('jobs',$tile,$id,$data))nsw_json_out(['ok'=>false,'err'=>'Could not save the job listing — try again in a moment','error'=>'Could not save the job listing — try again in a moment'],500);
nsw_log('post_job',"shards/$tile/$id.job.txt");
nsw_write_static();/* public nsw.txt refresh shares dirty/freshness throttle (≤30s): skip re-glob while stamp fresh; live truth remains shards + API */
nsw_json_out(['ok'=>true,'id'=>$id,'brains'=>['spam_mlp'=>['brain'=>'spam_mlp','score'=>round($mlpJob,4),'flag'=>$mlpJob>=0.55,'threshold'=>NSW_MLP_THRESHOLD]]]);}
if($api==='post_resume'){
if($_SERVER['REQUEST_METHOD']!=='POST')nsw_json_out(['ok'=>false,'err'=>'POST only','error'=>'POST only'],405);
$ip=$_SERVER['REMOTE_ADDR']??'0.0.0.0';
/* RR318: post_resume tile gate plain English · RR357 schema ok:false+err */
$tile=$_POST['tile']??'';if(!nsw_tile_ok($tile))nsw_json_out(['ok'=>false,'err'=>'Pick a map tile (location) before posting a résumé','error'=>'Pick a map tile (location) before posting a résumé'],400);
if(trim((string)($_POST['name']??''))===''||trim((string)($_POST['experience']??''))==='')nsw_json_out(['ok'=>false,'err'=>'Need a name and some experience on the résumé.','error'=>'Need a name and some experience on the résumé.'],400);
if(trim((string)($_POST['email']??''))==='')nsw_json_out(['ok'=>false,'err'=>'Missing contact: put an email on the listing so employers can reach you (no account).','error'=>'Missing contact: put an email on the listing so employers can reach you (no account).'],400);
$uid=preg_replace('/[^a-zA-Z0-9_-]/','',(string)($_POST['uid']??''));if(strlen($uid)<8||strlen($uid)>64)$uid='ip';/* no/garbage id => share one strict per-IP slot */
$rl=nsw_rate_check($ip,'resumes',$uid);if($rl['wait']>0)nsw_json_out(['ok'=>false,'err'=>'Too many requests from your network — wait a moment and try again','error'=>'rate_limited','retry_after'=>$rl['wait'],'reason'=>$rl['reason']],429);/* AFTER validation; per-id cooldown + per-IP id cap, trips on submit */
$mlpRes=nsw_nn_score_mlp(($_POST['name']??'').' '.($_POST['experience']??'').' '.($_POST['wanted']??'').' '.($_POST['education']??'').' '.($_POST['resume_text']??''));
/* RR344 P1-WORK-CONTENT-FLAGGED-PLAIN: keep error code for face JS; err/msg plain for API strangers */
if($mlpRes>=NSW_MLP_THRESHOLD){nsw_log('post_resume_flagged','tile='.$tile);nsw_json_out(['ok'=>false,'error'=>'content_flagged','err'=>'That résumé looks like spam and was not posted — rewrite the name/experience and try again','msg'=>'That résumé looks like spam and was not posted — rewrite the name/experience and try again','brains'=>['spam_mlp'=>['brain'=>'spam_mlp','score'=>round($mlpRes,4),'flag'=>true,'threshold'=>NSW_MLP_THRESHOLD]]],422);}
$id=nsw_new_id($ip);$remote=!empty($_POST['remote'])&&$_POST['remote']!=='0';
$data=['id'=>$id,'tile'=>$tile,'name'=>nsw_san($_POST['name'],120),'email'=>nsw_san($_POST['email'],200),'phone'=>nsw_san($_POST['phone']??'',40),'min_salary'=>nsw_san($_POST['min_salary']??'',80),'education'=>nsw_san($_POST['education']??'',300),'experience'=>nsw_san($_POST['experience'],8000),'wanted'=>nsw_san($_POST['wanted']??'',300),'resume_text'=>nsw_san($_POST['resume_text']??'',8000),'remote'=>$remote,'timestamp'=>time()];
if($mlpRes>=0.55)$data['spam_mlp']=['brain'=>'spam_mlp','score'=>round($mlpRes,4),'flag'=>true];
/* RR364 P1-WORK-STORAGE-PLAIN */
if(!nsw_store('resumes',$tile,$id,$data))nsw_json_out(['ok'=>false,'err'=>'Could not save the résumé — try again in a moment','error'=>'Could not save the résumé — try again in a moment'],500);
nsw_log('post_resume',"shards/$tile/$id.resume.txt");
nsw_write_static();/* public nsw.txt refresh shares dirty/freshness throttle (≤30s): skip re-glob while stamp fresh; live truth remains shards + API */
nsw_json_out(['ok'=>true,'id'=>$id,'brains'=>['spam_mlp'=>['brain'=>'spam_mlp','score'=>round($mlpRes,4),'flag'=>$mlpRes>=0.55,'threshold'=>NSW_MLP_THRESHOLD]]]);}
if($api==='capacity'){header('Access-Control-Allow-Origin: *');nsw_json_out(['ok'=>true,'tiles'=>count(glob(nsw_shards().'/*',GLOB_ONLYDIR)?:[]),'parity'=>nsw_norm_hash()]);}
/* DEMAND: record sanitized search keyword into seed/demand.txt for optional seeder. */
if($api==='demand'){if(($_SERVER['REQUEST_METHOD']??'')!=='POST'){http_response_code(204);exit;}$ip=$_SERVER['REMOTE_ADDR']??'0.0.0.0';$bw=nsw_browse_check($ip);if($bw>0)nsw_json_out(['ok'=>false,'err'=>'Too many requests from your network — wait a moment and try again','error'=>'rate_limited','retry_after'=>$bw,'reason'=>'busy'],429);$q=trim(preg_replace('/\s+/',' ',preg_replace('/[\x00-\x1f<>]+/',' ',(string)($_GET['q']??''))));$ln=function_exists('mb_strlen')?mb_strlen($q,'UTF-8'):strlen($q);if($q!==''&&$ln>=2&&$ln<=40){$ql=function_exists('mb_strtolower')?mb_strtolower($q,'UTF-8'):strtolower($q);$df=nsw_seed_dir().DIRECTORY_SEPARATOR.'demand.txt';$ls=is_file($df)?(file($df,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[]):[];$has=false;foreach($ls as$l){if((function_exists('mb_strtolower')?mb_strtolower(trim($l),'UTF-8'):strtolower(trim($l)))===$ql){$has=true;break;}}if(!$has){$ls[]=$q;if(count($ls)>300)$ls=array_slice($ls,-300);@file_put_contents($df,implode("\n",$ls)."\n",LOCK_EX);}}http_response_code(204);exit;}
if($api==='mirror'){header('Access-Control-Allow-Origin: *');header('Access-Control-Allow-Headers: Content-Type');/* RR345/RR373 + JSON body parity with date/chat */if($_SERVER['REQUEST_METHOD']==='OPTIONS'){http_response_code(204);exit;}$add=['accepted'=>0,'rejected'=>0,'changed'=>false];/* P1-WORK-MIRROR-GET-METHOD: GET is sample-only JSON (never write). Mirror ingest is POST-only. */if($_SERVER['REQUEST_METHOD']==='POST'){$raw='';if(isset($_POST['m'])&&(string)$_POST['m']!=='')$raw=nsw_mirror_field_cap(is_array($_POST['m'])?implode("\n",$_POST['m']):(string)$_POST['m']);elseif(isset($_POST['host'])&&(string)$_POST['host']!=='')$raw=nsw_mirror_field_cap((string)$_POST['host']);elseif(isset($_POST['url'])&&(string)$_POST['url']!=='')$raw=nsw_mirror_field_cap((string)$_POST['url']);else{$in=nsw_mirror_body_read();if($in!==''&&stripos((string)($_SERVER['CONTENT_TYPE']??''),'application/json')!==false){$jd=json_decode($in,true);if(is_array($jd)){if(isset($jd['m']))$raw=(string)$jd['m'];elseif(isset($jd['url']))$raw=(string)$jd['url'];elseif(isset($jd['host']))$raw=(string)$jd['host'];}}elseif($in!==''&&preg_match('/(?:^|&)(?:m|host|url)=([^&]*)/i',$in,$mm))$raw=rawurldecode($mm[1]);elseif($in!=='')$raw=trim($in);}$parts=$raw===''?[]:(is_array($raw)?$raw:preg_split('/[\s,]+/',(string)$raw));if($raw!=='')$add=nsw_mirrors_add($parts);}elseif(!in_array(strtoupper((string)($_SERVER['REQUEST_METHOD']??'GET')),['GET','HEAD'],true)){nsw_json_out(['ok'=>false,'err'=>'method not allowed','allow'=>'GET, POST','error'=>'method not allowed'],405);}nsw_json_out(['ok'=>true,'mirrors'=>nsw_mirrors_sample(8),'accepted'=>(int)$add['accepted'],'rejected'=>(int)$add['rejected'],'law'=>'Private/RFC2606/example hosts rejected — never sampled']);}
if($api==='model'){header('Access-Control-Allow-Origin: *');header('Content-Type: application/json; charset=utf-8');$j=@gzuncompress(base64_decode(NSW_MLP_BLOB));echo($j!==false?$j:'null');exit;}/* the frozen spam MLP, inflated, so the BROWSER can run the same filter on mirror-merged listings */
if($api==='vote'){/* vote is same-host only — no Access-Control-Allow-Origin: *; enough downs unlink the shard */
if(!nsw_vote_same_site())nsw_json_out(['ok'=>false,'err'=>'Vote must come from this site — open the listing on this host and vote there','error'=>'same_site_required'],403);
if($_SERVER['REQUEST_METHOD']!=='POST')nsw_json_out(['ok'=>false,'err'=>'POST only','error'=>'POST only'],405);
$ip=$_SERVER['REMOTE_ADDR']??'0.0.0.0';
/* RR357: vote validation schema ok:false+err (face still reads error) */
$id=preg_replace('/[^0-9a-f_]/','',(string)($_POST['id']??''));if(strlen($id)<10||strlen($id)>40)nsw_json_out(['ok'=>false,'err'=>'That listing id looks invalid — refresh the board and try again','error'=>'That listing id looks invalid — refresh the board and try again'],400);
$vdir=(($_POST['dir']??'')==='up')?1:((($_POST['dir']??'')==='down')?-1:0);if($vdir===0)nsw_json_out(['ok'=>false,'err'=>'Vote must be up or down','error'=>'Vote must be up or down'],400);
$tile=$_POST['tile']??'';if(!nsw_tile_ok($tile))nsw_json_out(['ok'=>false,'err'=>'Pick a map tile (location) before voting','error'=>'Pick a map tile (location) before voting'],400);
$stype=(($_POST['type']??'')==='resume')?'resume':((($_POST['type']??'')==='job')?'job':'');if($stype==='')nsw_json_out(['ok'=>false,'err'=>'Vote type must be job or resume','error'=>'Vote type must be job or resume'],400);
if(!nsw_vote_check($ip))nsw_json_out(['ok'=>false,'err'=>'Too many requests from your network — wait a moment and try again','error'=>'rate_limited','retry_after'=>NSW_RATE_WINDOW,'reason'=>'busy'],429);
/* COUNTS LIVE IN THE FILENAME: {id}.u{up}.d{down}.{stype}.txt - a vote is an atomic rename, NO votes/ file.
Per-IP-per-post dedup (so a downvote = a person, not a click) lives in the /dev/shm-preferred rate file (RAM, forgettable). */
list($rd,$rf)=nsw_rate_file($ip);$ra=nsw_rate_read($rf);$vp=(isset($ra['vp'])&&is_array($ra['vp']))?$ra['vp']:[];
$cur=null;foreach([$tile,NSW_REMOTE_TILE] as$tt){$g=glob(nsw_shards()."/$tt/$id.u*.d*.$stype.txt");if($g){$cur=$g[0];break;}}
/* RR338 P1-WORK-VOTE-GONE-PLAIN: bare "gone" → stranger plain English */
if($cur===null)nsw_json_out(['error'=>'That listing is gone — refresh the board and try again','ok'=>false,'err'=>'That listing is gone — refresh the board and try again'],404);
$up=0;$down=0;if(preg_match('/\.u(\d+)\.d(\d+)\.'.$stype.'\.txt$/',basename($cur),$mm)){$up=(int)$mm[1];$down=(int)$mm[2];}
if(in_array($id,$vp,true))nsw_json_out(['ok'=>true,'up'=>$up,'down'=>$down,'dup'=>true]);
if($vdir>0)$up++;else $down++;
$vp[]=$id;if(count($vp)>200)$vp=array_slice($vp,-200);$ra['vp']=$vp;nsw_rate_write($rf,$ra);
if($down-$up>=nsw_downvote_threshold()){foreach(glob(nsw_shards()."/$tile/$id.u*.d*.$stype.txt")?:[]as$x)@unlink($x);foreach(glob(nsw_shards().'/'.NSW_REMOTE_TILE."/$id.u*.d*.$stype.txt")?:[]as$x)@unlink($x);nsw_log('removed_by_downvote',"$tile/$id d=$down u=$up");nsw_json_out(['ok'=>true,'removed'=>true]);}
@rename($cur,dirname($cur).DIRECTORY_SEPARATOR."$id.u$up.d$down.$stype.txt");
foreach(glob(nsw_shards().'/'.NSW_REMOTE_TILE."/$id.u*.d*.$stype.txt")?:[]as$rg)@rename($rg,nsw_shards().'/'.NSW_REMOTE_TILE."/$id.u$up.d$down.$stype.txt");
nsw_json_out(['ok'=>true,'up'=>$up,'down'=>$down]);}
/* RR336 P1-WORK-UNKNOWN-API-PLAIN: route hints + ok:false (not bare unknown api) */
nsw_json_out(['ok'=>false,'err'=>'Unknown work API - use selfhash, jobs, resumes, post_job, post_resume, capacity, demand, mirror, model, vote, or open the jobs face','api'=>$api,'error'=>'Unknown work API - use selfhash, jobs, resumes, post_job, post_resume, capacity, demand, mirror, model, vote, or open the jobs face'],404);}
/* ?src=1 view/parity (inline) + ?download=1 (Options "Download index.php") — same bytes; ONLY download forces attachment */
if(isset($_GET['src'])||isset($_GET['download'])){header('Access-Control-Allow-Origin: *');header('Access-Control-Expose-Headers: X-NSW-Parity-SHA256, X-NSW-Source-SHA256');/* CORS so a browser on ANOTHER node can fetch+hash our source for the parity/malice check */header('Content-Type: text/plain; charset=utf-8');if(isset($_GET['download']))header('Content-Disposition: attachment; filename="index.php"');/* ?src=1 stays inline so View source / parity fetch open as text; ?download=1 saves index.php */header('X-NSW-Source-SHA256: '.hash_file('sha256',__FILE__));header('X-NSW-Parity-SHA256: '.nsw_norm_hash());/* ^ exact bytes (debug) vs normalized parity (what mirrors compare - tolerant of formatting) */header('Content-Length: '.filesize(__FILE__));readfile(__FILE__);exit;}
nsw_static_tick();/* a normal page load → (re)write the public static dump + CORS .htaccess (throttled) so outside browsers can read this node even on a bot-walled free host */
?>
No-Signup Work · jobs & resumes (contact on listing)
Options
Mirrors
Donate
Jobs · Resumes · No Signup
Jobs & resumes
Board Post or browse work & resumes — no signup/login · put contact on the listing Contact How to reach you lives on the listing Expiry Listings fade after ~32 days No wallet here Optional donate · money/buy on nosignup.trade · no local balance
18+ · experimental · unmoderated · no recovery desk scams exist · enter at your own risk.
I AGREE ENTER
I am a minor — leave
Work is hire/fire boards only — open a corner to browse jobs, post a job, leave a resume, or browse resumes. Contact stays on each listing. Currency and buy/sell live on
nosignup.trade (not here).
x Mirrors Free tributaries. Host a copy · help the network · zero cut · no price power. Free mirrors help the network; hosting is unpaid until parent-proven hits (no free daily host pay); host so the swarm stays hard to kill. No free pay on work; money/buy lives on nosignup.trade . One .php file — drop on any PHP host.
↓ Download this file · View source
Host a copy — stage URL
Known public roots:
Close
x Donate Optional — never required. One .php file. Work has no site-local wallet — Money/buy on nosignup.trade (buy on book / money site).
↓ Download this file
Full donate — copy addresses
BITCOIN bc1qqnu6n0jztxl4f6krv7klradghle09uhyu7uymz
MONERO 8Ab24DppUvcdtHfm7K8gTqdBTmPCBiak1GwxgPm1C3osYVQL2QdC1C8GMwggKF77RKKzDgP2R8E3VH8ifetsKms5AqkVyVg
LITECOIN ltc1qlpdy8qzejcmjdn6vwarpyz8djdlk780w4qkwyp
Close
×
Browse Jobs
Post a Job
Leave a Resume
Browse Resumes (CV's)
🔗
About “mirrored” listings
Listings marked 🔗 Mirrored from … are not hosted by us . Your browser pulled them live, just now, from another nosignup node and is showing them as a courtesy. We don’t store them - leave this page and they’re gone from here.
They exist only while that other node keeps them public. To change or remove a mirrored listing, contact the node shown on it - not us. We’re only a temporary window onto it.
Heads up: to show these, your browser contacts those other nodes directly , so each one may see and log your request (like visiting any website). They’re nodes you staged under Mirrors → Host a copy .
Got it
$
One .php file - drop it on any PHP host. No build step, no dependencies, it just runs. If this is useful to you, a little keeps it alive.Money/buy (on trade, not this board): buy on trade book / optional donate on nosignup.trade . Work has no site-local wallet/ads - listings expire on the ~32d board clock. Money/buy stays on nosignup.trade.
↓ Download index.php
→ Trade buy on book / money site
BITCOIN - electrum bc1qqnu6n0jztxl4f6krv7klradghle09uhyu7uymz
MONERO - feather 8Ab24DppUvcdtHfm7K8gTqdBTmPCBiak1GwxgPm1C3osYVQL2QdC1C8GMwggKF77RKKzDgP2R8E3VH8ifetsKms5AqkVyVg
LITECOIN - electrum-ltc ltc1qlpdy8qzejcmjdn6vwarpyz8djdlk780w4qkwyp
Close