Skip to content

B02 Plan B: split Groth16 verifier into @zeroauth/verifier workspace#29

Merged
pulkitpareek18 merged 2 commits into
mainfrom
dev
May 14, 2026
Merged

B02 Plan B: split Groth16 verifier into @zeroauth/verifier workspace#29
pulkitpareek18 merged 2 commits into
mainfrom
dev

Conversation

@pulkitpareek18
Copy link
Copy Markdown
Collaborator

Day 4 of Week 1. Today's demo battery cadence fired on time (09:55 IST, still HOLD); main work is the verifier service split.

Plan B chosen

Per yesterday's plan-mode design doc, TypeScript workspace instead of Rust separate repo. Picked for single-engineer velocity. HTTP shape is deliberately Rust-compatible — future swap is structural, not behavioural.

What ships

New `verifier/` workspace

  • `verifier/package.json` — name `@zeroauth/verifier`, tiny dep tree (express + snarkjs + winston + uuid; no pg, no helmet)
  • `verifier/src/server.ts` — Express on `127.0.0.1:3001`. `POST /verify` + `GET /health`.
  • `verifier/src/groth16.ts` — snarkjs wrapping; `initVerifier(vkeyPath)` + `verifyProof(proof, signals)`
  • `verifier/src/types.ts` — wire types (Rust-shaped, future-proof)
  • `verifier/src/logger.ts` — Winston, service-tagged
  • `verifier/README.md` — trust boundary spelled out: loopback-only, never expose without mTLS + threat-model update + ADR
  • Root `package.json` adds `verifier` to `workspaces` + 3 convenience scripts (`verifier:dev`, `verifier:build`, `verifier:start`)

API repo changes

  • `src/services/zkp.ts` (209 → ~270 lines but the new lines are mostly comments + the HTTP path). Public surface UNCHANGED — `initZKP()`, `verifyBiometricProof()`, `verifyProofOffChain()`, `getCircuitInfo()`, `isZKPReady()` all behave identically from a caller's perspective. Internal: when `VERIFIER_URL` is set, delegates to the service; otherwise inline-fallback (the v0 path).
  • Replay defense (timestamp window + UUID nonce + signal shape) stays in zkp.ts. Verifier is a pure crypto primitive.
  • On-chain re-verification stays in zkp.ts (depends on ethers).
  • New config: `VERIFIER_URL` (default "" → inline mode), `VERIFIER_TIMEOUT_MS` (default 2000).

Why production is safe to merge today

VERIFIER_URL is unset in production `/opt/zeroauth/.env`. That means after this PR lands and the deploy fires, prod `src/services/zkp.ts` runs the inline-fallback path — byte-identical behavior to before. The new verifier package ships in the bundle but doesn't run. Tomorrow's PR flips production over by (a) adding the verifier to docker-compose, (b) setting `VERIFIER_URL=http://verifier:3001\` in prod env, (c) retiring the inline fallback.

Test plan

  • `npx tsc --noEmit` — clean (both root + verifier)
  • `npm test` — 68 → 73 passing. New `tests/zkp-service-mode.test.ts` mocks global.fetch, sets `config.zkp.verifierUrl`, asserts: POST shape correctness, verifier-says-pass yields verified, verifier-says-fail yields rejected, non-2xx yields rejected (no false positives on 500), network error yields rejected.
  • `npm run lint` — 0 errors, 10 pre-existing warnings unchanged
  • Verifier smoke locally: `npm run verifier:dev` boots; `GET /health` returns `{"status":"ok","vkeyAvailable":true}`; `POST /verify` with junk proof returns `{"verified":false,"structuralFallback":false}`; malformed body returns 400 `invalid_request`.
  • CI validate + Playwright green on this PR
  • After merge: deploy workflow ships; production `/v1/auth/zkp/verify` smoke still works (inline path, unchanged behavior)

Out of scope for this PR (Friday Day 5 work)

  • docker-compose dev/prod stack changes
  • Production `.env` `VERIFIER_URL` flip (the "make verifier the default" cutover)
  • SQLite audit log + hash chain (B02 design doc §4.3)
  • Inline-fallback removal in `src/services/zkp.ts`
  • Governance repo's `docs/threat-model/verifier.md` promotion from stub
  • ADR-0008 capturing the TS-vs-Rust decision formally

🤖 Generated with Claude Code

pulkitpareek18 and others added 2 commits May 14, 2026 11:30
Per the plan-mode design doc, this is Plan B (TypeScript workspace, not
Rust) — chosen for single-engineer velocity. The HTTP shape is
Rust-compatible so a future swap is structural, not behavioural.

Architecture:

- New verifier/ npm workspace with package.json/tsconfig/server.ts.
  Listens on 127.0.0.1:3001 by default. Tiny dep tree: express,
  snarkjs, winston, uuid (no pg, no helmet — not customer-facing).
- POST /verify accepts proof + publicSignals (length 3) + optional
  circuitVersion + correlationId. Returns verified bool + verifier
  audit id + latency_ms + structuralFallback flag.
- GET /health reports loaded-vkey state + uptime; used by the API at
  startup to fail loud if the verifier is misconfigured.
- The verifier trusts its caller — loopback-only is the trust
  boundary. Never expose without mTLS + per-caller rate-limit (and
  threat-model update + ADR).

API repo changes:

- src/services/zkp.ts shrinks: when VERIFIER_URL is set it becomes a
  thin HTTP client; otherwise it falls back to the inline snarkjs path
  (v0 behaviour, marked for removal after Friday Day 5's prod rollout).
- Replay defense (5-min timestamp window + UUIDv4 nonce check + signal
  shape) stays in zkp.ts — the verifier is a pure crypto primitive.
- On-chain re-verification (when blockchain.verifyOnChain=true) stays
  in zkp.ts — depends on ethers which the verifier doesn't need.
- isZKPReady() now reflects verifier /health (service mode) or inline
  snarkjs load state (inline mode). getCircuitInfo() exposes the
  active mode + URL for debugging.

Config:

- New env vars: VERIFIER_URL (default empty → inline mode),
  VERIFIER_TIMEOUT_MS (default 2000). Per the plan-mode doc, these
  ship today with production unchanged; tomorrow's PR adds the
  verifier to docker-compose, sets VERIFIER_URL in prod .env, and
  retires the inline fallback.

Tests:

- 68 → 73 passing. New tests/zkp-service-mode.test.ts has 5 cases:
  POST shape correctness, verifier-says-pass, verifier-says-fail,
  non-2xx returns false (no false positives on 500), network-error
  returns false. Mocks global.fetch — no actual verifier needed for
  CI.
- Existing tests stay green via the inline-fallback path (no
  VERIFIER_URL in test env).

Verifier smoke (local):
  npm run verifier:dev  # boots on :3001
  curl /health  -> {"status":"ok","vkeyAvailable":true,...}
  POST /verify with junk proof -> {"verified":false,"structuralFallback":false}
  POST /verify with malformed body -> 400 invalid_request

Out of scope for today (Friday Day 5 PR):

- docker-compose dev/prod stack changes
- production .env VERIFIER_URL flip
- SQLite audit log + hash chain (B02 §4.3 design doc)
- Inline-fallback removal in src/services/zkp.ts
- Governance repo's docs/threat-model/verifier.md promotion from stub
- ADR-0008 capturing the TS-vs-Rust decision formally

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 14, 2026 06:08
@pulkitpareek18 pulkitpareek18 merged commit 883d2ba into main May 14, 2026
2 checks passed
@pulkitpareek18 pulkitpareek18 deleted the dev branch May 14, 2026 06:08
@pulkitpareek18 pulkitpareek18 review requested due to automatic review settings May 14, 2026 06:30
pulkitpareek18 added a commit that referenced this pull request May 15, 2026
Plan B (TS workspace) chosen yesterday. Yesterday's PR #29 landed the
verifier package in the repo. Today's PR Phase 2 flips production to
actually use it instead of the inline-snarkjs fallback that's been
serving since v0.

Dockerfile:

- Adds a `verifier-build` stage that npm-ci's the verifier workspace
  against the root lockfile (reproducible), compiles src/ → dist/.
- Adds a `verifier-production` stage: slim alpine image, non-root user
  uid 1001, flat `npm install --omit=dev` (verifier has 4 prod deps:
  express, snarkjs, winston, uuid — workspace-aware ci complicates a
  per-package prod install; trade-off accepted per ADR-0005). Copies
  the compiled JS + the production vkey. Healthcheck on /health.
  Binds 0.0.0.0:3001 inside the container so docker network reaches
  it; no host port binding so it stays loopback-only at the boundary.

docker-compose.yml:

- New `zeroauth-verifier` service in BOTH the `dev` and `prod`
  profiles. `expose: 3001` (no `ports:` — no host binding).
  Healthcheck wired.
- `zeroauth-prod` gains:
    VERIFIER_URL=http://zeroauth-verifier:3001
    VERIFIER_TIMEOUT_MS=2000
  in its `environment:` block (not via .env — wired directly so a
  hand-edited prod .env can't drift from the compose intent).
- `zeroauth-prod.depends_on` now requires `zeroauth-verifier` to be
  service_healthy before starting. Deploy fails loud if the verifier
  can't load its vkey or bind its port.
- `zeroauth-dev` gets the same wiring so local dev exercises the
  service path by default. Developers who want the inline-snarkjs
  fallback can override with `VERIFIER_URL=` in their .env.

Local validation:

- `docker build --target verifier-production` builds clean
- `docker run` + `curl /health` returns
    {"status":"ok","version":"0.1.0","vkeyAvailable":true,"uptimeSeconds":5}
- `POST /verify` with a structurally-valid junk proof exercises the
  real Groth16 verifier against the real vkey (structuralFallback:false)
  and rejects it correctly (verified:false, 543ms — first call cost
  includes snarkjs init; subsequent calls are <50ms in the same image).

Post-deploy verification plan (after this PR merges):

- The deploy workflow runs scripts/deploy-remote.sh which does
  `docker compose --profile prod up -d --build --remove-orphans` — that
  auto-picks-up the new zeroauth-verifier service.
- After healthchecks pass, the API container's
  src/services/zkp.ts switches from the inline path to the HTTP
  path because VERIFIER_URL is now set in its environment.
- I'll smoke-test by POSTing a /v1/auth/zkp/verify and confirming
  the API logs show "ZKP: verifier service: FAIL/PASS" with a
  verifierAuditId (the service path's signature in zkp.ts:212) instead
  of "ZKP: inline Groth16: …" (the legacy path's signature).

Out of scope (separate follow-ups today):

- SQLite append-only audit log + hash chain in the verifier (task 3)
- ADR-0008 capturing the TS-vs-Rust decision formally (task 4)
- Promotion of governance/docs/threat-model/verifier.md from stub →
  full with A-V01 through A-V05 entries (task 5)
- Retirement of the inline-fallback code path in zkp.ts (next week)

Tests: 228 passing (no change). Typecheck clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pulkitpareek18 added a commit that referenced this pull request May 15, 2026
* QA log — 2026-05-15 (HOLD, surrogate green, email NOW delivering)

* B02 Phase 2: ship verifier as its own container in prod

Plan B (TS workspace) chosen yesterday. Yesterday's PR #29 landed the
verifier package in the repo. Today's PR Phase 2 flips production to
actually use it instead of the inline-snarkjs fallback that's been
serving since v0.

Dockerfile:

- Adds a `verifier-build` stage that npm-ci's the verifier workspace
  against the root lockfile (reproducible), compiles src/ → dist/.
- Adds a `verifier-production` stage: slim alpine image, non-root user
  uid 1001, flat `npm install --omit=dev` (verifier has 4 prod deps:
  express, snarkjs, winston, uuid — workspace-aware ci complicates a
  per-package prod install; trade-off accepted per ADR-0005). Copies
  the compiled JS + the production vkey. Healthcheck on /health.
  Binds 0.0.0.0:3001 inside the container so docker network reaches
  it; no host port binding so it stays loopback-only at the boundary.

docker-compose.yml:

- New `zeroauth-verifier` service in BOTH the `dev` and `prod`
  profiles. `expose: 3001` (no `ports:` — no host binding).
  Healthcheck wired.
- `zeroauth-prod` gains:
    VERIFIER_URL=http://zeroauth-verifier:3001
    VERIFIER_TIMEOUT_MS=2000
  in its `environment:` block (not via .env — wired directly so a
  hand-edited prod .env can't drift from the compose intent).
- `zeroauth-prod.depends_on` now requires `zeroauth-verifier` to be
  service_healthy before starting. Deploy fails loud if the verifier
  can't load its vkey or bind its port.
- `zeroauth-dev` gets the same wiring so local dev exercises the
  service path by default. Developers who want the inline-snarkjs
  fallback can override with `VERIFIER_URL=` in their .env.

Local validation:

- `docker build --target verifier-production` builds clean
- `docker run` + `curl /health` returns
    {"status":"ok","version":"0.1.0","vkeyAvailable":true,"uptimeSeconds":5}
- `POST /verify` with a structurally-valid junk proof exercises the
  real Groth16 verifier against the real vkey (structuralFallback:false)
  and rejects it correctly (verified:false, 543ms — first call cost
  includes snarkjs init; subsequent calls are <50ms in the same image).

Post-deploy verification plan (after this PR merges):

- The deploy workflow runs scripts/deploy-remote.sh which does
  `docker compose --profile prod up -d --build --remove-orphans` — that
  auto-picks-up the new zeroauth-verifier service.
- After healthchecks pass, the API container's
  src/services/zkp.ts switches from the inline path to the HTTP
  path because VERIFIER_URL is now set in its environment.
- I'll smoke-test by POSTing a /v1/auth/zkp/verify and confirming
  the API logs show "ZKP: verifier service: FAIL/PASS" with a
  verifierAuditId (the service path's signature in zkp.ts:212) instead
  of "ZKP: inline Groth16: …" (the legacy path's signature).

Out of scope (separate follow-ups today):

- SQLite append-only audit log + hash chain in the verifier (task 3)
- ADR-0008 capturing the TS-vs-Rust decision formally (task 4)
- Promotion of governance/docs/threat-model/verifier.md from stub →
  full with A-V01 through A-V05 entries (task 5)
- Retirement of the inline-fallback code path in zkp.ts (next week)

Tests: 228 passing (no change). Typecheck clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pulkitpareek18 added a commit that referenced this pull request May 15, 2026
…29)

* QA log — 2026-05-14 (Blocked + surrogate green, second DW01 run, first on-cadence)

* B02 Plan B: split Groth16 verifier into @zeroauth/verifier workspace

Per the plan-mode design doc, this is Plan B (TypeScript workspace, not
Rust) — chosen for single-engineer velocity. The HTTP shape is
Rust-compatible so a future swap is structural, not behavioural.

Architecture:

- New verifier/ npm workspace with package.json/tsconfig/server.ts.
  Listens on 127.0.0.1:3001 by default. Tiny dep tree: express,
  snarkjs, winston, uuid (no pg, no helmet — not customer-facing).
- POST /verify accepts proof + publicSignals (length 3) + optional
  circuitVersion + correlationId. Returns verified bool + verifier
  audit id + latency_ms + structuralFallback flag.
- GET /health reports loaded-vkey state + uptime; used by the API at
  startup to fail loud if the verifier is misconfigured.
- The verifier trusts its caller — loopback-only is the trust
  boundary. Never expose without mTLS + per-caller rate-limit (and
  threat-model update + ADR).

API repo changes:

- src/services/zkp.ts shrinks: when VERIFIER_URL is set it becomes a
  thin HTTP client; otherwise it falls back to the inline snarkjs path
  (v0 behaviour, marked for removal after Friday Day 5's prod rollout).
- Replay defense (5-min timestamp window + UUIDv4 nonce check + signal
  shape) stays in zkp.ts — the verifier is a pure crypto primitive.
- On-chain re-verification (when blockchain.verifyOnChain=true) stays
  in zkp.ts — depends on ethers which the verifier doesn't need.
- isZKPReady() now reflects verifier /health (service mode) or inline
  snarkjs load state (inline mode). getCircuitInfo() exposes the
  active mode + URL for debugging.

Config:

- New env vars: VERIFIER_URL (default empty → inline mode),
  VERIFIER_TIMEOUT_MS (default 2000). Per the plan-mode doc, these
  ship today with production unchanged; tomorrow's PR adds the
  verifier to docker-compose, sets VERIFIER_URL in prod .env, and
  retires the inline fallback.

Tests:

- 68 → 73 passing. New tests/zkp-service-mode.test.ts has 5 cases:
  POST shape correctness, verifier-says-pass, verifier-says-fail,
  non-2xx returns false (no false positives on 500), network-error
  returns false. Mocks global.fetch — no actual verifier needed for
  CI.
- Existing tests stay green via the inline-fallback path (no
  VERIFIER_URL in test env).

Verifier smoke (local):
  npm run verifier:dev  # boots on :3001
  curl /health  -> {"status":"ok","vkeyAvailable":true,...}
  POST /verify with junk proof -> {"verified":false,"structuralFallback":false}
  POST /verify with malformed body -> 400 invalid_request

Out of scope for today (Friday Day 5 PR):

- docker-compose dev/prod stack changes
- production .env VERIFIER_URL flip
- SQLite audit log + hash chain (B02 §4.3 design doc)
- Inline-fallback removal in src/services/zkp.ts
- Governance repo's docs/threat-model/verifier.md promotion from stub
- ADR-0008 capturing the TS-vs-Rust decision formally


---------
pulkitpareek18 added a commit that referenced this pull request May 15, 2026
* QA log — 2026-05-15 (HOLD, surrogate green, email NOW delivering)

* B02 Phase 2: ship verifier as its own container in prod

Plan B (TS workspace) chosen yesterday. Yesterday's PR #29 landed the
verifier package in the repo. Today's PR Phase 2 flips production to
actually use it instead of the inline-snarkjs fallback that's been
serving since v0.

Dockerfile:

- Adds a `verifier-build` stage that npm-ci's the verifier workspace
  against the root lockfile (reproducible), compiles src/ → dist/.
- Adds a `verifier-production` stage: slim alpine image, non-root user
  uid 1001, flat `npm install --omit=dev` (verifier has 4 prod deps:
  express, snarkjs, winston, uuid — workspace-aware ci complicates a
  per-package prod install; trade-off accepted per ADR-0005). Copies
  the compiled JS + the production vkey. Healthcheck on /health.
  Binds 0.0.0.0:3001 inside the container so docker network reaches
  it; no host port binding so it stays loopback-only at the boundary.

docker-compose.yml:

- New `zeroauth-verifier` service in BOTH the `dev` and `prod`
  profiles. `expose: 3001` (no `ports:` — no host binding).
  Healthcheck wired.
- `zeroauth-prod` gains:
    VERIFIER_URL=http://zeroauth-verifier:3001
    VERIFIER_TIMEOUT_MS=2000
  in its `environment:` block (not via .env — wired directly so a
  hand-edited prod .env can't drift from the compose intent).
- `zeroauth-prod.depends_on` now requires `zeroauth-verifier` to be
  service_healthy before starting. Deploy fails loud if the verifier
  can't load its vkey or bind its port.
- `zeroauth-dev` gets the same wiring so local dev exercises the
  service path by default. Developers who want the inline-snarkjs
  fallback can override with `VERIFIER_URL=` in their .env.

Local validation:

- `docker build --target verifier-production` builds clean
- `docker run` + `curl /health` returns
    {"status":"ok","version":"0.1.0","vkeyAvailable":true,"uptimeSeconds":5}
- `POST /verify` with a structurally-valid junk proof exercises the
  real Groth16 verifier against the real vkey (structuralFallback:false)
  and rejects it correctly (verified:false, 543ms — first call cost
  includes snarkjs init; subsequent calls are <50ms in the same image).

Post-deploy verification plan (after this PR merges):

- The deploy workflow runs scripts/deploy-remote.sh which does
  `docker compose --profile prod up -d --build --remove-orphans` — that
  auto-picks-up the new zeroauth-verifier service.
- After healthchecks pass, the API container's
  src/services/zkp.ts switches from the inline path to the HTTP
  path because VERIFIER_URL is now set in its environment.
- I'll smoke-test by POSTing a /v1/auth/zkp/verify and confirming
  the API logs show "ZKP: verifier service: FAIL/PASS" with a
  verifierAuditId (the service path's signature in zkp.ts:212) instead
  of "ZKP: inline Groth16: …" (the legacy path's signature).

Out of scope (separate follow-ups today):

- SQLite append-only audit log + hash chain in the verifier (task 3)
- ADR-0008 capturing the TS-vs-Rust decision formally (task 4)
- Promotion of governance/docs/threat-model/verifier.md from stub →
  full with A-V01 through A-V05 entries (task 5)
- Retirement of the inline-fallback code path in zkp.ts (next week)

Tests: 228 passing (no change). Typecheck clean.


---------
pulkitpareek18 pushed a commit that referenced this pull request May 28, 2026
v0 storyboard for the bank pitch deck under docs/gtm/bank-pitch-deck-v0.md.
Captures slide-by-slide speaker time, visual, speaker notes, pain-point
trace, required engineering artefacts, compliance trace, and the
failure-mode-if-cut for each of the 20 slides. The deck backs the
22-minute live demo and is the commercial spine of the Anchor Bank
conversation.

Every pain point referenced lifts directly from
docs/plan/bfsi-v1/01-pain-points.md (P1 DPDP §8 reportable-breach,
P2 Aadhaar e-KYC dependency, P3 SMS OTP cost + SIM-swap, P4 audit-log
tamper evidence, P5 RBI Digital Lending consent, P6 ATO, P7 high-value
transaction binding, P10 DPDP §2(t) + data-localisation). Demo handoffs
on slides 8, 14, 15 reference scenes 1-5 of docs/plan/bfsi-v1/02-bank-demo.md
and are operationally backed by docs/operations/anchor-bank-demo-runbook.md.
Compliance slide 10 and roadmap slide 18 trace to
docs/compliance/compliance-roadmap-v1.md quarterly milestones and
deliverable IDs (D-Q1-05 DPDP §2(t) memo, D-Q2-06 ISO Stage 1,
D-Q2-10 SOC 2 Type I report, D-Q3-06 RBI sandbox application,
D-Q3-13 ISO 27001 certificate, D-Q4-02 SOC 2 Type II report,
D-Q4-08 first paid bank).

Ticket: A42-W2-Wed.
Reviewers: Agents #28, #29, #48.
Owner: Agent #42 (CRO).

[no-test]
pulkitpareek18 pushed a commit that referenced this pull request May 28, 2026
Agent #29 (Senior PM, BFSI) — week 1 tickets A29-W1-Mon through
A29-W1-Fri. Delivers the six bank intel packs (HDFC, ICICI, Axis,
SBI YONO, IDFC FIRST, RBL) plus the v1 cold-outreach sequence that
Agent #43 (BFSI North) and Agent #44 (BFSI South + PSBs) consume
for pre-call prep.

Files added:

- docs/product/bank-intel/README.md — index; explains that the
  packs are research-grade artefacts for pre-sales prep, not for
  external distribution; lists update cadence and language
  constraints.
- docs/product/bank-intel/hdfc.md — HDFC Bank Ltd. intel pack;
  pain hooks P1, P4, P7 from docs/plan/bfsi-v1/01-pain-points.md.
- docs/product/bank-intel/icici.md — ICICI Bank Ltd.; pain hooks
  P3, P6, P1.
- docs/product/bank-intel/axis.md — Axis Bank Ltd.; pain hooks
  P4, P7, P1.
- docs/product/bank-intel/sbi-yono.md — State Bank of India /
  YONO; pain hooks P2, P9, P6.
- docs/product/bank-intel/idfc-first.md — IDFC FIRST Bank Ltd.;
  pain hooks P9, P3, P1.
- docs/product/bank-intel/rbl.md — RBL Bank Ltd.; pain hooks
  P5, P4, P1.
- docs/gtm/outreach-sequence-v1.md — five-email cold-outreach
  sequence (day 0, 4, 9, 16, 23); subject lines all <= 50 chars,
  bodies 100-150 words, per-bank personalisation map; no banned
  phrases from CLAUDE.md.

Verification:

- Each intel pack is 176-187 lines (target band 150-300).
- Every fact is either cited [src: ...] or marked [VERIFY].
- No named executives without a verified public-record source.
- Every file carries an INTERNAL header in the top three lines.
- Banned-phrase scan clean: no "AI-powered", no "deepfake-immune"
  without the visual-spoofing-class qualifier, no "Dr. Pulkit",
  no "production stack".
- Subject lines: all 22 variants fit <= 50 chars by Python len().
- Email bodies: word count 105-125 (target 100-150) excluding
  placeholder tokens.

References:

- docs/plan/bfsi-v1/01-pain-points.md (commercial spine; P1-P10).
- docs/plan/bfsi-v1/02-bank-demo.md (demo Scenes 1-6 reflected in
  per-pack "why ZeroAuth resonates here" sections).
- docs/plan/bfsi-v1/03-team.md role 29, 43, 44.
- docs/operations/anchor-bank-demo-runbook.md (one-page summary
  PDF reference in Email 3).
- docs/compliance/compliance-roadmap-v1.md (DPDP and RBI section
  references in the RBL pack and the SBI pack).

[no-test] markdown-only.
pulkitpareek18 pushed a commit that referenced this pull request May 28, 2026
v0 storyboard for the bank pitch deck under docs/gtm/bank-pitch-deck-v0.md.
Captures slide-by-slide speaker time, visual, speaker notes, pain-point
trace, required engineering artefacts, compliance trace, and the
failure-mode-if-cut for each of the 20 slides. The deck backs the
22-minute live demo and is the commercial spine of the Anchor Bank
conversation.

Every pain point referenced lifts directly from
docs/plan/bfsi-v1/01-pain-points.md (P1 DPDP §8 reportable-breach,
P2 Aadhaar e-KYC dependency, P3 SMS OTP cost + SIM-swap, P4 audit-log
tamper evidence, P5 RBI Digital Lending consent, P6 ATO, P7 high-value
transaction binding, P10 DPDP §2(t) + data-localisation). Demo handoffs
on slides 8, 14, 15 reference scenes 1-5 of docs/plan/bfsi-v1/02-bank-demo.md
and are operationally backed by docs/operations/anchor-bank-demo-runbook.md.
Compliance slide 10 and roadmap slide 18 trace to
docs/compliance/compliance-roadmap-v1.md quarterly milestones and
deliverable IDs (D-Q1-05 DPDP §2(t) memo, D-Q2-06 ISO Stage 1,
D-Q2-10 SOC 2 Type I report, D-Q3-06 RBI sandbox application,
D-Q3-13 ISO 27001 certificate, D-Q4-02 SOC 2 Type II report,
D-Q4-08 first paid bank).

Ticket: A42-W2-Wed.
Reviewers: Agents #28, #29, #48.
Owner: Agent #42 (CRO).

[no-test]
pulkitpareek18 pushed a commit that referenced this pull request May 28, 2026
Agent #29 (Senior PM, BFSI) — week 1 tickets A29-W1-Mon through
A29-W1-Fri. Delivers the six bank intel packs (HDFC, ICICI, Axis,
SBI YONO, IDFC FIRST, RBL) plus the v1 cold-outreach sequence that
Agent #43 (BFSI North) and Agent #44 (BFSI South + PSBs) consume
for pre-call prep.

Files added:

- docs/product/bank-intel/README.md — index; explains that the
  packs are research-grade artefacts for pre-sales prep, not for
  external distribution; lists update cadence and language
  constraints.
- docs/product/bank-intel/hdfc.md — HDFC Bank Ltd. intel pack;
  pain hooks P1, P4, P7 from docs/plan/bfsi-v1/01-pain-points.md.
- docs/product/bank-intel/icici.md — ICICI Bank Ltd.; pain hooks
  P3, P6, P1.
- docs/product/bank-intel/axis.md — Axis Bank Ltd.; pain hooks
  P4, P7, P1.
- docs/product/bank-intel/sbi-yono.md — State Bank of India /
  YONO; pain hooks P2, P9, P6.
- docs/product/bank-intel/idfc-first.md — IDFC FIRST Bank Ltd.;
  pain hooks P9, P3, P1.
- docs/product/bank-intel/rbl.md — RBL Bank Ltd.; pain hooks
  P5, P4, P1.
- docs/gtm/outreach-sequence-v1.md — five-email cold-outreach
  sequence (day 0, 4, 9, 16, 23); subject lines all <= 50 chars,
  bodies 100-150 words, per-bank personalisation map; no banned
  phrases from CLAUDE.md.

Verification:

- Each intel pack is 176-187 lines (target band 150-300).
- Every fact is either cited [src: ...] or marked [VERIFY].
- No named executives without a verified public-record source.
- Every file carries an INTERNAL header in the top three lines.
- Banned-phrase scan clean: no "AI-powered", no "deepfake-immune"
  without the visual-spoofing-class qualifier, no "Dr. Pulkit",
  no "production stack".
- Subject lines: all 22 variants fit <= 50 chars by Python len().
- Email bodies: word count 105-125 (target 100-150) excluding
  placeholder tokens.

References:

- docs/plan/bfsi-v1/01-pain-points.md (commercial spine; P1-P10).
- docs/plan/bfsi-v1/02-bank-demo.md (demo Scenes 1-6 reflected in
  per-pack "why ZeroAuth resonates here" sections).
- docs/plan/bfsi-v1/03-team.md role 29, 43, 44.
- docs/operations/anchor-bank-demo-runbook.md (one-page summary
  PDF reference in Email 3).
- docs/compliance/compliance-roadmap-v1.md (DPDP and RBI section
  references in the RBL pack and the SBI pack).

[no-test] markdown-only.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant