@zkp2p/zkp2p-attestation 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,7 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.0
4
+
5
+ - Expand buyer TEE SDK types from Venmo-only to all 15 server-registered platforms.
6
+ - Tie each buyer TEE platform to its valid `actionType`, metadata shape, and named session-material header map.
7
+ - Require documented buyer TEE session-material headers in the per-platform TypeScript types (e.g. Wise `Cookie` or `X-Access-Token`, Revolut `Cookie` and `x-device-id`). A payload missing the required headers is a type error at the call site.
8
+ - Export `AttestationOutput`, `BuyerTeeVerifier`, `/buyer/supported`, and service response types for callers.
9
+ - Add `verifyBuyerTeePayment()` and `uploadSellerCredential()` one-shot helpers that chain attest → encrypt → POST → unwrap and return a typed result.
10
+ - Enforce `timeoutMs` across buyer TEE verify and seller credential upload POST requests, including through response body reads so stalled streams abort.
11
+ - Preserve structured unsuccessful ServiceResponse details on SDK errors via a new `SERVICE_RESPONSE_ERROR` code carrying `details.responseObject` — enables UIs to consume Wise multi-profile `WISE_PROFILE_SELECTION_REQUIRED` payloads and any future business-logic 4xx.
12
+ - Reject successful ServiceResponse envelopes that omit a `responseObject` (defends against bad-deploy / proxy-rewrite cases that would otherwise resolve helpers with `undefined`).
13
+ - Add buyer TEE discriminated-union type tests for Wise metadata/action narrowing and Revolut header enforcement.
14
+ - Drop the deprecated `verifyingContract` from the new buyer TEE verify helper parameters; the server resolves it from `DEPLOYMENT_ENV`.
15
+ - Keep the internal service-response envelope out of the public SDK type exports.
16
+
3
17
  ## 1.1.0
4
18
 
19
+ - Add buyer TEE session-material encryption helpers.
5
20
  - Add platform-aware seller credential upload encryption.
6
21
  - Support Wise seller credential uploads with `platform: "wise"` and no top-level `payeeId`.
7
22
  - Preserve the existing payee-based upload shape for Venmo, Cash App, and PayPal.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @zkp2p/zkp2p-attestation
2
2
 
3
- Client-side verifier and encryptor for ZKP2P Nitro seller credential uploads.
3
+ Client-side verifier and encryptor for ZKP2P Nitro seller credential uploads and buyer TEE session-material requests.
4
4
 
5
5
  The package runs in Chrome MV3 service workers, browser DOM contexts, React Native with a Web Crypto polyfill, and Node >= 20. Library entrypoints use `fetch`, `SubtleCrypto`, `crypto.getRandomValues`, and `Uint8Array`; they do not import `node:*` modules or use `Buffer`.
6
6
 
@@ -57,6 +57,17 @@ await fetch(`${attestationServiceUrl}/seller/credentials/wise`, {
57
57
 
58
58
  This fetches `GET /attestation?nonce=...`, verifies the Nitro document to the pinned AWS root and PCR8, extracts the attested seller-upload RSA SPKI, and returns a compact JWE for `POST /seller/credentials/:platform`.
59
59
 
60
+ For the same flow without hand-rolling the POST:
61
+
62
+ ```ts
63
+ const credentialBundle = await nitro.uploadSellerCredential({
64
+ platform: "wise",
65
+ sessionMaterial: {
66
+ apiToken: "<wise-api-token>",
67
+ },
68
+ });
69
+ ```
70
+
60
71
  Venmo, Cash App, and PayPal still require a top-level `payeeId`; existing callers can keep using the same call shape:
61
72
 
62
73
  ```ts
@@ -66,6 +77,68 @@ const encryptedUpload = await nitro.createEncryptedSellerCredentialUpload({
66
77
  });
67
78
  ```
68
79
 
80
+ Buyer TEE requests use the same attested upload key and compact JWE envelope. The typed helper encrypts the captured
81
+ session material, posts `{ encryptedSessionMaterial, metadata, chainId, intent }` to
82
+ `POST /buyer/verify/:platform/:actionType`, unwraps the service envelope, and returns a typed `AttestationOutput`:
83
+
84
+ ```ts
85
+ const attestation = await nitro.verifyBuyerTeePayment({
86
+ platform: "venmo",
87
+ actionType: "transfer_venmo",
88
+ sessionMaterial: {
89
+ Cookie: "<captured-cookie-header>",
90
+ "User-Agent": "<captured-user-agent>",
91
+ },
92
+ metadata: { senderId: "<venmo-account-id>", index: 0 },
93
+ chainId,
94
+ intent,
95
+ });
96
+ ```
97
+
98
+ The helper is a thin wrapper over the existing wire format; callers can still hand-roll the final POST:
99
+
100
+ ```ts
101
+ const encryptedSessionMaterial = await nitro.createEncryptedBuyerTeeSessionMaterial({
102
+ platform: "wise",
103
+ actionType: "transfer_wise",
104
+ sessionMaterial: { "X-Access-Token": "<captured-token>" },
105
+ });
106
+
107
+ await fetch(`${attestationServiceUrl}/buyer/verify/wise/transfer_wise`, {
108
+ method: "POST",
109
+ headers: { "content-type": "application/json" },
110
+ body: JSON.stringify({
111
+ encryptedSessionMaterial,
112
+ metadata: { profileId: "41246868", transactionId: "123456789" },
113
+ chainId,
114
+ intent,
115
+ }),
116
+ });
117
+ ```
118
+
119
+ Buyer TEE platform matrix:
120
+
121
+ | Platform | `actionType` | Required session-material headers | Metadata fields |
122
+ |---|---|---|---|
123
+ | `venmo` | `transfer_venmo` | `Cookie` | `senderId`, `index` |
124
+ | `cashapp` | `transfer_cashapp` | `Cookie`, `x-csrf-token`, `x-device-name`, `x-request-signature`, `x-request-uuid`, `cash-web-request`, `x-web-device-info`, `x-web-context`, `x-bt-id` | `senderId`, `index` |
125
+ | `luxon` | `transfer_luxon` | `X-Auth-Token` | `transferId` |
126
+ | `monzo` | `transfer_monzo` | `Authorization` | `txId` |
127
+ | `n26` | `transfer_n26` | `Cookie`, `csrf-token` | `body`, `paymentId` |
128
+ | `wise` | `transfer_wise` | `Cookie` or `X-Access-Token` | `profileId`, `transactionId` |
129
+ | `revolut` | `transfer_revolut` | `Cookie`, `x-device-id` | `index`, `paymentId` |
130
+ | `idfc` | `transfer_idfc` | `Cookie` | `senderId`, `index` |
131
+ | `citi` | `transfer_zelle` | `Cookie` | `index`, optional `transactionId` |
132
+ | `chime` | `transfer_chime` | `Cookie` | `body` |
133
+ | `chase` | `transfer_zelle` | `Cookie`, `x-jpmc-channel`, `x-jpmc-csrf-token`, `Referer`, `Origin` | `index` |
134
+ | `bankofamerica` | `transfer_zelle` | `Cookie` | `index`, `confirmationNumber` |
135
+ | `mercadopago` | `transfer_mercadopago` | `Cookie` | `paymentId`, `urlParamsFrom` |
136
+ | `paypal` | `transfer_paypal` | `Cookie` | `index` |
137
+ | `alipay` | `transfer_alipay` | `Cookie` | `tradeNo` |
138
+
139
+ Per-platform session-material types require these headers using the canonical names shown above while still allowing
140
+ additional captured headers.
141
+
69
142
  ## Cache-Friendly Path
70
143
 
71
144
  ```ts
@@ -80,6 +153,19 @@ const encryptedUpload = await nitro.encryptSellerCredentialUpload({
80
153
  });
81
154
  ```
82
155
 
156
+ For buyer TEE flows with a cached attestation:
157
+
158
+ ```ts
159
+ const encryptedSessionMaterial = await nitro.encryptBuyerTeeSessionMaterial({
160
+ key: verified.attestedSellerUploadKey,
161
+ platform: "venmo",
162
+ actionType: "transfer_venmo",
163
+ sessionMaterial: {
164
+ Cookie: "<captured-cookie-header>",
165
+ },
166
+ });
167
+ ```
168
+
83
169
  The attested SPKI is stable within one enclave process. If the enclave restarts, cached keys become stale and upload decrypt will fail; fetch a fresh attestation for a new session.
84
170
 
85
171
  ## React Native Wiring
@@ -101,9 +187,13 @@ Any conforming `SubtleCrypto` works. The package does not require `Buffer`.
101
187
 
102
188
  ```ts
103
189
  import {
190
+ createEncryptedBuyerTeeSessionMaterial,
104
191
  createEncryptedSellerCredentialUpload,
192
+ encryptBuyerTeeSessionMaterial,
105
193
  encryptSellerCredentialUpload,
106
194
  fetchAndVerifyAttestation,
195
+ uploadSellerCredential,
196
+ verifyBuyerTeePayment,
107
197
  } from "@zkp2p/zkp2p-attestation";
108
198
  ```
109
199
 
@@ -4470,6 +4470,9 @@ function requireArray(value, label) {
4470
4470
  fail("PAYLOAD_FIELD_MISSING", `Attestation payload field ${label} must be an array`);
4471
4471
  }
4472
4472
 
4473
+ // src/timeout.ts
4474
+ var DEFAULT_TIMEOUT_MS = 1e4;
4475
+
4473
4476
  // src/trust/pins.ts
4474
4477
  var STAGING_PCR8 = "5636e3bd96f847cf12cfd9de7faa8cad0e6fa00962ce16ba185f8e5ea57105abb3cc9cc34f1e1e4de3444ceabcca7485";
4475
4478
  var PRODUCTION_PCR8 = "41a4ae0b9b96752cab5addb7d22689b3070e564e29f90a54316fa33fa38ea51387a6e887ea4f5a4b0cc34f69cea3f40e";
@@ -4518,7 +4521,6 @@ function findHostPin(hostPins, hostname) {
4518
4521
  }
4519
4522
 
4520
4523
  // src/fetchAndVerifyAttestation.ts
4521
- var DEFAULT_TIMEOUT_MS = 1e4;
4522
4524
  var DEFAULT_FRESHNESS_WINDOW_MS = 5 * 60 * 1e3;
4523
4525
  async function fetchAndVerifyAttestation(params) {
4524
4526
  const fetcher = resolveFetch(params.fetch);