@xkova/sdk 0.1.0-alpha.1 → 0.1.0-alpha.10

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 (51) hide show
  1. package/README.md +324 -32
  2. package/dist/abi.d.ts +40 -0
  3. package/dist/abi.js +25 -0
  4. package/dist/client.d.ts +4 -0
  5. package/dist/client.js +62 -3
  6. package/dist/generated/types.d.ts +8629 -5182
  7. package/dist/held-approval.d.ts +41 -0
  8. package/dist/held-approval.js +33 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +1 -0
  11. package/dist/member-action-intents.js +2 -2
  12. package/dist/member-bff.d.ts +60 -21
  13. package/dist/member-bff.js +81 -79
  14. package/dist/member-resources.d.ts +67 -1
  15. package/dist/member-resources.js +9 -5
  16. package/dist/request-signing.js +6 -0
  17. package/dist/resources/account-holders.d.ts +131 -1
  18. package/dist/resources/account-holders.js +44 -9
  19. package/dist/resources/branding.d.ts +10 -0
  20. package/dist/resources/branding.js +2 -0
  21. package/dist/resources/contacts.d.ts +2 -2
  22. package/dist/resources/contacts.js +3 -3
  23. package/dist/resources/escrows.d.ts +3 -0
  24. package/dist/resources/payment-requests.d.ts +4 -0
  25. package/dist/resources/payments.d.ts +13 -0
  26. package/dist/resources/payments.js +7 -0
  27. package/dist/resources/ramps.d.ts +73 -64
  28. package/dist/resources/ramps.js +2 -2
  29. package/dist/resources/rwa.d.ts +9 -9
  30. package/dist/resources/tenant.d.ts +15 -0
  31. package/dist/resources/tenant.js +6 -1
  32. package/dist/resources/tokenization.d.ts +30 -11
  33. package/dist/resources/tokenization.js +10 -10
  34. package/dist/resources/treasury.d.ts +404 -0
  35. package/dist/resources/treasury.js +115 -0
  36. package/dist/resources/wallets.d.ts +2 -0
  37. package/dist/resources/webhooks.d.ts +1 -1
  38. package/dist/resources/webhooks.js +2 -2
  39. package/dist/resources/workflows.d.ts +7 -6
  40. package/dist/resources/workflows.js +87 -24
  41. package/dist/resources/workforce-wallets.d.ts +34 -0
  42. package/dist/resources/workforce-wallets.js +19 -0
  43. package/dist/url.d.ts +1 -0
  44. package/dist/url.js +4 -0
  45. package/dist/webhook.js +1 -1
  46. package/dist/workforce-bff.d.ts +202 -0
  47. package/dist/workforce-bff.js +462 -0
  48. package/examples/postgres-checkpoint-store.mjs +116 -0
  49. package/examples/postgres-checkpoints.sql +9 -0
  50. package/llms.txt +29 -9
  51. package/package.json +8 -3
@@ -1,33 +1,56 @@
1
1
  const DEFAULT_POLL = { attempts: 30, intervalMs: 2000 };
2
- const SUCCESS = new Set(['confirmed', 'completed', 'settled', 'succeeded', 'deployed', 'active']);
3
- const FAILURE = new Set(['failed', 'reverted', 'cancelled', 'canceled', 'expired', 'rejected']);
2
+ const PENDING_OPERATION = new Set(['pending_sign', 'submission_pending', 'relayed']);
3
+ const PENDING_TOKEN = new Set(['pending_deploy', 'awaiting_admin_setup']);
4
4
  export class WorkflowClient {
5
5
  client;
6
6
  constructor(client) {
7
7
  this.client = client;
8
8
  }
9
9
  async tokenDeploy(standard, body, opts = {}) {
10
+ const poll = pollOptions(opts.poll, opts.signal);
11
+ validatePoll(poll);
12
+ if (!['erc20', 'erc721', 'erc1155'].includes(standard)) {
13
+ throw new TypeError('Unsupported token standard');
14
+ }
15
+ poll.signal?.throwIfAborted();
16
+ const mutation = { ...opts, ...(poll.signal !== undefined && { signal: poll.signal }) };
10
17
  const t = this.client.tokenization;
11
18
  const deployed = standard === 'erc20'
12
- ? await t.deployErc20(body, opts)
19
+ ? await t.deployErc20(body, mutation)
13
20
  : standard === 'erc721'
14
- ? await t.deployErc721(body, opts)
15
- : await t.deployErc1155(body, opts);
21
+ ? await t.deployErc721(body, mutation)
22
+ : await t.deployErc1155(body, mutation);
16
23
  const tokenId = readString(deployed, 'customer_token_id');
17
- return pollEntity(() => t.retrieve(tokenId), pollOptions(opts.poll, opts.signal), 'token');
24
+ const operationId = readString(deployed, 'operation_id');
25
+ return pollEntity(() => t.retrieve(tokenId, poll), poll, tokenId, operationId);
18
26
  }
19
- /** Mint to a holder and wait for confirmation. */
27
+ /** Submit once and observe the exact mint operation. Required human signing remains separate. */
20
28
  async tokenMint(tokenId, body, opts = {}) {
21
- await this.client.tokenization.mint(tokenId, body, opts);
22
- return pollEntity(() => this.client.tokenization.retrieve(tokenId), pollOptions(opts.poll, opts.signal), 'token');
29
+ const poll = pollOptions(opts.poll, opts.signal);
30
+ validatePoll(poll);
31
+ poll.signal?.throwIfAborted();
32
+ const minted = await this.client.tokenization.mint(tokenId, body, {
33
+ ...opts,
34
+ ...(poll.signal !== undefined && { signal: poll.signal }),
35
+ });
36
+ const operationId = readString(minted, 'operation_id');
37
+ await pollOperation(this.client, tokenId, operationId, 'mint', poll);
38
+ poll.signal?.throwIfAborted();
39
+ const token = await this.client.tokenization.retrieve(tokenId, poll);
40
+ poll.signal?.throwIfAborted();
41
+ if (readString(token, 'id') !== tokenId)
42
+ throw new Error('API returned a different customer token');
43
+ return token;
23
44
  }
24
45
  /**
25
- * Off-ramp: resolve the burn address and create the request. The member then
26
- * burns stablecoin to the returned address out-of-band; poll
27
- * `client.ramps.getOffRamp(id)` for settlement.
46
+ * Resolve the registered burn address and create the caller's burn-backed
47
+ * request. This helper does not submit a transaction or establish settlement;
48
+ * poll `client.ramps.getOffRamp(id)` for the resulting request's state.
28
49
  */
29
50
  async offRampInitiate(chainRef, body, opts = {}) {
30
- const burnAddress = await this.client.ramps.offRampBurnAddress({ chain_ref: chainRef });
51
+ opts.signal?.throwIfAborted();
52
+ const burnAddress = await this.client.ramps.offRampBurnAddress({ chain_ref: chainRef }, opts);
53
+ opts.signal?.throwIfAborted();
31
54
  const request = await this.client.ramps.createOffRamp(body, opts);
32
55
  return { request, burnAddress };
33
56
  }
@@ -42,29 +65,69 @@ function readString(obj, key) {
42
65
  }
43
66
  return v;
44
67
  }
45
- async function pollEntity(fetchOne, poll, label) {
68
+ function validatePoll(poll) {
69
+ const { attempts, intervalMs } = { ...DEFAULT_POLL, ...poll };
70
+ if (!Number.isSafeInteger(attempts) ||
71
+ attempts < 1 ||
72
+ !Number.isFinite(intervalMs) ||
73
+ intervalMs < 0 ||
74
+ intervalMs > 2_147_483_647) {
75
+ throw new TypeError('Polling requires positive attempts and a nonnegative interval');
76
+ }
77
+ }
78
+ async function pollOperation(client, tokenId, operationId, kind, poll) {
79
+ const { attempts, intervalMs, signal } = { ...DEFAULT_POLL, ...poll };
80
+ for (let i = 0; i < attempts; i++) {
81
+ signal?.throwIfAborted();
82
+ const operation = await client.tokenization.getOperation(tokenId, operationId, poll);
83
+ signal?.throwIfAborted();
84
+ if (readString(operation, 'id') !== operationId ||
85
+ readString(operation, 'customer_token_id') !== tokenId ||
86
+ readString(operation, 'kind') !== kind) {
87
+ throw new Error('API returned a different tokenization operation');
88
+ }
89
+ const status = readString(operation, 'status');
90
+ if (status === 'confirmed')
91
+ return;
92
+ if (!PENDING_OPERATION.has(status)) {
93
+ throw new Error(`operation ${operationId} reached a failed or unsupported status: ${status}`);
94
+ }
95
+ if (i + 1 < attempts)
96
+ await sleep(intervalMs, signal);
97
+ }
98
+ throw new Error(`operation ${operationId} remains pending after ${attempts} attempts; observe it before submitting another mutation`);
99
+ }
100
+ async function pollEntity(fetchOne, poll, tokenId, operationId) {
46
101
  const { attempts, intervalMs, signal } = { ...DEFAULT_POLL, ...poll };
47
102
  let last;
48
103
  for (let i = 0; i < attempts; i++) {
49
104
  signal?.throwIfAborted();
50
105
  last = await fetchOne();
51
- const status = String(last?.['status'] ?? '');
52
- if (SUCCESS.has(status))
106
+ signal?.throwIfAborted();
107
+ if (readString(last, 'id') !== tokenId)
108
+ throw new Error(`API returned a different customer token for deployment operation ${operationId}`);
109
+ const status = readString(last, 'status');
110
+ if (status === 'active')
53
111
  return last;
54
- if (FAILURE.has(status)) {
55
- throw new Error(`${label} reached terminal failure status: ${status}`);
112
+ if (!PENDING_TOKEN.has(status)) {
113
+ throw new Error(`token ${tokenId} for deployment operation ${operationId} reached a failed or unsupported status: ${status}`);
56
114
  }
57
- await sleep(intervalMs, signal);
115
+ if (i + 1 < attempts)
116
+ await sleep(intervalMs, signal);
58
117
  }
59
- throw new Error(`${label} did not reach a terminal status after ${attempts} attempts`);
118
+ throw new Error(`token ${tokenId} for deployment operation ${operationId} remains pending after ${attempts} attempts; observe that customer token before submitting another mutation`);
60
119
  }
61
120
  function sleep(ms, signal) {
62
121
  return new Promise((resolve, reject) => {
63
122
  signal?.throwIfAborted();
64
- const timer = setTimeout(resolve, ms);
65
- signal?.addEventListener('abort', () => {
123
+ const aborted = () => {
66
124
  clearTimeout(timer);
67
- reject(signal.reason);
68
- }, { once: true });
125
+ reject(signal?.reason);
126
+ };
127
+ const timer = setTimeout(() => {
128
+ signal?.removeEventListener('abort', aborted);
129
+ resolve();
130
+ }, ms);
131
+ signal?.addEventListener('abort', aborted, { once: true });
69
132
  });
70
133
  }
@@ -0,0 +1,34 @@
1
+ import { Resource, type ReqBody } from './base.js';
2
+ import type { XKOVAMutationOptions } from '../client.js';
3
+ /** Current workforce human's canonical wallet, never selected by browser identity. */
4
+ export declare class WorkforceWalletsResource extends Resource {
5
+ list(): Promise<{
6
+ data?: import("../generated/types.js").components["schemas"]["StaffMpcWallet"][];
7
+ }>;
8
+ /** Fresh exact human proof is required before a provider admission can be issued. */
9
+ provision(options?: XKOVAMutationOptions): Promise<{
10
+ mpc_wallet: import("../generated/types.js").components["schemas"]["StaffMpcWallet"];
11
+ wallet_auth: import("../generated/types.js").components["schemas"]["WalletAdmissionBootstrap"];
12
+ challenge: {
13
+ challenge_id: string;
14
+ nonce: string;
15
+ typed_data: import("../generated/types.js").components["schemas"]["StaffMpcEnrollmentTypedData"];
16
+ expires_at: string;
17
+ };
18
+ }>;
19
+ /** Activate only after signing the API's exact one-time enrollment typed data. */
20
+ register(body: ReqBody<'workforceWalletRegister'>, options?: XKOVAMutationOptions): Promise<{
21
+ id: import("../generated/types.js").components["schemas"]["StaffMpcWalletId"];
22
+ staff_id: import("../generated/types.js").components["schemas"]["StaffId"];
23
+ address: string | null;
24
+ state: "pending_provisioning" | "active" | "decommissioned";
25
+ provider_resolution: "pending" | "resolved" | "review_required";
26
+ created_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
27
+ updated_at: import("../generated/types.js").components["schemas"]["TimestampUtc"];
28
+ }>;
29
+ /** Binds one ceremony to the current resource's frozen Safe digest and nonce. */
30
+ signingBootstrap(body: ReqBody<'workforceWalletSigningBootstrap'>, options?: XKOVAMutationOptions): Promise<{
31
+ mpc_wallet: import("../generated/types.js").components["schemas"]["StaffMpcWallet"];
32
+ wallet_auth: import("../generated/types.js").components["schemas"]["WalletAdmissionBootstrap"];
33
+ }>;
34
+ }
@@ -0,0 +1,19 @@
1
+ import { Resource } from './base.js';
2
+ /** Current workforce human's canonical wallet, never selected by browser identity. */
3
+ export class WorkforceWalletsResource extends Resource {
4
+ list() {
5
+ return this.getJson('/workforce-auth/me/wallets');
6
+ }
7
+ /** Fresh exact human proof is required before a provider admission can be issued. */
8
+ provision(options) {
9
+ return this.postJson('/workforce-auth/me/wallets/provision', undefined, options);
10
+ }
11
+ /** Activate only after signing the API's exact one-time enrollment typed data. */
12
+ register(body, options) {
13
+ return this.postJson('/workforce-auth/me/wallets/register', body, options);
14
+ }
15
+ /** Binds one ceremony to the current resource's frozen Safe digest and nonce. */
16
+ signingBootstrap(body, options) {
17
+ return this.postJson('/workforce-auth/me/wallets/signing-bootstrap', body, options);
18
+ }
19
+ }
package/dist/url.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function isAllowedProtocol(url: URL): boolean;
package/dist/url.js ADDED
@@ -0,0 +1,4 @@
1
+ export function isAllowedProtocol(url) {
2
+ return (url.protocol === 'https:' ||
3
+ (url.protocol === 'http:' && (url.hostname === 'localhost' || url.hostname === '127.0.0.1')));
4
+ }
package/dist/webhook.js CHANGED
@@ -45,7 +45,7 @@ function parseHeader(header) {
45
45
  t = n;
46
46
  }
47
47
  else if (key === 'v1') {
48
- if (!/^[0-9a-f]+$/.test(val))
48
+ if (!/^[0-9a-f]{64}$/.test(val))
49
49
  return null;
50
50
  v1s.push(val);
51
51
  }
@@ -0,0 +1,202 @@
1
+ import { type XKOVAClientOptions } from './client.js';
2
+ import { WorkforceWalletsResource } from './resources/workforce-wallets.js';
3
+ export { serializeXKOVAMemberSessionCookie as serializeXKOVAWorkforceSessionCookie, serializeXKOVAMemberFlowCookie as serializeXKOVAWorkforceFlowCookie, serializeClearedXKOVAMemberCookie as serializeClearedXKOVAWorkforceCookie, readXKOVAMemberCookie as readXKOVAWorkforceCookie, readXKOVAMemberCallbackFlow as readXKOVAWorkforceCallbackFlow, xkovaMemberFlowCookieName as xkovaWorkforceFlowCookieName, createXKOVAMemberCsrfToken as createXKOVAWorkforceCsrfToken, verifyXKOVAMemberCsrfToken as verifyXKOVAWorkforceCsrfToken, assertXKOVAMemberRequestOrigin as assertXKOVAWorkforceRequestOrigin, } from './member-bff.js';
4
+ export interface XKOVAWorkforceBffClientOptions extends XKOVAClientOptions {
5
+ /** Exact nonsecret workforce registration selector. This is not a member selector. */
6
+ readonly workforceKey: string;
7
+ }
8
+ export interface XKOVAWorkforceSession {
9
+ readonly session_id: string;
10
+ readonly application_id: string;
11
+ readonly staff_id: string;
12
+ readonly person_id: string;
13
+ readonly tenant_id: string;
14
+ readonly workspace_id: string;
15
+ readonly provider_namespace: string;
16
+ readonly provider_subject: string;
17
+ readonly roles: readonly string[];
18
+ readonly scopes: readonly string[];
19
+ readonly resource_grants: {
20
+ readonly treasury_wallet_ids: readonly string[];
21
+ readonly customer_token_ids: readonly string[];
22
+ };
23
+ readonly action_authorization_enabled: boolean;
24
+ readonly expires_at: string;
25
+ readonly absolute_expires_at: string;
26
+ }
27
+ export interface XKOVAWorkforceSessionMaterial {
28
+ readonly session_token: string;
29
+ readonly refresh_token: string;
30
+ readonly refresh_attempt_token: string;
31
+ readonly session: XKOVAWorkforceSession;
32
+ }
33
+ export interface XKOVAWorkforceActionReview {
34
+ readonly operation: string;
35
+ readonly proof_method: string;
36
+ readonly review: Readonly<Record<string, unknown>>;
37
+ readonly review_digest: string;
38
+ readonly expires_at: string;
39
+ }
40
+ export interface XKOVAWorkforceActionChallenge {
41
+ readonly nonce: string;
42
+ readonly issuer: string;
43
+ readonly audience: string;
44
+ readonly authorization_endpoint: string;
45
+ readonly max_auth_age_seconds: number;
46
+ readonly required_acr_values: readonly string[];
47
+ readonly required_amr_values: readonly string[];
48
+ readonly expires_at: string;
49
+ readonly review: Readonly<Record<string, unknown>>;
50
+ readonly review_digest: string;
51
+ }
52
+ /** Confidential, one-use authority for the unchanged reviewed request only. */
53
+ export interface XKOVAWorkforceActionGrant {
54
+ readonly grant_token: string;
55
+ readonly expires_at: string;
56
+ }
57
+ export interface StoredXKOVAWorkforceSession<T = unknown> {
58
+ readonly clientFingerprint: string;
59
+ readonly authorizationCodeHash: string;
60
+ readonly material: XKOVAWorkforceSessionMaterial;
61
+ readonly applicationExpiresAt: number;
62
+ readonly applicationData: T;
63
+ /** Persist before remote logout. It permanently blocks refresh and resource resolution. */
64
+ readonly logoutPending?: boolean;
65
+ }
66
+ /**
67
+ * Encrypt credentials and proofs at rest. All writes commit before resolving,
68
+ * independently of later callback errors. replace is exact-existing-only.
69
+ * runExclusive serializes the same record across every BFF replica. It is not
70
+ * a surrounding rollback transaction. Use separate transaction/session stores.
71
+ */
72
+ export interface XKOVAWorkforceStore<T> {
73
+ put(reference: string, value: T): Promise<void>;
74
+ get(reference: string): Promise<T | null>;
75
+ replace(reference: string, value: T): Promise<void>;
76
+ delete(reference: string): Promise<void>;
77
+ runExclusive<R>(reference: string, work: () => Promise<R>): Promise<R>;
78
+ }
79
+ export interface XKOVAWorkforceAuthorizationTransaction<T = unknown> {
80
+ readonly clientFingerprint: string;
81
+ readonly status: 'pending' | 'completed';
82
+ readonly redirectUri: string;
83
+ readonly codeVerifier: string;
84
+ readonly codeChallenge: string;
85
+ readonly exchangeAttemptId: string;
86
+ readonly sessionReference: string;
87
+ readonly expiresAt: number;
88
+ readonly transactionId?: string;
89
+ readonly nonce?: string;
90
+ readonly issuer?: string;
91
+ readonly audience?: string;
92
+ /** Written before the one-use provider call. An unknown result is never redeemed again. */
93
+ readonly providerExchangeStarted?: {
94
+ readonly codeHash: string;
95
+ readonly applicationData: T;
96
+ };
97
+ readonly stagedProofToken?: string;
98
+ }
99
+ export declare class XKOVAWorkforceBffError extends Error {
100
+ readonly code: 'transaction_unavailable' | 'binding_mismatch' | 'provider_exchange_outcome_unknown' | 'session_unavailable';
101
+ constructor(code: 'transaction_unavailable' | 'binding_mismatch' | 'provider_exchange_outcome_unknown' | 'session_unavailable');
102
+ }
103
+ /** Confidential workforce protocol. It neither enrolls a subject nor creates local staff authority. */
104
+ export declare class XKOVAWorkforceBffClient {
105
+ private readonly options;
106
+ private readonly client;
107
+ private readonly fingerprint;
108
+ constructor(options: XKOVAWorkforceBffClientOptions);
109
+ beginAuthorization<T>(input: {
110
+ browserOrigin: string;
111
+ redirectUri: string;
112
+ transactionStore: XKOVAWorkforceStore<XKOVAWorkforceAuthorizationTransaction<T>>;
113
+ }): Promise<{
114
+ state: string;
115
+ nonce: string;
116
+ redirectUri: string;
117
+ codeChallenge: string;
118
+ codeChallengeMethod: "S256";
119
+ issuer: string;
120
+ audience: string;
121
+ authorizationEndpoint: string;
122
+ maxAuthAgeSeconds: number;
123
+ requiredAcrValues: string[];
124
+ expiresAt: string;
125
+ }>;
126
+ completeAuthorizationCallback<T>(input: {
127
+ callbackUrl: string;
128
+ /** Read from the genuine initiating browser's HttpOnly flow cookie. */
129
+ expectedState: string;
130
+ transactionStore: XKOVAWorkforceStore<XKOVAWorkforceAuthorizationTransaction<T>>;
131
+ sessionStore: XKOVAWorkforceStore<StoredXKOVAWorkforceSession<T>>;
132
+ applicationData: T;
133
+ /** Perform the provider's real code exchange and signature/nonce checks server-side. */
134
+ exchangeProviderCode: (input: {
135
+ code: string;
136
+ codeVerifier: string;
137
+ redirectUri: string;
138
+ expectedNonce: string;
139
+ issuer: string;
140
+ audience: string;
141
+ }) => Promise<{
142
+ proofToken: string;
143
+ }>;
144
+ }): Promise<{
145
+ reference: string;
146
+ session: StoredXKOVAWorkforceSession<T>;
147
+ }>;
148
+ getSession(sessionToken: string): Promise<XKOVAWorkforceSession>;
149
+ resolveSession<T>(input: {
150
+ reference: string;
151
+ sessionStore: XKOVAWorkforceStore<StoredXKOVAWorkforceSession<T>>;
152
+ }): Promise<StoredXKOVAWorkforceSession<T> | null>;
153
+ /** Request-scoped resources only. Check the browser's Origin/CSRF before invoking writes. */
154
+ resolveResources<T>(input: {
155
+ reference: string;
156
+ sessionStore: XKOVAWorkforceStore<StoredXKOVAWorkforceSession<T>>;
157
+ browserOrigin: string;
158
+ /** Keep the API-issued grant on the server and repeat only its frozen request. */
159
+ actionGrant?: XKOVAWorkforceActionGrant;
160
+ }): Promise<{
161
+ session: StoredXKOVAWorkforceSession<T>;
162
+ resources: {
163
+ treasury: import("./resources/treasury.js").TreasuryResource;
164
+ tokenization: import("./resources/index.js").TokenizationResource;
165
+ wallets: WorkforceWalletsResource;
166
+ };
167
+ } | null>;
168
+ /** Review the locator returned by human_authorization_required. Never send it to a third-party host. */
169
+ inspectAction(input: {
170
+ authorizationToken: string;
171
+ sessionToken: string;
172
+ browserOrigin: string;
173
+ }): Promise<XKOVAWorkforceActionReview>;
174
+ /** Starts a real provider ceremony after the user reviews the exact request. No action is executed. */
175
+ beginActionProof(input: {
176
+ authorizationToken: string;
177
+ sessionToken: string;
178
+ browserOrigin: string;
179
+ }): Promise<XKOVAWorkforceActionChallenge>;
180
+ /** Submit the real, freshly verified provider token. A lost response is never automatically retried. */
181
+ completeActionProof(input: {
182
+ authorizationToken: string;
183
+ sessionToken: string;
184
+ browserOrigin: string;
185
+ nonce: string;
186
+ proofToken: string;
187
+ }): Promise<XKOVAWorkforceActionGrant>;
188
+ logoutSession<T>(input: {
189
+ reference: string;
190
+ sessionStore: XKOVAWorkforceStore<StoredXKOVAWorkforceSession<T>>;
191
+ }): Promise<void>;
192
+ private assertSession;
193
+ private postJson;
194
+ private getJson;
195
+ }
196
+ /** Advisory browser UI data only; provider identity, credentials and grants stay confidential. */
197
+ export declare function projectXKOVAWorkforceSession(value: StoredXKOVAWorkforceSession): {
198
+ signedIn: true;
199
+ staffId: string;
200
+ roles: string[];
201
+ expiresAt: string;
202
+ };