Spaces:
Running
Running
feat(landing): deploy holographic Series-A front door
Browse filesHolographic governed-inference hero (vendored Three.js r160 MIT), live ledger counter + WebCrypto verify + mesh viz; spa_root prefers a11oy_landing.html. Signed-off-by: Stephen Lutar <stephenlutar2@gmail.com>
- a11oy_landing.html +536 -0
- static/a11oy_landing.js +254 -0
a11oy_landing.html
ADDED
|
@@ -0,0 +1,536 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<!--
|
| 3 |
+
a11oy — front door (holographic landing). Served at the Space root "/" by serve.py.
|
| 4 |
+
SOVEREIGN: Three.js r160 (MIT) vendored in-image at /hero/vendor3d. 0 runtime CDN.
|
| 5 |
+
HONESTY DOCTRINE v11 LOCKED — every figure on this page is fetched live and labelled
|
| 6 |
+
honestly (LIVE / DOWN / empty-state). Nothing is fabricated. Λ = Conjecture 1 (advisory,
|
| 7 |
+
NOT a theorem). locked-proven kernel = EXACTLY 8. Receipts are signed on write, never on GET.
|
| 8 |
+
© Stephen P. Lutar Jr. (ORCID 0009-0001-0110-4173) · Apache-2.0
|
| 9 |
+
-->
|
| 10 |
+
<html lang="en">
|
| 11 |
+
<head>
|
| 12 |
+
<meta charset="utf-8" />
|
| 13 |
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
| 14 |
+
<title>a11oy — governed inference, signed and shown</title>
|
| 15 |
+
<meta name="description" content="a11oy governs every AI turn before it runs and seals it as a signed receipt you can verify offline. They hide the governor; we sign and show it." />
|
| 16 |
+
<link rel="icon" href="/social-preview.svg" />
|
| 17 |
+
<style>
|
| 18 |
+
:root{
|
| 19 |
+
--bg:#070b16; --deep:#0a0f1e; --surface:#10161f; --border:#22304a;
|
| 20 |
+
--teal:#39d8c8; --teal-soft:#39d8c833; --violet:#6a7bff; --gold:#cda64a;
|
| 21 |
+
--ink:#eaf1f7; --sub:#9fb2c9; --ghost:#64768f;
|
| 22 |
+
--ok:#39d8c8; --warn:#cda64a; --down:#e06a6a;
|
| 23 |
+
--r:16px; --maxw:1180px;
|
| 24 |
+
--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,Helvetica,Arial,sans-serif;
|
| 25 |
+
--mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
|
| 26 |
+
}
|
| 27 |
+
*{box-sizing:border-box}
|
| 28 |
+
html,body{margin:0;padding:0}
|
| 29 |
+
body{
|
| 30 |
+
background:
|
| 31 |
+
radial-gradient(1200px 700px at 70% -10%, #14213a 0%, transparent 60%),
|
| 32 |
+
radial-gradient(900px 600px at 10% 10%, #0d1830 0%, transparent 55%),
|
| 33 |
+
var(--bg);
|
| 34 |
+
color:var(--ink); font-family:var(--sans); line-height:1.55;
|
| 35 |
+
-webkit-font-smoothing:antialiased; overflow-x:hidden;
|
| 36 |
+
}
|
| 37 |
+
a{color:inherit;text-decoration:none}
|
| 38 |
+
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 24px}
|
| 39 |
+
.mono{font-family:var(--mono)}
|
| 40 |
+
|
| 41 |
+
/* ---- nav ---- */
|
| 42 |
+
header.nav{position:sticky;top:0;z-index:40;
|
| 43 |
+
backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
|
| 44 |
+
background:linear-gradient(180deg,#070b16cc,#070b1688);
|
| 45 |
+
border-bottom:1px solid var(--border)}
|
| 46 |
+
.nav .wrap{display:flex;align-items:center;gap:18px;height:64px}
|
| 47 |
+
.brand{display:flex;align-items:center;gap:11px;font-weight:700;letter-spacing:.2px}
|
| 48 |
+
.brand svg{display:block}
|
| 49 |
+
.brand .sub{color:var(--ghost);font-weight:500;font-size:12px;letter-spacing:2px;text-transform:uppercase}
|
| 50 |
+
.nav nav{margin-left:auto;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
|
| 51 |
+
.nav nav a{padding:8px 13px;border-radius:10px;color:var(--sub);font-size:14px;font-weight:500;transition:.15s}
|
| 52 |
+
.nav nav a:hover{color:var(--ink);background:#ffffff0e}
|
| 53 |
+
.btn{display:inline-flex;align-items:center;gap:8px;padding:10px 16px;border-radius:11px;
|
| 54 |
+
font-weight:600;font-size:14px;border:1px solid transparent;cursor:pointer;transition:.15s;white-space:nowrap}
|
| 55 |
+
.btn-primary{background:linear-gradient(135deg,var(--teal),#2bb6a8);color:#04130f;
|
| 56 |
+
box-shadow:0 6px 24px -8px var(--teal)}
|
| 57 |
+
.btn-primary:hover{transform:translateY(-1px);box-shadow:0 10px 30px -8px var(--teal)}
|
| 58 |
+
.btn-ghost{border-color:var(--border);color:var(--ink);background:#ffffff08}
|
| 59 |
+
.btn-ghost:hover{border-color:var(--teal);color:var(--teal)}
|
| 60 |
+
|
| 61 |
+
/* ---- hero ---- */
|
| 62 |
+
.hero{position:relative;min-height:92vh;display:flex;align-items:center;overflow:hidden}
|
| 63 |
+
#hero-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:0;display:block}
|
| 64 |
+
.hero-fallback{position:absolute;inset:0;z-index:0;display:none;
|
| 65 |
+
background:radial-gradient(600px 600px at 65% 45%, #39d8c81f, transparent 70%)}
|
| 66 |
+
.hero .wrap{position:relative;z-index:2;padding-top:48px;padding-bottom:48px}
|
| 67 |
+
.hero-inner{max-width:680px}
|
| 68 |
+
.eyebrow{display:inline-flex;align-items:center;gap:9px;padding:6px 13px;border-radius:999px;
|
| 69 |
+
border:1px solid var(--teal-soft);background:#39d8c812;color:var(--teal);
|
| 70 |
+
font-size:12.5px;font-weight:600;letter-spacing:.4px;margin-bottom:22px}
|
| 71 |
+
.eyebrow .dot{width:7px;height:7px;border-radius:50%;background:var(--teal);
|
| 72 |
+
box-shadow:0 0 0 0 var(--teal);animation:pulse 2.4s infinite}
|
| 73 |
+
@keyframes pulse{0%{box-shadow:0 0 0 0 #39d8c8aa}70%{box-shadow:0 0 0 9px #39d8c800}100%{box-shadow:0 0 0 0 #39d8c800}}
|
| 74 |
+
h1.title{font-size:clamp(2.3rem,5.6vw,4rem);line-height:1.04;margin:0 0 18px;
|
| 75 |
+
font-weight:760;letter-spacing:-1.4px}
|
| 76 |
+
h1.title .grad{background:linear-gradient(120deg,var(--teal),var(--violet));
|
| 77 |
+
-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
|
| 78 |
+
.lede{font-size:clamp(1.05rem,2vw,1.3rem);color:var(--sub);max-width:600px;margin:0 0 28px}
|
| 79 |
+
.lede b{color:var(--ink);font-weight:600}
|
| 80 |
+
.cta-row{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:30px}
|
| 81 |
+
.hero-stats{display:flex;gap:14px;flex-wrap:wrap}
|
| 82 |
+
.stat{padding:13px 17px;border-radius:13px;border:1px solid var(--border);
|
| 83 |
+
background:linear-gradient(180deg,#ffffff0c,#ffffff04);min-width:150px;backdrop-filter:blur(6px)}
|
| 84 |
+
.stat .k{font-size:1.55rem;font-weight:720;font-family:var(--mono);line-height:1.1}
|
| 85 |
+
.stat .l{font-size:11.5px;color:var(--ghost);text-transform:uppercase;letter-spacing:1.1px;margin-top:3px}
|
| 86 |
+
.stat .k.teal{color:var(--teal)}
|
| 87 |
+
|
| 88 |
+
/* ---- generic section ---- */
|
| 89 |
+
section.band{padding:72px 0;position:relative}
|
| 90 |
+
.band h2{font-size:clamp(1.6rem,3.2vw,2.3rem);font-weight:720;letter-spacing:-.6px;margin:0 0 12px}
|
| 91 |
+
.band .kick{color:var(--teal);font-weight:600;font-size:13px;letter-spacing:1.6px;text-transform:uppercase;margin:0 0 10px}
|
| 92 |
+
.band p.intro{color:var(--sub);max-width:680px;font-size:1.05rem;margin:0 0 36px}
|
| 93 |
+
|
| 94 |
+
.grid{display:grid;gap:18px}
|
| 95 |
+
.g3{grid-template-columns:repeat(3,1fr)}
|
| 96 |
+
.g2{grid-template-columns:repeat(2,1fr)}
|
| 97 |
+
@media(max-width:900px){.g3,.g2{grid-template-columns:1fr}}
|
| 98 |
+
|
| 99 |
+
.card{padding:24px;border-radius:var(--r);border:1px solid var(--border);
|
| 100 |
+
background:linear-gradient(180deg,#ffffff0b,#ffffff05);position:relative;overflow:hidden}
|
| 101 |
+
.card::before{content:"";position:absolute;inset:0;border-radius:var(--r);padding:1px;
|
| 102 |
+
background:linear-gradient(135deg,#39d8c855,transparent 40%);
|
| 103 |
+
-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
|
| 104 |
+
-webkit-mask-composite:xor;mask-composite:exclude;opacity:.6;pointer-events:none}
|
| 105 |
+
.card h3{margin:0 0 8px;font-size:1.12rem;font-weight:680}
|
| 106 |
+
.card p{margin:0;color:var(--sub);font-size:.96rem}
|
| 107 |
+
.card .ic{width:38px;height:38px;border-radius:10px;display:grid;place-items:center;
|
| 108 |
+
background:#39d8c815;border:1px solid var(--teal-soft);color:var(--teal);margin-bottom:14px;font-size:18px}
|
| 109 |
+
|
| 110 |
+
/* ---- labels / chips ---- */
|
| 111 |
+
.chip{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border-radius:999px;
|
| 112 |
+
font-size:12px;font-weight:600;font-family:var(--mono);border:1px solid var(--border)}
|
| 113 |
+
.chip .dot{width:8px;height:8px;border-radius:50%}
|
| 114 |
+
.chip.live{color:var(--ok);border-color:#39d8c855;background:#39d8c810}
|
| 115 |
+
.chip.live .dot{background:var(--ok);box-shadow:0 0 8px var(--ok)}
|
| 116 |
+
.chip.down{color:var(--down);border-color:#e06a6a55;background:#e06a6a10}
|
| 117 |
+
.chip.down .dot{background:var(--down)}
|
| 118 |
+
.chip.wait{color:var(--ghost)}
|
| 119 |
+
.chip.wait .dot{background:var(--ghost)}
|
| 120 |
+
.chip.gold{color:var(--gold);border-color:#cda64a55;background:#cda64a10}
|
| 121 |
+
.chip.gold .dot{background:var(--gold)}
|
| 122 |
+
|
| 123 |
+
/* ---- verify panel ---- */
|
| 124 |
+
.verify{display:grid;grid-template-columns:1.05fr .95fr;gap:22px;align-items:start}
|
| 125 |
+
@media(max-width:900px){.verify{grid-template-columns:1fr}}
|
| 126 |
+
.term{border-radius:14px;border:1px solid var(--border);background:#060a13;overflow:hidden;font-family:var(--mono)}
|
| 127 |
+
.term .bar{display:flex;align-items:center;gap:7px;padding:10px 14px;border-bottom:1px solid var(--border);background:#0b1120}
|
| 128 |
+
.term .bar i{width:11px;height:11px;border-radius:50%;display:block}
|
| 129 |
+
.term .bar i:nth-child(1){background:#e06a6a}.term .bar i:nth-child(2){background:#cda64a}.term .bar i:nth-child(3){background:#39d8c8}
|
| 130 |
+
.term .bar .t{margin-left:8px;color:var(--ghost);font-size:12px}
|
| 131 |
+
.term .body{padding:16px;font-size:12.5px;line-height:1.7;max-height:330px;overflow:auto;white-space:pre-wrap;word-break:break-word}
|
| 132 |
+
.term .body .ln{color:var(--sub)}
|
| 133 |
+
.term .body .ok{color:var(--ok)}
|
| 134 |
+
.term .body .er{color:var(--down)}
|
| 135 |
+
.term .body .mut{color:var(--ghost)}
|
| 136 |
+
.term .body .hl{color:var(--teal)}
|
| 137 |
+
.verdict{margin-top:14px;padding:14px 16px;border-radius:12px;border:1px solid var(--border);font-weight:600;display:none}
|
| 138 |
+
.verdict.show{display:block}
|
| 139 |
+
.verdict.pass{border-color:#39d8c8;background:#39d8c810;color:var(--ok)}
|
| 140 |
+
.verdict.fail{border-color:#e06a6a;background:#e06a6a10;color:var(--down)}
|
| 141 |
+
|
| 142 |
+
/* ---- mesh ---- */
|
| 143 |
+
.mesh-list{display:flex;flex-direction:column;gap:12px}
|
| 144 |
+
.node{display:flex;align-items:center;gap:14px;padding:16px 18px;border-radius:13px;
|
| 145 |
+
border:1px solid var(--border);background:linear-gradient(180deg,#ffffff0a,#ffffff04)}
|
| 146 |
+
.node .nm{font-weight:640}
|
| 147 |
+
.node .meta{color:var(--ghost);font-size:12.5px;font-family:var(--mono);margin-top:2px}
|
| 148 |
+
.node .right{margin-left:auto;text-align:right}
|
| 149 |
+
|
| 150 |
+
/* ---- footer ---- */
|
| 151 |
+
footer{border-top:1px solid var(--border);padding:46px 0 60px;color:var(--ghost);font-size:13.5px}
|
| 152 |
+
footer .cols{display:flex;gap:40px;flex-wrap:wrap;justify-content:space-between}
|
| 153 |
+
footer a{color:var(--sub)}footer a:hover{color:var(--teal)}
|
| 154 |
+
footer .lk{display:flex;flex-direction:column;gap:8px}
|
| 155 |
+
.disc{margin-top:32px;padding-top:22px;border-top:1px solid var(--border);max-width:760px;line-height:1.6}
|
| 156 |
+
|
| 157 |
+
.muted{color:var(--ghost)}
|
| 158 |
+
.skel{color:var(--ghost);font-family:var(--mono)}
|
| 159 |
+
</style>
|
| 160 |
+
</head>
|
| 161 |
+
<body>
|
| 162 |
+
|
| 163 |
+
<!-- ============================ NAV ============================ -->
|
| 164 |
+
<header class="nav">
|
| 165 |
+
<div class="wrap">
|
| 166 |
+
<a class="brand" href="/" aria-label="a11oy home">
|
| 167 |
+
<svg width="30" height="30" viewBox="0 0 32 32" fill="none" aria-hidden="true">
|
| 168 |
+
<defs><linearGradient id="lg" x1="0" y1="0" x2="1" y2="1">
|
| 169 |
+
<stop offset="0" stop-color="#39d8c8"/><stop offset="1" stop-color="#6a7bff"/></linearGradient></defs>
|
| 170 |
+
<circle cx="16" cy="16" r="13" stroke="url(#lg)" stroke-width="2"/>
|
| 171 |
+
<circle cx="16" cy="16" r="5" fill="url(#lg)"/>
|
| 172 |
+
<path d="M16 3v8M16 21v8M3 16h8M21 16h8" stroke="url(#lg)" stroke-width="1.6" opacity=".7"/>
|
| 173 |
+
</svg>
|
| 174 |
+
<span>a11oy<span class="sub" style="margin-left:9px">SZL Holdings</span></span>
|
| 175 |
+
</a>
|
| 176 |
+
<nav>
|
| 177 |
+
<a href="/console">Console</a>
|
| 178 |
+
<a href="/verify">Verify</a>
|
| 179 |
+
<a href="/assurance">Assurance</a>
|
| 180 |
+
<a href="/willay">WILLAY</a>
|
| 181 |
+
<a href="/governance">Governance</a>
|
| 182 |
+
<a class="btn btn-primary" href="/console">Open Console →</a>
|
| 183 |
+
</nav>
|
| 184 |
+
</div>
|
| 185 |
+
</header>
|
| 186 |
+
|
| 187 |
+
<!-- ============================ HERO ============================ -->
|
| 188 |
+
<section class="hero">
|
| 189 |
+
<canvas id="hero-canvas"></canvas>
|
| 190 |
+
<div class="hero-fallback" id="hero-fallback"></div>
|
| 191 |
+
<div class="wrap">
|
| 192 |
+
<div class="hero-inner">
|
| 193 |
+
<span class="eyebrow"><span class="dot"></span> Governed inference · signed receipts · verify offline</span>
|
| 194 |
+
<h1 class="title">Every AI turn,<br><span class="grad">governed and signed.</span></h1>
|
| 195 |
+
<p class="lede">a11oy gates every model call against a constitution <b>before it runs</b>,
|
| 196 |
+
routes it on a sovereign mesh, and seals the decision as a signed receipt you can verify
|
| 197 |
+
yourself. <b>They hide the governor. We sign and show it.</b></p>
|
| 198 |
+
<div class="cta-row">
|
| 199 |
+
<a class="btn btn-primary" href="/console">Open the Console →</a>
|
| 200 |
+
<a class="btn btn-ghost" href="#verify">Verify a receipt offline</a>
|
| 201 |
+
</div>
|
| 202 |
+
<div class="hero-stats">
|
| 203 |
+
<div class="stat">
|
| 204 |
+
<div class="k teal" id="hs-receipts">—</div>
|
| 205 |
+
<div class="l">Signed receipts <span id="hs-receipts-chip"></span></div>
|
| 206 |
+
</div>
|
| 207 |
+
<div class="stat">
|
| 208 |
+
<div class="k" id="hs-lambda">0.97</div>
|
| 209 |
+
<div class="l">Λ trust ceiling · advisory</div>
|
| 210 |
+
</div>
|
| 211 |
+
<div class="stat">
|
| 212 |
+
<div class="k" id="hs-proven">8</div>
|
| 213 |
+
<div class="l">Locked-proven formulas</div>
|
| 214 |
+
</div>
|
| 215 |
+
</div>
|
| 216 |
+
</div>
|
| 217 |
+
</div>
|
| 218 |
+
</section>
|
| 219 |
+
|
| 220 |
+
<!-- ====================== HOW IT WORKS ====================== -->
|
| 221 |
+
<section class="band wrap" id="how">
|
| 222 |
+
<p class="kick">The governed loop</p>
|
| 223 |
+
<h2>Gate before it runs. Sign what it did.</h2>
|
| 224 |
+
<p class="intro">Most AI stacks bolt safety on after the answer. a11oy puts a deny-by-default
|
| 225 |
+
governor in front of every action and a signed, hash-chained receipt behind it — so a buyer,
|
| 226 |
+
an auditor, or a regulator can replay the decision instead of trusting a screenshot.</p>
|
| 227 |
+
<div class="grid g3">
|
| 228 |
+
<div class="card"><div class="ic">⛓</div><h3>Gate</h3>
|
| 229 |
+
<p>Each turn clears the constitution, the doctrine gate, and the policy guards before a
|
| 230 |
+
single token is generated. No clearance, no run.</p></div>
|
| 231 |
+
<div class="card"><div class="ic">⚖</div><h3>Route</h3>
|
| 232 |
+
<p>Smart Routing picks the smallest sovereign engine that clears the sensitivity class and
|
| 233 |
+
license tier — self-hosted first, never leaking sensitive context.</p></div>
|
| 234 |
+
<div class="card"><div class="ic">🔏</div><h3>Sign</h3>
|
| 235 |
+
<p>The decision is sealed as a DSSE receipt, ECDSA‑P256 signed and hash-chained
|
| 236 |
+
(SHA3‑256). Signed on write, never on a read.</p></div>
|
| 237 |
+
</div>
|
| 238 |
+
</section>
|
| 239 |
+
|
| 240 |
+
<!-- ====================== VERIFY OFFLINE ====================== -->
|
| 241 |
+
<section class="band" id="verify" style="background:linear-gradient(180deg,#0a0f1e00,#0a0f1e88)">
|
| 242 |
+
<div class="wrap">
|
| 243 |
+
<p class="kick">The trust demo</p>
|
| 244 |
+
<h2>Verify a live signature in your own browser.</h2>
|
| 245 |
+
<p class="intro">This makes a real governed call, fetches a11oy's public key, and checks the
|
| 246 |
+
ECDSA‑P256 signature over the DSSE payload using your browser's WebCrypto — no server
|
| 247 |
+
round-trip for the verification, nothing to take on faith. Tamper with one byte and it fails.</p>
|
| 248 |
+
<div class="verify">
|
| 249 |
+
<div>
|
| 250 |
+
<div class="term">
|
| 251 |
+
<div class="bar"><i></i><i></i><i></i><span class="t">webcrypto · verify offline</span></div>
|
| 252 |
+
<div class="body" id="vlog"><span class="mut">// click “Run verification” to make a governed call and check its signature locally.</span></div>
|
| 253 |
+
</div>
|
| 254 |
+
<div class="verdict" id="vverdict"></div>
|
| 255 |
+
<div style="margin-top:14px;display:flex;gap:12px;flex-wrap:wrap">
|
| 256 |
+
<button class="btn btn-primary" id="vrun">Run verification</button>
|
| 257 |
+
<a class="btn btn-ghost" href="/verify">Open the full Verify surface →</a>
|
| 258 |
+
</div>
|
| 259 |
+
</div>
|
| 260 |
+
<div class="grid" style="gap:14px">
|
| 261 |
+
<div class="card"><h3>What gets checked</h3>
|
| 262 |
+
<p style="margin-bottom:10px">1 · <span class="mono">POST /api/a11oy/v1/govern/infer</span> — a real governed turn.<br>
|
| 263 |
+
2 · <span class="mono">GET /cosign.pub</span> — the in-image public key (PEM).<br>
|
| 264 |
+
3 · Rebuild the DSSE PAE, recompute SHA‑256, run <span class="mono">crypto.subtle.verify</span>.</p>
|
| 265 |
+
<p class="muted">DER→raw r‖s conversion happens in-browser; the private key never leaves the box.</p>
|
| 266 |
+
</div>
|
| 267 |
+
<div class="card"><h3>Why it matters</h3>
|
| 268 |
+
<p>A signature anyone can check, against a key they fetched themselves, is the difference
|
| 269 |
+
between “trust us” and proof. The same logic backs every receipt in the ledger.</p>
|
| 270 |
+
</div>
|
| 271 |
+
</div>
|
| 272 |
+
</div>
|
| 273 |
+
</div>
|
| 274 |
+
</section>
|
| 275 |
+
|
| 276 |
+
<!-- ====================== SOVEREIGN MESH ====================== -->
|
| 277 |
+
<section class="band wrap" id="mesh">
|
| 278 |
+
<p class="kick">Sovereign compute mesh</p>
|
| 279 |
+
<h2>Real nodes. Honest status. No fake green lights.</h2>
|
| 280 |
+
<p class="intro">Inference runs on a governed mesh of sovereign engines. The board below is live
|
| 281 |
+
from <span class="mono">/api/a11oy/v1/govern/health</span>. A node that is offline is shown
|
| 282 |
+
offline — we never paint a down engine green.</p>
|
| 283 |
+
<div class="mesh-list" id="mesh-list">
|
| 284 |
+
<div class="node"><div><div class="nm skel">Loading mesh…</div>
|
| 285 |
+
<div class="meta">querying /api/a11oy/v1/govern/health</div></div>
|
| 286 |
+
<div class="right"><span class="chip wait"><span class="dot"></span>…</span></div></div>
|
| 287 |
+
</div>
|
| 288 |
+
</section>
|
| 289 |
+
|
| 290 |
+
<!-- ====================== ASSURANCE / NARRATIVE ====================== -->
|
| 291 |
+
<section class="band" style="background:linear-gradient(180deg,#0a0f1e00,#0d18308c)">
|
| 292 |
+
<div class="wrap">
|
| 293 |
+
<p class="kick">Built for buyers and auditors</p>
|
| 294 |
+
<h2>An assurance overlay for AI you can defend in a review.</h2>
|
| 295 |
+
<div class="grid g3" style="margin-top:30px">
|
| 296 |
+
<div class="card"><div class="ic">📐</div><h3>Honest by construction</h3>
|
| 297 |
+
<p>Capabilities are labelled LIVE / MEASURED / SAMPLE / MODELED / ROADMAP. The trust
|
| 298 |
+
ceiling Λ is an advisory bound (Conjecture 1) — never asserted as a theorem, never 100%.</p></div>
|
| 299 |
+
<div class="card"><div class="ic">🧾</div><h3>Replayable evidence</h3>
|
| 300 |
+
<p>Every governed decision carries a signed receipt and a hash-chain link. An auditor
|
| 301 |
+
replays the chain to a byte-identical root instead of trusting a dashboard.</p></div>
|
| 302 |
+
<div class="card"><div class="ic">🛡</div><h3>Deny by default</h3>
|
| 303 |
+
<p>New action paths must clear governance before they execute. A truthful BLOCKED is the
|
| 304 |
+
designed outcome — better than a fabricated pass.</p></div>
|
| 305 |
+
</div>
|
| 306 |
+
<div style="margin-top:34px;display:flex;gap:12px;flex-wrap:wrap">
|
| 307 |
+
<a class="btn btn-primary" href="/assurance">See the assurance surface →</a>
|
| 308 |
+
<a class="btn btn-ghost" href="/willay">Explore WILLAY</a>
|
| 309 |
+
<a class="btn btn-ghost" href="/governance">Governance model</a>
|
| 310 |
+
</div>
|
| 311 |
+
</div>
|
| 312 |
+
</section>
|
| 313 |
+
|
| 314 |
+
<!-- ============================ FOOTER ============================ -->
|
| 315 |
+
<footer>
|
| 316 |
+
<div class="wrap">
|
| 317 |
+
<div class="cols">
|
| 318 |
+
<div style="max-width:320px">
|
| 319 |
+
<a class="brand" href="/" style="margin-bottom:12px">
|
| 320 |
+
<svg width="26" height="26" viewBox="0 0 32 32" fill="none" aria-hidden="true">
|
| 321 |
+
<circle cx="16" cy="16" r="13" stroke="url(#lg)" stroke-width="2"/>
|
| 322 |
+
<circle cx="16" cy="16" r="5" fill="url(#lg)"/></svg>
|
| 323 |
+
<span>a11oy</span></a>
|
| 324 |
+
<p class="muted" style="margin:6px 0 0">The governed agentic substrate of SZL Holdings.
|
| 325 |
+
Governed inference, signed receipts, sovereign compute.</p>
|
| 326 |
+
</div>
|
| 327 |
+
<div class="lk"><strong style="color:var(--ink)">Product</strong>
|
| 328 |
+
<a href="/console">Console</a><a href="/verify">Verify</a>
|
| 329 |
+
<a href="/assurance">Assurance</a><a href="/willay">WILLAY</a></div>
|
| 330 |
+
<div class="lk"><strong style="color:var(--ink)">Platform</strong>
|
| 331 |
+
<a href="/governance">Governance</a><a href="/frontier">Frontier</a>
|
| 332 |
+
<a href="/orbital">Orbital</a><a href="/api/a11oy/v1/honest">Honest status (JSON)</a></div>
|
| 333 |
+
</div>
|
| 334 |
+
<p class="disc">Honesty doctrine v11. Λ is Conjecture 1 — an advisory trust ceiling, not a
|
| 335 |
+
theorem, never 100%. The locked-proven formula kernel is exactly 8 (of ~35 wired, ~185 in the
|
| 336 |
+
corpus). Receipts are signed on state changes, never on reads. Joules are MEASURED only with a
|
| 337 |
+
live exporter delta; otherwise shown as SAMPLE. © Stephen P. Lutar Jr. · Apache-2.0.</p>
|
| 338 |
+
</div>
|
| 339 |
+
</footer>
|
| 340 |
+
|
| 341 |
+
<!-- ===================== SOVEREIGN IMPORTMAP (vendored, NO CDN) ===================== -->
|
| 342 |
+
<script type="importmap">
|
| 343 |
+
{ "imports": {
|
| 344 |
+
"three": "/hero/vendor3d/three.module.min.js",
|
| 345 |
+
"three/addons/": "/hero/vendor3d/"
|
| 346 |
+
} }
|
| 347 |
+
</script>
|
| 348 |
+
|
| 349 |
+
<!-- ===================== HERO BOOT (Three.js holographic field) ===================== -->
|
| 350 |
+
<script type="module">
|
| 351 |
+
import { mountHero } from "/landing/app.js";
|
| 352 |
+
const canvas = document.getElementById("hero-canvas");
|
| 353 |
+
try {
|
| 354 |
+
const h = mountHero(canvas);
|
| 355 |
+
if (!h || !h.ok) {
|
| 356 |
+
canvas.style.display = "none";
|
| 357 |
+
document.getElementById("hero-fallback").style.display = "block";
|
| 358 |
+
} else {
|
| 359 |
+
window.__a11oyHero = h;
|
| 360 |
+
}
|
| 361 |
+
} catch (e) {
|
| 362 |
+
canvas.style.display = "none";
|
| 363 |
+
document.getElementById("hero-fallback").style.display = "block";
|
| 364 |
+
}
|
| 365 |
+
</script>
|
| 366 |
+
|
| 367 |
+
<!-- ===================== LIVE DATA + WEBCRYPTO VERIFY (no deps) ===================== -->
|
| 368 |
+
<script>
|
| 369 |
+
(function(){
|
| 370 |
+
"use strict";
|
| 371 |
+
const $ = (id) => document.getElementById(id);
|
| 372 |
+
const esc = (s) => String(s).replace(/[&<>"]/g, c => ({'&':'&','<':'<','>':'>','"':'"'}[c]));
|
| 373 |
+
|
| 374 |
+
/* ---------- 1) live receipt counter + chain head ---------- */
|
| 375 |
+
(async function loadLake(){
|
| 376 |
+
try{
|
| 377 |
+
const r = await fetch("/api/lake/v1/health", {cache:"no-store"});
|
| 378 |
+
const d = await r.json();
|
| 379 |
+
const total = (typeof d.total_receipts === "number") ? d.total_receipts : null;
|
| 380 |
+
$("hs-receipts").textContent = (total === null) ? "—" : total.toLocaleString();
|
| 381 |
+
const alg = d.chain_alg || "sha3_256";
|
| 382 |
+
$("hs-receipts-chip").innerHTML =
|
| 383 |
+
'<span class="chip live" style="margin-left:6px"><span class="dot"></span>' + esc(alg) + '</span>';
|
| 384 |
+
}catch(e){
|
| 385 |
+
$("hs-receipts").textContent = "—";
|
| 386 |
+
$("hs-receipts-chip").innerHTML =
|
| 387 |
+
'<span class="chip down" style="margin-left:6px"><span class="dot"></span>offline</span>';
|
| 388 |
+
}
|
| 389 |
+
})();
|
| 390 |
+
|
| 391 |
+
/* ---------- 3) sovereign mesh viz ---------- */
|
| 392 |
+
(async function loadMesh(){
|
| 393 |
+
const host = $("mesh-list");
|
| 394 |
+
try{
|
| 395 |
+
const r = await fetch("/api/a11oy/v1/govern/health", {cache:"no-store"});
|
| 396 |
+
const d = await r.json();
|
| 397 |
+
const mesh = Array.isArray(d.mesh) ? d.mesh : [];
|
| 398 |
+
const rows = [];
|
| 399 |
+
mesh.forEach(n => {
|
| 400 |
+
const live = !!n.live;
|
| 401 |
+
const cls = live ? "live" : "down";
|
| 402 |
+
const lbl = live ? "LIVE" : "DOWN";
|
| 403 |
+
const tier = n.tier ? (" · " + esc(n.tier)) : "";
|
| 404 |
+
rows.push(
|
| 405 |
+
'<div class="node"><div>'+
|
| 406 |
+
'<div class="nm">'+esc(n.name || "engine")+'</div>'+
|
| 407 |
+
'<div class="meta">'+esc(n.model || "—")+tier+(n.effort?(" · "+esc(n.effort)):"")+'</div>'+
|
| 408 |
+
'</div><div class="right">'+
|
| 409 |
+
'<span class="chip '+cls+'"><span class="dot"></span>'+lbl+'</span>'+
|
| 410 |
+
'</div></div>'
|
| 411 |
+
);
|
| 412 |
+
});
|
| 413 |
+
// GLM engine: honest-DOWN when not on metal
|
| 414 |
+
if (d.glm && d.glm.on_metal_live === false){
|
| 415 |
+
rows.push(
|
| 416 |
+
'<div class="node"><div>'+
|
| 417 |
+
'<div class="nm">GLM engine</div>'+
|
| 418 |
+
'<div class="meta">'+esc(d.glm.model_tag || "glm")+' · not in mesh</div>'+
|
| 419 |
+
'</div><div class="right">'+
|
| 420 |
+
'<span class="chip down"><span class="dot"></span>DOWN</span>'+
|
| 421 |
+
'</div></div>'
|
| 422 |
+
);
|
| 423 |
+
}
|
| 424 |
+
const liveN = (typeof d.engines_live === "number") ? d.engines_live : mesh.filter(n=>n.live).length;
|
| 425 |
+
const totN = (typeof d.engines_total === "number") ? d.engines_total : mesh.length;
|
| 426 |
+
rows.push(
|
| 427 |
+
'<div class="node" style="border-style:dashed"><div>'+
|
| 428 |
+
'<div class="nm muted">Mesh summary</div>'+
|
| 429 |
+
'<div class="meta">'+liveN+' / '+totN+' engines live · governance '+(d.governance?'on':'off')+'</div>'+
|
| 430 |
+
'</div><div class="right"><span class="chip '+(liveN>0?'live':'down')+'"><span class="dot"></span>'+
|
| 431 |
+
(liveN>0?'LIVE':'NONE')+'</span></div></div>'
|
| 432 |
+
);
|
| 433 |
+
host.innerHTML = rows.join("") ||
|
| 434 |
+
'<div class="node"><div class="nm muted">No engines reported</div></div>';
|
| 435 |
+
}catch(e){
|
| 436 |
+
host.innerHTML =
|
| 437 |
+
'<div class="node"><div><div class="nm">Mesh health unreachable</div>'+
|
| 438 |
+
'<div class="meta">/api/a11oy/v1/govern/health did not respond</div></div>'+
|
| 439 |
+
'<div class="right"><span class="chip down"><span class="dot"></span>OFFLINE</span></div></div>';
|
| 440 |
+
}
|
| 441 |
+
})();
|
| 442 |
+
|
| 443 |
+
/* ---------- 2) WebCrypto ECDSA-P256 DSSE verify (Tier-1 logic) ---------- */
|
| 444 |
+
function b64Decode(s){const bin=atob(s);const b=new Uint8Array(bin.length);for(let i=0;i<bin.length;i++)b[i]=bin.charCodeAt(i);return b;}
|
| 445 |
+
function derToRaw(der){
|
| 446 |
+
let i=0; if(der[i++]!==0x30) throw new Error("not DER SEQUENCE");
|
| 447 |
+
let sl=der[i++]; if(sl&0x80){let nb=sl&0x7f;sl=0;for(let b=0;b<nb;b++)sl=(sl<<8)|der[i++];}
|
| 448 |
+
function readInt(){if(der[i++]!==0x02)throw new Error("expected INTEGER");let len=der[i++];
|
| 449 |
+
if(len&0x80){let nb=len&0x7f;len=0;for(let b=0;b<nb;b++)len=(len<<8)|der[i++];}
|
| 450 |
+
const v=der.slice(i,i+len);i+=len;return v;}
|
| 451 |
+
const r=readInt(),s=readInt();
|
| 452 |
+
function pad32(a){let j=0;while(j<a.length-1&&a[j]===0)j++;const st=a.slice(j);
|
| 453 |
+
const o=new Uint8Array(32);const off=32-st.length;if(off<0)throw new Error("int too long");o.set(st,off);return o;}
|
| 454 |
+
const raw=new Uint8Array(64);raw.set(pad32(r),0);raw.set(pad32(s),32);return raw;
|
| 455 |
+
}
|
| 456 |
+
function buildPAE(type,body){const enc=new TextEncoder();const t=enc.encode(type);
|
| 457 |
+
const pre=enc.encode("DSSEv1 "+t.length+" ");const mid=enc.encode(" "+body.length+" ");
|
| 458 |
+
const buf=new Uint8Array(pre.length+t.length+mid.length+body.length);let o=0;
|
| 459 |
+
buf.set(pre,o);o+=pre.length;buf.set(t,o);o+=t.length;buf.set(mid,o);o+=mid.length;buf.set(body,o);return buf;}
|
| 460 |
+
async function sha256hex(buf){const h=await crypto.subtle.digest("SHA-256",buf);
|
| 461 |
+
return Array.from(new Uint8Array(h)).map(b=>b.toString(16).padStart(2,"0")).join("");}
|
| 462 |
+
async function importPub(pem){const b64=pem.replace(/-----BEGIN PUBLIC KEY-----/,"").replace(/-----END PUBLIC KEY-----/,"").replace(/\s+/g,"");
|
| 463 |
+
return crypto.subtle.importKey("spki", b64Decode(b64).buffer, {name:"ECDSA",namedCurve:"P-256"}, false, ["verify"]);}
|
| 464 |
+
|
| 465 |
+
let busy=false;
|
| 466 |
+
function log(html){const b=$("vlog");b.innerHTML+= "\n"+html;b.scrollTop=b.scrollHeight;}
|
| 467 |
+
function reset(){$("vlog").innerHTML='<span class="mut">// running…</span>';
|
| 468 |
+
const v=$("vverdict");v.className="verdict";v.textContent="";}
|
| 469 |
+
|
| 470 |
+
async function runVerify(){
|
| 471 |
+
if(busy) return; busy=true;
|
| 472 |
+
const btn=$("vrun"); btn.disabled=true; btn.textContent="Verifying…";
|
| 473 |
+
reset();
|
| 474 |
+
try{
|
| 475 |
+
log('<span class="ln">→ POST /api/a11oy/v1/govern/infer</span>');
|
| 476 |
+
const resp=await fetch("/api/a11oy/v1/govern/infer",{method:"POST",
|
| 477 |
+
headers:{"Content-Type":"application/json"},
|
| 478 |
+
body:JSON.stringify({prompt:"hello",vertical:"general",declared:"PUBLIC"})});
|
| 479 |
+
const data=await resp.json();
|
| 480 |
+
const dsse=data.dsse||{}, receipt=data.receipt||{};
|
| 481 |
+
log('<span class="ok"> decision: '+esc(data.decision||"?")+'</span>'+
|
| 482 |
+
' <span class="mut">Λ='+esc((data.governance&&data.governance.lambda)||"?")+' (Conjecture 1, advisory)</span>');
|
| 483 |
+
|
| 484 |
+
log('<span class="ln">→ GET /cosign.pub</span>');
|
| 485 |
+
const pem=await (await fetch("/cosign.pub")).text();
|
| 486 |
+
const pub=await importPub(pem);
|
| 487 |
+
log('<span class="mut"> public key imported (ECDSA P-256, SPKI)</span>');
|
| 488 |
+
|
| 489 |
+
if(!dsse.signed){
|
| 490 |
+
log('<span class="er"> envelope is UNSIGNED in this runtime — cannot verify.</span>');
|
| 491 |
+
verdict(false,"Envelope unsigned in this runtime. Receipt chain still valid; signature unavailable.");
|
| 492 |
+
return;
|
| 493 |
+
}
|
| 494 |
+
const payloadType=dsse.payloadType||"application/vnd.szl.khipu+json";
|
| 495 |
+
const payload=b64Decode(dsse.payload||"");
|
| 496 |
+
log('<span class="mut"> payload SHA-256: '+(await sha256hex(payload.buffer)).slice(0,32)+'…</span>');
|
| 497 |
+
|
| 498 |
+
const pae=buildPAE(payloadType,payload);
|
| 499 |
+
const paeSha=await sha256hex(pae.buffer);
|
| 500 |
+
log('<span class="ln">→ rebuild DSSE PAE · SHA-256 '+paeSha.slice(0,24)+'…</span>');
|
| 501 |
+
|
| 502 |
+
const sigs=dsse.signatures||[];
|
| 503 |
+
if(!sigs.length){verdict(false,"No signatures in envelope.");return;}
|
| 504 |
+
let sig=b64Decode(sigs[0].sig||""), raw=sig;
|
| 505 |
+
if(sig[0]===0x30){ raw=derToRaw(sig); log('<span class="mut"> DER→raw r‖s converted in-browser</span>'); }
|
| 506 |
+
log('<span class="ln">→ crypto.subtle.verify(ECDSA, SHA-256)</span>');
|
| 507 |
+
let ok=await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},pub,raw.buffer,pae.buffer);
|
| 508 |
+
if(!ok && sig[0]===0x30){ ok=await crypto.subtle.verify({name:"ECDSA",hash:"SHA-256"},pub,sig.buffer,pae.buffer); }
|
| 509 |
+
|
| 510 |
+
if(ok){
|
| 511 |
+
log('<span class="ok">✓ signature VALID — verified locally in your browser.</span>');
|
| 512 |
+
const kid=(sigs[0].keyid||"").slice(0,16);
|
| 513 |
+
verdict(true,"VERIFIED — WebCrypto ECDSA-P256 signature valid over the DSSE PAE."+
|
| 514 |
+
(kid?(" keyid "+esc(kid)+"…"):"")+" Nothing trusted; everything checked.");
|
| 515 |
+
}else{
|
| 516 |
+
log('<span class="er">✗ verification returned false.</span>');
|
| 517 |
+
verdict(false,"Signature did NOT verify against the fetched key.");
|
| 518 |
+
}
|
| 519 |
+
}catch(e){
|
| 520 |
+
log('<span class="er">! '+esc(e.message||e)+'</span>');
|
| 521 |
+
verdict(false,"Verification could not complete: "+esc(e.message||e));
|
| 522 |
+
}finally{
|
| 523 |
+
busy=false; btn.disabled=false; btn.textContent="Run again";
|
| 524 |
+
}
|
| 525 |
+
}
|
| 526 |
+
function verdict(pass,msg){const v=$("vverdict");
|
| 527 |
+
v.className="verdict show "+(pass?"pass":"fail");
|
| 528 |
+
v.textContent=(pass?"✓ ":"✗ ")+msg;}
|
| 529 |
+
|
| 530 |
+
document.addEventListener("DOMContentLoaded",()=>{
|
| 531 |
+
const b=$("vrun"); if(b) b.addEventListener("click",runVerify);
|
| 532 |
+
});
|
| 533 |
+
})();
|
| 534 |
+
</script>
|
| 535 |
+
</body>
|
| 536 |
+
</html>
|
static/a11oy_landing.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ============================================================================
|
| 2 |
+
* a11oy_landing.js — holographic hero for the a11oy front door.
|
| 3 |
+
*
|
| 4 |
+
* THE MOTIF: a "governed inference field" — a holographic glass governance core
|
| 5 |
+
* (fresnel icosahedron) wrapped by an instanced-particle shell whose points are
|
| 6 |
+
* gated inference tokens streaming inward and being sealed at the core. The core
|
| 7 |
+
* pulses on the advisory Λ trust-ceiling; particles that "pass the gate" brighten
|
| 8 |
+
* to holo-teal, the rest dim — a literal picture of deny-by-default governance.
|
| 9 |
+
*
|
| 10 |
+
* SOVEREIGN: Three.js r160 (MIT) + nothing else, vendored in-image under
|
| 11 |
+
* /hero/vendor3d (importmap in a11oy_landing.html). 0 runtime CDN. Bloom is faked
|
| 12 |
+
* with additive fresnel + a layered glow sprite (no postprocessing dependency).
|
| 13 |
+
*
|
| 14 |
+
* HONESTY DOCTRINE v11: Λ = Conjecture 1 (advisory, NOT a theorem). Nothing here
|
| 15 |
+
* fabricates a number — the scene is a motif; all live figures are fetched and
|
| 16 |
+
* labelled by a11oy_landing.html. locked-proven kernel = EXACTLY 8.
|
| 17 |
+
*
|
| 18 |
+
* PERF: capped DPR, instanced points (single draw call), 60fps target. Honors
|
| 19 |
+
* prefers-reduced-motion (renders one static frame) and downshifts particle count
|
| 20 |
+
* on small / low-DPR devices. Signed-off-by: Stephen P. Lutar Jr.
|
| 21 |
+
* ========================================================================== */
|
| 22 |
+
import * as THREE from "three";
|
| 23 |
+
|
| 24 |
+
const REDUCED = window.matchMedia &&
|
| 25 |
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
| 26 |
+
const MOBILE = Math.min(window.innerWidth, window.innerHeight) < 720 ||
|
| 27 |
+
/Mobi|Android/i.test(navigator.userAgent);
|
| 28 |
+
|
| 29 |
+
const TEAL = new THREE.Color(0x39d8c8);
|
| 30 |
+
const DEEP = new THREE.Color(0x6a7bff);
|
| 31 |
+
const DIM = new THREE.Color(0x1b2740);
|
| 32 |
+
|
| 33 |
+
export function mountHero(canvas) {
|
| 34 |
+
let renderer;
|
| 35 |
+
try {
|
| 36 |
+
renderer = new THREE.WebGLRenderer({
|
| 37 |
+
canvas, antialias: !MOBILE, alpha: true, powerPreference: "high-performance",
|
| 38 |
+
});
|
| 39 |
+
} catch (e) {
|
| 40 |
+
return { ok: false, reason: String(e) };
|
| 41 |
+
}
|
| 42 |
+
if (!renderer.getContext()) return { ok: false, reason: "no-webgl" };
|
| 43 |
+
|
| 44 |
+
const DPR = Math.min(window.devicePixelRatio || 1, MOBILE ? 1.5 : 2);
|
| 45 |
+
renderer.setPixelRatio(DPR);
|
| 46 |
+
renderer.setClearColor(0x000000, 0);
|
| 47 |
+
|
| 48 |
+
const scene = new THREE.Scene();
|
| 49 |
+
const camera = new THREE.PerspectiveCamera(46, 1, 0.1, 100);
|
| 50 |
+
camera.position.set(0, 0, 7.2);
|
| 51 |
+
|
| 52 |
+
const root = new THREE.Group();
|
| 53 |
+
scene.add(root);
|
| 54 |
+
|
| 55 |
+
// ---- Governance core: fresnel-shaded glass icosahedron --------------------
|
| 56 |
+
const coreGeo = new THREE.IcosahedronGeometry(1.55, MOBILE ? 2 : 4);
|
| 57 |
+
const coreMat = new THREE.ShaderMaterial({
|
| 58 |
+
transparent: true,
|
| 59 |
+
blending: THREE.AdditiveBlending,
|
| 60 |
+
depthWrite: false,
|
| 61 |
+
uniforms: {
|
| 62 |
+
uTime: { value: 0 },
|
| 63 |
+
uLambda: { value: 0.97 }, // advisory Λ ceiling (Conjecture 1)
|
| 64 |
+
uTeal: { value: new THREE.Vector3(TEAL.r, TEAL.g, TEAL.b) },
|
| 65 |
+
uDeep: { value: new THREE.Vector3(DEEP.r, DEEP.g, DEEP.b) },
|
| 66 |
+
},
|
| 67 |
+
vertexShader: /* glsl */`
|
| 68 |
+
varying vec3 vN; varying vec3 vView;
|
| 69 |
+
uniform float uTime;
|
| 70 |
+
void main(){
|
| 71 |
+
vN = normalize(normalMatrix * normal);
|
| 72 |
+
vec3 p = position;
|
| 73 |
+
// gentle breathing displacement along the normal
|
| 74 |
+
float w = sin(uTime*0.8 + position.y*2.0)*0.03
|
| 75 |
+
+ sin(uTime*1.3 + position.x*3.0)*0.02;
|
| 76 |
+
p += normal * w;
|
| 77 |
+
vec4 mv = modelViewMatrix * vec4(p,1.0);
|
| 78 |
+
vView = normalize(-mv.xyz);
|
| 79 |
+
gl_Position = projectionMatrix * mv;
|
| 80 |
+
}`,
|
| 81 |
+
fragmentShader: /* glsl */`
|
| 82 |
+
precision highp float;
|
| 83 |
+
varying vec3 vN; varying vec3 vView;
|
| 84 |
+
uniform float uTime; uniform float uLambda;
|
| 85 |
+
uniform vec3 uTeal; uniform vec3 uDeep;
|
| 86 |
+
void main(){
|
| 87 |
+
float fres = pow(1.0 - max(dot(normalize(vN), normalize(vView)), 0.0), 2.4);
|
| 88 |
+
// Λ-pulse: the shell brightens toward the advisory ceiling, never to 1.0
|
| 89 |
+
float pulse = 0.5 + 0.5*sin(uTime*1.6);
|
| 90 |
+
float glow = fres * (0.55 + 0.45*pulse) * uLambda;
|
| 91 |
+
vec3 col = mix(uDeep, uTeal, fres);
|
| 92 |
+
gl_FragColor = vec4(col * glow, clamp(glow,0.0,0.92));
|
| 93 |
+
}`,
|
| 94 |
+
});
|
| 95 |
+
const core = new THREE.Mesh(coreGeo, coreMat);
|
| 96 |
+
root.add(core);
|
| 97 |
+
|
| 98 |
+
// wire lattice over the core (deny-by-default cage)
|
| 99 |
+
const cage = new THREE.LineSegments(
|
| 100 |
+
new THREE.EdgesGeometry(new THREE.IcosahedronGeometry(1.62, 1)),
|
| 101 |
+
new THREE.LineBasicMaterial({ color: 0x39d8c8, transparent: true, opacity: 0.18 })
|
| 102 |
+
);
|
| 103 |
+
root.add(cage);
|
| 104 |
+
|
| 105 |
+
// ---- Inference field: instanced particle shell ---------------------------
|
| 106 |
+
const COUNT = REDUCED ? 1400 : (MOBILE ? 2600 : 7000);
|
| 107 |
+
const pGeo = new THREE.BufferGeometry();
|
| 108 |
+
const pos = new Float32Array(COUNT * 3);
|
| 109 |
+
const seed = new Float32Array(COUNT); // per-particle phase
|
| 110 |
+
const radius = new Float32Array(COUNT); // home radius
|
| 111 |
+
const gate = new Float32Array(COUNT); // 1 = passed gate, 0 = denied
|
| 112 |
+
for (let i = 0; i < COUNT; i++) {
|
| 113 |
+
// even-ish sphere distribution (golden spiral)
|
| 114 |
+
const t = i / COUNT;
|
| 115 |
+
const phi = Math.acos(1 - 2 * t);
|
| 116 |
+
const theta = Math.PI * (1 + Math.sqrt(5)) * i;
|
| 117 |
+
const r = 2.4 + Math.random() * 2.6;
|
| 118 |
+
pos[i*3+0] = Math.sin(phi) * Math.cos(theta) * r;
|
| 119 |
+
pos[i*3+1] = Math.cos(phi) * r;
|
| 120 |
+
pos[i*3+2] = Math.sin(phi) * Math.sin(theta) * r;
|
| 121 |
+
seed[i] = Math.random() * Math.PI * 2;
|
| 122 |
+
radius[i] = r;
|
| 123 |
+
gate[i] = Math.random() < 0.62 ? 1.0 : 0.0; // ~Λ share pass the gate
|
| 124 |
+
}
|
| 125 |
+
pGeo.setAttribute("position", new THREE.BufferAttribute(pos, 3));
|
| 126 |
+
pGeo.setAttribute("aSeed", new THREE.BufferAttribute(seed, 1));
|
| 127 |
+
pGeo.setAttribute("aRadius", new THREE.BufferAttribute(radius, 1));
|
| 128 |
+
pGeo.setAttribute("aGate", new THREE.BufferAttribute(gate, 1));
|
| 129 |
+
|
| 130 |
+
const pMat = new THREE.ShaderMaterial({
|
| 131 |
+
transparent: true,
|
| 132 |
+
blending: THREE.AdditiveBlending,
|
| 133 |
+
depthWrite: false,
|
| 134 |
+
uniforms: {
|
| 135 |
+
uTime: { value: 0 },
|
| 136 |
+
uDpr: { value: DPR },
|
| 137 |
+
uTeal: { value: new THREE.Vector3(TEAL.r, TEAL.g, TEAL.b) },
|
| 138 |
+
uDim: { value: new THREE.Vector3(DIM.r, DIM.g, DIM.b) },
|
| 139 |
+
},
|
| 140 |
+
vertexShader: /* glsl */`
|
| 141 |
+
attribute float aSeed; attribute float aRadius; attribute float aGate;
|
| 142 |
+
uniform float uTime; uniform float uDpr;
|
| 143 |
+
varying float vGate; varying float vTw;
|
| 144 |
+
void main(){
|
| 145 |
+
vGate = aGate;
|
| 146 |
+
// tokens drift inward then reset — a stream toward the governed core
|
| 147 |
+
float flow = fract(uTime*0.06 + aSeed*0.16);
|
| 148 |
+
float r = mix(aRadius, 1.75, flow*flow);
|
| 149 |
+
vec3 p = normalize(position) * r;
|
| 150 |
+
// subtle orbital sway
|
| 151 |
+
p.x += sin(uTime*0.5 + aSeed)*0.05;
|
| 152 |
+
p.y += cos(uTime*0.4 + aSeed*1.3)*0.05;
|
| 153 |
+
vTw = 0.6 + 0.4*sin(uTime*3.0 + aSeed*6.0);
|
| 154 |
+
vec4 mv = modelViewMatrix * vec4(p,1.0);
|
| 155 |
+
float size = (aGate>0.5 ? 5.5 : 2.6) * uDpr;
|
| 156 |
+
gl_PointSize = size * (300.0 / -mv.z);
|
| 157 |
+
gl_Position = projectionMatrix * mv;
|
| 158 |
+
}`,
|
| 159 |
+
fragmentShader: /* glsl */`
|
| 160 |
+
precision highp float;
|
| 161 |
+
varying float vGate; varying float vTw;
|
| 162 |
+
uniform vec3 uTeal; uniform vec3 uDim;
|
| 163 |
+
void main(){
|
| 164 |
+
vec2 uv = gl_PointCoord - 0.5;
|
| 165 |
+
float d = length(uv);
|
| 166 |
+
if (d > 0.5) discard;
|
| 167 |
+
float a = smoothstep(0.5, 0.0, d);
|
| 168 |
+
vec3 col = mix(uDim, uTeal, vGate) * (vGate>0.5 ? vTw : 0.5);
|
| 169 |
+
gl_FragColor = vec4(col, a * (vGate>0.5 ? 0.95 : 0.4));
|
| 170 |
+
}`,
|
| 171 |
+
});
|
| 172 |
+
const points = new THREE.Points(pGeo, pMat);
|
| 173 |
+
root.add(points);
|
| 174 |
+
|
| 175 |
+
// ---- soft additive halo sprite (fake bloom, no postprocessing) -----------
|
| 176 |
+
const halo = new THREE.Sprite(new THREE.SpriteMaterial({
|
| 177 |
+
map: makeHaloTexture(), transparent: true, blending: THREE.AdditiveBlending,
|
| 178 |
+
depthWrite: false, opacity: 0.55, color: 0x39d8c8,
|
| 179 |
+
}));
|
| 180 |
+
halo.scale.set(9, 9, 1);
|
| 181 |
+
scene.add(halo);
|
| 182 |
+
|
| 183 |
+
// ---- resize ---------------------------------------------------------------
|
| 184 |
+
function resize() {
|
| 185 |
+
const r = canvas.getBoundingClientRect();
|
| 186 |
+
const w = Math.max(1, r.width), h = Math.max(1, r.height);
|
| 187 |
+
renderer.setSize(w, h, false);
|
| 188 |
+
camera.aspect = w / h;
|
| 189 |
+
camera.updateProjectionMatrix();
|
| 190 |
+
}
|
| 191 |
+
resize();
|
| 192 |
+
window.addEventListener("resize", resize, { passive: true });
|
| 193 |
+
|
| 194 |
+
// ---- pointer parallax -----------------------------------------------------
|
| 195 |
+
let px = 0, py = 0, tx = 0, ty = 0;
|
| 196 |
+
if (!REDUCED) {
|
| 197 |
+
window.addEventListener("pointermove", (e) => {
|
| 198 |
+
tx = (e.clientX / window.innerWidth - 0.5);
|
| 199 |
+
ty = (e.clientY / window.innerHeight - 0.5);
|
| 200 |
+
}, { passive: true });
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
// ---- render loop ----------------------------------------------------------
|
| 204 |
+
const clock = new THREE.Clock();
|
| 205 |
+
let raf = 0, running = true;
|
| 206 |
+
|
| 207 |
+
function frame() {
|
| 208 |
+
if (!running) return;
|
| 209 |
+
const t = clock.getElapsedTime();
|
| 210 |
+
coreMat.uniforms.uTime.value = t;
|
| 211 |
+
pMat.uniforms.uTime.value = t;
|
| 212 |
+
px += (tx - px) * 0.04; py += (ty - py) * 0.04;
|
| 213 |
+
root.rotation.y = t * 0.12 + px * 0.6;
|
| 214 |
+
root.rotation.x = py * 0.4;
|
| 215 |
+
cage.rotation.y = -t * 0.05;
|
| 216 |
+
renderer.render(scene, camera);
|
| 217 |
+
raf = requestAnimationFrame(frame);
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
if (REDUCED) {
|
| 221 |
+
coreMat.uniforms.uTime.value = 1.2;
|
| 222 |
+
pMat.uniforms.uTime.value = 1.2;
|
| 223 |
+
renderer.render(scene, camera);
|
| 224 |
+
} else {
|
| 225 |
+
// pause when the hero scrolls out of view (battery + perf)
|
| 226 |
+
const io = new IntersectionObserver((ents) => {
|
| 227 |
+
for (const en of ents) {
|
| 228 |
+
if (en.isIntersecting && !running) { running = true; clock.start(); frame(); }
|
| 229 |
+
else if (!en.isIntersecting && running) { running = false; cancelAnimationFrame(raf); }
|
| 230 |
+
}
|
| 231 |
+
}, { threshold: 0.01 });
|
| 232 |
+
io.observe(canvas);
|
| 233 |
+
frame();
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
return { ok: true, renderer, setLambda(v){ coreMat.uniforms.uLambda.value = v; } };
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
// radial-gradient halo texture, built in-canvas (no asset, no CDN)
|
| 240 |
+
function makeHaloTexture() {
|
| 241 |
+
const s = 256;
|
| 242 |
+
const c = document.createElement("canvas");
|
| 243 |
+
c.width = c.height = s;
|
| 244 |
+
const g = c.getContext("2d");
|
| 245 |
+
const grad = g.createRadialGradient(s/2, s/2, 0, s/2, s/2, s/2);
|
| 246 |
+
grad.addColorStop(0.0, "rgba(57,216,200,0.55)");
|
| 247 |
+
grad.addColorStop(0.25, "rgba(57,216,200,0.18)");
|
| 248 |
+
grad.addColorStop(1.0, "rgba(57,216,200,0.0)");
|
| 249 |
+
g.fillStyle = grad;
|
| 250 |
+
g.fillRect(0, 0, s, s);
|
| 251 |
+
const tex = new THREE.CanvasTexture(c);
|
| 252 |
+
tex.needsUpdate = true;
|
| 253 |
+
return tex;
|
| 254 |
+
}
|