{"_id":"@blazing-customs/ppx-client","_rev":"9-324946d7aad047f37129bdec78328e90","name":"@blazing-customs/ppx-client","dist-tags":{"latest":"0.1.0-alpha.4"},"versions":{"0.1.0-alpha.0":{"name":"@blazing-customs/ppx-client","version":"0.1.0-alpha.0","keywords":["ppx","preference-profile-exchange","oauth","consent","mcp","a2a","ag-ui","agents","ai"],"author":{"name":"Blazing Customs"},"license":"Apache-2.0","_id":"@blazing-customs/ppx-client@0.1.0-alpha.0","maintainers":[{"name":"coolblaze03","email":"chabli.boler@gmail.com"}],"homepage":"https://blazing-customs.github.io/ppx-spec/","bugs":{"url":"https://github.com/Blazing-Customs/ppx-sdks/issues"},"dist":{"shasum":"707865358ac8248e41c168d4317011d23677fa1a","tarball":"https://registry.npmjs.org/@blazing-customs/ppx-client/-/ppx-client-0.1.0-alpha.0.tgz","fileCount":27,"integrity":"sha512-GrroBIwr+pmiuNBdimb/UvCaJHUqJ4KEY4U2fNa2r3X4JyxKgIhLk5ztq7CUdALWK5GkETy9OO8RlLHWrqGU7g==","signatures":[{"sig":"MEQCID6OA+wbxE/bQLei80rS2OR2m9Jhu6a6FxS6L9zoLHPEAiB4wStejpyJLzhIiWqaPvO+nJ/fjOPTrxIjj/9GGaWLUQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58852},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.17.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a4e9193d1de69d638b74fa52f8727ab9f03dcabc","scripts":{"lint":"tsc --noEmit","build":"tsc","clean":"rm -rf dist","watch":"tsc --watch"},"_npmUser":{"name":"coolblaze03","email":"chabli.boler@gmail.com"},"repository":{"url":"git+https://github.com/Blazing-Customs/ppx-sdks.git","type":"git","directory":"typescript/client"},"_npmVersion":"10.8.2","description":"TypeScript client for the Preference Profile Exchange (PPX) reference provider and any conformant implementation.","directories":{},"_nodeVersion":"20.20.2","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/ppx-client_0.1.0-alpha.0_1785446303804_0.9528631959673193","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Speaks the withdrawn v1 consent flow; providers now reject it. Use 0.1.0-alpha.4."},"0.1.0-alpha.1":{"name":"@blazing-customs/ppx-client","version":"0.1.0-alpha.1","keywords":["ppx","preference-profile-exchange","oauth","consent","mcp","a2a","ag-ui","agents","ai"],"author":{"name":"Blazing Customs"},"license":"Apache-2.0","_id":"@blazing-customs/ppx-client@0.1.0-alpha.1","maintainers":[{"name":"coolblaze03","email":"chabli.boler@gmail.com"}],"homepage":"https://blazing-customs.github.io/ppx-spec/","bugs":{"url":"https://github.com/Blazing-Customs/ppx-sdks/issues"},"dist":{"shasum":"ab3e6c015389d823d56d84851609a69c9454ce0e","tarball":"https://registry.npmjs.org/@blazing-customs/ppx-client/-/ppx-client-0.1.0-alpha.1.tgz","fileCount":27,"integrity":"sha512-OjuGqxSocOI6CxKzBHjUOQS1lss3QH9UTPnFD/83VdUogjSHCFMOj4y2UfQJhHP18rdgSLKBbxFp9Qf1W57mXg==","signatures":[{"sig":"MEUCIDhaRYON/xiaiTE7rn5HASWD3BB2Xu1ENbKtejPKGjVMAiEA7LCVn9Xx3mqbowQut8snsdV14PvcCUvOBFA4tENVr/4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":58631},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.17.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a4e9193d1de69d638b74fa52f8727ab9f03dcabc","scripts":{"lint":"tsc --noEmit","build":"tsc","clean":"rm -rf dist","watch":"tsc --watch"},"_npmUser":{"name":"coolblaze03","email":"chabli.boler@gmail.com"},"deprecated":"Speaks the withdrawn v1 consent flow; providers now reject it. Use 0.1.0-alpha.4.","repository":{"url":"git+https://github.com/Blazing-Customs/ppx-sdks.git","type":"git","directory":"typescript/client"},"_npmVersion":"10.8.2","description":"TypeScript client for the Preference Profile Exchange (PPX) reference provider and any conformant implementation.","directories":{},"_nodeVersion":"20.20.2","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/ppx-client_0.1.0-alpha.1_1785446421464_0.623124383932284","host":"s3://npm-registry-packages-npm-production"}},"0.1.0-alpha.2":{"name":"@blazing-customs/ppx-client","version":"0.1.0-alpha.2","keywords":["ppx","preference-profile-exchange","oauth","consent","mcp","a2a","ag-ui","agents","ai"],"author":{"name":"Blazing Customs"},"license":"Apache-2.0","_id":"@blazing-customs/ppx-client@0.1.0-alpha.2","maintainers":[{"name":"coolblaze03","email":"chabli.boler@gmail.com"}],"homepage":"https://blazing-customs.github.io/ppx-spec/","dist":{"shasum":"1aef7e8eca19d96951de9a89b1c11dbbbeb08e4a","tarball":"https://registry.npmjs.org/@blazing-customs/ppx-client/-/ppx-client-0.1.0-alpha.2.tgz","fileCount":31,"integrity":"sha512-aIGCjhhCWCfOYEt43c7QZVYg0tfL6WLieigtOi7uE7w7gpWYFqrlwaLyvjSyP9p9Zme9/SxuM0rdYIMFnaTN2Q==","signatures":[{"sig":"MEQCIDf9a7eP1G2yiHQniOpbF8BH3ZcXgTuZ4zbO6BPRe96PAiBeAAHUockebwxH+mw4fmbLmMV5p3G+ZEYKQs6lpWFviA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68381},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.17.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"565838313702aaf09804746c4df74b85e213a126","scripts":{"lint":"tsc --noEmit","test":"npm run build && node --test test/*.test.mjs","build":"tsc","clean":"rm -rf dist","watch":"tsc --watch"},"_npmUser":{"name":"coolblaze03","email":"chabli.boler@gmail.com"},"deprecated":"Broken: fails to import entirely (ERR_MODULE_NOT_FOUND). Use 0.1.0-alpha.4.","_npmVersion":"10.8.2","description":"TypeScript client for the Preference Profile Exchange (PPX) reference provider and any conformant implementation.","directories":{},"_nodeVersion":"20.20.2","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/ppx-client_0.1.0-alpha.2_1785892989004_0.7619426397371678","host":"s3://npm-registry-packages-npm-production"}},"0.1.0-alpha.3":{"name":"@blazing-customs/ppx-client","version":"0.1.0-alpha.3","keywords":["ppx","preference-profile-exchange","oauth","consent","mcp","a2a","ag-ui","agents","ai"],"author":{"name":"Blazing Customs"},"license":"Apache-2.0","_id":"@blazing-customs/ppx-client@0.1.0-alpha.3","maintainers":[{"name":"coolblaze03","email":"chabli.boler@gmail.com"}],"homepage":"https://blazing-customs.github.io/ppx-spec/","dist":{"shasum":"9103f181c742da6d4132b47098a8cc48c3928bc4","tarball":"https://registry.npmjs.org/@blazing-customs/ppx-client/-/ppx-client-0.1.0-alpha.3.tgz","fileCount":31,"integrity":"sha512-sCty1yU9M9vSfASarBaV39SBOXf3Y+gVU1n+fxO043efEeiHgyAe1vrxKdtj1HfQCArMRCtUVR9J+hEcxLVZlA==","signatures":[{"sig":"MEYCIQCD2yocDecNGwgK2KGWsKqPBO6Amerg09VnLBDD9uWkgAIhANzVPEyCmdRsBJrEUmQT+bFznCbANsNbtqcF9Xjb5kuC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":68387},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.17.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"833bcc12381a7a58d3bff1c0fcd18ec23cce0be1","scripts":{"lint":"tsc --noEmit","test":"npm run build && node --test test/*.test.mjs","build":"tsc","clean":"rm -rf dist","watch":"tsc --watch"},"_npmUser":{"name":"coolblaze03","email":"chabli.boler@gmail.com"},"deprecated":"Calls /v1/profile/me, which no provider serves. Use 0.1.0-alpha.4.","_npmVersion":"10.8.2","description":"TypeScript client for the Preference Profile Exchange (PPX) reference provider and any conformant implementation.","directories":{},"_nodeVersion":"20.20.2","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/ppx-client_0.1.0-alpha.3_1785894432654_0.07117948594699341","host":"s3://npm-registry-packages-npm-production"}},"0.1.0-alpha.4":{"name":"@blazing-customs/ppx-client","version":"0.1.0-alpha.4","keywords":["ppx","preference-profile-exchange","oauth","consent","mcp","a2a","ag-ui","agents","ai"],"author":{"name":"Blazing Customs"},"license":"Apache-2.0","_id":"@blazing-customs/ppx-client@0.1.0-alpha.4","maintainers":[{"name":"coolblaze03","email":"chabli.boler@gmail.com"}],"homepage":"https://blazing-customs.github.io/ppx-spec/","dist":{"shasum":"7c4bb40b6218659734ad58d47d7874b5cdde0989","tarball":"https://registry.npmjs.org/@blazing-customs/ppx-client/-/ppx-client-0.1.0-alpha.4.tgz","fileCount":31,"integrity":"sha512-tbzZDF+fSWyMJiSy7M4w0VSEU6D3yrb3xOXfCAIfgQ2RdVUfBWg/q46d4RF5CDyMC/0aKEAoYKV4MhPpIyq2SA==","signatures":[{"sig":"MEUCIAV03ttSpdBaaY1wseuMlpxP5TzV85XcCti9QvBqDbyNAiEAiVYViA/KFR/xic+snKJodRNKQueEB+IRSKnSKr7+mGU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":69131},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=18.17.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"1792559ce7c3fbedef14f83fde8c83a1804b26e2","scripts":{"lint":"tsc --noEmit","test":"npm run build && node --test test/*.test.mjs","build":"tsc","clean":"rm -rf dist","watch":"tsc --watch"},"_npmUser":{"name":"coolblaze03","email":"chabli.boler@gmail.com"},"_npmVersion":"10.8.2","description":"TypeScript client for the Preference Profile Exchange (PPX) reference provider and any conformant implementation.","directories":{},"_nodeVersion":"20.20.2","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0"},"_npmOperationalInternal":{"tmp":"tmp/ppx-client_0.1.0-alpha.4_1785896832215_0.9602257376470202","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-07-30T21:18:23.624Z","modified":"2026-08-05T02:27:50.635Z","0.1.0-alpha.0":"2026-07-30T21:18:23.958Z","0.1.0-alpha.1":"2026-07-30T21:20:21.633Z","0.1.0-alpha.2":"2026-08-05T01:23:09.149Z","0.1.0-alpha.3":"2026-08-05T01:47:12.808Z","0.1.0-alpha.4":"2026-08-05T02:27:12.360Z"},"author":{"name":"Blazing Customs"},"license":"Apache-2.0","homepage":"https://blazing-customs.github.io/ppx-spec/","keywords":["ppx","preference-profile-exchange","oauth","consent","mcp","a2a","ag-ui","agents","ai"],"description":"TypeScript client for the Preference Profile Exchange (PPX) reference provider and any conformant implementation.","maintainers":[{"name":"coolblaze03","email":"chabli.boler@gmail.com"}],"readme":"# @blazing-customs/ppx-client\n\n> TypeScript client for the [Preference Profile Exchange (PPX)](https://blazing-customs.github.io/ppx-spec/)\n> reference provider and any conformant implementation.\n\n## Install\n\n```bash\nnpm i @blazing-customs/ppx-client\n```\n\nRequires Node 18.17+. Published version: **0.1.0-alpha.1** ([npm](https://www.npmjs.com/package/@blazing-customs/ppx-client)).\n\n> Alpha, tracking a **draft** specification. Expect breaking changes.\n\nRequires Node 18+ or a modern browser (uses `fetch` and `EventSource`/streams).\n\n## Quick start\n\n```ts\nimport { PpxClient, consentRedirectUrl, generatePkce } from \"@blazing-customs/ppx-client\";\n\nconst ppx = new PpxClient({ baseUrl: \"https://api.provider.app\" });\n\n// 1. Request a scoped grant. PKCE is mandatory and S256-only; keep the\n//    verifier in sessionStorage (tab-scoped) — it is sent only in step 3.\nconst pkce = await generatePkce();\n\nconst { grant_request_id, request_token } = await ppx.requestGrant({\n  client_id: \"my-app\",\n  subject_id: \"did:example:user-123\",\n  purposes: [\"recommendation\"],\n  allowed_domains: [\"fragrance\"],\n  allowed_namespaces: [\"fragrance\"],\n  allowed_operations: [\"read\"],\n  cross_domain_transfer: \"deny\",\n  writeback_policy: \"review_required\",\n  requested_duration_days: 30,\n  code_challenge: pkce.challenge,\n  code_challenge_method: \"S256\",\n  // Matched EXACTLY against what you registered. No longer a query parameter\n  // on the consent URL, so it cannot be rewritten in transit.\n  redirect_uri: window.location.origin + \"/callback\",\n});\n\n// `request_token` is the capability, returned ONCE. Stash it with the verifier\n// for the round trip; never put either in a URL.\nsessionStorage.setItem(\n  \"ppx.pending\",\n  JSON.stringify({ grant_request_id, request_token, verifier: pkce.verifier }),\n);\n\n// 2. Send the user to the provider's consent screen. This URL is safe to treat\n//    as public: the id in it exchanges for nothing on its own.\nwindow.location.href = consentRedirectUrl(\"https://app.provider.app\", grant_request_id);\n\n// 3. In your callback page, exchange. The id alone is NOT enough.\nconst pending = JSON.parse(sessionStorage.getItem(\"ppx.pending\")!);\nsessionStorage.removeItem(\"ppx.pending\"); // one shot\nconst tok = await ppx.mintToken(\n  pending.grant_request_id,\n  pending.request_token,\n  pending.verifier,\n  \"my-app\",\n);\n\n// 4. Use the token to read scoped claims\nconst profile = await ppx.effectiveProfile(\n  { context: { climate: \"hot_humid\" }, requested_namespaces: [\"fragrance\"] },\n  tok.access_token,\n);\n```\n\n## Grant re-use (skip the consent flow on return visits)\n\n```ts\n// Cache the grant_id in localStorage on first approval\nlocalStorage.setItem(\"my-app.grant\", tok.grant_id);\n\n// On return visits, re-mint without any user interaction\nconst cached = localStorage.getItem(\"my-app.grant\");\nif (cached) {\n  try {\n    const fresh = await ppx.refresh(\"my-app\", cached);\n    // use fresh.access_token\n  } catch (err) {\n    if (err instanceof PpxGrantRevokedError) {\n      localStorage.removeItem(\"my-app.grant\"); // → fall back to full flow\n    } else throw err;\n  }\n}\n```\n\n## Live consent events (AG-UI)\n\nThe provider streams AG-UI events during consent review. Subscribe to\nrender explanation text, state snapshots, and interrupts live:\n\n```ts\nconst unsub = ppx.onConsentEvents(grant_request_id, {\n  STATE_SNAPSHOT: (e) => render(e.data),\n  TEXT_MESSAGE_CONTENT: (e) => appendExplanation(e.delta),\n  INTERRUPT: (e) => showApproveReject(e.data),\n  TOOL_CALL_RESULT: (e) => (grantUrn = e.result.grant_urn),\n});\n\n// later\nunsub();\n```\n\n## Surface reference\n\nThe client wraps every v1 endpoint on the reference provider.\n\n| Method | Endpoint | Auth |\n| --- | --- | --- |\n| `discoveryCard()` | `GET /.well-known/ppx-card.json` | none |\n| `grantJwks()` | `GET /.well-known/ppx-grant-jwks.json` | none |\n| `requestGrant(…)` | `POST /v1/consent/request` | none |\n| `getGrantRequest(id)` | `GET /v1/consent/request/{id}` | none |\n| `mintToken(id, requestToken, verifier, clientId, clientSecret?)` | `POST /v1/consent/token` | none |\n| `refresh(client, grant)` | `POST /v1/consent/refresh` | none |\n| `listGrants()` | `GET /v1/consent/grants` | user |\n| `revokeGrant(id)` | `POST /v1/consent/revoke` | user |\n| `auditEvents(…)` | `GET /v1/audit/events` | user |\n| `myProfile()` | `GET /v1/profile/export` | user |\n| `profileSummary()` | `GET /v1/profile/summary` | grant |\n| `queryClaims(…)` | `POST /v1/profile/query` | grant |\n| `effectiveProfile(…)` | `POST /v1/profile/effective` | grant |\n| `proposeUpdates(…)` | `POST /v1/profile/propose-updates` | grant |\n| `listExtensions()` | `GET /v1/extensions` | none |\n| `onConsentEvents(id, h)` | `GET /v1/ag-ui/consent/{id}` (SSE) | none |\n\n## Errors\n\nAll non-2xx responses throw `PpxError` with `.status`, `.body`, `.url`.\n`410 Gone` throws the subclass `PpxGrantRevokedError` — the idiomatic\nsignal to clear a cached `grant_id` and prompt for re-approval.\n\n## License\n\nApache-2.0.\n","readmeFilename":"README.md"}