@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 +69 -0
- package/dist/abi.d.ts +40 -0
- package/dist/abi.js +25 -0
- package/dist/generated/types.d.ts +386 -3
- package/dist/member-bff.d.ts +53 -4
- package/dist/member-bff.js +63 -6
- package/dist/member-resources.d.ts +17 -1
- package/dist/member-resources.js +7 -6
- package/dist/resources/account-holders.d.ts +107 -1
- package/dist/resources/account-holders.js +36 -7
- package/dist/resources/branding.d.ts +10 -0
- package/dist/resources/branding.js +2 -0
- package/dist/resources/escrows.d.ts +3 -0
- package/dist/resources/payment-requests.d.ts +4 -0
- package/dist/resources/tenant.d.ts +15 -0
- package/dist/resources/tenant.js +6 -1
- package/dist/resources/tokenization.d.ts +15 -0
- package/dist/resources/wallets.d.ts +2 -0
- package/examples/postgres-checkpoint-store.mjs +116 -0
- package/examples/postgres-checkpoints.sql +9 -0
- package/llms.txt +1 -1
- package/package.json +3 -2
|
@@ -11,6 +11,7 @@ export declare class PaymentRequestsResource extends Resource {
|
|
|
11
11
|
has_more: boolean;
|
|
12
12
|
}>;
|
|
13
13
|
create(body: ReqBody<'createPaymentRequest'>, opts?: XKOVAMutationOptions): Promise<{
|
|
14
|
+
notification_status?: "queued" | "sent" | "failed" | "cancelled";
|
|
14
15
|
id?: import("../generated/types.js").components["schemas"]["PaymentRequestId"];
|
|
15
16
|
requester_id?: import("../generated/types.js").components["schemas"]["AccountHolderId"];
|
|
16
17
|
payer_id?: import("../generated/types.js").components["schemas"]["AccountHolderId"] | null;
|
|
@@ -26,6 +27,7 @@ export declare class PaymentRequestsResource extends Resource {
|
|
|
26
27
|
updated_at?: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
27
28
|
}>;
|
|
28
29
|
retrieve(id: string): Promise<{
|
|
30
|
+
notification_status?: "queued" | "sent" | "failed" | "cancelled";
|
|
29
31
|
id?: import("../generated/types.js").components["schemas"]["PaymentRequestId"];
|
|
30
32
|
requester_id?: import("../generated/types.js").components["schemas"]["AccountHolderId"];
|
|
31
33
|
payer_id?: import("../generated/types.js").components["schemas"]["AccountHolderId"] | null;
|
|
@@ -82,6 +84,7 @@ export declare class PaymentRequestsResource extends Resource {
|
|
|
82
84
|
finalized_at: import("../generated/types.js").components["schemas"]["TimestampUtc"] | null;
|
|
83
85
|
}>;
|
|
84
86
|
cancel(id: string, opts?: XKOVAMutationOptions): Promise<{
|
|
87
|
+
notification_status?: "queued" | "sent" | "failed" | "cancelled";
|
|
85
88
|
id?: import("../generated/types.js").components["schemas"]["PaymentRequestId"];
|
|
86
89
|
requester_id?: import("../generated/types.js").components["schemas"]["AccountHolderId"];
|
|
87
90
|
payer_id?: import("../generated/types.js").components["schemas"]["AccountHolderId"] | null;
|
|
@@ -97,6 +100,7 @@ export declare class PaymentRequestsResource extends Resource {
|
|
|
97
100
|
updated_at?: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
98
101
|
}>;
|
|
99
102
|
decline(id: string, body?: ReqBody<'declinePaymentRequest'>, opts?: XKOVAMutationOptions): Promise<{
|
|
103
|
+
notification_status?: "queued" | "sent" | "failed" | "cancelled";
|
|
100
104
|
id?: import("../generated/types.js").components["schemas"]["PaymentRequestId"];
|
|
101
105
|
requester_id?: import("../generated/types.js").components["schemas"]["AccountHolderId"];
|
|
102
106
|
payer_id?: import("../generated/types.js").components["schemas"]["AccountHolderId"] | null;
|
|
@@ -47,6 +47,12 @@ export declare class TenantResource extends Resource {
|
|
|
47
47
|
publishable_key: string;
|
|
48
48
|
name: string;
|
|
49
49
|
provider_kind: "xkova_hosted" | "oidc" | "signed_launch";
|
|
50
|
+
provider_namespace: string;
|
|
51
|
+
issuer: string | null;
|
|
52
|
+
audience: string | null;
|
|
53
|
+
jwks_uri: string | null;
|
|
54
|
+
allowed_jwt_algorithms: ("RS256" | "PS256" | "ES256" | "EdDSA")[];
|
|
55
|
+
proof_binding_mode: "authorization_nonce" | "server_assertion_jti";
|
|
50
56
|
enrollment_mode: import("../generated/types.js").components["schemas"]["MemberAuthEnrollmentMode"];
|
|
51
57
|
is_default: boolean;
|
|
52
58
|
status: "active" | "principal_disabled";
|
|
@@ -73,6 +79,12 @@ export declare class TenantResource extends Resource {
|
|
|
73
79
|
publishable_key: string;
|
|
74
80
|
name: string;
|
|
75
81
|
provider_kind: "xkova_hosted" | "oidc" | "signed_launch";
|
|
82
|
+
provider_namespace: string;
|
|
83
|
+
issuer: string | null;
|
|
84
|
+
audience: string | null;
|
|
85
|
+
jwks_uri: string | null;
|
|
86
|
+
allowed_jwt_algorithms: ("RS256" | "PS256" | "ES256" | "EdDSA")[];
|
|
87
|
+
proof_binding_mode: "authorization_nonce" | "server_assertion_jti";
|
|
76
88
|
enrollment_mode: import("../generated/types.js").components["schemas"]["MemberAuthEnrollmentMode"];
|
|
77
89
|
is_default: boolean;
|
|
78
90
|
status: "active" | "principal_disabled";
|
|
@@ -90,6 +102,9 @@ export declare class TenantResource extends Resource {
|
|
|
90
102
|
created_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
91
103
|
updated_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
92
104
|
}>;
|
|
105
|
+
/** Disables the exact Hosted Auth or OIDC member application. */
|
|
106
|
+
disableMemberAuthApplication(id: string, opts?: XKOVAMutationOptions): Promise<void>;
|
|
107
|
+
/** Existing Hosted Auth convenience name. */
|
|
93
108
|
disableHostedApplication(id: string, opts?: XKOVAMutationOptions): Promise<void>;
|
|
94
109
|
configureOidcApplication(body: ReqBody<'configureMemberAuthOidcApplication'>, opts?: XKOVAMutationOptions): Promise<{
|
|
95
110
|
id: string;
|
package/dist/resources/tenant.js
CHANGED
|
@@ -15,9 +15,14 @@ export class TenantResource extends Resource {
|
|
|
15
15
|
updateHostedApplication(id, body, opts) {
|
|
16
16
|
return this.patchJson(`/tenant/member-auth/applications/${this.enc(id)}`, body, opts);
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
/** Disables the exact Hosted Auth or OIDC member application. */
|
|
19
|
+
disableMemberAuthApplication(id, opts) {
|
|
19
20
|
return this.deleteJson(`/tenant/member-auth/applications/${this.enc(id)}`, opts);
|
|
20
21
|
}
|
|
22
|
+
/** Existing Hosted Auth convenience name. */
|
|
23
|
+
disableHostedApplication(id, opts) {
|
|
24
|
+
return this.disableMemberAuthApplication(id, opts);
|
|
25
|
+
}
|
|
21
26
|
configureOidcApplication(body, opts) {
|
|
22
27
|
return this.putJson('/tenant/member-auth/application', body, opts);
|
|
23
28
|
}
|
|
@@ -186,6 +186,9 @@ export declare class TokenizationResource extends Resource {
|
|
|
186
186
|
raw_contract: string | null;
|
|
187
187
|
raw_function: string | null;
|
|
188
188
|
raw_args: string[] | null;
|
|
189
|
+
failure_reason_code: string | null;
|
|
190
|
+
failure_reason_detail: string | null;
|
|
191
|
+
failure_retryable: boolean;
|
|
189
192
|
created_at: string;
|
|
190
193
|
updated_at: string;
|
|
191
194
|
}>;
|
|
@@ -222,6 +225,9 @@ export declare class TokenizationResource extends Resource {
|
|
|
222
225
|
raw_contract: string | null;
|
|
223
226
|
raw_function: string | null;
|
|
224
227
|
raw_args: string[] | null;
|
|
228
|
+
failure_reason_code: string | null;
|
|
229
|
+
failure_reason_detail: string | null;
|
|
230
|
+
failure_retryable: boolean;
|
|
225
231
|
created_at: string;
|
|
226
232
|
updated_at: string;
|
|
227
233
|
}>;
|
|
@@ -261,6 +267,9 @@ export declare class TokenizationResource extends Resource {
|
|
|
261
267
|
raw_contract: string | null;
|
|
262
268
|
raw_function: string | null;
|
|
263
269
|
raw_args: string[] | null;
|
|
270
|
+
failure_reason_code: string | null;
|
|
271
|
+
failure_reason_detail: string | null;
|
|
272
|
+
failure_retryable: boolean;
|
|
264
273
|
created_at: string;
|
|
265
274
|
updated_at: string;
|
|
266
275
|
}>;
|
|
@@ -292,6 +301,9 @@ export declare class TokenizationResource extends Resource {
|
|
|
292
301
|
raw_contract: string | null;
|
|
293
302
|
raw_function: string | null;
|
|
294
303
|
raw_args: string[] | null;
|
|
304
|
+
failure_reason_code: string | null;
|
|
305
|
+
failure_reason_detail: string | null;
|
|
306
|
+
failure_retryable: boolean;
|
|
295
307
|
created_at: string;
|
|
296
308
|
updated_at: string;
|
|
297
309
|
}>;
|
|
@@ -323,6 +335,9 @@ export declare class TokenizationResource extends Resource {
|
|
|
323
335
|
raw_contract: string | null;
|
|
324
336
|
raw_function: string | null;
|
|
325
337
|
raw_args: string[] | null;
|
|
338
|
+
failure_reason_code: string | null;
|
|
339
|
+
failure_reason_detail: string | null;
|
|
340
|
+
failure_retryable: boolean;
|
|
326
341
|
created_at: string;
|
|
327
342
|
updated_at: string;
|
|
328
343
|
}>;
|
|
@@ -16,6 +16,7 @@ export declare class WalletsResource extends Resource {
|
|
|
16
16
|
updated_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
|
|
17
17
|
}>;
|
|
18
18
|
balance(id: string, query: Query<'getWalletBalance'>): Promise<{
|
|
19
|
+
data_freshness: import("../generated/types.js").components["schemas"]["DataFreshness"][];
|
|
19
20
|
chain_id: number;
|
|
20
21
|
wallet: string;
|
|
21
22
|
token: string;
|
|
@@ -34,6 +35,7 @@ export declare class WalletsResource extends Resource {
|
|
|
34
35
|
has_more: boolean;
|
|
35
36
|
} & {
|
|
36
37
|
data?: import("../generated/types.js").components["schemas"]["LedgerEntry"][];
|
|
38
|
+
data_freshness: import("../generated/types.js").components["schemas"]["DataFreshness"][];
|
|
37
39
|
}>;
|
|
38
40
|
decommission(id: string, opts?: XKOVAMutationOptions): Promise<{
|
|
39
41
|
id: import("../generated/types.js").components["schemas"]["WalletId"];
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
|
|
3
|
+
|
|
4
|
+
/** Install pg separately. The application owns the pool, schema, retention and key rotation. */
|
|
5
|
+
export class PostgresCheckpointStore {
|
|
6
|
+
#context = new AsyncLocalStorage();
|
|
7
|
+
#key;
|
|
8
|
+
|
|
9
|
+
constructor(pool, namespace, encryptionKey) {
|
|
10
|
+
if (!/^[a-z][a-z0-9_-]{0,63}$/.test(namespace)) throw new Error('Invalid store namespace');
|
|
11
|
+
if (!Buffer.isBuffer(encryptionKey) || encryptionKey.length !== 32)
|
|
12
|
+
throw new Error('A 32-byte application encryption key is required');
|
|
13
|
+
this.pool = pool;
|
|
14
|
+
this.namespace = namespace;
|
|
15
|
+
this.#key = Buffer.from(encryptionKey);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#binding(reference) {
|
|
19
|
+
return JSON.stringify([this.namespace, reference]);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#encrypt(reference, record) {
|
|
23
|
+
const iv = randomBytes(12);
|
|
24
|
+
const cipher = createCipheriv('aes-256-gcm', this.#key, iv);
|
|
25
|
+
cipher.setAAD(Buffer.from(this.#binding(reference)));
|
|
26
|
+
const bytes = Buffer.concat([cipher.update(JSON.stringify(record), 'utf8'), cipher.final()]);
|
|
27
|
+
return Buffer.concat([iv, cipher.getAuthTag(), bytes]);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#decrypt(reference, bytes) {
|
|
31
|
+
if (!Buffer.isBuffer(bytes) || bytes.length < 29) throw new Error('Invalid stored envelope');
|
|
32
|
+
const decipher = createDecipheriv('aes-256-gcm', this.#key, bytes.subarray(0, 12));
|
|
33
|
+
decipher.setAAD(Buffer.from(this.#binding(reference)));
|
|
34
|
+
decipher.setAuthTag(bytes.subarray(12, 28));
|
|
35
|
+
return JSON.parse(
|
|
36
|
+
Buffer.concat([decipher.update(bytes.subarray(28)), decipher.final()]).toString('utf8'),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#db() {
|
|
41
|
+
return this.#context.getStore()?.client ?? this.pool;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async put(reference, record) {
|
|
45
|
+
await this.#db().query(
|
|
46
|
+
'INSERT INTO xkova_helper_checkpoints(namespace, reference, envelope, expires_at) VALUES ($1,$2,$3,$4)',
|
|
47
|
+
[this.namespace, reference, this.#encrypt(reference, record), this.#expiry(record)],
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async get(reference) {
|
|
52
|
+
const result = await this.#db().query(
|
|
53
|
+
'SELECT envelope FROM xkova_helper_checkpoints WHERE namespace=$1 AND reference=$2 AND expires_at > now()',
|
|
54
|
+
[this.namespace, reference],
|
|
55
|
+
);
|
|
56
|
+
return result.rowCount ? this.#decrypt(reference, result.rows[0].envelope) : null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async replace(reference, record) {
|
|
60
|
+
const result = await this.#db().query(
|
|
61
|
+
'UPDATE xkova_helper_checkpoints SET envelope=$3, expires_at=$4 WHERE namespace=$1 AND reference=$2',
|
|
62
|
+
[this.namespace, reference, this.#encrypt(reference, record), this.#expiry(record)],
|
|
63
|
+
);
|
|
64
|
+
if (result.rowCount !== 1) throw new Error('Cannot replace a missing checkpoint');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async delete(reference) {
|
|
68
|
+
await this.#db().query(
|
|
69
|
+
'DELETE FROM xkova_helper_checkpoints WHERE namespace=$1 AND reference=$2',
|
|
70
|
+
[this.namespace, reference],
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#expiry(record) {
|
|
75
|
+
const value = record.applicationExpiresAt ?? record.expiresAt;
|
|
76
|
+
if (!Number.isSafeInteger(value)) throw new Error('Invalid checkpoint expiry');
|
|
77
|
+
return new Date(value);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** A session lock, with separate autocommit checkpoints, never an outer SQL transaction. */
|
|
81
|
+
async runExclusive(reference, work) {
|
|
82
|
+
const existing = this.#context.getStore();
|
|
83
|
+
if (existing) {
|
|
84
|
+
if (existing.reference !== reference) throw new Error('Nested references are unsupported');
|
|
85
|
+
return work();
|
|
86
|
+
}
|
|
87
|
+
const client = await this.pool.connect();
|
|
88
|
+
let locked = false;
|
|
89
|
+
let discard = false;
|
|
90
|
+
try {
|
|
91
|
+
await client.query("SET lock_timeout = '5s'");
|
|
92
|
+
await client.query("SET statement_timeout = '10s'");
|
|
93
|
+
await client.query('SELECT pg_advisory_lock(hashtextextended($1, 0))', [
|
|
94
|
+
this.#binding(reference),
|
|
95
|
+
]);
|
|
96
|
+
locked = true;
|
|
97
|
+
return await this.#context.run({ client, reference }, work);
|
|
98
|
+
} finally {
|
|
99
|
+
try {
|
|
100
|
+
if (locked) {
|
|
101
|
+
const result = await client.query(
|
|
102
|
+
'SELECT pg_advisory_unlock(hashtextextended($1, 0)) AS released',
|
|
103
|
+
[this.#binding(reference)],
|
|
104
|
+
);
|
|
105
|
+
if (result.rows[0]?.released !== true) throw new Error('Checkpoint lock was lost');
|
|
106
|
+
}
|
|
107
|
+
await client.query('RESET lock_timeout');
|
|
108
|
+
await client.query('RESET statement_timeout');
|
|
109
|
+
} catch {
|
|
110
|
+
// A connection with an uncertain lock must never return to the pool.
|
|
111
|
+
discard = true;
|
|
112
|
+
}
|
|
113
|
+
client.release(discard);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
-- Apply through your application's normal migration process, to its own database.
|
|
2
|
+
CREATE TABLE xkova_helper_checkpoints (
|
|
3
|
+
namespace text NOT NULL,
|
|
4
|
+
reference text NOT NULL,
|
|
5
|
+
envelope bytea NOT NULL,
|
|
6
|
+
expires_at timestamptz NOT NULL,
|
|
7
|
+
PRIMARY KEY (namespace, reference)
|
|
8
|
+
);
|
|
9
|
+
CREATE INDEX xkova_helper_checkpoints_expiry ON xkova_helper_checkpoints (expires_at);
|
package/llms.txt
CHANGED
|
@@ -10,7 +10,7 @@ Use this package on a Node.js 22+ server. Read the installed declarations before
|
|
|
10
10
|
- `dist/member-bff.d.ts`: authorization, session persistence, refresh, logout, action reviews, and human authorization.
|
|
11
11
|
- `dist/member-resources.d.ts`: typed resources bound to the exact authenticated member.
|
|
12
12
|
- [Quickstart](https://docs.xkova.com/getting-started.html): sandbox access and first authenticated call.
|
|
13
|
-
- [Customer OpenAPI](https://github.com/XKOVA/typescript-sdk/blob/main/schema/customer-api.json):
|
|
13
|
+
- [Customer OpenAPI](https://github.com/XKOVA/typescript-sdk/blob/main/schema/customer-api.json): machine-readable contract for the public SDK source. For an installed release, use its generated declarations.
|
|
14
14
|
- [SDK guide](https://docs.xkova.com/sdk-overview.html): client and resource examples.
|
|
15
15
|
- [Workflow guide](https://docs.xkova.com/sdk-workflows.html): supported workflow helpers.
|
|
16
16
|
- [Member integration](https://docs.xkova.com/embedded-member.html): browser, BFF, identity, and signing boundaries.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xkova/sdk",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.7",
|
|
4
4
|
"description": "TypeScript SDK for the XKOVA API.",
|
|
5
5
|
"homepage": "https://docs.xkova.com",
|
|
6
6
|
"repository": {
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
},
|
|
47
47
|
"files": [
|
|
48
48
|
"dist",
|
|
49
|
-
"llms.txt"
|
|
49
|
+
"llms.txt",
|
|
50
|
+
"examples"
|
|
50
51
|
],
|
|
51
52
|
"dependencies": {
|
|
52
53
|
"viem": "^2.21.0"
|