diff --git a/app/controls/page.tsx b/app/controls/page.tsx index 060f44e..dd1ecee 100644 --- a/app/controls/page.tsx +++ b/app/controls/page.tsx @@ -1,8 +1,5 @@ import type { Metadata } from "next"; -import BoundaryNotice from "@components/BoundaryNotice"; import ClaimFirewall from "@components/ClaimFirewall"; -import PageHero from "@components/PageHero"; -import SectionHeader from "@components/SectionHeader"; import { ceiling } from "@config/site"; export const metadata: Metadata = { @@ -17,25 +14,72 @@ export const metadata: Metadata = { export default function ControlsPage() { return ( <> - -
- +
+
+
+

CI claim boundary console

+

+ Claim Firewall +

+

+ Unsupported security claims should fail before they reach the public page. + Public wording stays below the evidence ceiling until evidence linkage and explicit promotion clear a stronger claim. +

+
+ RENDERING_ONLY + {ceiling} + NOT_PUBLIC_SAFE +
+
+ + + +
+
+ PUBLIC WORDING ROUTE + BLOCKED +
+
+
+ 01 + WORDING +

Copy, metadata, proof cards, reviewer summaries.

+
+ +
-
- + +
diff --git a/app/globals.css b/app/globals.css index ae46cf6..b21571a 100644 --- a/app/globals.css +++ b/app/globals.css @@ -6316,6 +6316,869 @@ body::after { border-radius: 3px; } +/* Claim Firewall command center (/controls) ------------------------ */ +.controls-hero { + position: relative; + overflow: hidden; + padding: clamp(54px, 8vw, 88px) 0 clamp(34px, 5vw, 56px); + border-bottom: 1px solid var(--moon-border); + background: + radial-gradient(80% 80% at 18% 8%, rgba(59, 130, 246, 0.24), transparent 58%), + radial-gradient(60% 70% at 86% 16%, rgba(30, 64, 116, 0.16), transparent 54%), + linear-gradient(180deg, rgba(4, 8, 15, 0.98), rgba(3, 6, 11, 0.94)); +} + +.controls-hero::before { + content: ""; + position: absolute; + inset: 0; + background: + linear-gradient(90deg, rgba(143, 216, 255, 0.055) 1px, transparent 1px), + linear-gradient(180deg, rgba(143, 216, 255, 0.035) 1px, transparent 1px); + background-size: 46px 46px; + mask-image: radial-gradient(circle at 45% 30%, rgba(0, 0, 0, 0.86), transparent 76%); + pointer-events: none; +} + +.controls-hero__grid { + position: relative; + display: grid; + gap: 18px; + grid-template-columns: minmax(0, 1fr); + align-items: stretch; +} + +@media (min-width: 980px) { + .controls-hero__grid { + grid-template-columns: minmax(0, 0.82fr) minmax(280px, 0.36fr); + grid-template-areas: + "copy rail" + "console console"; + } + .controls-hero__copy { grid-area: copy; } + .controls-hero__rail { grid-area: rail; } + .controls-hero__console { grid-area: console; } +} + +.controls-hero__copy { + max-width: 840px; + padding-top: 4px; +} + +.controls-hero__title { + margin-top: 10px; + color: var(--silver-bright); + font-size: clamp(3rem, 8vw, 6.8rem); + line-height: 0.86; + font-weight: 850; + letter-spacing: 0; + text-shadow: 0 0 34px rgba(59, 130, 246, 0.18); +} + +.controls-hero__lede { + max-width: 72ch; + margin: 22px 0 0; + color: var(--silver); + font-size: clamp(1rem, 1.5vw, 1.18rem); + line-height: 1.65; +} + +.controls-hero__pills { + display: flex; + flex-wrap: wrap; + gap: 9px; + margin-top: 22px; +} + +.controls-hero__pills span { + display: inline-flex; + align-items: center; + min-height: 34px; + padding: 8px 12px; + border: 1px solid rgba(143, 216, 255, 0.28); + border-radius: 999px; + background: rgba(143, 216, 255, 0.07); + color: var(--ice-blue); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.66rem; + font-weight: 800; + letter-spacing: 0.14em; +} + +.controls-hero__pills .controls-hero__pill--blocked { + border-color: var(--blocked-red-soft); + background: rgba(252, 165, 165, 0.06); + color: var(--blocked-red); +} + +.controls-hero__rail { + position: relative; + align-self: end; + padding: 18px 18px 18px 22px; + border: 1px solid rgba(143, 216, 255, 0.24); + border-left: 3px solid var(--electric-blue-bright); + border-radius: 18px 4px 18px 4px; + background: linear-gradient(180deg, rgba(11, 18, 32, 0.82), rgba(4, 7, 12, 0.92)); + box-shadow: 0 18px 70px rgba(0, 0, 0, 0.42); +} + +.controls-hero__rail::after { + content: ""; + position: absolute; + right: 14px; + top: 14px; + width: 10px; + height: 10px; + border-radius: 999px; + background: var(--electric-blue-bright); + box-shadow: 0 0 18px var(--electric-blue-glow); +} + +.controls-hero__rail-label { + display: block; + color: var(--electric-blue-bright); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.62rem; + font-weight: 800; + letter-spacing: 0.22em; + text-transform: uppercase; +} + +.controls-hero__rail p { + margin: 11px 0 0; + color: var(--silver); + font-size: 0.9rem; + line-height: 1.5; +} + +.controls-hero__console { + position: relative; + margin-top: clamp(8px, 2vw, 18px); + padding: clamp(18px, 3vw, 30px); + border: 1px solid var(--moon-border-bright); + border-radius: 26px 8px 26px 8px; + background: + radial-gradient(80% 100% at 48% 0%, rgba(59, 130, 246, 0.18), transparent 56%), + linear-gradient(180deg, rgba(12, 19, 32, 0.94), rgba(3, 6, 11, 0.98)); + box-shadow: + 0 0 0 1px rgba(143, 216, 255, 0.08) inset, + 0 36px 110px rgba(0, 0, 0, 0.62); +} + +.controls-hero__console::before { + content: ""; + position: absolute; + inset: 16px; + border: 1px solid rgba(143, 216, 255, 0.08); + border-radius: 18px 4px 18px 4px; + pointer-events: none; +} + +.controls-hero__console-head { + position: relative; + display: flex; + flex-wrap: wrap; + justify-content: space-between; + gap: 12px; + align-items: center; + color: var(--muted); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.66rem; + font-weight: 800; + letter-spacing: 0.2em; +} + +.controls-hero__flow { + position: relative; + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(48px, 0.18fr) minmax(0, 1.2fr) minmax(48px, 0.18fr) minmax(0, 1fr); + gap: 12px; + align-items: center; + margin-top: 22px; +} + +.controls-hero__node { + position: relative; + min-width: 0; + min-height: 170px; + padding: 18px; + border: 1px solid var(--moon-border); + border-radius: 16px 4px 16px 4px; + background: rgba(4, 8, 15, 0.72); +} + +.controls-hero__node--scanner { + min-height: 210px; + border-color: var(--electric-blue-bright); + background: + radial-gradient(100% 80% at 50% 0%, rgba(59, 130, 246, 0.18), transparent 62%), + rgba(4, 8, 15, 0.84); + transform: translateY(-10px); +} + +.controls-hero__node--ceiling { + border-color: rgba(224, 189, 99, 0.52); +} + +.controls-hero__node span { + display: block; + color: var(--electric-blue-bright); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.7rem; + font-weight: 800; + letter-spacing: 0.18em; +} + +.controls-hero__node strong { + display: block; + margin-top: 18px; + color: var(--silver-bright); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: clamp(1rem, 1.7vw, 1.28rem); + letter-spacing: 0.14em; +} + +.controls-hero__node p { + margin: 16px 0 0; + color: var(--silver); + font-size: 0.9rem; + line-height: 1.5; +} + +.controls-hero__node em { + position: absolute; + left: 18px; + bottom: 18px; + display: inline-flex; + padding: 6px 9px; + border: 1px dashed var(--blocked-red-soft); + border-radius: 999px; + color: var(--blocked-red); + background: rgba(252, 165, 165, 0.06); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.58rem; + font-style: normal; + font-weight: 800; + letter-spacing: 0.14em; + text-transform: uppercase; +} + +.controls-hero__beam { + height: 2px; + background: linear-gradient(90deg, var(--electric-blue), var(--ice-blue)); + box-shadow: 0 0 18px var(--electric-blue-glow); +} + +.controls-hero__beam::after { + content: ""; + display: block; + margin-left: auto; + margin-top: -5px; + width: 12px; + height: 12px; + border-top: 2px solid var(--ice-blue); + border-right: 2px solid var(--ice-blue); + transform: rotate(45deg); +} + +.controls-hero__beam--blocked { + background: linear-gradient(90deg, var(--ice-blue), var(--blocked-red)); + box-shadow: 0 0 18px rgba(252, 165, 165, 0.24); +} + +.controls-hero__beam--blocked::after { + border-color: var(--blocked-red); +} + +.controls-hero__meter { + position: relative; + display: grid; + grid-template-columns: repeat(6, minmax(0, 1fr)); + gap: 3px; + margin-top: 20px; + border: 1px solid rgba(143, 216, 255, 0.14); + border-radius: 999px; + padding: 4px; + background: rgba(3, 6, 11, 0.72); +} + +.controls-hero__meter span { + min-width: 0; + padding: 8px 9px; + border-radius: 999px; + background: rgba(143, 216, 255, 0.08); + color: var(--ice-blue); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.58rem; + font-weight: 800; + letter-spacing: 0.08em; + text-align: center; + text-transform: uppercase; + overflow-wrap: anywhere; +} + +.controls-hero__meter .controls-hero__meter-blocked { + background: rgba(252, 165, 165, 0.10); + color: var(--blocked-red); +} + +.controls-hero__boundary-strip { + position: relative; + display: flex; + flex-wrap: wrap; + gap: 8px 14px; + align-items: center; + margin-top: 14px; + padding: 11px 14px; + border: 1px solid rgba(224, 189, 99, 0.28); + border-left: 3px solid var(--ceiling-amber); + border-radius: 12px 4px 12px 4px; + background: rgba(224, 189, 99, 0.055); + color: var(--silver); + font-size: 0.88rem; + line-height: 1.45; +} + +.controls-hero__boundary-strip strong { + color: var(--silver-bright); +} + +.controls-main { + padding-top: clamp(26px, 5vw, 48px); + padding-bottom: clamp(48px, 8vw, 84px); +} + +.claim-firewall-demo { + display: grid; + gap: clamp(16px, 2.4vw, 26px); +} + +.claim-firewall-demo__control, +.claim-firewall-demo__panel { + position: relative; + overflow: hidden; + border: 1px solid var(--moon-border-bright); + border-radius: 14px; + background: + radial-gradient(120% 90% at 18% 0%, rgba(59, 130, 246, 0.14), transparent 50%), + linear-gradient(180deg, rgba(13, 20, 34, 0.92), rgba(4, 7, 12, 0.98)); + box-shadow: + 0 0 0 1px rgba(143, 216, 255, 0.08) inset, + 0 28px 80px rgba(0, 0, 0, 0.52); +} + +.claim-firewall-demo__control { + padding: clamp(22px, 4vw, 34px); +} + +.claim-firewall-demo__control::before, +.claim-firewall-demo__panel::before { + content: ""; + position: absolute; + inset: 0; + background: + linear-gradient(90deg, rgba(143, 216, 255, 0.06) 1px, transparent 1px), + linear-gradient(180deg, rgba(143, 216, 255, 0.035) 1px, transparent 1px); + background-size: 38px 38px; + mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), transparent 72%); + pointer-events: none; +} + +.claim-firewall-demo__control-head, +.claim-firewall-demo__panel-head { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + gap: 16px; +} + +.claim-firewall-demo__title { + margin-top: 8px; + color: var(--silver-bright); + font-size: clamp(1.45rem, 3vw, 2.4rem); + line-height: 1.05; + letter-spacing: 0; + font-weight: 800; +} + +.claim-firewall-demo__panel { + padding: 22px; +} + +.claim-firewall-demo__panel-title { + margin-top: 6px; + color: var(--silver-bright); + font-size: clamp(1.1rem, 2vw, 1.45rem); + font-weight: 750; + letter-spacing: 0; +} + +.claim-firewall-demo__panel-status { + position: relative; + display: inline-flex; + align-items: center; + min-height: 30px; + padding: 7px 10px; + border: 1px solid var(--diagram-line); + border-radius: 999px; + background: rgba(143, 216, 255, 0.07); + color: var(--ice-blue); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.62rem; + font-weight: 800; + letter-spacing: 0.16em; + text-transform: uppercase; +} + +.claim-firewall-demo__flow { + position: relative; + display: grid; + grid-template-columns: 1fr auto 1fr auto 1fr; + gap: 14px; + align-items: stretch; + margin-top: 28px; +} + +.claim-firewall-demo__node { + position: relative; + min-width: 0; + padding: 18px; + border: 1px solid var(--moon-border); + border-radius: 10px; + background: rgba(5, 9, 16, 0.72); +} + +.claim-firewall-demo__node::after { + content: ""; + position: absolute; + inset: 0; + border-radius: inherit; + box-shadow: 0 0 22px rgba(59, 130, 246, 0.12) inset; + pointer-events: none; +} + +.claim-firewall-demo__node--scanner { + border-color: var(--electric-blue-bright); + background: + radial-gradient(90% 100% at 50% 0%, rgba(59, 130, 246, 0.15), transparent 58%), + rgba(5, 9, 16, 0.82); +} + +.claim-firewall-demo__node--ceiling { + border-color: rgba(224, 189, 99, 0.45); +} + +.claim-firewall-demo__node-code { + display: block; + color: var(--electric-blue-bright); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.68rem; + font-weight: 800; + letter-spacing: 0.2em; +} + +.claim-firewall-demo__node strong { + display: block; + margin-top: 10px; + color: var(--silver-bright); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + letter-spacing: 0.14em; + font-size: 0.88rem; +} + +.claim-firewall-demo__node p { + margin: 12px 0 0; + color: var(--silver); + font-size: 0.88rem; + line-height: 1.55; +} + +.claim-firewall-demo__arrow { + align-self: center; + color: var(--electric-blue-bright); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 1rem; + font-weight: 800; + text-shadow: 0 0 16px var(--electric-blue-glow); +} + +.claim-firewall-demo__blocked-line { + margin-top: 14px; + padding: 8px 10px; + border: 1px dashed var(--blocked-red-soft); + border-radius: 4px; + background: rgba(252, 165, 165, 0.06); + color: var(--blocked-red); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.62rem; + letter-spacing: 0.14em; + text-transform: uppercase; +} + +.claim-firewall-demo__console-line { + position: relative; + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 8px; + margin: 22px 0 0; +} + +.claim-firewall-demo__console-line span { + height: 4px; + border-radius: 999px; + background: linear-gradient(90deg, var(--electric-blue), var(--ice-blue), var(--blocked-red)); + box-shadow: 0 0 18px rgba(59, 130, 246, 0.22); + opacity: 0.78; +} + +.claim-firewall-demo__boundary { + position: relative; + margin: 20px 0 0; + max-width: 82ch; + color: var(--silver-bright); + font-size: 1rem; + line-height: 1.65; +} + +.claim-firewall-demo__panel--blocked { + border-color: rgba(252, 165, 165, 0.34); + background: + radial-gradient(90% 90% at 90% 0%, rgba(252, 165, 165, 0.10), transparent 55%), + linear-gradient(180deg, rgba(25, 10, 16, 0.72), rgba(4, 7, 12, 0.98)); +} + +.claim-firewall-demo__chips { + position: relative; + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 18px; +} + +.claim-firewall-demo__chip { + display: inline-flex; + align-items: center; + min-height: 30px; + padding: 7px 10px; + border: 1px solid var(--blocked-red-soft); + border-radius: 999px; + background: + repeating-linear-gradient(135deg, rgba(252, 165, 165, 0.055) 0 6px, transparent 6px 12px), + rgba(252, 165, 165, 0.035); + color: #ffbdc7; + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.62rem; + font-weight: 750; + letter-spacing: 0.08em; + text-transform: uppercase; + overflow-wrap: anywhere; +} + +.claim-firewall-demo__examples { + display: grid; + gap: 18px; +} + +@media (min-width: 900px) { + .claim-firewall-demo__examples { grid-template-columns: 1fr 1fr; } +} + +.claim-firewall-demo__panel--unsafe { + border-color: rgba(252, 165, 165, 0.26); +} + +.claim-firewall-demo__panel--allowed { + border-color: rgba(143, 216, 255, 0.24); +} + +.claim-firewall-demo__list, +.claim-firewall-demo__requirements, +.claim-firewall-demo__meter, +.claim-firewall-demo__timeline, +.claim-firewall-demo__outcomes { + position: relative; + list-style: none; + margin: 18px 0 0; + padding: 0; +} + +.claim-firewall-demo__list { + display: grid; + gap: 10px; +} + +.claim-firewall-demo__list li { + padding: 12px 13px; + border: 1px solid var(--moon-border); + border-radius: 6px; + color: var(--silver); + background: rgba(5, 9, 16, 0.54); + font-size: 0.9rem; + line-height: 1.5; +} + +.claim-firewall-demo__list--allowed li { + border-left: 3px solid var(--electric-blue); +} + +.claim-firewall-demo__list--unsafe li { + border-left: 3px solid var(--blocked-red); + color: #e6c5cd; +} + +.claim-firewall-demo__requirements { + display: grid; + gap: 10px; +} + +.claim-firewall-demo__requirements li { + display: grid; + grid-template-columns: 44px 1fr; + gap: 12px; + align-items: start; + padding: 13px 14px; + border: 1px solid var(--moon-border); + border-radius: 6px; + background: rgba(5, 9, 16, 0.56); + color: var(--silver); + font-size: 0.9rem; + line-height: 1.5; +} + +.claim-firewall-demo__requirements span, +.claim-firewall-demo__timeline span, +.claim-firewall-demo__meter-index { + color: var(--electric-blue-bright); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.68rem; + font-weight: 800; + letter-spacing: 0.16em; +} + +.claim-firewall-demo__meter { + display: flex; + gap: 0; + overflow-x: auto; + padding: 4px; + border: 1px solid rgba(143, 216, 255, 0.14); + border-radius: 999px; + background: rgba(3, 6, 11, 0.72); +} + +.claim-firewall-demo__meter-step { + position: relative; + flex: 1 0 170px; + min-width: 0; + padding: 14px 16px 16px; + border: 0; + border-right: 1px solid rgba(143, 216, 255, 0.12); + border-radius: 999px; + background: rgba(143, 216, 255, 0.055); +} + +.claim-firewall-demo__meter-step::before { + content: ""; + position: absolute; + left: 16px; + right: 16px; + top: 5px; + height: 3px; + border-radius: 999px; + background: var(--electric-blue); +} + +.claim-firewall-demo__meter-step--warn::before { + background: var(--ceiling-amber); +} + +.claim-firewall-demo__meter-step--blocked::before { + background: var(--blocked-red); +} + +.claim-firewall-demo__meter-step--blocked { + background: rgba(252, 165, 165, 0.08); + border-right: 0; +} + +.claim-firewall-demo__meter-step strong { + display: block; + margin-top: 10px; + color: var(--silver-bright); + font-size: 0.88rem; + line-height: 1.25; +} + +.claim-firewall-demo__meter-step em { + display: inline-flex; + margin-top: 10px; + padding: 4px 7px; + border: 1px solid var(--diagram-line); + border-radius: 999px; + color: var(--ice-blue); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.58rem; + font-style: normal; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.claim-firewall-demo__meter-step--blocked em { + border-color: var(--blocked-red-soft); + color: var(--blocked-red); +} + +.claim-firewall-demo__meter-step p { + margin: 11px 0 0; + color: var(--muted); + font-size: 0.78rem; + line-height: 1.45; +} + +.claim-firewall-demo__timeline { + display: grid; + gap: 10px; +} + +@media (min-width: 820px) { + .claim-firewall-demo__timeline { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } +} + +.claim-firewall-demo__timeline li { + position: relative; + padding: 13px; + border: 1px solid var(--moon-border); + border-radius: 8px; + background: rgba(5, 9, 16, 0.58); +} + +.claim-firewall-demo__timeline li:not(:last-child)::after { + content: "->"; + position: absolute; + right: -17px; + top: 50%; + transform: translateY(-50%); + color: var(--electric-blue-bright); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; +} + +.claim-firewall-demo__timeline strong { + display: block; + margin-top: 8px; + color: var(--silver-bright); + font-size: 0.86rem; + line-height: 1.25; +} + +.claim-firewall-demo__panel--outcome { + border-color: rgba(143, 216, 255, 0.28); +} + +.claim-firewall-demo__outcomes { + display: grid; + gap: 9px; +} + +@media (min-width: 760px) { + .claim-firewall-demo__outcomes { grid-template-columns: repeat(5, minmax(0, 1fr)); } +} + +.claim-firewall-demo__outcomes li { + position: relative; + min-height: 116px; + padding: 13px; + border: 1px solid var(--blocked-red-soft); + border-radius: 14px 4px 14px 4px; + background: + repeating-linear-gradient(135deg, rgba(252, 165, 165, 0.045) 0 6px, transparent 6px 12px), + rgba(5, 9, 16, 0.66); + color: var(--silver-bright); + font-size: 0.78rem; + line-height: 1.35; +} + +.claim-firewall-demo__outcomes li span { + display: block; + color: var(--silver); +} + +.claim-firewall-demo__outcomes li strong { + display: block; + margin: 10px 0; + color: var(--blocked-red); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.78rem; + letter-spacing: 0.18em; +} + +.claim-firewall-demo__outcomes li em { + position: absolute; + left: 13px; + bottom: 12px; + color: var(--blocked-red); + font-family: "JetBrains Mono", "SFMono-Regular", Consolas, monospace; + font-size: 0.58rem; + font-style: normal; + font-weight: 800; + letter-spacing: 0.18em; + text-transform: uppercase; +} + +.claim-firewall-demo__outcome-copy { + position: relative; + margin: 16px 0 0; + padding: 14px 16px; + border: 1px solid rgba(143, 216, 255, 0.24); + border-left: 3px solid var(--electric-blue-bright); + border-radius: 6px; + background: rgba(143, 216, 255, 0.055); + color: var(--silver); + line-height: 1.6; +} + +@media (max-width: 820px) { + .controls-hero__flow, + .claim-firewall-demo__flow { + grid-template-columns: 1fr; + } + + .controls-hero__beam { + width: 2px; + height: 34px; + justify-self: center; + } + + .controls-hero__beam::after { + margin: 21px 0 0 -5px; + transform: rotate(135deg); + } + + .controls-hero__node--scanner { + transform: none; + } + + .controls-hero__meter { + grid-template-columns: repeat(2, minmax(0, 1fr)); + border-radius: 16px; + } + + .controls-hero__meter span { + border-radius: 12px; + } + + .claim-firewall-demo__arrow { + justify-self: center; + transform: rotate(90deg); + } + + .claim-firewall-demo__timeline li:not(:last-child)::after { + display: none; + } +} + /* Prior-context strip (demoted V1 metrics) ------------------------ */ .prior-context-strip { border-top: 1px dashed var(--diagram-line); diff --git a/app/page.tsx b/app/page.tsx index e3de0ed..79af708 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -39,6 +39,14 @@ export default function HomePage() { Each stage shows what happens, what control sits over it, and what gets blocked. The verifier owns pass and fail; human review owns merge authority.

+ + CLAIM FIREWALL + Unsupported public security claims fail before they ship. + + Open the public wording gate that keeps website rendering below proof authority. + + Inspect Claim Firewall -> + diff --git a/app/proof/page.tsx b/app/proof/page.tsx index 281ac1a..aa950a3 100644 --- a/app/proof/page.tsx +++ b/app/proof/page.tsx @@ -209,7 +209,15 @@ export default function ProofIndexPage() { Where to inspect next. -
+
+ + CLAIM FIREWALL + Claim Firewall control surface + + Review the public wording gate that keeps website rendering below proof authority. + + Open Claim Firewall -> + GOVERNANCE SAVES Controls that prevented unsafe truth diff --git a/components/ClaimFirewall.tsx b/components/ClaimFirewall.tsx index 81fdbce..0c89581 100644 --- a/components/ClaimFirewall.tsx +++ b/components/ClaimFirewall.tsx @@ -6,58 +6,200 @@ import { unsafeWordingExamples, } from "@data/claims"; +const ceilingLevels = [ + { + label: "Source truth", + state: "reviewable", + detail: "Source-controlled wording can be inspected, but source presence does not prove runtime.", + tone: "active", + }, + { + label: "Validation truth", + state: "controlled", + detail: "Deterministic validation can support controlled-test wording at the current ceiling.", + tone: "active", + }, + { + label: "Runtime candidate", + state: "candidate only", + detail: "Runtime candidates remain below public proof until separately evidenced and promoted.", + tone: "warn", + }, + { + label: "Signal / evidence review", + state: "gated", + detail: "Signal and evidence claims require separate review before public wording can move.", + tone: "warn", + }, + { + label: "Human approval", + state: "authority", + detail: "Human review authorizes promotion; AI and green checks do not.", + tone: "active", + }, + { + label: "Public proof", + state: "blocked until promoted", + detail: "Public-safe status remains blocked unless explicit evidence linkage and promotion clear.", + tone: "blocked", + }, +]; + +const blockedTransformations = [ + { + from: "validation", + to: "runtime proof", + }, + { + from: "website rendering", + to: "proof", + }, + { + from: "green CI", + to: "approval", + }, + { + from: "AI support", + to: "disposition authority", + }, + { + from: "runtime candidate", + to: "public-safe proof", + }, +]; + export default function ClaimFirewall() { return ( -
-
-

Allowed claims

-
    - {allowedClaims.map((claim, i) => ( -
  • {claim}
  • +
    +
    +
    +
    +

    Evidence ceiling gauge

    +

    Claim levels stay separated

    +
    + PUBLIC-SAFE BLOCKED UNLESS PROMOTED +
    +
      + {ceilingLevels.map((level, index) => ( +
    1. + {String(index + 1).padStart(2, "0")} + {level.label} + {level.state} +

      {level.detail}

      +
    2. ))} -
+
-
-

Blocked / not claimed

-
+ +
+
+

Blocked / not claimed

+ CONTROLLED RISK CHIPS +
+
{blockedClaims.map((claim) => ( - + {claim} ))}
-
-

Promotion requirements

-
    + +
    +
    +

    Allowed wording examples

    +
      + {safeWordingExamples.map((claim, i) => ( +
    • {claim}
    • + ))} +
    +
    + +
    +

    Unsafe wording examples

    +
      + {unsafeWordingExamples.map((item, i) => ( +
    • {item}
    • + ))} +
    +
    +
    + +
    +
    +

    Promotion requirements

    + EVIDENCE LINKAGE REQUIRED +
    +
      {promotionRequirements.map((item, i) => ( -
    1. {item}
    2. +
    3. + {String(i + 1).padStart(2, "0")} + {item} +
    4. ))} -
+
-
-

Wording examples

-
+ +
+
-

Safe wording

-
    - {safeWordingExamples.map((item, i) => ( -
  • {item}
  • - ))} -
+

Promotion gate timeline

+

Evidence moves before wording moves

+ FAIL CLOSED +
+
    + {[ + "Source truth", + "Validation truth", + "Runtime candidate", + "Signal / evidence review", + "Human approval", + "Public proof", + ].map((step, index) => ( +
  1. + {String(index + 1).padStart(2, "0")} + {step} +
  2. + ))} +
+
+ +
+
-

Unsafe wording

-
    - {unsafeWordingExamples.map((item, i) => ( -
  • {item}
  • - ))} -
+

Outcome panel

+

What the firewall prevents

+ AI LABOR / HUMAN AUTHORITY +
+
    + {blockedTransformations.map((item) => ( +
  • + {item.from} + + {item.to} + blocked +
  • + ))} +
+

+ AI-assisted security work can move fast, but public wording stays governed: the scanner + constrains unsupported language, then human review decides whether evidence is sufficient + for any explicit promotion. +

+
+ +
+
+

Allowed claim basis

+ BELOW CEILING
+
    + {allowedClaims.map((claim, i) => ( +
  • {claim}
  • + ))} +
); diff --git a/public/.well-known/hawkinsoperations-proof.json b/public/.well-known/hawkinsoperations-proof.json index d416dd0..a341d29 100644 --- a/public/.well-known/hawkinsoperations-proof.json +++ b/public/.well-known/hawkinsoperations-proof.json @@ -21,6 +21,12 @@ "url": "https://hawkinsoperations.com/proof/", "use": "Review public proof navigation, verifier cards, and claim ceilings." }, + { + "id": "claim-firewall", + "label": "Claim Firewall", + "url": "https://hawkinsoperations.com/controls/", + "use": "Review the public wording gate that keeps website rendering below proof authority." + }, { "id": "validation-registry", "label": "Validation registry", diff --git a/public/agent.md b/public/agent.md index 8a0b91b..626ca3d 100644 --- a/public/agent.md +++ b/public/agent.md @@ -7,6 +7,7 @@ This public website exposes read, review, and navigation metadata for agents and - `/.well-known/hawkinsoperations-proof.json` - `/.well-known/agent-skills/index.json` - `/proof/` +- `/controls/` - `/validation/` - `/architecture/truth-surfaces/` - `/architecture/repo-authority-map/` diff --git a/scripts/verify-site-contract.mjs b/scripts/verify-site-contract.mjs index aa0bc00..a056cad 100644 --- a/scripts/verify-site-contract.mjs +++ b/scripts/verify-site-contract.mjs @@ -60,6 +60,7 @@ const primaryNavMatch = navigationData.match(/export const primaryNavigation: Na const expectedPrimaryNav = [ { label: "Home", href: "/" }, { label: "Proof", href: "/proof/" }, + { label: "Controls", href: "/controls/" }, { label: "Artifacts", href: "/artifacts/" }, { label: "Detections", href: "/detections/" }, { label: "AI Security", href: "/ai-security/" }, @@ -138,8 +139,33 @@ if (homepageLabelFailures.length > 0) { const proofPage = readFileSync(join(root, "app/proof/page.tsx"), "utf8"); const proofHoDet001Page = readFileSync(join(root, "app/proof/ho-det-001/page.tsx"), "utf8"); const currentProofSpine = readFileSync(join(root, "components/CurrentProofSpine.tsx"), "utf8"); +const controlsPage = readFileSync(join(root, "app/controls/page.tsx"), "utf8"); +const claimFirewallComponent = readFileSync(join(root, "components/ClaimFirewall.tsx"), "utf8"); const proofRecordsData = readFileSync(join(root, "src/data/proofRecords.ts"), "utf8"); const navigationSource = readFileSync(join(root, "src/data/navigation.ts"), "utf8"); +const claimFirewallFrontDoorRequiredTerms = [ + ["src/data/navigation.ts", navigationSource, 'label: "Controls"'], + ["src/data/navigation.ts", navigationSource, 'href: "/controls/"'], + ["app/page.tsx", homePage, 'href="/controls/"'], + ["app/page.tsx", homePage, "Claim Firewall"], + ["app/page.tsx", homePage, "Unsupported public security claims fail before they ship."], + ["app/page.tsx", homePage, "Inspect Claim Firewall"], + ["app/proof/page.tsx", proofPage, 'href="/controls/"'], + ["app/proof/page.tsx", proofPage, "Claim Firewall control surface"], + ["app/proof/page.tsx", proofPage, "Open Claim Firewall"], + ["app/proof/page.tsx", proofPage, "website rendering below proof authority"], + ["app/controls/page.tsx", controlsPage, "Website rendering is not proof"], + ["app/controls/page.tsx", controlsPage, "Public proof requires evidence linkage and explicit promotion."], +]; +const claimFirewallFrontDoorFailures = claimFirewallFrontDoorRequiredTerms + .filter(([, source, term]) => !source.includes(term)) + .map(([file, , term]) => `${file} must include ${term}.`); + +if (claimFirewallFrontDoorFailures.length > 0) { + console.error(`Claim Firewall front-door invariant failed:\n${claimFirewallFrontDoorFailures.map((line) => `- ${line}`).join("\n")}`); + process.exit(1); +} + const lifetimeLedgerRequiredTerms = [ ["app/proof/page.tsx", proofPage, "Lifetime Case Ledger v1"], ["app/proof/page.tsx", proofPage, "total_ledger_events"], @@ -244,6 +270,43 @@ if (currentProofSpineFailures.length > 0) { process.exit(1); } +const claimFirewallVisualRequiredTerms = [ + ["app/controls/page.tsx", controlsPage, "Claim Firewall"], + ["app/controls/page.tsx", controlsPage, "Public wording stays below the evidence ceiling"], + ["app/controls/page.tsx", controlsPage, "Website rendering is not proof"], + ["app/controls/page.tsx", controlsPage, "controls-hero"], + ["app/controls/page.tsx", controlsPage, "Unsupported security claims should fail before they reach the public page"], + ["app/controls/page.tsx", controlsPage, "WORDING"], + ["app/controls/page.tsx", controlsPage, "SCANNER"], + ["app/controls/page.tsx", controlsPage, "CEILING"], + ["app/controls/page.tsx", controlsPage, "PUBLIC WORDING ROUTE"], + ["app/controls/page.tsx", controlsPage, "public proof blocked"], + ["app/controls/page.tsx", controlsPage, "Public inspection layer"], + ["app/controls/page.tsx", controlsPage, "controls-hero__boundary-strip"], + ["app/controls/page.tsx", controlsPage, "Public proof requires evidence linkage and explicit promotion."], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "claim-firewall-demo"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "Evidence ceiling gauge"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "Blocked / not claimed"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "CONTROLLED RISK CHIPS"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "Allowed wording examples"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "Unsafe wording examples"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "Promotion gate timeline"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "Outcome panel"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "website rendering"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "green CI"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "AI support"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "runtime candidate"], + ["components/ClaimFirewall.tsx", claimFirewallComponent, "public-safe proof"], +]; +const claimFirewallVisualFailures = claimFirewallVisualRequiredTerms + .filter(([, source, term]) => !source.includes(term)) + .map(([file, , term]) => `${file} must include ${term}.`); + +if (claimFirewallVisualFailures.length > 0) { + console.error(`Claim Firewall visual invariant failed:\n${claimFirewallVisualFailures.map((line) => `- ${line}`).join("\n")}`); + process.exit(1); +} + if (!proofHoDet001Page.includes('title: "HO-DET-001 | HawkinsOperations"')) { console.error("HO-DET-001 proof route metadata must use HawkinsOperations, not stale HawkinsOps branding."); process.exit(1); @@ -268,6 +331,12 @@ if (!Array.isArray(discoveryProof.blocked_claims) || !discoveryProof.blocked_cla if (!Array.isArray(discoveryProof.reviewer_routes) || discoveryProof.reviewer_routes.length < 4) { discoveryFailures.push("public/.well-known/hawkinsoperations-proof.json must expose reviewer_routes for machine-readable navigation."); } +if (!discoveryProof.reviewer_routes?.some((route) => route.id === "claim-firewall" && route.url === "https://hawkinsoperations.com/controls/")) { + discoveryFailures.push("public/.well-known/hawkinsoperations-proof.json must expose /controls/ as the claim-firewall reviewer route."); +} +if (!agentMarkdown.includes("/controls/")) { + discoveryFailures.push("public/agent.md must list /controls/ as a public entry point."); +} if (agentSkills.agent_capability_boundary !== "read_review_navigation_only") { discoveryFailures.push("public/.well-known/agent-skills/index.json must cap agent_capability_boundary at read_review_navigation_only."); } diff --git a/src/data/navigation.ts b/src/data/navigation.ts index 8ff62fb..8e7eea2 100644 --- a/src/data/navigation.ts +++ b/src/data/navigation.ts @@ -7,6 +7,7 @@ export type NavItem = { export const primaryNavigation: NavItem[] = [ { label: "Home", href: "/", description: "Reviewer cockpit" }, { label: "Proof", href: "/proof/", description: "Claim authority" }, + { label: "Controls", href: "/controls/", description: "Claim Firewall" }, { label: "Artifacts", href: "/artifacts/", description: "Reviewer receipts" }, { label: "Detections", href: "/detections/", description: "Detection engineering" }, { label: "AI Security", href: "/ai-security/", description: "AI-assisted SOC model" },