KYC, Verification & Trust
Status: 🟡 Partially implemented (claim/KYC engine complete; core submission tables mostly empty; verification priced-for but unbuilt) · Last validated: 2026-09-06
Identity/business verification, directory claims, and trust scoring. Validated against classs/ClaimKycModule.php, classs/KooviraTrustScoreEngine.php, and the live schema.
Engine (ClaimKycModule)
| Method | Line | What |
|---|---|---|
ensureSchemaReady() | 72 | idempotent schema guard |
submitBusinessKyc(userId, companyId, category, post, files) | 172 | merchant business KYC |
submitPropertyClaim(userId, post, files) | 307 | claim a property listing |
submitListingClaim(userId, listingId, post, files) | 685 | claim a directory listing |
issueClaimOtp(userId, purpose, meta) | 460 | OTP gate on claim submit |
verifyClaimOtp(userId, code, purpose) | 476 | verify the claim OTP |
setClaimStatus(requestId, newStatus, adminId, reason) | 541 | admin approve/reject/resubmit |
createAppeal(userId, parentRequestId, post, files) | 856 | appeal a rejection |
getUserClaims(userId) | 971 | a user's claims |
notifyClaimEvent(requestId, event, reason) | 1004 | fire notifications on state change |
Data model (2026-09-06)
| Table | Rows | Role |
|---|---|---|
claim_kyc_requests | 0 (verified 2026-09-06) | the claim/KYC request header + status — empty |
claim_kyc_documents | 6 | uploaded documents |
kyc_submissions | 0 | (dormant/empty) |
kyc_documents | 0 (verified 2026-09-06) | document store — empty |
verification_orders | 0 | paid verification orders — empty |
verification_plans | 0 | verification pricing — empty |
entity_listing_claims | 0 | directory claims recorded — 0 ever |
ai_trust_scores | 13 | user/entity trust score |
ai_trust_entity_score | 0 (verified 2026-09-06) | entity-level trust — empty |
Module-specific KYC/verification tables (each vertical adds its own): kv_partner_kyc_documents, kv_pharmacy_rx_verifications, legal_professional_verification, sr_service_provider_kyc_docs, student_verification, campus_user_verification, institute_verification_requests, merchant_module_kyc_doc_types, merchant_module_kyc_notes, fitness_trust_score.
Claim / KYC state machine
draft → submitted (issueClaimOtp → verifyClaimOtp) → under_review
→ approved (setClaimStatus, adminId) → [entitlements granted]
→ rejected → createAppeal → under_review …
Each transition: setClaimStatus writes the request row + notifyClaimEvent fires in-app/email/SMS. Approval is what grants a merchant the ability to publish/transact in a KYC-gated module.
The gate chain (why a merchant can't publish)
Module on (kv_module_control) → Enrolled (kv_module_registry) → Membership tier → KYC approved (claim_kyc_requests) → publish/transaction permission. A break anywhere renders the "available for X accounts" / "complete verification" message. This chain is the backbone of the Error Center troubleshooting entry "merchant cannot publish product".
Validated gaps
- Directory claim conversion = 0.
entity_listing_claims= 0 despite ~3Mentity_listings.
The claim funnel (submitListingClaim, OTP, docs) is built and exercised (6 doc rows), but there is no landing page/CTA a merchant would see — a promotion gap, not a code gap.
- **Orphaned claim documents (flagged, not fixed — data-integrity issue, out of scope for this
documentation pass):** all 6 claim_kyc_documents rows carry a request_id (1, 15, 16) that does not exist in claim_kyc_requests (0 rows, verified 2026-09-06). Every uploaded claim document is currently a dangling reference. Two of the six rows (rowId 3-4, request_id=15) also store document_path in a malformed mixed-separator form (/\uploaddir\0\kyc_claims\2026-08-20\...webp) unlike the clean /uploads/kyc_claims/... paths on rowId 1-2 — worth an engineering look at submitPropertyClaim/submitListingClaim's file-storage call.
- Verification is priced-for but unbuilt.
verification_plans/verification_orders= 0
despite a payment page existing. No purchasable verification product today.
- Regulated modules require REAL licences (validated in memory
pharmacy-licence-mandatory):
never fabricate or self-verify a regulatory credential on prod (Schedule H / pharmacy).
Trust score
KooviraTrustScoreEngine computes ai_trust_scores (13 rows) from signals (verification, ratings, activity). Consumed by search ranking and the trust badge. Detail: to be expanded in a trust doc.
Business rules
BR-KYC-001— claim submit is OTP-gated (issueClaimOtp/verifyClaimOtp).BR-KYC-002— publishing/transacting in a KYC-gated module requires an approved
claim_kyc_requests row.
BR-KYC-003— regulated verticals require real regulatory licences; no self-verification on prod.
Errors (prefix KYC-E)
KYC-E001claim OTP invalid/expired — inspect the OTP purpose + timestamp.KYC-E002"cannot publish" — walk the gate chain above; usually KYC not approved or membership missing.KYC-E003verification purchase impossible —verification_plansempty (unbuilt).
Change-impact
KYC approval unlocks publishing/transaction across modules; changing the gate chain affects every merchant vertical. Re-test: submit→OTP→approve grants the right entitlement; rejection→appeal loops; notifications fire.