diff --git a/packages/web/app/globals.css b/packages/web/app/globals.css index ace4fa1..1684bd0 100644 --- a/packages/web/app/globals.css +++ b/packages/web/app/globals.css @@ -288,3 +288,316 @@ body { background: var(--color-ink); color: var(--color-paper); } @media (prefers-reduced-motion: reduce) { .cloud-node { animation: none; opacity: 1; transform: none; } } + +/* + * ───────────────────────────────────────────────────────────────────────────────────── + * Editorial homepage layer (design/editorial-homepage, 2026-09-28). + * AIVH editorial-motion-web-design, Mode 002 PRODUCT_CONVERSION_LANDING. + * + * Scoped to `.home-*` classes used only by app/page.tsx, so no other route changes. The + * brand holds: ink ground, Geist, emerald only for the primary action (never atmosphere). + * Tone alternation is the rhythm device: ink → paper (the page's single light band, at + * the PROBLEM beat) → ink → ink-2 → ink … Type sizes are fluid clamp() values fitted to + * the real headlines ("AI agents need an identity." breaks into two lines at 1280 and + * three at 390). Section padding varies by density class instead of one uniform value. + * ───────────────────────────────────────────────────────────────────────────────────── + */ +.home { + /* Paper-band roles. ink-soft on paper is 10.3:1, muted-on-paper 7.2:1 (WCAG AA body). */ + --home-ink-soft: #334155; + --home-muted-on-paper: #475569; + --home-rule-on-paper: #cbd5e1; + --home-ease: cubic-bezier(0.2, 0.7, 0.2, 1); +} + +/* Same shell as the header and footer (max-w-6xl + px-5/6/8) so every left edge aligns. */ +.home-shell { margin-inline: auto; width: 100%; max-width: 72rem; padding-inline: 1.25rem; } +@media (min-width: 640px) { .home-shell { padding-inline: 1.5rem; } } +@media (min-width: 1024px) { .home-shell { padding-inline: 2rem; } } + +/* Density classes (storyboard): immersive > editorial > informational. */ +.home-pad-immersive { padding-block: clamp(4.5rem, 11vw, 10rem); } +.home-pad-editorial { padding-block: clamp(4rem, 9vw, 8rem); } +.home-pad-info { padding-block: clamp(3.5rem, 6vw, 6rem); } +.home-ground-2 { background: var(--color-ink-2); } + +/* Type roles. */ +.home-display { + font-size: clamp(3rem, 8.6vw, 8.75rem); + font-weight: 600; + line-height: 0.94; + letter-spacing: -0.045em; + text-wrap: balance; + max-width: 14ch; +} +.home-display-2 { + font-size: clamp(2.5rem, 6vw, 5.5rem); + font-weight: 600; + line-height: 0.98; + letter-spacing: -0.04em; + text-wrap: balance; +} +.home-statement { + font-size: clamp(2rem, 4.4vw, 4rem); + font-weight: 600; + line-height: 1.02; + letter-spacing: -0.035em; + text-wrap: balance; +} +.home-h2 { + font-size: clamp(2rem, 3.8vw, 3.5rem); + font-weight: 600; + line-height: 1.04; + letter-spacing: -0.03em; + text-wrap: balance; +} +.home-h3 { + font-size: clamp(1.375rem, 2.2vw, 2.25rem); + font-weight: 600; + line-height: 1.1; + letter-spacing: -0.02em; + text-wrap: balance; +} +.home-h4 { font-size: 1.125rem; font-weight: 600; line-height: 1.3; letter-spacing: -0.01em; color: var(--color-paper); } +.home-lede { font-size: clamp(1.125rem, 1.5vw, 1.375rem); line-height: 1.55; color: var(--color-paper-dim); max-width: 36ch; text-wrap: pretty; } +.home-convert .home-lede { max-width: 52ch; } +.home-body { font-size: 1.0625rem; line-height: 1.65; color: var(--color-paper-dim); max-width: 62ch; text-wrap: pretty; } +.home-note { font-size: 0.9375rem; line-height: 1.65; color: var(--color-paper-dim); max-width: 64ch; text-wrap: pretty; } +.home-label { + font-size: 0.75rem; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.12em; + color: var(--color-muted); +} +.home-numeral { + font-size: clamp(5rem, 12vw, 11rem); + font-weight: 600; + line-height: 0.85; + letter-spacing: -0.06em; + font-variant-numeric: tabular-nums; + font-family: var(--font-mono); + color: var(--color-paper); +} + +/* Links. Text + underline, never a second colour (brand guide: colour is for state). */ +.home-inline-link { color: var(--color-paper); text-decoration: underline; text-underline-offset: 3px; } +.home-inline-link:hover { text-decoration-thickness: 2px; } +.home-textlink { + display: inline-flex; + min-height: 44px; + align-items: center; + gap: 0.5rem; + font-size: 0.9375rem; + font-weight: 600; + color: var(--color-paper); + text-decoration: underline; + text-decoration-color: var(--color-line-strong); + text-underline-offset: 6px; +} +.home-textlink:hover { text-decoration-color: var(--color-paper); } +.home-links { display: flex; flex-wrap: wrap; column-gap: 1.75rem; } + +/* The one hover motion the mode allows: the CTA arrow nudge. */ +.home-cta-arrow { display: inline-block; transition: transform 240ms var(--home-ease); } +@media (prefers-reduced-motion: no-preference) { + a:hover > .home-cta-arrow, a:focus-visible > .home-cta-arrow { transform: translateX(6px); } +} + +/* Above-the-fold load-in. Always completes (no observer); off under reduced motion. */ +@keyframes home-rise { from { opacity: 0; transform: translateY(28px); } to { opacity: 1; transform: none; } } +@media (prefers-reduced-motion: no-preference) { + .rise { animation: home-rise 900ms var(--home-ease) both; animation-delay: calc(var(--rise-i, 0) * 90ms); } +} + +/* HOOK ─ copy left, identifier specimen right; stacks under 900px. */ +.home-hero-grid { display: grid; gap: 3.5rem; align-items: end; } +@media (min-width: 900px) { .home-hero-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 4rem; } } +.home-specimen { border-top: 1px solid var(--color-line-strong); padding-top: 1.25rem; } +.home-specimen-id { + margin-top: 1rem; + font-family: var(--font-mono); + font-size: clamp(1.125rem, 2.1vw, 1.75rem); + line-height: 1.15; + letter-spacing: -0.01em; + color: var(--color-paper); + overflow-wrap: anywhere; +} +.home-specimen-notes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem 2rem; margin-top: 1.5rem; } +.home-specimen-notes dt { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--color-muted); } +.home-specimen-notes dd { margin-top: 0.25rem; font-size: 0.9375rem; line-height: 1.5; color: var(--color-paper-dim); } + +/* PROBLEM ─ the single light band. */ +.ground-paper { background: var(--color-paper); color: var(--color-ink); color-scheme: light; } +.ground-paper .home-body { color: var(--home-ink-soft); } +.ground-paper .home-inline-link { color: var(--color-ink); } +.ground-paper :where(a, button):focus-visible { outline-color: var(--color-ink); } +.home-label-on-paper { color: var(--home-muted-on-paper); } +.home-problem { display: grid; gap: 4rem; } +@media (min-width: 900px) { + .home-problem { grid-template-columns: repeat(12, minmax(0, 1fr)); row-gap: 5rem; } + .home-problem-a { grid-column: 1 / span 7; } + .home-problem-b { grid-column: 6 / span 7; } +} +.home-questions { display: grid; gap: 1.5rem; border-top: 1px solid var(--home-rule-on-paper); padding-top: 1.5rem; } +@media (min-width: 900px) { .home-questions { grid-template-columns: minmax(0, 3fr) minmax(0, 9fr); } } +.home-questions ol { display: grid; } +.home-questions li { + display: flex; + align-items: baseline; + gap: 1.25rem; + padding-block: 0.875rem; + border-bottom: 1px solid var(--home-rule-on-paper); + font-size: clamp(1.25rem, 2.2vw, 2rem); + font-weight: 500; + letter-spacing: -0.02em; + line-height: 1.2; +} +.home-q-n { font-family: var(--font-mono); font-size: 0.8125rem; color: var(--home-muted-on-paper); font-variant-numeric: tabular-nums; } + +/* MECHANISM ─ pillar rows (verb-led rows, not cards). */ +.home-rows { border-top: 1px solid var(--color-line-strong); } +.home-row { + display: grid; + gap: 0.75rem; + padding-block: 1.75rem; + border-bottom: 1px solid var(--color-line); +} +@media (min-width: 900px) { + .home-row { grid-template-columns: 4rem minmax(0, 4fr) minmax(0, 6fr) minmax(0, 2.5fr); gap: 2rem; align-items: baseline; padding-block: 2.25rem; } +} +.home-row-n { font-family: var(--font-mono); font-size: 0.8125rem; color: var(--color-muted); } +.home-row-body { font-size: 1rem; line-height: 1.65; color: var(--color-paper-dim); max-width: 62ch; } +.home-row-tag { font-size: 0.75rem; color: var(--color-muted); } +@media (min-width: 900px) { .home-row-tag { text-align: right; } } + +/* Lifecycle rail: horizontal from 900px, a vertical list with its markers below. */ +.home-rail { display: grid; gap: 0; position: relative; } +.home-rail li { position: relative; display: grid; gap: 0.25rem; padding: 0 0 1.75rem 2rem; } +.home-rail li::before { + content: ""; + position: absolute; + left: 5px; + top: 14px; + bottom: 0; + width: 1px; + background: var(--color-line-strong); +} +.home-rail li:last-child::before { display: none; } +.home-rail-marker { + position: absolute; + left: 0; + top: 3px; + width: 11px; + height: 11px; + border-radius: 999px; + background: var(--color-paper); +} +.home-rail li.is-pending .home-rail-marker { background: transparent; border: 1px dashed var(--color-paper-dim); } +.home-rail-n { font-family: var(--font-mono); font-size: 0.75rem; color: var(--color-muted); } +.home-rail-label { font-size: 0.9375rem; color: var(--color-paper); } +.home-rail-sub { font-size: 0.875rem; color: var(--color-paper-dim); } +.home-rail-flag { + justify-self: start; + margin-top: 0.5rem; + border: 1px dashed var(--color-line-strong); + border-radius: 0.375rem; + padding: 0.25rem 0.5rem; + font-size: 0.75rem; + color: var(--color-muted); +} +@media (min-width: 900px) { + .home-rail { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 1.5rem; } + .home-rail li { padding: 1.75rem 0 0 0; align-content: start; } + .home-rail li::before { left: 0; right: -1.5rem; top: 5px; bottom: auto; width: auto; height: 1px; } + .home-rail li.is-pending::before { background: repeating-linear-gradient(to right, var(--color-line-strong) 0 6px, transparent 6px 10px); } + .home-rail-marker { top: 0; } +} + +/* PRODUCT ─ resolver split. */ +.home-split { display: grid; gap: 3rem; align-items: center; } +@media (min-width: 900px) { .home-split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 5rem; } } +.home-resolver { + border: 1px solid var(--color-line-strong); + border-radius: 1rem; + background: var(--color-ink); + padding: clamp(1.25rem, 3vw, 2.5rem); +} +.home-resolver-outcomes { display: grid; gap: 1.25rem; margin-top: 1.5rem; padding-top: 1.5rem; border-top: 1px solid var(--color-line); } +@media (min-width: 560px) { .home-resolver-outcomes { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem; } } +.home-resolver-outcomes dt { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--color-muted); } +.home-resolver-outcomes dd { margin-top: 0.375rem; font-size: 0.9375rem; line-height: 1.55; color: var(--color-paper-dim); } + +/* LEVELS ─ the ceiling at display scale beside the ladder. */ +.home-levels { display: grid; gap: 3rem; align-items: start; } +@media (min-width: 900px) { .home-levels { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: 5rem; } } +.home-list { display: grid; gap: 0.875rem; } +.home-list li { position: relative; padding-left: 1.25rem; font-size: 0.9375rem; line-height: 1.6; color: var(--color-paper-dim); } +.home-list li::before { content: "–"; position: absolute; left: 0; color: var(--color-muted); } +.home-two { display: grid; gap: 3rem; } +@media (min-width: 900px) { .home-two { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4rem; } } + +/* DEVELOPERS ─ sub-blocks separated by rules, each in a different form. */ +.home-dev-top { display: grid; gap: 3rem; align-items: start; } +@media (min-width: 900px) { .home-dev-top { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); gap: 4rem; } } +.home-subblock { margin-top: clamp(4rem, 8vw, 6.5rem); padding-top: clamp(2.5rem, 5vw, 4rem); border-top: 1px solid var(--color-line); } +.home-discovery, .home-badge { display: grid; gap: 3rem; } +@media (min-width: 900px) { + .home-discovery { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 4rem; } + .home-badge { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 4rem; } +} +.home-chain { display: flex; flex-wrap: wrap; gap: 1.5rem 0; } +.home-chain li { display: grid; grid-template-columns: auto auto; column-gap: 1.25rem; align-items: baseline; padding-right: 1.25rem; } +.home-chain-label { grid-column: 1; font-size: clamp(1rem, 1.5vw, 1.25rem); color: var(--color-paper); } +.home-chain-sub { grid-column: 1; font-size: 0.8125rem; color: var(--color-muted); } +.home-chain-arrow { grid-column: 2; grid-row: 1; color: var(--color-muted); } +.home-code { + display: block; + overflow-x: auto; + border-radius: 0.5rem; + border: 1px solid var(--color-line); + background: var(--color-ink-3); + padding: 0.875rem 1rem; + font-family: var(--font-mono); + font-size: 0.8125rem; + line-height: 1.6; + color: var(--color-paper-dim); + white-space: pre-wrap; + overflow-wrap: anywhere; +} + +/* FIT ─ one row of four statements divided by rules, not four cards. */ +.home-fit { display: grid; border-top: 1px solid var(--color-line-strong); } +.home-fit > li { padding-block: 1.75rem; border-bottom: 1px solid var(--color-line); } +@media (min-width: 640px) { + .home-fit { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .home-fit > li:nth-child(odd) { padding-right: 2rem; } + .home-fit > li:nth-child(even) { padding-left: 2rem; border-left: 1px solid var(--color-line); } +} +@media (min-width: 1024px) { + .home-fit { grid-template-columns: repeat(4, minmax(0, 1fr)); } + .home-fit > li { padding: 2rem 2rem 2rem 0; border-bottom: 0; } + .home-fit > li + li { padding-left: 2rem; border-left: 1px solid var(--color-line); } +} +.home-eco-head { display: grid; gap: 2rem; align-items: end; } +@media (min-width: 900px) { .home-eco-head { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); gap: 4rem; } } + +/* CONVERSION */ +.home-convert { display: grid; gap: 2.5rem; align-items: end; } +@media (min-width: 900px) { .home-convert { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 5rem; } } + +/* OBJECTIONS ─ visible question/answer pairs (no accordion: nothing hides without JS). */ +.home-objections { display: grid; border-top: 1px solid var(--color-line-strong); } +.home-objections > div { display: grid; gap: 0.5rem; padding-block: 1.5rem; border-bottom: 1px solid var(--color-line); } +@media (min-width: 900px) { .home-objections > div { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 3rem; } } +.home-objections dt { font-size: clamp(1.125rem, 1.6vw, 1.375rem); font-weight: 600; letter-spacing: -0.015em; line-height: 1.3; } +.home-objections dd { font-size: 0.9375rem; line-height: 1.65; color: var(--color-paper-dim); max-width: 62ch; } + +/* Grid children may shrink below their content's min-content (long mono strings wrap). */ +:is(.home-hero-grid, .home-problem, .home-questions, .home-split, .home-levels, .home-two, .home-dev-top, + .home-discovery, .home-badge, .home-eco-head, .home-convert, .home-objections > div, .home-row) > * { min-width: 0; } + +@media (prefers-reduced-motion: reduce) { + .rise { animation: none !important; } + .home-cta-arrow { transition: none; } +} diff --git a/packages/web/app/page.tsx b/packages/web/app/page.tsx index d230016..448d4c1 100644 --- a/packages/web/app/page.tsx +++ b/packages/web/app/page.tsx @@ -1,15 +1,13 @@ import Link from "next/link"; import { SearchBar } from "@/components/SearchBar"; import { Terminal } from "@/components/Terminal"; -import { IdentityStory } from "@/components/IdentityStory"; -import { LifecycleDiagram, TrustModelDiagram, CryptoChainDiagram, TwoPathDiagram } from "@/components/Diagrams"; +import { TrustModelDiagram, TwoPathDiagram } from "@/components/Diagrams"; import { EcosystemHub, type CloudCluster } from "@/components/ecosystem/EcosystemHub"; import { buildCloudClusters, getEcosystem } from "@/lib/ecosystem"; -import { Section } from "@/components/ui/Section"; import { Reveal } from "@/components/ui/Reveal"; -import { Tabs } from "@/components/ui/Tabs"; import { LevelLadder } from "@/components/LevelLadder"; import { BadgeStates } from "@/components/BadgeStates"; +import { LiveBadgeExample } from "@/components/LiveBadgeExample"; import type { Metadata } from "next"; import { SITE_URL } from "@/lib/api"; @@ -22,12 +20,29 @@ export const metadata: Metadata = pageMetadata({ absoluteTitle: true, }); -/** - * Organization + WebSite + SoftwareApplication in one graph. `sameAs` lists only the - * public GitHub organization — the one external profile AgenID actually operates. No - * logo URL beyond our own mark, no founding date, no address: nothing here is asserted - * that the site does not itself show. +/* + * Editorial homepage (design/editorial-homepage, 2026-09-28). Mode 002 + * PRODUCT_CONVERSION_LANDING of the AIVH editorial-motion-web-design skill. + * + * CONVERSION BRIEF + * Primary "Give Your Agent an Identity" → /issue. Success signal: the wizard's + * POST /api/v1/agents returns 2xx and the new identifier resolves at /a/. + * Secondary "Verify an Agent" → /verify (same label and destination as the header). + * The live resolver sits inline in #verify for visitors who stay on the page. + * Friction No account. The key is generated and the manifest signed in the browser; + * only the public half is registered. About a minute. + * Trust Who is behind it (AI Venture Holdings LLC, JSON-LD), MIT spec, public source, + * independent conformance suite, and the level ceiling stated in plain words. + * Proof PRODUCT DEMONSTRATION only: the live resolver and the terminal transcript. + * No customer proof or performance figures exist, and none are shown. + * Objections Private key? Which level? Trust AgenID's database? npm? Partners? Revocation? + * Events cta_click{location}, resolver_submit — marked with data-event attributes; + * no analytics provider is installed, so nothing is sent yet (logged gap). + * + * Every factual sentence from the previous homepage is kept. The order changed, the words + * did not. In particular "defined" and "issued" stay two separate, labelled claims. */ + const HOME_JSON_LD = { "@context": "https://schema.org", "@graph": [ @@ -69,6 +84,9 @@ const HOME_JSON_LD = { ], }; +const PRIMARY = { label: "Give Your Agent an Identity", href: "/issue" } as const; +const SECONDARY = { label: "Verify an Agent", href: "/verify" } as const; + const PILLARS = [ { n: "01", @@ -90,17 +108,34 @@ const PILLARS = [ }, ]; +/** Identity lifecycle. Steps that need an authority signature say so, in words. */ +const LIFECYCLE = [ + { label: "Agent", sub: "agenid: minted", pending: false }, + { label: "Manifest", sub: "operator self-declaration", pending: false }, + { label: "ManifestProof", sub: "operator-signed, DECLARED", pending: false }, + { label: "Authority checks evidence", sub: "DNS TXT, org registry, …", pending: true }, + { label: "VerificationAssertion", sub: "authority-signed, VERIFIED", pending: true }, + { label: "Independent verification", sub: "anyone re-checks offline", pending: false }, +]; + +/** Cryptographic chain, as one typographic sequence. */ +const CHAIN = [ + { label: "Manifest", sub: "canonical JSON" }, + { label: "RFC 8785 JCS", sub: "deterministic bytes" }, + { label: "SHA-256", sub: "manifest_digest" }, + { label: "Signed object", sub: "ManifestProof / Assertion" }, + { label: "Ed25519 (pure)", sub: "RFC 8032, no pre-hash" }, + { label: "Verify()", sub: "anyone, offline" }, +]; + /** * Two separate questions, deliberately two separate columns. * * `definedInV111` is a fact about the SPECIFICATION: the level exists, with a claim type * and an evidence type, and a conforming implementation could issue it. * `issuedToday` is a fact about THIS DEPLOYMENT: whether agenid.com actually issues it - * right now. They were one boolean called `issuable`, rendered as "issuable in v1.1.1", - * which a reader has every reason to read as "available" — and L2, L3 and L4 are not - * available, because issuing any of them requires the root authority key, which does not - * exist yet. Collapsing a spec capability and a deployed capability into one word is the - * defect; the two columns are the fix. + * right now. L2, L3 and L4 are not available, because issuing any of them requires the + * root authority key, which does not exist yet. */ const LEVELS = [ { l: "L1", name: "Registered", claim: "registration", evidence: "schema_validation", definedInV111: true, issuedToday: true }, @@ -112,16 +147,55 @@ const LEVELS = [ const AUDIENCES = [ { title: "Developers", body: "SDK, API, MCP server, and docs to attach a verifiable identity to an agent you're building.", cta: "Read the Quick Start", href: "/docs/onboarding" }, - { title: "Businesses", body: "Give the agents you deploy a permanent identity and accountability trail — and verify agents you didn't build.", cta: "Verify an Agent", href: "/verify" }, + { title: "Businesses", body: "Give the agents you deploy a permanent identity and accountability trail — and verify agents you didn't build.", cta: SECONDARY.label, href: SECONDARY.href }, { title: "AI Platforms", body: "Identity infrastructure for the agents built on your platform — see what's actually integrated today.", cta: "See the Ecosystem", href: "/ecosystem" }, { title: "Enterprise", body: "Verification methodology, key management, and conformance — everything the Trust Center discloses openly.", cta: "Open the Trust Center", href: "/trust" }, ]; +/** + * Objections, answered only with statements this page already makes elsewhere. Plain text + * so it can feed both the visible list and the FAQPage JSON-LD without drifting. + */ +const OBJECTIONS = [ + { + q: "Does my private key leave my machine?", + a: "No. Your browser generates the Ed25519 key and signs the operator manifest locally, then registers only the public half. There is no account to create.", + }, + { + q: "What level will my agent get?", + a: "L1_REGISTERED: registered here, operator self-declaration verified. L2, L3 and L4 are defined in v1.1.1 but not issued, because the root authority key has not been generated yet.", + }, + { + q: "Do I have to trust AgenID's database?", + a: "No. The registry is for discovery, not trust. Every proof is a signature over RFC 8785 canonical bytes that anyone can re-verify offline with any Ed25519 implementation.", + }, + { + q: "Can I install the SDK from npm?", + a: "Not yet. @agenid/core, @agenid/cli and @agenid/mcp-server are not published to npm. Running them today means building from the public, MIT-licensed monorepo source.", + }, + { + q: "Are the listed platforms partners?", + a: "No. They are listed as Compatible: a technical statement about carrying an identity through each platform's existing, documented API surface. None ships AgenID code and none is a partner.", + }, + { + q: "Can an identity be suspended or revoked?", + a: "The protocol defines those status transitions and the badge renders them, but no write path on this deployment sets them yet. Every registered agent is ACTIVE.", + }, +]; + +const FAQ_JSON_LD = { + "@context": "https://schema.org", + "@type": "FAQPage", + mainEntity: OBJECTIONS.map((o) => ({ + "@type": "Question", + name: o.q, + acceptedAnswer: { "@type": "Answer", text: o.a }, + })), +}; + /** * Chip for the verification-levels table. It describes the PROTOCOL, not an agent, so it - * never uses a trust colour: mint and amber mean "verified" and "self-declared" on every - * badge and card, and this table used to reuse them for "defined" and "not issued" — the - * same colours meaning the opposite thing one scroll apart. Shape and words carry state. + * never uses a trust colour. Shape and words carry state. */ function LevelChip({ kind }: { kind: "issued" | "defined" | "not-issued" | "reserved" }) { const text = { issued: "issued today", defined: "defined", "not-issued": "not issued", reserved: "reserved name only" }[kind]; @@ -141,387 +215,503 @@ export default function Home() { const compatibleCount = ecosystem.filter((e) => e.status === "compatible").length; const verifiedIntegrationCount = ecosystem.filter((e) => e.status === "verified-integration").length; const partnerCount = ecosystem.filter((e) => e.status === "official-partner").length; - // Props come finished out of the registry — see buildCloudClusters()'s note on why the - // page does not map entries to labels itself. const clusters: CloudCluster[] = buildCloudClusters(); - const provenPanel = ( -
- -

None of these three states is ever inferred from another. That rule is enforced by key role at verification time, not by convention.

-
-
-

Proven, by signature

-
    -
  • · A specific operator key signed a specific manifest, at a specific digest (ManifestProof).
  • -
  • · A specific authority key signed a specific claim, against specific evidence, for a specific manifest version and validity window (VerificationAssertion).
  • -
  • · The signature is over RFC 8785 canonical bytes — reproducible by any independent implementation.
  • -
  • · A tampered payload, wrong key, or wrong key role (operator signing an assertion, or vice versa) fails verification, not just convention.
  • -
-
-
-

Not proven — by design or not yet built

-
    -
  • · Verification ≠ compliance. A VERIFIED claim is bound to what its evidence type actually checked (domain control, org identity, a deployment sample) — never a general safety or legal guarantee.
  • -
  • · L5 (L5_CONTINUOUSLY_MONITORED) is a reserved name only. No continuous-integrity claim exists in v1.1.1 — it cannot be issued.
  • -
  • · AUTHORIZED (what an agent is permitted to do) is not part of v1.1.1. A signed authorization object exists in @agenid/core as v1.2-DRAFT — draft, not normative, not ratified, and not issuable. Nothing on this deployment issues or evaluates an authorization claim, and no agent here carries one.
  • -
  • · The production root authority key has not completed its HSM ceremony. The verification mechanism for trust anchors is fully specified and testable (§9.5) — the root key itself is a pre-launch operational step, not a protocol gap. Until it is done, no VerificationAssertion can be signed, so L2, L3 and L4 are defined but not issued here.
  • -
-
-
+ return ( +
+ {/* eslint-disable-next-line react/no-danger */} + '} - -

- Re-resolves from the registry every time it renders, so it always shows whatever the registry currently reports for that identifier — it is never a static image of a past result. The badge is the human-facing UI; the signed record underneath is what actually carries trust. The protocol defines agent status transitions (CHANGED, STALE, SUSPENDED, REVOKED) and the badge renders them, but no write path on this deployment sets them yet — every registered agent is ACTIVE, and there is no revocation flow today. -

-
-
What the badge can say
- +
+ +
+
+

The registry is for discovery, not trust.

+

+ AgenID's registry helps you find a manifest and its proofs. It is never the thing you have to trust: every proof is a signature over canonical JSON that you can re-verify yourself, offline, with any RFC 8785 + Ed25519 implementation — including one that shares no code with AgenID's own. The independent conformance suite exists to prove exactly that: the spec holds up when nobody is trusting AgenID's word for it. +

-
- Live example (points at an unregistered example ID, so it honestly shows “unavailable”): -
- '} + +

+ Re-resolves from the registry every time it renders, so it always shows whatever the registry currently reports for that identifier — it is never a static image of a past result. The badge is the human-facing UI; the signed record underneath is what actually carries trust. The protocol defines agent status transitions (CHANGED, STALE, SUSPENDED, REVOKED) and the badge renders them, but no write path on this deployment sets them yet — every registered agent is ACTIVE, and there is no revocation flow today. +

+
+
+

What the badge can say

+
+
+ Live example (points at an unregistered example ID, so it honestly shows “unavailable”): +
+ +
+
+

AI can verify AI.

+

+ @agenid/mcp-server puts that same resolution and verification behind a stdio MCP tool — an agent running in any MCP client can call resolve_agent_identity and verify_agent_manifest directly, no HTTP client required. +

+

+ Not yet installable.{" "} + @agenid/mcp-server is not published to npm — neither it nor{" "} + @agenid/core nor @agenid/cli has been + published. The brief below documents the integration pattern and the tool surface; running the server + today means building it from the public monorepo source. Nothing here is available to install from npm. +

+

+ Read the MCP integration brief → +

+
+
+

The spec is the source of truth. Code follows it.

+

+ AgenID-protocol/spec is public and MIT-licensed — the protocol specification, five normative JSON Schemas, deterministic test vectors, and a public errata log. Changes to identity, cryptography, serialization, or verification semantics require a published erratum before any implementation follows. Two are on record: a key-identifier URI fix and a number-domain canonicalization rule (E1), and the namespace unification onto a single agenid.com domain (E2) — both applied, both re-verified against regenerated test vectors. +

+

+ AgenID-protocol/conformance is a separate, public, MIT-licensed test runner with zero AgenID knowledge — 34 of 34 checks pass, verified in CI on every push. +

+

+ Open protocol · Open-source specification · Machine-readable · Platform independent · Cryptographically verifiable · Independent verification +

+

+ View on GitHub ↗ +

+
-
+ + + {/* ── 7 · AUDIENCE FIT — one row, not four cards ───────────────────────── */} +
+
+ +

Built for developers. Designed for everyone.

+

What brings you here?

+
+
    + {AUDIENCES.map((a, i) => ( + +

    {a.title}

    +

    {a.body}

    + + {a.cta} → + +
    + ))} +
+
+
-
-
-

AI can verify AI

-

- {/* This named three specific MCP client applications by brand. AgenID has not - run this server in any of them, and the ecosystem registry — the single - source of truth for which companies this site names — carries no entry for - any of them. A vendor name is a claim about that vendor; it needs evidence - or it does not belong on the page. */} - @agenid/mcp-server puts that same resolution and verification behind a stdio MCP tool — an agent running in any MCP client can call resolve_agent_identity and verify_agent_manifest directly, no HTTP client required. -

-

- Not yet installable.{" "} - @agenid/mcp-server is not published to npm — neither it nor{" "} - @agenid/core nor @agenid/cli has been - published. The brief below documents the integration pattern and the tool surface; running the server - today means building it from the public monorepo source. Nothing here is available to install from npm. -

-
- Read the MCP integration brief + {/* ── 7b · FIT, continued — the ecosystem ──────────────────────────────── */} +
+
+ +
+

The agent ecosystem

+

The platforms change. The identity doesn't.

+

+ AgenID is designed to work across the platforms where AI agents live. An agenid:<ULID> identifies the agent, never the model or platform underneath it — nothing in the protocol references OpenAI, Anthropic, Google, an open-source model, or any specific runtime. The identity survives a change of model provider, agent framework, or hosting infrastructure. +

+
+
+
-
-

The spec is the source of truth. Code follows it.

-

- AgenID-protocol/spec is public and MIT-licensed — the protocol specification, five normative JSON Schemas, deterministic test vectors, and a public errata log. Changes to identity, cryptography, serialization, or verification semantics require a published erratum before any implementation follows. Two are on record: a key-identifier URI fix and a number-domain canonicalization rule (E1), and the namespace unification onto a single agenid.com domain (E2) — both applied, both re-verified against regenerated test vectors. +

+

+ {ecosystemCount} platforms listed across {layerCount} layers · {compatibleCount} Compatible ·{" "} + {verifiedIntegrationCount} verified integrations · {partnerCount} partners. Listed as{" "} + Compatible — a + technical statement about carrying an identity through each platform's existing, documented API surface. None + of them ships AgenID code, none is a partner, and no adapter package exists for any of them.{" "} + See the full compatibility matrix.

-

- AgenID-protocol/conformance is a separate, public, MIT-licensed test runner with zero AgenID knowledge — 34 of 34 checks pass, verified in CI on every push. +

+ Interoperability is tested, not assumed: the §8 deterministic test vectors — real Ed25519 signatures over RFC 8785 canonical bytes — let any language implementation prove it produces byte-identical output, independent of AgenID's own TypeScript reference implementation.

-
- {["Open protocol", "Open-source specification", "Machine-readable", "Platform independent", "Cryptographically verifiable", "Independent verification"].map((t) => ( - {t} - ))} -
-
-
- - {/* 8 · THE AGENT ECOSYSTEM */} -
The platforms change. The identity doesn't.} - lede={ - <> - AgenID is designed to work across the platforms where AI agents live. An agenid:<ULID> identifies the agent, never the model or platform underneath it — nothing in the protocol references OpenAI, Anthropic, Google, an open-source model, or any specific runtime. The identity survives a change of model provider, agent framework, or hosting infrastructure. - - } - > - - -

- {/* Counts are read from the registry, never typed. This sentence said "five layers" - until a sixth was added, which is the whole argument for deriving it. Every - number now carries its denominator. */} - {ecosystemCount} platforms listed across {layerCount} layers · {compatibleCount} Compatible ·{" "} - {verifiedIntegrationCount} verified integrations · {partnerCount} partners. Listed as{" "} - Compatible — a - technical statement about carrying an identity through each platform's existing, documented API surface. None - of them ships AgenID code, none is a partner, and no adapter package exists for any of them.{" "} - - See the full compatibility matrix - - . -

- -

- Interoperability is tested, not assumed: the §8 deterministic test vectors — real Ed25519 signatures over RFC 8785 canonical bytes — let any language implementation prove it produces byte-identical output, independent of AgenID's own TypeScript reference implementation. -

-
- - {/* 9 · GET AGENID — registration flow, real */} -
-
- Give Your Agent an Identity - Do it from a terminal +
+ + {/* ── 8 · CONVERSION ───────────────────────────────────────────────────── */} +
+
+ +

Give your AI agent an identity

+

Get AgenID.

+
+ +

+ Name your agent and your browser does the rest: it generates an Ed25519 key, signs the operator manifest locally, and registers the public half. You get a resolvable identifier and a Verification Card in about a minute — no account, and no private key ever leaves your machine. +

+
+ + {PRIMARY.label} → + + + Do it from a terminal → + +
+

+ Issues L1_REGISTERED — registered here, operator self-declaration verified. Not a third-party check of the + operator, the domain, or the organization. +

+
+
+
+ + {/* ── 9 · OBJECTION HANDLING — visible statements, no accordion ────────── */} +
+
+ +

Before you register

+

Questions a careful operator asks.

+
+
+ {OBJECTIONS.map((o) => ( +
+
{o.q}
+
{o.a}
+
+ ))} +
+
+
+ + {/* ── 10 · CLOSING PAYOFF ──────────────────────────────────────────────── */} +
+
+ +

Before your agent speaks for you, give it an identity anyone can check.

+
+ + {PRIMARY.label} → + + + {SECONDARY.label} → + +
+
-

- Issues L1_REGISTERED — registered here, operator self-declaration verified. Not a third-party check of the - operator, the domain, or the organization. -

-
+
); } diff --git a/packages/web/components/LiveBadgeExample.tsx b/packages/web/components/LiveBadgeExample.tsx new file mode 100644 index 0000000..4c3eba8 --- /dev/null +++ b/packages/web/components/LiveBadgeExample.tsx @@ -0,0 +1,28 @@ +"use client"; + +import { useEffect, useRef } from "react"; + +/** + * The homepage's live badge example. The embed used to be a server-rendered