Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 75 additions & 67 deletions VIDEO_TRANSCRIPT.md
Original file line number Diff line number Diff line change
@@ -1,118 +1,126 @@
# Video transcript — the 5:00 pitch (recorded at submission)
# Video transcript — the 5:00 pitch (plain-English version)

Shot list assumes the live demo (with the deterministic seed). Timestamps are
beats, not hard cuts. One take, screen + voice, no intro animation — the first
10 seconds must carry the thesis.
Same beats as before, but the spoken lines are plain and simple — short
sentences, no jargon without a quick explanation. Read it like you talk.
Timestamps are beats, not hard cuts. One take, screen + voice. The first
10 seconds carry the whole idea.

## 0:00–0:20 — the thesis
## 0:00–0:20 — the big idea

**On screen:** the landing page, hero stamp.

> "Razorpay's homepage already sells the future: AI agents, shopping in your
> app, paying on their own. Everyone is building the buyer side of that
> counter. Somebody has to build the other side — the part a payments company
> needs before it lets an agent spend. Customs is both sides, in one repo."
> "AI agents are starting to shop and pay on their own. Almost everyone is
> building the buying side. Almost nobody is building the selling side
> the part a payments company needs before it lets a robot spend money.
> We built both sides, in one project. It's called Customs."

## 0:20–1:05 — the buyer side (the brief's named example, live)
## 0:20–1:05 — the buyer side (live)

**On screen:** Playground. Type "headphones under 5000".

> "Here's the agent. Every step it takes is visible — the search, the tool
> calls, the wire format, and the price, recomputed server-side. I'll take the
> earbuds and check out."
> "Here is the buying agent. I type: 'headphones under 5000.' Watch every
> step it takes — the search, the tools it calls, the messages it sends,
> and the price. The website re-checks the price on its own server, so
> nobody can trick it with a fake number. Now I say: 'checkout.'"

Type "checkout".

> "The desk signs a mandate: an amount cap, the item list, an expiry, and my
> trust tier — Ed25519 over canonical JSON. As the buyer's principal, I approve
> the envelope, and only then does the agent bind and pay."
> "Before it pays, the agent gets a permission slip. It says the most it
> can spend, what it can buy, when it expires, and how much this user is
> trusted. It is signed with a strong digital signature. I approve it.
> Only then can the agent pay."

Approve → gate checklist → capture.

> "The gate re-verified everything at bind time — signature, tier bounds,
> live prices, quantities. Deterministic code, zero tokens: the LLM never
> decides money. That's the line the brief draws, and it's the line we hold."
> "And just before money moves, plain code — not AI — checks everything
> again: the signature, the spending limit, the prices, the counts. The
> AI can talk. Only this code can move money. That is the rule, and we
> never break it."

## 1:05–1:50 — the refusal beat (failure, handled)
## 1:05–1:50 — the attack (failure, handled)

**On screen:** red-team panel → "Overspend the tier" → BLOCKED.

> "Now the interesting part. I attack my own product. An unverified session
> tries a ₹2,199 mouse against a ₹500 tier — refused, with a reason code, and
> the attempt is hash-chained into the audit log. Twelve authored attacks,
> each with its expected verdict. Run `make fuzz` — twelve out of twelve,
> every time. Not a demo: CI."
> "Now the best part. I attack my own product. A fake session tries to
> buy a 2,199-rupee mouse with a 500-rupee limit. Blocked — with a short
> code that says why. And the attempt is saved in a log that cannot be
> secretly edited. We wrote twelve attacks like this. All twelve are
> blocked, every time we test. Not just a demo — it runs in our build
> check."

**On screen:** "Tamper the signature" → BLOCKED · SIGNATURE_INVALID.

> "Tamper the mandate after signing — the signature check kills it. And this
> ledger is tamper-evident: `make audit` flips one historical byte and the
> chain breaks exactly there."
> "What if someone edits the permission slip after it is signed? The
> signature catches it. And if anyone changes one old entry in the log,
> the chain breaks at that exact spot. Nothing can be changed in
> secret."

## 1:50–2:35 — the merchant side (the empty cell)
## 1:50–2:35 — the merchant side

**On screen:** Control Room. The P&L meter counting up.

> "Now walk around the counter. The Control Room is what the merchant — and
> honestly, what Razorpay — needs to see. Agent GMV, revenue at list MDR, the
> AI serving cost from metered tokens, and the net, live. At one million
> payments a month this channel nets eight figures — the formula and every
> assumption ship in the repo, regenerated by command, never hand-written."
> "Now walk around the counter. This is the merchant's room — what the
> shop, and honestly what Razorpay, would want to see. How much agents
> are selling. What it costs to serve them. What is left as profit.
> Live. At one million payments a month, this channel earns real money
> — and every number here can be re-made with one command. Nothing was
> typed in by hand."

**On screen:** approval queue → approve the ₹18,999 hold.

> "Orders over ten thousand rupees hold for a human, any tier. I approve — it
> captures, and it's replayable span-by-span. This is the brief's 'one
> failure handled gracefully', except it's twelve, and they're in CI."
> "One more rule. Any order above ten thousand rupees waits for a human.
> I approve this one — it completes, step by step, right in front of
> you."

## 2:35–3:20 — the protocol matrix (why this generalizes)
## 2:35–3:20 — works with any agent protocol

**On screen:** adapter switcher → MCP-style → wire chip expands.

> "The same gate behind three protocols — direct, MCP-shaped, ACP-shaped.
> Same tool implementations, same verdicts, different wire overhead — and the
> ablation measures exactly that: verdict parity everywhere, byte cost
> published. When ACP and friends settle, the adapter is a transport swap,
> not a rewrite."
> "Agent systems speak different languages — direct calls, MCP, ACP. Our
> gate does not care. The same checks sit behind all three. We measured
> all three: same decisions, different message sizes — and we published
> the byte cost. If a new standard wins, we swap the transport. We do
> not rewrite the product."

## 3:20–4:05 — the proof layer (built for machine judges)
## 3:20–4:05 — built to be checked by a machine

**On screen:** terminal — `make triage` scrolling.

> "Fifteen hundred repos will be submitted. Triage will be machine-assisted,
> so this repo is built to be judged by a machine: JUDGE.md maps every claim
> to a file and a regenerate command. `make verify` is the same check CI runs
> — zero dependencies, plain node. No number in this repo was typed by a
> human, no link ships until it answers 200, and the engineering log records
> every incident, each one turned into a test."
> "Thousands of projects will be judged. Many will be checked by a
> machine first. So we built this repo to be checked by a machine. One
> file maps every claim to a file and a command. One command — `make
> verify` — checks the whole repo with plain node, no setup. No number
> was typed by a human. No link ships unless it works. And every bug we
> ever hit became a test — forever."

## 4:05–4:45 — honesty slide (scope, limits, next)
## 4:05–4:45 — what we have NOT done (honesty slide)

**On screen:** the honest scope ledger, one card at a time.

> "What's not done, on purpose, said plainly: the payment rail runs labeled
> simulation until test keys are attached — the spike that flips it ships
> ready. x402 is a declared stretch, not a promise. Voice, later. The demo
> history is a deterministic seed through the real engine — no hand-written
> ledger lines anywhere. Every limit is labeled in the product, not hidden in
> a footnote."
> "Now, what we have not donesaid plainly. The payment rail runs in
> clearly labeled simulation mode until Razorpay test keys are attached.
> The code to flip it on is ready, and we already tested it against the
> real API. The demo history comes from a fixed seed through the real
> engine — no fake rows anywhere. Voice is for later. Every limit is
> written on the screen, not hidden in a footnote."

## 4:45–5:00 — close

**On screen:** the manifest receipt, stamp lands.

> "The buyer side everyone is building. The desk nobody has built. Both
> sides, bounded, metered, replayable — and provable to a machine in sixty
> "Everyone is building the buyer. Nobody built the desk. Both sides —
> limited, measured, replayable — and provable to a machine in sixty
> seconds. Customs. Thank you."

---

**Recording notes**
**Recording notes (simple)**

- Use the live seeded state (reset demo before recording) — numbers match the
committed results.
- Cursor + typing must be visible; the step chips are the transparency story.
- Keep the terminal font large enough to read `make triage` output at 720p.
- The refusal beat (1:05) is the emotional center — don't rush it.
- Total: 5:00 hard limit. If over, cut the protocol matrix interior, never the
refusal or the honesty slide.
- Reset the demo before recording, so the numbers on screen match the
numbers in the repo.
- Keep the cursor and your typing visible — watching the steps happen is
the whole trust story.
- Make the terminal text big enough to read at 720p.
- Do not rush the attack part at 1:05 — it is the heart of the video.
- Hard limit: 5:00. If you run long, cut inside the protocol section —
never the attack, never the honesty slide.
114 changes: 110 additions & 4 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,21 @@ html.light {
html:not(.light) ::-webkit-calendar-picker-indicator {
filter: invert(1);
}
/* the paper grain — the felt world's fiber at a whisper over every
surface. One fixed layer, one raster (a 180px fractal-noise tile,
desaturated), soft-light blend so it reads on both desks without
tinting either. pointer-events: none — it is texture, never a
surface, and it never animates. */
body::before {
content: "";
position: fixed;
inset: 0;
z-index: 80;
pointer-events: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.6' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
mix-blend-mode: soft-light;
opacity: 0.28;
}
}

@layer utilities {
Expand Down Expand Up @@ -657,7 +672,10 @@ html.light {
.hb-glint {
animation: hb-glint 9.5s ease-in-out infinite;
}
.hero-bot:hover .hb-eye {
/* the hover eye-fill is a day-desk tell — on the night desk the
cleared sage reads as the green the desk avoids; dark hover lifts
the aurora instead (below) and leaves the eyes alone */
html.light .hero-bot:hover .hb-eye {
fill: var(--cleared);
}

Expand All @@ -667,18 +685,61 @@ html.light {
and a small warm-up on hover. No CSS transform ever touches this
element — that is the containment contract. */
.hb-aurora {
opacity: 0.55;
/* the night ledger keeps the bot from going green-dominant — but
not colorless: the aurora sits at a third strength, a balanced
pastel sweep instead of the day desk's saturated wash */
opacity: 0.26;
transition: opacity 0.6s ease;
}
html.light .hb-aurora {
opacity: 0.38;
}
.hero-bot:hover .hb-aurora {
opacity: 0.65;
opacity: 0.34;
}
html.light .hero-bot:hover .hb-aurora {
opacity: 0.46;
}
/* the felt mat's dye washes follow the same law: all four colors
stay present on the night desk — SCREEN-blended so the pastels
glow on the dark felt instead of drowning in it, the same trick
light does with opacity alone. Colorful, never the green field
the day desk wears. The pompoms stay loud. */
.hfx-wash {
transition: opacity 0.6s ease;
}
html:not(.light) .hfx-wash {
opacity: 0.5;
mix-blend-mode: screen;
}

/* the egg vs the mat, night desk: the day body gradient is dark ink
on a light field — over the near-black felt it has no contrast, so
the mascot dissolves into the fabric. The dark variant lifts the
fill and firms the outline, so the orb reads IN FRONT of the mat. */
html:not(.light) .hb-body-path {
fill: url(#hb-body-dark);
stroke-opacity: 0.45;
}

/* the idle yawn — after thirty quiet seconds the desk yawns: the
eyes close to happy slits (the whole eye unit squishes, so the
glints can never float free), and the smile stretches wide on a
slower ease — eyes snap, mouth spreads. Blink is suspended for
the yawn; on wake it resumes and the eyes pop open. Transitions
and one transform: nothing structural moves. */
.hb-smile {
transform-box: fill-box;
transform-origin: center;
transition: transform 0.55s cubic-bezier(0.45, 0, 0.25, 1);
}
.hero-bot.yawning .hb-smile {
transform: scaleX(1.55) translateY(1.6px);
}
.hero-bot.yawning .hb-eye-unit {
animation: none;
transform: scaleY(0.3);
}
/* the blush warms a touch when visited — the smallest tell of a
happy bot; a paint-only transition, nothing structural moves */
.hb-blush {
Expand Down Expand Up @@ -766,6 +827,49 @@ html.light {
}
}

/* ---------------- the wool mat's pompoms ---------------- */
/* transform/opacity only — the felt's filters are static paint and
rasterize once; the yarn just bobs, each ball on its own clock */
@keyframes hb-pom-bob {
0%,
100% {
transform: translateY(0) rotate(var(--tilt, 0deg));
}
50% {
transform: translateY(-6px) rotate(calc(var(--tilt, 0deg) + 2.5deg));
}
}
.hb-pom {
transform-box: fill-box;
transform-origin: center;
animation: hb-pom-bob 5.2s ease-in-out infinite;
}
.hb-pom2 {
animation-duration: 6.1s;
animation-delay: -1.8s;
}
.hb-pom3 {
animation-duration: 5.7s;
animation-delay: -3.1s;
}

/* the desk agent's thinking yarn — a small ball tilting side to side
while it works; transform-only, killed for reduced motion */
@keyframes agent-yarn-wobble {
0%,
100% {
transform: rotate(-9deg) translateY(0);
}
50% {
transform: rotate(9deg) translateY(-1.5px);
}
}
.agent-yarn {
transform-box: fill-box;
transform-origin: center;
animation: agent-yarn-wobble 0.85s ease-in-out infinite;
}

/* ---------------- the customs bot's moves ---------------- */
@keyframes hb-float {
from {
Expand Down Expand Up @@ -863,7 +967,9 @@ html.light {
.hb-eye-unit,
.hb-eyes,
.hb-glint,
.hb-shadow {
.hb-shadow,
.hb-pom,
.agent-yarn {
animation: none !important;
}
.pulse-dot::after {
Expand Down
Loading
Loading