@xkova/sdk 0.1.0-alpha.5 → 0.1.0-alpha.7

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/README.md CHANGED
@@ -124,6 +124,10 @@ const balance = await xkova.accountHolders.selfBalance({
124
124
  });
125
125
  ```
126
126
 
127
+ `selfBalance` can return a partial answer. A chain not known right now has no
128
+ entries in `balances` and a null `through_block` in `data_freshness`, so check
129
+ that before treating a missing token as zero or adding balances together.
130
+
127
131
  ## Register a Hosted Auth application
128
132
 
129
133
  Hosted Auth provides an optional XKOVA-hosted sign-in flow. Register an
@@ -216,6 +220,26 @@ proofs, and manages session refresh and logout. Implement its session,
216
220
  authorization-transaction, and direct proof-exchange store contracts in your
217
221
  own database. It does not include a web framework or database adapter.
218
222
 
223
+ `runExclusive` is an exclusivity boundary, not an all-or-nothing SQL
224
+ transaction. Every awaited `put`, `replace` and `delete` must commit before
225
+ returning, and remain committed if later callback work throws. Wrapping the
226
+ whole callback in a rollback transaction can erase a staged proof after its
227
+ one-time provider code was consumed. The same rule protects refresh-attempt
228
+ checkpoints. Reconcile an uncertain write acknowledgement using the exact
229
+ record and attempt identity, rather than starting a new operation.
230
+
231
+ The package includes [a PostgreSQL checkpoint-store example](examples/postgres-checkpoint-store.mjs)
232
+ and its [application-owned table definition](examples/postgres-checkpoints.sql).
233
+ Install `pg` in your backend and apply the table definition through your own
234
+ migration process. Instantiate separate stores with namespaces such as
235
+ `authorization`, `sessions` and `exchange`, one shared pool and an existing
236
+ 32-byte application encryption key. The example uses session advisory locks
237
+ across replicas, independent autocommit checkpoints, authenticated encryption
238
+ bound to namespace/reference, exact replacement without upsert, and connection
239
+ discard when lock release is uncertain. Do not use a transaction-pooling proxy
240
+ for session locks. Own key rotation, pool deadlines and expired-record cleanup
241
+ in your application; do not log records or encryption material.
242
+
219
243
  Authorization, Account Center, and action transactions expire within ten
220
244
  minutes of starting the request, or at the server's expiry if sooner. Late,
221
245
  expired, or excessively long-lived responses are rejected. Keep your BFF's
@@ -246,6 +270,51 @@ To exchange a proof without a browser callback, call `establishSession` with an
246
270
  `exchangeId`. Persist that ID before the first attempt and reuse it on retries.
247
271
  The store serializes attempts and preserves the exchange and session references.
248
272
 
273
+ ### Enroll an external identity-provider member
274
+
275
+ For a registered OIDC connection, the confidential backend can call
276
+ `memberAuth.enrollExternalMember({ externalSub, applicationConfigVersion,
277
+ idempotencyKey })`. Use the exact opaque subject from a fully verified provider
278
+ proof, the final read-back application configuration version, and one persisted
279
+ operation key. Never link by email. The API derives issuer namespace, tenant,
280
+ workspace and application from the registered connection and its bound
281
+ `member_auth` API principal. The header selector and body selector must match.
282
+ An existing issuer/subject membership is returned without replacing its identity,
283
+ status or wallet bindings. A held or closed member remains held or closed.
284
+
285
+ Enrollment creates or finds a membership, not an authenticated session or wallet.
286
+ The normal nonce-bound provider-proof exchange remains required. For callback
287
+ flows use `completeAuthorizationCallback`'s optional `ensureMemberEnrollment`
288
+ hook. It runs after the one-time provider proof is durably staged, with a stable
289
+ `idempotencyKey` preserved across retries. Verify the staged proof's signature,
290
+ issuer, audience, algorithm, expiry and nonce, then call `enrollExternalMember`
291
+ with its exact `sub`. Return that result from the hook. The helper checks that
292
+ the resulting authenticated session resolves to the enrolled account holder.
293
+ Do not put a fallible enrollment call inside `exchangeProviderCode`, before
294
+ the provider result has been staged. A version conflict requires reviewing the
295
+ changed registration and starting a new authorization flow, not blind retries.
296
+
297
+ ```ts
298
+ const completion = await memberAuth.completeAuthorizationCallback({
299
+ ...callbackInput,
300
+ ensureMemberEnrollment: async ({ proofToken, idempotencyKey }) => {
301
+ // This application function performs full JOSE and exact nonce validation.
302
+ const verified = await verifyRegisteredProviderProof(proofToken);
303
+ return memberAuth.enrollExternalMember({
304
+ externalSub: verified.sub,
305
+ applicationConfigVersion: registration.config_version,
306
+ idempotencyKey,
307
+ });
308
+ },
309
+ });
310
+ ```
311
+
312
+ The verifier and `registration` are application prerequisites in this example,
313
+ not SDK-provided provider validation or discovery functions. The public endpoint
314
+ is `POST /v1/member-auth/enrollments`; it accepts no caller-selected account
315
+ holder, tenant, issuer namespace, email or permissions. Enrollment alone never
316
+ qualifies fresh action assurance, signing authority or settlement.
317
+
249
318
  ### Account Center and action callbacks
250
319
 
251
320
  Account Center accepts a same-origin `applicationReturnUri` and preserves it
package/dist/abi.d.ts CHANGED
@@ -336,6 +336,14 @@ export declare const erc20XGaslessAbi: readonly [{
336
336
  readonly name: "";
337
337
  readonly type: "string";
338
338
  readonly internalType: "string";
339
+ }, {
340
+ readonly name: "";
341
+ readonly type: "uint8";
342
+ readonly internalType: "uint8";
343
+ }, {
344
+ readonly name: "";
345
+ readonly type: "address";
346
+ readonly internalType: "address";
339
347
  }, {
340
348
  readonly name: "";
341
349
  readonly type: "address";
@@ -362,6 +370,10 @@ export declare const erc20XGaslessAbi: readonly [{
362
370
  readonly name: "_symbol";
363
371
  readonly type: "string";
364
372
  readonly internalType: "string";
373
+ }, {
374
+ readonly name: "decimals_";
375
+ readonly type: "uint8";
376
+ readonly internalType: "uint8";
365
377
  }, {
366
378
  readonly name: "defaultAdmin";
367
379
  readonly type: "address";
@@ -370,6 +382,10 @@ export declare const erc20XGaslessAbi: readonly [{
370
382
  readonly name: "minter";
371
383
  readonly type: "address";
372
384
  readonly internalType: "address";
385
+ }, {
386
+ readonly name: "burner";
387
+ readonly type: "address";
388
+ readonly internalType: "address";
373
389
  }, {
374
390
  readonly name: "pauser";
375
391
  readonly type: "address";
@@ -1062,6 +1078,10 @@ export declare const erc20XGaslessAbi: readonly [{
1062
1078
  readonly type: "error";
1063
1079
  readonly name: "InvalidAddress";
1064
1080
  readonly inputs: readonly [];
1081
+ }, {
1082
+ readonly type: "error";
1083
+ readonly name: "InvalidDecimals";
1084
+ readonly inputs: readonly [];
1065
1085
  }, {
1066
1086
  readonly type: "error";
1067
1087
  readonly name: "InvalidImplementation";
@@ -5482,6 +5502,14 @@ export declare const tokenizationAbis: {
5482
5502
  readonly name: "";
5483
5503
  readonly type: "string";
5484
5504
  readonly internalType: "string";
5505
+ }, {
5506
+ readonly name: "";
5507
+ readonly type: "uint8";
5508
+ readonly internalType: "uint8";
5509
+ }, {
5510
+ readonly name: "";
5511
+ readonly type: "address";
5512
+ readonly internalType: "address";
5485
5513
  }, {
5486
5514
  readonly name: "";
5487
5515
  readonly type: "address";
@@ -5508,6 +5536,10 @@ export declare const tokenizationAbis: {
5508
5536
  readonly name: "_symbol";
5509
5537
  readonly type: "string";
5510
5538
  readonly internalType: "string";
5539
+ }, {
5540
+ readonly name: "decimals_";
5541
+ readonly type: "uint8";
5542
+ readonly internalType: "uint8";
5511
5543
  }, {
5512
5544
  readonly name: "defaultAdmin";
5513
5545
  readonly type: "address";
@@ -5516,6 +5548,10 @@ export declare const tokenizationAbis: {
5516
5548
  readonly name: "minter";
5517
5549
  readonly type: "address";
5518
5550
  readonly internalType: "address";
5551
+ }, {
5552
+ readonly name: "burner";
5553
+ readonly type: "address";
5554
+ readonly internalType: "address";
5519
5555
  }, {
5520
5556
  readonly name: "pauser";
5521
5557
  readonly type: "address";
@@ -6208,6 +6244,10 @@ export declare const tokenizationAbis: {
6208
6244
  readonly type: "error";
6209
6245
  readonly name: "InvalidAddress";
6210
6246
  readonly inputs: readonly [];
6247
+ }, {
6248
+ readonly type: "error";
6249
+ readonly name: "InvalidDecimals";
6250
+ readonly inputs: readonly [];
6211
6251
  }, {
6212
6252
  readonly type: "error";
6213
6253
  readonly name: "InvalidImplementation";
package/dist/abi.js CHANGED
@@ -443,6 +443,16 @@ export const erc20XGaslessAbi = [
443
443
  "type": "string",
444
444
  "internalType": "string"
445
445
  },
446
+ {
447
+ "name": "",
448
+ "type": "uint8",
449
+ "internalType": "uint8"
450
+ },
451
+ {
452
+ "name": "",
453
+ "type": "address",
454
+ "internalType": "address"
455
+ },
446
456
  {
447
457
  "name": "",
448
458
  "type": "address",
@@ -476,6 +486,11 @@ export const erc20XGaslessAbi = [
476
486
  "type": "string",
477
487
  "internalType": "string"
478
488
  },
489
+ {
490
+ "name": "decimals_",
491
+ "type": "uint8",
492
+ "internalType": "uint8"
493
+ },
479
494
  {
480
495
  "name": "defaultAdmin",
481
496
  "type": "address",
@@ -486,6 +501,11 @@ export const erc20XGaslessAbi = [
486
501
  "type": "address",
487
502
  "internalType": "address"
488
503
  },
504
+ {
505
+ "name": "burner",
506
+ "type": "address",
507
+ "internalType": "address"
508
+ },
489
509
  {
490
510
  "name": "pauser",
491
511
  "type": "address",
@@ -1376,6 +1396,11 @@ export const erc20XGaslessAbi = [
1376
1396
  "name": "InvalidAddress",
1377
1397
  "inputs": []
1378
1398
  },
1399
+ {
1400
+ "type": "error",
1401
+ "name": "InvalidDecimals",
1402
+ "inputs": []
1403
+ },
1379
1404
  {
1380
1405
  "type": "error",
1381
1406
  "name": "InvalidImplementation",