@xkova/sdk 0.1.0-alpha.1

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.
Files changed (76) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +453 -0
  3. package/dist/abi.d.ts +10288 -0
  4. package/dist/abi.js +6645 -0
  5. package/dist/client.d.ts +80 -0
  6. package/dist/client.js +251 -0
  7. package/dist/cursor.d.ts +21 -0
  8. package/dist/cursor.js +28 -0
  9. package/dist/errors.d.ts +31 -0
  10. package/dist/errors.js +63 -0
  11. package/dist/generated/types.d.ts +13371 -0
  12. package/dist/generated/types.js +3 -0
  13. package/dist/idempotency.d.ts +25 -0
  14. package/dist/idempotency.js +46 -0
  15. package/dist/index.d.ts +11 -0
  16. package/dist/index.js +8 -0
  17. package/dist/member-action-intents.d.ts +72 -0
  18. package/dist/member-action-intents.js +181 -0
  19. package/dist/member-bff.d.ts +535 -0
  20. package/dist/member-bff.js +1594 -0
  21. package/dist/member-resources.d.ts +203 -0
  22. package/dist/member-resources.js +56 -0
  23. package/dist/request-signing.d.ts +23 -0
  24. package/dist/request-signing.js +112 -0
  25. package/dist/resources/account-holders.d.ts +295 -0
  26. package/dist/resources/account-holders.js +166 -0
  27. package/dist/resources/base.d.ts +47 -0
  28. package/dist/resources/base.js +25 -0
  29. package/dist/resources/branding.d.ts +154 -0
  30. package/dist/resources/branding.js +34 -0
  31. package/dist/resources/chains.d.ts +6 -0
  32. package/dist/resources/chains.js +6 -0
  33. package/dist/resources/contacts.d.ts +55 -0
  34. package/dist/resources/contacts.js +22 -0
  35. package/dist/resources/escrows.d.ts +45 -0
  36. package/dist/resources/escrows.js +18 -0
  37. package/dist/resources/fee-schedules.d.ts +40 -0
  38. package/dist/resources/fee-schedules.js +15 -0
  39. package/dist/resources/index.d.ts +21 -0
  40. package/dist/resources/index.js +21 -0
  41. package/dist/resources/integration-gateways.d.ts +114 -0
  42. package/dist/resources/integration-gateways.js +27 -0
  43. package/dist/resources/onboarding.d.ts +18 -0
  44. package/dist/resources/onboarding.js +9 -0
  45. package/dist/resources/payment-requests.d.ts +115 -0
  46. package/dist/resources/payment-requests.js +27 -0
  47. package/dist/resources/payments.d.ts +182 -0
  48. package/dist/resources/payments.js +33 -0
  49. package/dist/resources/ramps.d.ts +163 -0
  50. package/dist/resources/ramps.js +44 -0
  51. package/dist/resources/rwa.d.ts +397 -0
  52. package/dist/resources/rwa.js +150 -0
  53. package/dist/resources/tenant.d.ts +136 -0
  54. package/dist/resources/tenant.js +42 -0
  55. package/dist/resources/tokenization.d.ts +394 -0
  56. package/dist/resources/tokenization.js +126 -0
  57. package/dist/resources/transactions.d.ts +8 -0
  58. package/dist/resources/transactions.js +6 -0
  59. package/dist/resources/wallets.d.ts +56 -0
  60. package/dist/resources/wallets.js +21 -0
  61. package/dist/resources/webhooks.d.ts +115 -0
  62. package/dist/resources/webhooks.js +43 -0
  63. package/dist/resources/workflows.d.ts +44 -0
  64. package/dist/resources/workflows.js +70 -0
  65. package/dist/resources/workspace-tokens.d.ts +6 -0
  66. package/dist/resources/workspace-tokens.js +6 -0
  67. package/dist/resources/workspaces.d.ts +25 -0
  68. package/dist/resources/workspaces.js +12 -0
  69. package/dist/retry.d.ts +21 -0
  70. package/dist/retry.js +44 -0
  71. package/dist/rwa-verify.d.ts +50 -0
  72. package/dist/rwa-verify.js +159 -0
  73. package/dist/webhook.d.ts +24 -0
  74. package/dist/webhook.js +56 -0
  75. package/llms.txt +84 -0
  76. package/package.json +62 -0
package/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,453 @@
1
+ # @xkova/sdk
2
+
3
+ TypeScript client for the XKOVA API. Use it on your server to manage account
4
+ holders, wallets, payments, tokenization, and other customer resources.
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npm install @xkova/sdk@0.1.0-alpha.1
10
+ ```
11
+
12
+ Requires Node.js 22 or newer. Keep this package and your API keys on the server.
13
+
14
+ For a web application with signed-in account holders, use the included
15
+ `@xkova/sdk/member-bff` helper to manage sessions in your backend for frontend
16
+ (BFF). The optional `@xkova/browser` package calls that BFF from the browser.
17
+
18
+ ## Create a client
19
+
20
+ ```ts
21
+ import { XKOVAClient } from '@xkova/sdk';
22
+
23
+ const xkova = XKOVAClient.forTenant({
24
+ baseUrl: 'https://sandbox-api.xkova.com',
25
+ apiKey: process.env.XKOVA_API_KEY!,
26
+ timeoutMs: 10_000,
27
+ });
28
+
29
+ const chains = await xkova.chains.listAvailable();
30
+ const assets = await xkova.workspaceTokens.list();
31
+ ```
32
+
33
+ Create one client per workspace API key. The key determines the tenant,
34
+ workspace, and environment. You can pass an API origin or a URL ending in `/v1`.
35
+ Failed API requests throw `XKOVAApiError`.
36
+
37
+ ## Production request signing
38
+
39
+ Production writes require your bearer API key and an active signing credential
40
+ registered to the same API principal. Supply the credential ID, algorithm, and
41
+ a callback to your key provider:
42
+
43
+ ```ts
44
+ import { XKOVAClient, type XKOVARequestSignInput } from '@xkova/sdk';
45
+
46
+ async function signWithCustomerKey(input: XKOVARequestSignInput): Promise<Uint8Array> {
47
+ // Adapt this call to your KMS or HSM. Return signature bytes, not base64 text.
48
+ return customerKeyProvider.sign(input);
49
+ }
50
+
51
+ const production = XKOVAClient.forTenant({
52
+ baseUrl: 'https://api.xkova.com',
53
+ apiKey: process.env.XKOVA_API_KEY!,
54
+ requestSigner: {
55
+ credentialId: process.env.XKOVA_SIGNING_CREDENTIAL_ID!,
56
+ algorithm: 'ecdsa-p256-sha256',
57
+ sign: signWithCustomerKey,
58
+ },
59
+ });
60
+ ```
61
+
62
+ The private key stays with your key provider. The callback must return:
63
+
64
+ | Algorithm | Signature format |
65
+ | ------------------- | ------------------------------------------------------ |
66
+ | `ecdsa-p256-sha256` | 64-byte IEEE P1363 |
67
+ | `ed25519` | 64 bytes |
68
+ | `rsa-pss-sha256` | RSA-PSS with SHA-256, MGF1 SHA-256, and a 32-byte salt |
69
+
70
+ The optional `lifetimeSeconds` accepts an integer from 30 to 60; the default is 45. The registered credential determines the algorithm. XKOVA omits the RFC
71
+ 9421 `alg` parameter because that RFC has no `rsa-pss-sha256` identifier.
72
+
73
+ The SDK sets `Signature-Input` and `Signature` using RFC 9421. Requests with a
74
+ body also receive an RFC 9530 SHA-256 `Content-Digest`. The signature covers the
75
+ destination, path, query, authorization, body metadata, idempotency key, and
76
+ XKOVA routing and member headers. The SDK serializes the body once, so it signs
77
+ the same bytes it sends.
78
+
79
+ Send signed requests to the configured public API origin. A proxy that changes
80
+ the `Host` authority will cause signature verification to fail.
81
+
82
+ A production write fails before sending if no signer is configured. Production
83
+ reads use bearer authentication. Sandbox requests need the API key; sandbox
84
+ writes are signed only when you configure `requestSigner`.
85
+
86
+ Each call gets a fresh nonce and signature. To retry a write, call the method
87
+ again with the same idempotency key and unchanged input. Manage signing
88
+ credentials in the Console.
89
+
90
+ Key rotation requires proof of possession of the successor key. Activation
91
+ allows five minutes of overlap with the previous key. Each credential can have
92
+ one live successor; either key can be revoked immediately.
93
+
94
+ ## Typed resources
95
+
96
+ Call resource methods with typed inputs:
97
+
98
+ ```ts
99
+ const quote = await xkova.payments.quote(
100
+ {
101
+ account_holder_id: 'ah_...',
102
+ from_wallet_id: 'wlt_...',
103
+ to_address: '0x...',
104
+ token_deployment_id: '...',
105
+ gross_amount: '25.00',
106
+ },
107
+ { idempotencyKey: crypto.randomUUID() },
108
+ );
109
+
110
+ const contacts = await xkova.contacts.list({ limit: 25 });
111
+ const paymentRequests = await xkova.paymentRequests.list({ limit: 25 });
112
+ ```
113
+
114
+ Writes accept an optional caller-provided `idempotencyKey`. Reuse the same key when retrying the same logical request. If omitted, the SDK generates a new key for that individual call.
115
+
116
+ Account-holder `self` methods require a member session and its application's
117
+ publishable key. Load both from your BFF's session store. These methods act on
118
+ the signed-in account holder; browser input cannot select a different person:
119
+
120
+ ```ts
121
+ const balance = await xkova.accountHolders.selfBalance({
122
+ memberSessionId: session.sessionId,
123
+ memberAuthPublishableKey: session.applicationData.memberAuthPublishableKey,
124
+ });
125
+ ```
126
+
127
+ ## Register a Hosted Auth application
128
+
129
+ Hosted Auth provides an optional XKOVA-hosted sign-in flow. Register an
130
+ application against an existing API principal in the same workspace, then add
131
+ its exact origin and callback URL:
132
+
133
+ ```ts
134
+ const application = await xkova.tenant.createHostedApplication({
135
+ api_key_id: 'key_1A2b3C4d5E6f7G8h9I0jK1',
136
+ name: 'Acme Member App',
137
+ enrollment_mode: 'invite_only',
138
+ is_default: true,
139
+ });
140
+
141
+ await xkova.tenant.createAllowedOrigin({
142
+ application_id: application.id,
143
+ origin: 'https://app.example.com',
144
+ });
145
+
146
+ await xkova.tenant.createRedirectUrl({
147
+ application_id: application.id,
148
+ purpose: 'authorization_result',
149
+ url: 'https://app.example.com/api/auth/callback',
150
+ });
151
+
152
+ const applications = await xkova.tenant.listMemberAuthApplications();
153
+ await xkova.tenant.updateHostedApplication(application.id, {
154
+ enrollment_mode: 'open',
155
+ });
156
+ await xkova.tenant.disableHostedApplication(application.id);
157
+ ```
158
+
159
+ The response includes a publishable key that identifies the application. It is
160
+ not a secret and grants no authority on its own. You control the name,
161
+ enrollment policy, default selection, allowed origins, callbacks, and enabled
162
+ state. XKOVA manages the Hosted identity provider.
163
+
164
+ ## Member BFF integration
165
+
166
+ Use `@xkova/sdk/member-bff` to manage account-holder authentication and sessions:
167
+
168
+ ```ts
169
+ import { XKOVAMemberBffClient, serializeXKOVAMemberSessionCookie } from '@xkova/sdk/member-bff';
170
+
171
+ const memberAuth = new XKOVAMemberBffClient({
172
+ baseUrl: process.env.XKOVA_API_URL!,
173
+ apiKey: process.env.XKOVA_API_KEY!,
174
+ publishableKey: process.env.XKOVA_PUBLISHABLE_KEY!,
175
+ requestSigner,
176
+ });
177
+
178
+ const start = await memberAuth.beginHostedAuthorization({
179
+ browserOrigin: 'https://app.example.com',
180
+ redirectUri: 'https://app.example.com/api/auth/callback',
181
+ transactionStore,
182
+ });
183
+
184
+ // Redirect only to start.authorizationUrl. Store start.state in the
185
+ // short-lived SameSite=Lax flow cookie, then recover it at callback.
186
+ const established = await memberAuth.completeHostedAuthorization({
187
+ callbackUrl: request.url,
188
+ expectedState: flowCookieState,
189
+ transactionStore,
190
+ sessionStore,
191
+ applicationData: {},
192
+ });
193
+ ```
194
+
195
+ For your own OIDC provider, use `beginAuthorization` and
196
+ `completeAuthorizationCallback`. Your BFF exchanges the provider's authorization
197
+ code unless your integration explicitly assigns that exchange to XKOVA. Both
198
+ sign-in paths use the same XKOVA session and store contracts.
199
+
200
+ ### Sandbox demo sign-in
201
+
202
+ For a sandbox application explicitly enabled for demo sign-in, call
203
+ `completeSandboxDemoAuthorization({ state: start.state, transactionStore })`
204
+ after `beginHostedAuthorization`. The SDK obtains the capability and exact
205
+ callback from the server-held transaction, validates the returned callback and
206
+ expiry, and returns `{ callbackUrl, expiresAt }`. Complete that callback through
207
+ `completeHostedAuthorization` with the original browser flow cookie. The API
208
+ reserves a demo account for the session. This operation is not
209
+ available to ordinary tenant applications or production workspaces, and it
210
+ accepts no member, email, wallet, or callback selector.
211
+
212
+ Keep the same pending reservation and transaction after an ambiguous admission
213
+ failure. Repeating the method uses the same idempotency key and recovers the
214
+ same demo account reservation. The method never retries automatically.
215
+ `isDefinitiveXKOVASandboxDemoAdmissionFailure(error)` identifies confirmed
216
+ rejection before an account was reserved; network, malformed-response, and
217
+ unknown server failures can leave the reservation outcome uncertain.
218
+ API errors retain their status, correlation ID, and Retry-After. Both admission
219
+ and session requests reject HTTP redirects.
220
+
221
+ ### Stores and callback recovery
222
+
223
+ The helper creates state, nonce, and PKCE values, validates callbacks, exchanges
224
+ proofs, and manages session refresh and logout. Implement its session,
225
+ authorization-transaction, and direct proof-exchange store contracts in your
226
+ own database. It does not include a web framework or database adapter.
227
+
228
+ Authorization, Account Center, and action transactions expire within ten
229
+ minutes of starting the request, or at the server's expiry if sooner. Late,
230
+ expired, or excessively long-lived responses are rejected. Keep your BFF's
231
+ clock synchronized so it can validate these deadlines.
232
+
233
+ After your authorization store persists `stagedProviderExchange`, repeating
234
+ the same callback reuses the stored proof, exchange attempt, and session
235
+ reference. It does not redeem the provider code again. Keep completed records
236
+ until their expiry so a lost response or store acknowledgement can recover the
237
+ session that was already created.
238
+
239
+ Before that record is stored, a lost provider response or store acknowledgement
240
+ may cause another call to `exchangeProviderCode`. Your provider adapter must
241
+ resolve that uncertainty or reject the attempt and start a new authorization
242
+ transaction. For later recoverable failures, preserve the flow cookie and
243
+ transaction. `XKOVAMemberAuthorizationTerminalError` means the transaction
244
+ cannot continue.
245
+
246
+ Recovery records bind the API origin, principal, and application. A shared store
247
+ can serve several applications, but one client cannot resume another's records.
248
+
249
+ If `exchangeProviderCode` returns a separate `nonceToken`, validate its JOSE
250
+ signature, issuer, audience, algorithm, expiry, and nonce first. The helper only
251
+ compares its nonce claim; XKOVA cannot validate a token it never receives.
252
+
253
+ To exchange a proof without a browser callback, call `establishSession` with an
254
+ `XKOVAMemberProofExchangeTransactionStore`, a session store, and a stable
255
+ `exchangeId`. Persist that ID before the first attempt and reuse it on retries.
256
+ The store serializes attempts and preserves the exchange and session references.
257
+
258
+ ### Account Center and action callbacks
259
+
260
+ Account Center accepts a same-origin `applicationReturnUri` and preserves it
261
+ through successful callback recovery. Member actions separately accept
262
+ `applicationReviewUri` for cancellation or expiry and `applicationReturnUri`
263
+ for the signing-completion destination. The exact resource and review location
264
+ stay in the confidential transaction. Callback query parameters cannot override
265
+ them. Terminal errors expose a stored review location only after validating the
266
+ client fingerprint and exact callback; missing transactions have no trusted
267
+ return location. They must use a neutral result screen, not guess an action.
268
+
269
+ Use `xkovaMemberFlowCookieName(prefix, state)` when setting the short-lived
270
+ HttpOnly Lax cookie and `readXKOVAMemberCallbackFlow()` when receiving the callback.
271
+ Each ceremony gets a distinct cookie, so concurrent tabs do not replace one
272
+ another's binding. Clear only the returned `cookieName` on completion or a
273
+ terminal error. Preserve both the cookie and durable transaction after a
274
+ recoverable failure. Never clear the ordinary application-session cookie just
275
+ because an action failed. These helpers do not themselves persist unfinished
276
+ form input or deduplicate business-resource creation.
277
+
278
+ ### Save and recover a payment review
279
+
280
+ Use `resolveActionIntents({ reference, sessionStore, intentStore })` to preserve
281
+ a review across reloads and authentication steps. The manager is bound to the
282
+ principal, application, member, and opaque application session. Its `create()`
283
+ stores a frozen typed payment, escrow, or payment-request approval plus reviewed
284
+ form fields and an exact same-origin review URI. It creates no business resource.
285
+ `read()` restores that review. Explicit `prepare()` serializes across replicas,
286
+ uses one stable creation idempotency key, and persists the resulting resource.
287
+ An ambiguous create/store acknowledgement can retry the identical request with
288
+ that same key. A changed request is a conflict, not a replacement. Signing and
289
+ execution remain separate, freshly authorized operations.
290
+
291
+ Generate the public review reference once with `createMemberActionReference()`
292
+ from `@xkova/browser`. It contains a six-byte millisecond creation time and 26
293
+ random bytes, encoded as 43 base64url characters. It grants no authority. The
294
+ server enforces one-hour expiry and at most five minutes of future clock skew.
295
+ Even after complete store loss, the same old reference cannot restart after the
296
+ API's 24-hour idempotency window. The store must encrypt review payloads at rest,
297
+ serialize each reference across replicas, and retain records through
298
+ `retainUntil` (the application session), not just the shorter review expiry.
299
+ Expired references return 410. Unknown or differently bound reviews return 404.
300
+ Do not silently create a new reference after either result; ask the person to
301
+ check activity and explicitly start a separate review.
302
+
303
+ ### Authorize an action
304
+
305
+ For payment, escrow, or member approval signing, use
306
+ `beginMemberAction()` and `completeMemberAction()` from the BFF helper. The
307
+ begin result selects the registered method: a Hosted application redirects to
308
+ the branded Account Center passkey ceremony. Your own OIDC integration receives
309
+ the required issuer, audience, nonce, maximum authentication age, ACR, and AMR
310
+ requirements for a fresh provider proof. Completion exchanges the one-use
311
+ result into a signing projection. The BFF then calls
312
+ `exchangeMemberActionSigningCode()` server-side and sets the returned opaque
313
+ signing session only on XKOVA's controlled signing surface. Do not place the
314
+ exchange code, member session, provider proof, or wallet signing credentials in
315
+ browser-accessible storage.
316
+
317
+ ### Call resources for the signed-in member
318
+
319
+ Validate the browser's exact Origin and session-bound CSRF token in your BFF
320
+ before handling a mutation. Resolve the session for each request:
321
+
322
+ ```ts
323
+ const resolved = await memberAuth.resolveResources({ reference, sessionStore });
324
+ if (!resolved) return new Response('Sign in required', { status: 401 });
325
+ const readiness = await resolved.resources.self.walletReadiness();
326
+ const security = await resolved.resources.self.actionReadiness();
327
+ const payment = await resolved.resources.payments.retrieve('pay_...');
328
+ ```
329
+
330
+ `self.actionReadiness()` reports passkey enrollment, recovery steps, or OIDC
331
+ setup without calling the provider or creating an action. Refresh it after
332
+ Account Center or credential changes. `requires_fresh_proof` stays true and
333
+ `provider_status` is `not_checked`: readiness describes setup, not approval or
334
+ provider health. Ownership, policy, quorum, and settlement still need their
335
+ own checks. A failed read must not enable an action.
336
+
337
+ `resolveResources` refreshes and validates the session, then binds every call
338
+ to its principal, application, and account holder. It rejects conflicting
339
+ session headers and actor overrides before sending. Resolve it for each BFF
340
+ request; do not cache it or send it to the browser. API scopes, roles, ownership,
341
+ revocation, and fresh authorization checks still apply.
342
+
343
+ Business requests use `no-store` and reject redirects so credentials cannot
344
+ follow a redirect. Network failures preserve the application session. Reuse the
345
+ original idempotency key when reconciling an uncertain write.
346
+
347
+ `resolved.resources.self.verification()` returns the member's verification
348
+ requirements and sessions through the public self-verification operation.
349
+ `resolved.resources.self.uploadAvatar(image)` performs presign, object upload,
350
+ confirmation, and refreshed avatar lookup. Pass a nonempty PNG, JPEG, WebP, or GIF
351
+ `Blob` of at most 5 MiB. Storage receives only the image bytes and their content
352
+ headers, never bearer credentials, request signatures, member context, or cookies.
353
+ The helper rejects redirects, expired capabilities, URL credentials, and non-HTTPS
354
+ storage URLs (localhost HTTP is permitted for local development). It does not
355
+ retry an upload. `XKOVAUploadError` identifies the object-storage stage without
356
+ exposing the signed URL; API failures retain `XKOVAApiError` metadata.
357
+
358
+ In sandbox, `resolved.resources.self.sandboxBankingContext()` returns the
359
+ member's simulated bank account and funding references. Keep them server-side
360
+ and pass them to the funding and off-ramp methods. This read creates no accounts
361
+ and moves no money. It rejects a mismatched tenant and returns 404 in production.
362
+
363
+ ### Session storage and cookies
364
+
365
+ Your application owns the routes, identity-provider integration, database,
366
+ deployment, and store encryption. Authorization and proof-exchange records can
367
+ contain provider proofs; protect them like refresh credentials. Serialize
368
+ refresh and logout for each session reference across all BFF instances.
369
+
370
+ Durable application cookies use the host-only `__Host-` prefix, `Secure`, `HttpOnly`, `Path=/`, and `SameSite=Strict`. A separate short-lived `SameSite=Lax` flow cookie is available only for OAuth or OIDC callback state. Do not send the API key, provider proof, XKOVA session ID, refresh token, or provider credentials to browser SDK code.
371
+
372
+ The publishable key is a non-secret application registration identifier. It grants no member or tenant authority by itself. The registered application pins tenant, workspace, environment, provider kind, issuer, audience, origins, redirects, and session policy, and must also match the authenticated workspace principal.
373
+
374
+ ## Cancellation and deadlines
375
+
376
+ Set `timeoutMs` on the client for a default request deadline. Mutation options and workflow polling also accept an `AbortSignal`:
377
+
378
+ ```ts
379
+ const controller = new AbortController();
380
+
381
+ await xkova.payments.cancel('pay_...', {
382
+ idempotencyKey: crypto.randomUUID(),
383
+ signal: controller.signal,
384
+ });
385
+ ```
386
+
387
+ The SDK does not automatically retry writes. Use `withRetry` with a stable idempotency key when retry behavior is appropriate for your application.
388
+
389
+ ## Errors
390
+
391
+ `XKOVAApiError.retryAfter` preserves the upstream `Retry-After` header when
392
+ present. A BFF should forward valid retry guidance with the original status and
393
+ correlation ID. This is response metadata, not automatic mutation retry.
394
+
395
+ ```ts
396
+ import { XKOVAApiError } from '@xkova/sdk/errors';
397
+
398
+ try {
399
+ await xkova.payments.retrieve('pay_...');
400
+ } catch (error) {
401
+ if (error instanceof XKOVAApiError) {
402
+ console.error(error.code, error.correlationId);
403
+ }
404
+ throw error;
405
+ }
406
+ ```
407
+
408
+ ## Webhooks and generated types
409
+
410
+ ```ts
411
+ import { verifyWebhookSignature } from '@xkova/sdk/webhook';
412
+ import type { components, paths } from '@xkova/sdk/types';
413
+ ```
414
+
415
+ Pass the raw request body to `verifyWebhookSignature`. The `types` subpath contains only the customer operations included in this SDK release.
416
+
417
+ The package also exposes `@xkova/sdk/rwa-verify` for offline RWA transparency proof verification and `@xkova/sdk/abi` for the documented customer contract ABIs.
418
+
419
+ ## Compatibility and documentation
420
+
421
+ This release targets API namespace `/v1` and Node.js 22+. See the
422
+ [XKOVA documentation](https://docs.xkova.com) for API and workflow guides. The
423
+ installed declarations list the methods in your version. Use the Console for
424
+ staff administration, API-key management, and signing-key registration.
425
+
426
+ ## Build with a coding assistant
427
+
428
+ Give your coding assistant the package-local [llms.txt](llms.txt), this README,
429
+ and the installed package declarations. The guide maps capabilities to resource
430
+ namespaces and explains authentication, production signing, member BFF stores,
431
+ idempotency, and settlement. It links the public customer OpenAPI and expanded
432
+ documentation. Installed declarations determine the methods available in your
433
+ version; live documentation may describe a newer release.
434
+
435
+ ## Thirdweb and dependencies
436
+
437
+ The only direct runtime dependency is `viem`, used for offline RWA signature
438
+ verification. This SDK does not import Thirdweb. The optional `@xkova/browser`
439
+ browser companion has no runtime dependencies. XKOVA manages wallet signing,
440
+ and API provider metadata may name Thirdweb. You do not need to install its SDK
441
+ or obtain Thirdweb credentials.
442
+
443
+ ## Contributing
444
+
445
+ Run `pnpm check` from the source repository root before committing. The
446
+ [contributor guide](https://github.com/XKOVA/typescript-sdk/blob/main/CONTRIBUTING.md)
447
+ covers generated files, local pre-push checks, writing rules, and packaging.
448
+
449
+ ## License
450
+
451
+ Copyright 2026 XKOVA LLC.
452
+
453
+ This package is licensed under the [Apache License, Version 2.0](LICENSE).