{"_id":"@canton-vc/adapter-persona","_rev":"3-addc1f8d9fa31c5af7cb79e347567cd3","name":"@canton-vc/adapter-persona","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@canton-vc/adapter-persona","version":"0.1.0","keywords":["canton","kyc","persona","withpersona","adapter","canton-vc"],"author":{"url":"https://github.com/Farukest","name":"Abdullah Faruk Özden","email":"abdullahfarukozden@gmail.com"},"license":"Apache-2.0","_id":"@canton-vc/adapter-persona@0.1.0","maintainers":[{"name":"0xflydev","email":"0xflydev@gmail.com"}],"homepage":"https://github.com/Farukest/canton-vc/tree/main/packages/adapter-persona#readme","bugs":{"url":"https://github.com/Farukest/canton-vc/issues"},"dist":{"shasum":"9d50a009766c923b501d74d88796e3a2ae0ae910","tarball":"https://registry.npmjs.org/@canton-vc/adapter-persona/-/adapter-persona-0.1.0.tgz","fileCount":8,"integrity":"sha512-R6utYsNIP2QWKL1GPtxgFTYK2py3UiuhtkV1ylONfSsNfUEN4cSfOb6WuL9dyCI6dHTCsY6GwnO1qUkwrhGUoA==","signatures":[{"sig":"MEUCICaH6CuTGLMYPHetK807DcCWXDgKIvFu6d2WMYe5c64aAiEAwzdLka+UZtCv9Pj25A/cUnfM927/CjAxfr9+8PBUSqU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":53439},"main":"./src/index.ts","type":"module","_from":"file:canton-vc-adapter-persona-0.1.0.tgz","types":"./src/index.ts","engines":{"node":">=18"},"exports":{".":{"types":"./src/index.ts","default":"./src/index.ts"}},"scripts":{"lint":"biome check src tests","test":"vitest run","clean":"rm -rf .turbo dist","typecheck":"tsc --noEmit"},"_npmUser":{"name":"0xflydev","email":"0xflydev@gmail.com"},"_resolved":"C:\\Users\\FARUKE~1\\AppData\\Local\\Temp\\ba9cb434ea71156ec92168737bcd648f\\canton-vc-adapter-persona-0.1.0.tgz","_integrity":"sha512-R6utYsNIP2QWKL1GPtxgFTYK2py3UiuhtkV1ylONfSsNfUEN4cSfOb6WuL9dyCI6dHTCsY6GwnO1qUkwrhGUoA==","repository":{"url":"git+https://github.com/Farukest/canton-vc.git","type":"git","directory":"packages/adapter-persona"},"_npmVersion":"11.6.2","description":"Persona KYC provider adapter for canton-vc. Wraps Persona's JSON:API inquiry endpoints (Bearer auth, Persona-Version-pinned request envelope, JSON:API relationships) with the Persona-Signature webhook scheme (HMAC-SHA256 over `<ts>.<rawBody>` with key rot","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","dependencies":{"zod":"4.3.6","@canton-vc/core":"0.1.0","@canton-vc/kyc-provider":"0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"2.1.8","typescript":"5.6.3","@types/node":"22.10.2"},"_npmOperationalInternal":{"tmp":"tmp/adapter-persona_0.1.0_1779586285617_0.893418665175131","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@canton-vc/adapter-persona","version":"0.2.0","keywords":["canton","kyc","persona","withpersona","adapter","canton-vc"],"author":{"url":"https://github.com/Farukest","name":"Abdullah Faruk Özden","email":"abdullahfarukozden@gmail.com"},"license":"Apache-2.0","_id":"@canton-vc/adapter-persona@0.2.0","maintainers":[{"name":"0xflydev","email":"0xflydev@gmail.com"}],"homepage":"https://github.com/Farukest/canton-vc/tree/main/packages/adapter-persona#readme","bugs":{"url":"https://github.com/Farukest/canton-vc/issues"},"dist":{"shasum":"1700edc24bfdf4d7117906d44647a079cea925d9","tarball":"https://registry.npmjs.org/@canton-vc/adapter-persona/-/adapter-persona-0.2.0.tgz","fileCount":8,"integrity":"sha512-oyHmKWAQnp4b17kVwZ7vIsFUSFxATrVObe7ICVFR/7r+Td64smsQDu/BMI5IC9/Ta9wNGvDu+7htRK4z0g7a/Q==","signatures":[{"sig":"MEQCIAsuy6j8Nukz3pldjNbLuP/C9uwKvPzo7hyEqFe/XIibAiBmsuEuYXSs1LM9r0qxDG1DBU+/UGgi8swPTn/dvVcWYQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":53439},"main":"./src/index.ts","type":"module","_from":"file:canton-vc-adapter-persona-0.2.0.tgz","types":"./src/index.ts","engines":{"node":">=18"},"exports":{".":{"types":"./src/index.ts","default":"./src/index.ts"}},"scripts":{"lint":"biome check src tests","test":"vitest run","clean":"rm -rf .turbo dist","typecheck":"tsc --noEmit"},"_npmUser":{"name":"0xflydev","email":"0xflydev@gmail.com"},"_resolved":"C:\\Users\\FARUKE~1\\AppData\\Local\\Temp\\dbca52e35a8f21f014ac57723fcfd5b0\\canton-vc-adapter-persona-0.2.0.tgz","_integrity":"sha512-oyHmKWAQnp4b17kVwZ7vIsFUSFxATrVObe7ICVFR/7r+Td64smsQDu/BMI5IC9/Ta9wNGvDu+7htRK4z0g7a/Q==","repository":{"url":"git+https://github.com/Farukest/canton-vc.git","type":"git","directory":"packages/adapter-persona"},"_npmVersion":"11.6.2","description":"Persona KYC provider adapter for canton-vc. Wraps Persona's JSON:API inquiry endpoints (Bearer auth, Persona-Version-pinned request envelope, JSON:API relationships) with the Persona-Signature webhook scheme (HMAC-SHA256 over `<ts>.<rawBody>` with key rot","directories":{},"sideEffects":false,"_nodeVersion":"24.12.0","dependencies":{"zod":"4.3.6","@canton-vc/core":"0.2.0","@canton-vc/kyc-provider":"0.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"2.1.8","typescript":"5.6.3","@types/node":"22.10.2"},"_npmOperationalInternal":{"tmp":"tmp/adapter-persona_0.2.0_1779984360470_0.1709419892279347","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@canton-vc/adapter-persona","version":"0.3.0","description":"Persona KYC provider adapter for canton-vc. Wraps Persona's JSON:API inquiry endpoints (Bearer auth, Persona-Version-pinned request envelope, JSON:API relationships) with the Persona-Signature webhook scheme (HMAC-SHA256 over `<ts>.<rawBody>` with key rot","license":"Apache-2.0","type":"module","main":"./src/index.ts","types":"./src/index.ts","exports":{".":{"types":"./src/index.ts","default":"./src/index.ts"}},"sideEffects":false,"engines":{"node":">=18"},"dependencies":{"zod":"4.3.6","@canton-vc/core":"0.3.0","@canton-vc/kyc-provider":"0.3.0"},"devDependencies":{"@types/node":"22.10.2","typescript":"5.6.3","vitest":"2.1.8"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/Farukest/canton-vc.git","directory":"packages/adapter-persona"},"keywords":["canton","kyc","persona","withpersona","adapter","canton-vc"],"author":{"name":"Abdullah Faruk Özden","email":"abdullahfarukozden@gmail.com","url":"https://github.com/Farukest"},"homepage":"https://github.com/Farukest/canton-vc/tree/main/packages/adapter-persona#readme","bugs":{"url":"https://github.com/Farukest/canton-vc/issues"},"scripts":{"lint":"biome check src tests","typecheck":"tsc --noEmit","test":"vitest run","clean":"rm -rf .turbo dist"},"_id":"@canton-vc/adapter-persona@0.3.0","_integrity":"sha512-1C7dXsH5JONXqizInBKc0DMJv2S7o4NsYLl5WTnYtwoqmHC+b5jBBdE2lsOeB7q80eARmnhuJWRganCTDG0G6A==","_resolved":"C:\\Users\\FARUKE~1\\AppData\\Local\\Temp\\abc9e35c9364264e26825ce23298d427\\canton-vc-adapter-persona-0.3.0.tgz","_from":"file:canton-vc-adapter-persona-0.3.0.tgz","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-1C7dXsH5JONXqizInBKc0DMJv2S7o4NsYLl5WTnYtwoqmHC+b5jBBdE2lsOeB7q80eARmnhuJWRganCTDG0G6A==","shasum":"7bf47c03107c03dea140af57fa3e178892bd38b8","tarball":"https://registry.npmjs.org/@canton-vc/adapter-persona/-/adapter-persona-0.3.0.tgz","fileCount":8,"unpackedSize":53439,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC3CYzlco3eMQwBrhnD08ZEqdSIsnRKjXeFCUqv7CoM2AIhANZXXfBX47iPYi6UP54oLLSoFflXsMoi10xSDY+cf/4o"}]},"_npmUser":{"name":"0xflydev","email":"0xflydev@gmail.com"},"directories":{},"maintainers":[{"name":"0xflydev","email":"0xflydev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/adapter-persona_0.3.0_1780019779234_0.8526655432305046"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-24T01:31:25.433Z","modified":"2026-05-29T01:56:19.546Z","0.1.0":"2026-05-24T01:31:25.761Z","0.2.0":"2026-05-28T16:06:00.634Z","0.3.0":"2026-05-29T01:56:19.389Z"},"bugs":{"url":"https://github.com/Farukest/canton-vc/issues"},"author":{"name":"Abdullah Faruk Özden","email":"abdullahfarukozden@gmail.com","url":"https://github.com/Farukest"},"license":"Apache-2.0","homepage":"https://github.com/Farukest/canton-vc/tree/main/packages/adapter-persona#readme","keywords":["canton","kyc","persona","withpersona","adapter","canton-vc"],"repository":{"type":"git","url":"git+https://github.com/Farukest/canton-vc.git","directory":"packages/adapter-persona"},"description":"Persona KYC provider adapter for canton-vc. Wraps Persona's JSON:API inquiry endpoints (Bearer auth, Persona-Version-pinned request envelope, JSON:API relationships) with the Persona-Signature webhook scheme (HMAC-SHA256 over `<ts>.<rawBody>` with key rot","maintainers":[{"name":"0xflydev","email":"0xflydev@gmail.com"}],"readme":"# @canton-vc/adapter-persona\n\nProduction [`KycProvider`](../kyc-provider) implementation for the\n[Persona](https://withpersona.com) KYC vendor.\n\n## Install\n\n```bash\npnpm add @canton-vc/adapter-persona @canton-vc/kyc-provider\n```\n\n## Usage\n\n```ts\nimport { PersonaAdapter } from '@canton-vc/adapter-persona';\n\nconst kyc = new PersonaAdapter({\n  apiKey: process.env.PERSONA_API_KEY!,            // Bearer token (`persona_…`)\n  webhookSecret: process.env.PERSONA_WEBHOOK_SECRET!, // signs inbound webhooks\n  identityTemplateId: process.env.PERSONA_IDENTITY_TEMPLATE_ID!, // `itmpl_…`\n  // optional:\n  addressTemplateId: process.env.PERSONA_ADDRESS_TEMPLATE_ID,\n});\n\n// 1. Start a session — redirect the user to session.redirectUrl (one-time link)\nconst session = await kyc.startSession({ userRef: 'user-123' });\n\n// 2. Pull the decision after the user completes the inquiry\nconst decision = await kyc.fetchDecision(session.sessionId);\n// decision.status === 'approved' | 'declined' | 'in_review' | 'pending' | 'expired'\n\n// 3. Verify webhook (in your /webhook/persona handler)\nconst event = await kyc.verifyWebhook(rawBody, request.headers);\nif (event === null) return new Response('invalid', { status: 400 });\n// event.type === 'decision' | 'session.expired'\n```\n\n## Authentication — Bearer token\n\nPersona uses a static Bearer token sent in the `Authorization` header\non every request. The adapter also pins `Persona-Version`, so a\nPersona-side schema bump cannot silently change the request envelope\nthe adapter expects.\n\n## Webhook signature — Persona-Signature\n\nPersona signs webhooks with `t=<timestamp>,v1=<hex-hmac>` in the\n`Persona-Signature` header. The HMAC is computed over\n`<timestamp>.<rawBody>` with a SHA-256 digest. The adapter:\n\n- Enforces a default 5-minute timestamp drift window (overridable).\n- Tolerates **multiple active webhook secrets** so issuers can rotate\n  secrets without a synchronous cutover — pass an array as\n  `webhookSecret` and the adapter accepts a signature from any one of\n  them in constant time.\n- Compares signatures via `crypto.timingSafeEqual` to defeat timing\n  side-channels.\n\n## Inquiry model\n\nPersona's identity model is **inquiry-centric** (one `inq_…` per KYC\nattempt) rather than session-centric. The adapter normalises this\nunder `KycProvider.startSession` / `KycProvider.fetchDecision` so the\ncall site looks the same as the Didit and Sumsub adapters. The\nunderlying inquiry id surfaces as `KycSession.sessionId` — store it\nas you would any opaque vendor handle.\n\n## Hosted flow — one-time link\n\n`startSession` creates an inquiry with `auto-create-one-time-link:\ntrue`. Persona responds with a short URL (`withpersona.com/verify?code=…`)\nthat the issuer redirects the user to; the URL expires after one use.\nThis avoids hosting Persona's WebSDK on the issuer's domain.\n\n## Decision level mapping\n\nPersona's `verification`-typed inquiries produce a list of\nsub-verifications (government ID, selfie, database, etc). The adapter\ncollapses these into the canton-vc `evidence` shape:\n\n| canton-vc field      | Derived from |\n|---|---|\n| `identityVerified`  | Document + selfie verification both `passed` |\n| `livenessVerified`  | Liveness sub-verification `passed` |\n| `addressVerified`   | Proof-of-address verification `passed` |\n| `level`             | `enhanced` when identity + address both pass; `basic` when identity alone passes |\n\n## Configuration reference\n\n| Field | Required | Default | Purpose |\n|---|---|---|---|\n| `apiKey` | ✅ | — | Persona API Bearer token. |\n| `webhookSecret` | ✅ | — | Webhook signing secret (string or `readonly string[]` for key rotation). |\n| `identityTemplateId` | ✅ | — | Persona inquiry template (`itmpl_…`) for identity. |\n| `addressTemplateId` |   | — | Persona inquiry template for proof-of-address. |\n| `baseUrl` |   | `https://api.withpersona.com` | API root. |\n| `personaVersion` |   | `2023-01-05` | Pinned `Persona-Version` header. |\n| `webhookDriftSeconds` |   | `300` | Allowed `Persona-Signature` `t=` drift. |\n| `requestTimeoutMs` |   | `10000` | Per-request HTTP timeout. |\n| `fetch` |   | `globalThis.fetch` | Override the fetch implementation. |\n| `clock` |   | `Date.now` | Override the wall-clock source. |\n\n## Implementing another vendor\n\nThe companion reference adapters\n[`@canton-vc/adapter-didit`](../adapter-didit) (static API key,\nsessions, canonical-JSON webhook HMAC) and\n[`@canton-vc/adapter-sumsub`](../adapter-sumsub) (per-request HMAC,\napplicants, multi-algorithm webhook digest) sit at the two other\ncorners of the KYC-vendor wire-shape design space. Persona is the\nthird structurally distinct shape (Bearer + JSON:API + inquiry +\nsigned-timestamp webhook). Pick whichever is closest to your target\nand adapt from there. Open an issue with the vendor name to claim\nthe next adapter.\n\n## License\n\nApache 2.0 — see [LICENSE](../../LICENSE).\n","readmeFilename":"README.md"}