diff --git a/web/index.html b/web/index.html index 651ea4d..a1eda5c 100644 --- a/web/index.html +++ b/web/index.html @@ -61,7 +61,7 @@ .topbar-nav a.navlink { color: var(--af-text-muted); text-decoration: none; } .topbar-nav a.navlink:hover { color: var(--af-text); } - /* ---- Hero: asymmetric two-column ---- */ + /* ---- Hero: stacked -- text band, then a full-width architecture diagram ---- */ .hero { background-image: radial-gradient(circle, var(--af-line) 1px, transparent 1px); background-size: 32px 32px; @@ -69,13 +69,10 @@ border-bottom: 1px solid var(--af-line); } .hero .wrap { - display: grid; - grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr); - gap: 3rem; - align-items: center; - padding-top: 4.5rem; - padding-bottom: 4.5rem; + padding-top: 4rem; + padding-bottom: 2.5rem; } + .hero-copy { max-width: 62ch; } .kicker { font-family: var(--af-font-mono); font-size: 0.8rem; @@ -115,7 +112,8 @@ .trust-line a { color: var(--af-accent); text-decoration: none; } .trust-line a:hover { text-decoration: underline; } - /* ---- Live audit-log demo ---- */ + /* ---- Live caption + severity dots (reused by the boundary diagram legend + and by the isolation feature cards below) ---- */ .feed-caption { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.6rem; font-size: 0.8rem; color: var(--af-text-muted); } .pulse-dot { position: relative; width: 8px; height: 8px; border-radius: 50%; background: var(--af-accent); flex: none; } .pulse-dot::after { @@ -123,29 +121,44 @@ animation: pulse 2s ease-out infinite; } @keyframes pulse { 0% { opacity: 0.6; transform: scale(1); } 100% { opacity: 0; transform: scale(2.8); } } - #feed-window { box-shadow: 0 30px 60px -20px rgb(0 0 0 / 0.6); max-width: 100%; } - #feed-banner { padding: 0.85rem 1rem 0.4rem; font-family: var(--af-font-mono); font-size: 0.78rem; color: var(--af-text-muted); border-bottom: 1px solid var(--af-line); } - #feed-banner div { padding: 0.1rem 0; white-space: pre-wrap; overflow-wrap: anywhere; } - #feed-body { min-height: 11rem; max-height: 11rem; padding: 0.6rem 1rem 0.85rem; overflow: hidden; font-family: var(--af-font-mono); font-size: 0.82rem; } - .feed-line { - display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; gap: 0.6rem; align-items: baseline; - padding: 0.3rem 0; color: var(--af-text-muted); - animation: feed-in 0.4s cubic-bezier(0.16, 1, 0.3, 1); - } - .feed-line .title { overflow-wrap: break-word; } - @keyframes feed-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } } - .feed-line .sev { text-transform: uppercase; font-size: 0.72rem; } - .feed-line .title { color: var(--af-text); } - .feed-line .who { color: var(--af-text-muted); opacity: 0.75; text-align: right; } .feed-tone { width: 6px; height: 6px; border-radius: 50%; align-self: center; } .feed-tone-info { background: #22d3ee; } .feed-tone-warn { background: #ffb000; } .feed-tone-critical { background: var(--af-accent); box-shadow: 0 0 8px color-mix(in srgb, var(--af-accent) 60%, transparent); } @media (prefers-reduced-motion: reduce) { - .feed-line { animation: none; } .pulse-dot::after { animation: none; opacity: 0; } } + /* ---- Boundary diagram: aigate's actual mechanism, drawn ---- */ + .boundary-stage { + border-top: 1px solid var(--af-line); + background: color-mix(in srgb, var(--af-surface) 45%, transparent); + padding: 2.25rem 0 3rem; + } + .boundary-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; } + .boundary-diagram { min-width: 760px; } + #boundary-svg { display: block; width: 100%; height: auto; } + #boundary-rect { fill: none; stroke: var(--af-accent); stroke-width: 2.5; opacity: 0.85; filter: drop-shadow(0 0 10px color-mix(in srgb, var(--af-accent) 45%, transparent)); } + .corner-bracket { fill: none; stroke: var(--af-accent); stroke-width: 3; stroke-linecap: square; } + .process-box { fill: var(--af-surface); stroke: var(--af-line); stroke-width: 1.5; } + .process-label { font-family: var(--af-font-mono); font-size: 15px; letter-spacing: 0.05em; fill: var(--af-text); font-weight: 600; text-transform: uppercase; } + .process-sublabel { font-family: var(--af-font-mono); font-size: 11px; fill: var(--af-text-muted); } + .gate-notch { fill: var(--af-bg); stroke: var(--af-line); stroke-width: 2; transition: fill 0.2s ease, stroke 0.2s ease, filter 0.2s ease; } + .gate-notch.tone-critical { stroke: var(--af-accent); fill: color-mix(in srgb, var(--af-accent) 30%, var(--af-bg)); filter: drop-shadow(0 0 7px color-mix(in srgb, var(--af-accent) 70%, transparent)); } + .gate-notch.tone-warn { stroke: #ffb000; fill: color-mix(in srgb, #ffb000 30%, var(--af-bg)); filter: drop-shadow(0 0 7px rgb(255 176 0 / 0.65)); } + .gate-notch.tone-info { stroke: #22d3ee; fill: color-mix(in srgb, #22d3ee 30%, var(--af-bg)); filter: drop-shadow(0 0 7px rgb(34 211 238 / 0.65)); } + .gate-tag { font-family: var(--af-font-mono); font-size: 14px; letter-spacing: 0.08em; fill: var(--af-text-muted); text-transform: uppercase; } + .dest-pill { fill: var(--af-surface); stroke: var(--af-line); stroke-width: 1.5; } + .dest-text { font-family: var(--af-font-mono); font-size: 12px; fill: var(--af-text-muted); } + .dest-subtag { font-family: var(--af-font-mono); font-size: 9px; letter-spacing: 0.1em; fill: var(--af-text-muted); opacity: 0.7; text-transform: uppercase; } + .syscall-dot { opacity: 0; } + .gate-pulse { fill: none; opacity: 0; } + .boundary-readout { margin-top: 1.1rem; font-family: var(--af-font-mono); font-size: 0.85rem; color: var(--af-text-muted); min-height: 1.4em; } + .boundary-legend { display: flex; gap: 1.5rem; flex-wrap: wrap; margin-top: 0.9rem; font-family: var(--af-font-mono); font-size: 0.78rem; color: var(--af-text-muted); } + .boundary-legend .swatch { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-right: 0.45rem; vertical-align: middle; } + .swatch-blocked { background: var(--af-accent); } + .swatch-allowed { background: #22d3ee; } + /* ---- Sections ---- */ section { padding: 4rem 0; border-top: 1px solid var(--af-line); } .section-head { margin-bottom: 2.25rem; max-width: 60ch; } @@ -199,15 +212,14 @@ footer a { text-decoration: underline; text-decoration-color: var(--af-line); text-underline-offset: 3px; } @media (max-width: 820px) { - .hero .wrap { grid-template-columns: 1fr; padding-top: 3rem; padding-bottom: 3rem; } + .hero .wrap { padding-top: 3rem; padding-bottom: 2rem; } + .boundary-stage { padding: 1.75rem 0 2.5rem; } .topbar-nav a[href^="#"] { display: none; } .topbar-nav { gap: 0.75rem; } } @media (max-width: 480px) { .topbar .wrap { flex-wrap: wrap; row-gap: 0.6rem; padding-top: 0.75rem; padding-bottom: 0.75rem; min-height: 0; } .topbar { min-height: 0; } - .feed-line { grid-template-columns: auto auto minmax(0, 1fr); } - .feed-line .who { display: none; } } .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; } @@ -230,7 +242,7 @@
-
+
OS-level sandbox for AI coding agents

A trust boundary the AI can't argue its way out of.

@@ -247,21 +259,61 @@

A trust boundary the AI can't argue its way out of.

The most-starred tool in the AxeForge portfolio. See it on GitHub.

+
-
-
Live demo (simulated output, not a real sandbox)
-
-
- - aigate run -- claude -
-
-
[aigate] sandbox active
-
[aigate] deny_read: .env, secrets/, ~/.ssh/, *.pem
-
[aigate] deny_exec: curl, wget, ssh, scp
-
[aigate] allow_net: api.anthropic.com, api.github.com
+
+
+
Live demo — simulated syscalls crossing the sandbox boundary, not a real sandbox
+
+
+ + Diagram of an AI agent process enclosed by a kernel-enforced sandbox boundary. Three gates control what may cross: FILE, EXEC, and NETWORK. Allowed syscalls pass through their gate; blocked syscalls bounce back inside the boundary. + + + + + + + + + + AI agent process + claude · cursor · aider + + + + + allowed host + api.anthropic.com + + + + + File + + + + Exec + + + + Net + + + + + + + + + +
-
+
+

Every file read, command, and network call the agent makes is checked against your rules before it runs.

+
+ Blocked — kernel refuses, the process physically cannot cross + Allowed — matches an explicit rule
@@ -419,43 +471,173 @@

Three commands to a sandboxed agent

gumshoe.

+ +