mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
Calculator, captable, careers, cloud, compare, contact and contact-sales, customers, dashboards, dataroom, datastore, dev, download, enso, enterprise, extension, family, integrations, investors, kai, learn, legal and their components say their words through t() in client code, <T> in server components and phrase() where copy is held as data; one sentence is one key, figures and links its arguments. Rebased on main: in every conflict main's file stands (its copy, layout and styling) and only the wrapping is added back, including copy main added since. Claude-Session: https://claude.ai/code/session_015XYKLjZtDTJEnMo4eK3AFH
75 lines
4.3 KiB
TypeScript
75 lines
4.3 KiB
TypeScript
'use client'
|
|
|
|
import { ArrowRight, Activity, Building2, FileText, Globe, ShieldCheck, UserCheck } from 'lucide-react'
|
|
import { ProductLanding } from '@/components/product/ProductLanding'
|
|
import { ProductFooter } from '@/components/products/ProductFooter'
|
|
import { useI18n } from '@hanzo/i18n/react'
|
|
|
|
/**
|
|
* Hanzo IDV, through the ONE product kit.
|
|
*
|
|
* authz, hsm and idv were a third-generation copy of the same page: a plain
|
|
* `<h1>` hero, a feature grid with NO heading above it, and a "Get started
|
|
* with X" card. See LLM.md, "Tailwind is NOT gone".
|
|
*
|
|
* EVERY WORD IS THE ONE THAT WAS HERE. The headless grid is why a section head
|
|
* is now optional in the kit rather than required — these three never had one,
|
|
* and writing three would be writing words nobody chose.
|
|
*/
|
|
|
|
export default function HanzoIDVPage() {
|
|
const { t } = useI18n()
|
|
return (
|
|
<>
|
|
<ProductLanding
|
|
title={"Hanzo IDV"}
|
|
lede={t("Hanzo IDV is one interface in front of the identity-verification vendors, so which vendor you use is a line of configuration rather than a rewrite of your onboarding. It does not verify anybody itself. It starts a check with the provider you chose, reads the verdict back, and proves that a callback came from them and not from someone who guessed the URL. Jumio and Onfido work end to end today; Plaid works by polling; the rest refuse until their response parsing is written, which is stated here because a verification service that guesses is worse than one that says it cannot tell.")}
|
|
ctas={[
|
|
{ label: t("View on GitHub"), href: "https://github.com/hanzoai" },
|
|
]}
|
|
what={{
|
|
pillars: [
|
|
{
|
|
icon: UserCheck,
|
|
title: t("Four calls, whichever vendor"),
|
|
body: t("Start a verification, check its status, parse a webhook, name yourself. Every provider implements the same four, so swapping one for another is configuration and not a rewrite of your onboarding."),
|
|
},
|
|
{
|
|
icon: Building2,
|
|
title: t("A verdict, or nothing"),
|
|
body: t("A provider whose response we do not parse refuses rather than answering. Two of them used to return approved without reading the reply — one for any response that was not an error, the other including a rejected document. Anything gating on that would have admitted an unverified person, so both now refuse until the parsing is written."),
|
|
},
|
|
{
|
|
icon: ShieldCheck,
|
|
title: t("A webhook has to prove it is one"),
|
|
body: t("Signatures are HMAC-SHA256 over the raw body, compared in constant time, with the header matched case-insensitively because the wire spelling and the canonical spelling differ. An empty signing secret is a refusal, never a skip — an HMAC under a key everybody knows is one anybody can compute."),
|
|
},
|
|
{
|
|
icon: FileText,
|
|
title: t("Polling where a callback cannot be trusted"),
|
|
body: t("Every result is verified before it counts. A webhook whose signature we can check is accepted; anything else is polled from the provider directly, so the verdict always comes from the source."),
|
|
},
|
|
{
|
|
icon: Activity,
|
|
title: t("Credentials come from KMS"),
|
|
body: t("The API token bills per check and the webhook token is what separates a provider's verdict from a forgery, so neither is a literal in the code and neither falls back to an environment variable. A missing secret fails at construction rather than producing a provider that quietly runs without one."),
|
|
},
|
|
{
|
|
icon: Globe,
|
|
title: t("Verification is not screening"),
|
|
body: t("Proving somebody is who they say is a different job from watching what they do afterwards. Sanctions lists, transaction monitoring, cases and the five-year record clock live in Hanzo Risk, and this does not duplicate them."),
|
|
},
|
|
],
|
|
}}
|
|
finalCta={{
|
|
title: t("Get started with IDV"),
|
|
buttons: [
|
|
{ label: t("View on GitHub"), href: "https://github.com/hanzoai" },
|
|
],
|
|
}}
|
|
/>
|
|
<ProductFooter slug={"idv"} name={"IDV"} />
|
|
</>
|
|
)
|
|
}
|