Phase 6 — Idenfy KYC integration #7
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 6 — Idenfy KYC integration
Tracks the s2-008 work item: lift the production-validated Idenfy KYC integration from the freezone backend into
hero_onboarding, gate Stripe/ClickPesa top-up on KYC completion, and add an admin view.Scope
Schema — new
crates/hero_onboarding_schema/schemas/onboarding/kyc.oschema(lifted from the consolidatedfreezone.oschema, trimmed to hero_onboarding scope — noresident_id, nopublic_key, since hero_onboarding has no DigitalResident or per-user keypair). AddsKycStatus = "pending" | "in_progress" | "completed" | "failed" | "expired"enum +KycSessionrootobject. Modifiesuser.oschemato addkyc_status: KycStatusandkyc_verified_at?: otime.Backend — new
crates/hero_onboarding_server/src/kyc.rs(KycProviderasync trait +IdenfyProviderimpl). Translation of freezoneproviders/kyc.rs: ureq sync → reqwest async, preserves HMAC-SHA256 webhook signature verification, preservesclient_idtimestamp-suffix trick (allows re-verification after KYC reset; webhook parser strips the suffix to recover the originalclient_id), preservesdemo+dev_modeescape hatches.Server routes — gate
/payment/intentonUser.kyc_status == Completed(renders error page with link to/kyc/startif blocked). AddsGET /kyc/start,GET /kyc/return,POST /kyc/reset,POST /webhooks/idenfy,GET /admin/list-kyc-sessions. Idenfy webhook updatesUser.kyc_status+User.kyc_verified_at+KycSession.statusonoverall == "approved" | "suspected".Admin — new
/kycview inhero_onboarding_adminreading/admin/list-users+/admin/list-kyc-sessions.CLI — extend
FORWARDED_ENVinhero_onboardingwithIDENFY_API_KEY,IDENFY_API_SECRET,IDENFY_API_URL,IDENFY_WEBHOOK_SECRET,IDENFY_DEV_MODE.Smoke —
scripts/smoke_kyc.shruns againstIDENFY_DEV_MODE=true(sidesteps live Idenfy sandbox dependency): payment_intent before KYC → blocked, /kyc/start → KycSession persisted, HMAC-signed mock callback → User.kyc_status = Completed, payment_intent after KYC → 302 to Stripe, admin-gating on /admin/list-kyc-sessions.KYC-gating order (D-15 candidate)
Decision: gate-at-paid-resource (recommended posture per
prompt2.md§3). KYC fires when the user clicks Top Up, not at first login. Rationale:kyc_status: Pending; no flag-day re-verification.Revisability cost if revisited later (gate-at-first-login):
/kyc/startafter challenge verificationPending→Required(if we add that state) is in-place oschema editUser.kyc_statusalready existsSchema-file-shape diff (vs meta-issue claim)
The meta-issue claimed
kyc.oschemaexists as a standalone file in the freezone backend. It doesn't — the freezone schema is consolidated into a singlefreezone.oschemafile. The KycStatus + KycSession type definitions are verbatim-copyable; the file layout differs. hero_onboarding follows a per-domain layout (one rootobject per file likebilling.oschema,user.oschema, etc.), so this Phase 6 shipskyc.oschemaas a fresh file containing only KYC-related types.Trimmed-out fields vs freezone:
resident_id— hero_onboarding has no DigitalResidentpublic_key— hero_onboarding has no per-user keypairidenfy_scan_ref→idenfy_scan_ref?(optional, kept)updated_at: otime→last_run_at: otime(per s2-007 Phase B finding 2 —updated_at: otimesilently collides with autogenupdated_at: u64)Acceptance gate
cargo check --workspacecargo test(+~3 new: schema CRUD auto for KycSession + 1 webhook parser unit test + 1 client_id-suffix-strip unit test)lab build --release --install --workspaceVICTORY 3/3lab infocheck3/3 cleancargo fmt --checkcleancargo clippy --workspace --all-targets -- -D warningscleanscripts/smoke_kyc.shGREENParent: lhumina_code/hero_onboarding#1