@shuttle.technology/authorization 0.1.0 → 0.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/README.md +1082 -666
  3. package/dist/accountLists.d.ts +28 -0
  4. package/dist/accountLists.js +27 -0
  5. package/dist/auth.d.ts +11 -11
  6. package/dist/auth.js +28 -54
  7. package/dist/client.d.ts +62 -174
  8. package/dist/client.js +381 -354
  9. package/dist/clientTypes.d.ts +56 -0
  10. package/dist/clientTypes.js +5 -0
  11. package/dist/configuration.d.ts +48 -0
  12. package/dist/configuration.js +72 -0
  13. package/dist/consentDebit.d.ts +36 -0
  14. package/dist/consentDebit.js +95 -0
  15. package/dist/credentials.d.ts +116 -0
  16. package/dist/credentials.js +315 -0
  17. package/dist/debitPermissionWire.d.ts +90 -0
  18. package/dist/debitPermissionWire.js +118 -0
  19. package/dist/debitPermissions.d.ts +39 -0
  20. package/dist/debitPermissions.js +117 -0
  21. package/dist/deviceRecovery.d.ts +40 -0
  22. package/dist/deviceRecovery.js +143 -0
  23. package/dist/deviceShares.d.ts +91 -0
  24. package/dist/deviceShares.js +204 -0
  25. package/dist/errors.d.ts +280 -0
  26. package/dist/errors.js +85 -0
  27. package/dist/linkedRecovery.d.ts +40 -0
  28. package/dist/linkedRecovery.js +49 -0
  29. package/dist/linkedRegistrations.d.ts +11 -0
  30. package/dist/linkedRegistrations.js +109 -0
  31. package/dist/linkedWallets.d.ts +46 -18
  32. package/dist/linkedWallets.js +85 -120
  33. package/dist/me.d.ts +27 -0
  34. package/dist/me.js +30 -0
  35. package/dist/mobile.d.ts +64 -0
  36. package/dist/mobile.js +69 -0
  37. package/dist/redirects.d.ts +45 -0
  38. package/dist/redirects.js +108 -0
  39. package/dist/serviceGrants.d.ts +52 -0
  40. package/dist/serviceGrants.js +46 -0
  41. package/dist/slice4.d.ts +20 -6
  42. package/dist/slice4.js +22 -8
  43. package/dist/streams.js +1 -1
  44. package/dist/walletCreateGrant.d.ts +62 -0
  45. package/dist/walletCreateGrant.js +89 -0
  46. package/dist/walletDisplayParts.d.ts +2 -0
  47. package/dist/walletDisplayParts.js +4 -0
  48. package/dist/walletOperations.d.ts +23 -6
  49. package/dist/walletOperations.js +31 -22
  50. package/dist/webRenewal.d.ts +92 -0
  51. package/dist/webRenewal.js +179 -0
  52. package/package.json +25 -23
@@ -0,0 +1,28 @@
1
+ export interface SessionProjection {
2
+ requestId: string;
3
+ items: Array<{
4
+ sessionId: string;
5
+ clientId: string;
6
+ state: string;
7
+ createdAt: string;
8
+ expiresAt: string;
9
+ current: boolean;
10
+ }>;
11
+ hasMore: boolean;
12
+ nextCursor?: string;
13
+ }
14
+ export interface WalletProjection {
15
+ requestId: string;
16
+ items: Array<{
17
+ walletId: string;
18
+ network: string;
19
+ address: string;
20
+ state: string;
21
+ generation: string;
22
+ mappingVersion: string;
23
+ }>;
24
+ hasMore: boolean;
25
+ nextCursor?: string;
26
+ }
27
+ export declare function parseSessionPage(payload: unknown): SessionProjection;
28
+ export declare function parseWalletPage(payload: unknown): WalletProjection;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Two paged lists of the account's own: its sessions (`GET /v1/sessions`)
3
+ * and the wallets the provider created for it (`GET /v1/wallets`), each read
4
+ * as strictly as every other answer.
5
+ */
6
+ import { ClientFlowError, canonicalDecimal, opaqueId, record } from "./auth.js";
7
+ import { pageEnvelope, pageProjection } from "./pages.js";
8
+ export function parseSessionPage(payload) {
9
+ const root = pageEnvelope(payload);
10
+ const items = root.items.map((value) => {
11
+ const item = record(value, ["session_id", "client_id", "state", "created_at", "expires_at", "current"]);
12
+ if (!opaqueId(item.session_id) || !opaqueId(item.client_id) || typeof item.state !== "string" || typeof item.created_at !== "string" || typeof item.expires_at !== "string" || typeof item.current !== "boolean")
13
+ throw new ClientFlowError("invalid_server_response");
14
+ return { sessionId: item.session_id, clientId: item.client_id, state: item.state, createdAt: item.created_at, expiresAt: item.expires_at, current: item.current };
15
+ });
16
+ return pageProjection(root.request_id, items, root.has_more, root.next_cursor);
17
+ }
18
+ export function parseWalletPage(payload) {
19
+ const root = pageEnvelope(payload);
20
+ const items = root.items.map((value) => {
21
+ const item = record(value, ["wallet_id", "network", "address", "state", "generation", "mapping_version"]);
22
+ if (!opaqueId(item.wallet_id) || typeof item.network !== "string" || typeof item.address !== "string" || typeof item.state !== "string" || !canonicalDecimal(item.generation) || !canonicalDecimal(item.mapping_version))
23
+ throw new ClientFlowError("invalid_server_response");
24
+ return { walletId: item.wallet_id, network: item.network, address: item.address, state: item.state, generation: item.generation, mappingVersion: item.mapping_version };
25
+ });
26
+ return pageProjection(root.request_id, items, root.has_more, root.next_cursor);
27
+ }
package/dist/auth.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type AuthorizationErrorCode } from "./errors.ts";
1
2
  export declare const identityMethods: readonly ["google", "apple", "telegram", "passkey"];
2
3
  export type IdentityMethod = (typeof identityMethods)[number];
3
4
  export type AuthIntent = "signup" | "login";
@@ -7,8 +8,9 @@ export declare class ClientFlowError extends Error {
7
8
  readonly code: string;
8
9
  constructor(code: string);
9
10
  }
11
+ /** A refusal the provider answered, with one code of its ErrorCode enum (`AuthorizationErrorCodes`). */
10
12
  export declare class AuthorizationError extends Error {
11
- readonly code: string;
13
+ readonly code: AuthorizationErrorCode;
12
14
  readonly retryable: boolean;
13
15
  readonly nextAction: NextAction;
14
16
  readonly requestId: string;
@@ -19,7 +21,7 @@ export declare class AuthorizationError extends Error {
19
21
  };
20
22
  readonly status: number;
21
23
  constructor(input: {
22
- code: string;
24
+ code: AuthorizationErrorCode;
23
25
  retryable: boolean;
24
26
  nextAction: NextAction;
25
27
  requestId: string;
@@ -31,15 +33,14 @@ export declare class AuthorizationError extends Error {
31
33
  status: number;
32
34
  });
33
35
  }
36
+ /** isAuthorizationError tells a provider refusal, and with codes one of those. */
37
+ export declare function isAuthorizationError(error: unknown, ...codes: AuthorizationErrorCode[]): error is AuthorizationError;
38
+ /**
39
+ * abortable waits for work, or rejects with the signal's reason as soon as
40
+ * the signal aborts; the work itself goes on for whoever else waits for it.
41
+ */
42
+ export declare function abortable<T>(work: Promise<T>, signal?: AbortSignal): Promise<T>;
34
43
  export declare function parseAuthorizationError(payload: unknown, status: number): AuthorizationError;
35
- type ErrorExpectation = {
36
- status: number;
37
- retryable: boolean;
38
- nextAction: NextAction;
39
- };
40
- declare const errorCatalog: Readonly<Record<string, ErrorExpectation>>;
41
- export type AuthorizationErrorCode = keyof typeof errorCatalog;
42
- export declare function isAuthorizationErrorCode(value: unknown): value is AuthorizationErrorCode;
43
44
  export declare function newHandoffBinding(crypto: Crypto): Promise<{
44
45
  state: string;
45
46
  verifier: string;
@@ -65,4 +66,3 @@ export declare function deadlineAfter(created: string, expires: string): boolean
65
66
  export declare function unexpiredRFC3339(value: unknown, nowMs: number): value is string;
66
67
  export declare function record(value: unknown, required: readonly string[], optional?: readonly string[]): Record<string, unknown>;
67
68
  export declare function isNextAction(value: unknown): value is NextAction;
68
- export {};
package/dist/auth.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { AuthorizationErrorContracts, isAuthorizationErrorCode, operationIdCodes, possibleCommitStatus } from "./errors.js";
1
2
  export const identityMethods = ["google", "apple", "telegram", "passkey"];
2
3
  export class ClientFlowError extends Error {
3
4
  code;
@@ -7,6 +8,7 @@ export class ClientFlowError extends Error {
7
8
  this.code = code;
8
9
  }
9
10
  }
11
+ /** A refusal the provider answered, with one code of its ErrorCode enum (`AuthorizationErrorCodes`). */
10
12
  export class AuthorizationError extends Error {
11
13
  code;
12
14
  retryable;
@@ -27,6 +29,28 @@ export class AuthorizationError extends Error {
27
29
  this.status = input.status;
28
30
  }
29
31
  }
32
+ /** isAuthorizationError tells a provider refusal, and with codes one of those. */
33
+ export function isAuthorizationError(error, ...codes) {
34
+ return error instanceof AuthorizationError && (codes.length === 0 || codes.includes(error.code));
35
+ }
36
+ /**
37
+ * abortable waits for work, or rejects with the signal's reason as soon as
38
+ * the signal aborts; the work itself goes on for whoever else waits for it.
39
+ */
40
+ export function abortable(work, signal) {
41
+ if (!signal)
42
+ return work;
43
+ return new Promise((resolve, reject) => {
44
+ const abort = () => reject(signal.reason);
45
+ if (signal.aborted) {
46
+ work.catch(() => { });
47
+ abort();
48
+ return;
49
+ }
50
+ signal.addEventListener("abort", abort, { once: true });
51
+ work.then((value) => { signal.removeEventListener("abort", abort); resolve(value); }, (error) => { signal.removeEventListener("abort", abort); reject(error); });
52
+ });
53
+ }
30
54
  export function parseAuthorizationError(payload, status) {
31
55
  const outer = record(payload, ["error"]);
32
56
  const error = record(outer.error, ["code", "retryable", "next_action", "request_id"], ["operation_id", "window"]);
@@ -36,9 +60,10 @@ export function parseAuthorizationError(payload, status) {
36
60
  if (error.operation_id !== undefined && !opaqueId(error.operation_id)) {
37
61
  throw new ClientFlowError("invalid_error_response");
38
62
  }
39
- const expected = errorCatalog[error.code];
40
- const possibleCommit = possibleCommitCodes.has(error.code) && error.operation_id !== undefined && error.retryable === false && error.next_action === "lookup_operation";
41
- if (!expected || expected.status !== status || (!possibleCommit && (error.retryable !== expected.retryable || error.next_action !== expected.nextAction))) {
63
+ const expected = isAuthorizationErrorCode(error.code) ? AuthorizationErrorContracts[error.code] : undefined;
64
+ const possibleCommit = expected !== undefined && error.operation_id !== undefined && error.retryable === false && error.next_action === "lookup_operation" &&
65
+ status === possibleCommitStatus(error.code);
66
+ if (!expected || (!possibleCommit && (expected.status !== status || error.retryable !== expected.retryable || error.next_action !== expected.nextAction))) {
42
67
  throw new ClientFlowError("invalid_error_response");
43
68
  }
44
69
  if (error.operation_id !== undefined && !possibleCommit && !operationIdCodes.has(error.code)) {
@@ -74,57 +99,6 @@ export function parseAuthorizationError(payload, status) {
74
99
  status,
75
100
  });
76
101
  }
77
- const errorCatalog = Object.freeze({
78
- INVALID_REQUEST: { status: 400, retryable: false, nextAction: "none" },
79
- REGISTRATION_SCOPE_SELECTION_REQUIRED: { status: 409, retryable: false, nextAction: "none" },
80
- CURSOR_INVALID: { status: 400, retryable: false, nextAction: "none" },
81
- UNSUPPORTED_VERSION: { status: 400, retryable: false, nextAction: "none" },
82
- UNAUTHORIZED: { status: 401, retryable: false, nextAction: "reauthenticate" },
83
- SCOPE_DENIED: { status: 403, retryable: false, nextAction: "none" },
84
- ORIGIN_NOT_ALLOWED: { status: 403, retryable: false, nextAction: "none" },
85
- LIMIT_PER_TRANSFER_EXCEEDED: { status: 403, retryable: false, nextAction: "none" },
86
- LIMIT_DAILY_EXCEEDED: { status: 403, retryable: false, nextAction: "none" },
87
- RECIPIENT_NOT_ALLOWED: { status: 403, retryable: false, nextAction: "none" },
88
- CONFIRMATION_METHOD_UNAVAILABLE: { status: 403, retryable: false, nextAction: "use_passkey" },
89
- USER_PROOF_REQUIRED: { status: 403, retryable: false, nextAction: "sign_user_request" },
90
- USER_PROOF_INVALID: { status: 403, retryable: false, nextAction: "sign_user_request" },
91
- REQUEST_GRANT_INVALID: { status: 403, retryable: false, nextAction: "use_passkey" },
92
- NOT_FOUND: { status: 404, retryable: false, nextAction: "none" },
93
- IDENTITY_NOT_REGISTERED: { status: 409, retryable: false, nextAction: "start_signup" },
94
- IDENTITY_ALREADY_REGISTERED: { status: 409, retryable: false, nextAction: "start_login" },
95
- IDENTITY_ALREADY_LINKED: { status: 409, retryable: false, nextAction: "none" },
96
- ACCOUNT_REFERENCE_UNBOUND: { status: 409, retryable: false, nextAction: "none" },
97
- LAST_FACTOR: { status: 409, retryable: false, nextAction: "none" },
98
- CONFIRMATION_REPLAYED: { status: 409, retryable: false, nextAction: "none" },
99
- CANNOT_CANCEL: { status: 409, retryable: false, nextAction: "none" },
100
- VERSION_CONFLICT: { status: 409, retryable: false, nextAction: "refresh_resource" },
101
- AUTHORIZATION_STALE: { status: 409, retryable: false, nextAction: "refresh_resource" },
102
- IDEMPOTENCY_CONFLICT: { status: 409, retryable: false, nextAction: "lookup_operation" },
103
- USER_PROOF_REPLAYED: { status: 409, retryable: false, nextAction: "lookup_operation" },
104
- OPERATION_NOT_AUTHORIZED: { status: 409, retryable: false, nextAction: "use_passkey" },
105
- RESULT_NOT_READY: { status: 409, retryable: true, nextAction: "wait_for_result" },
106
- TRANSFER_IN_FLIGHT: { status: 409, retryable: true, nextAction: "retry_same_request" },
107
- ATTEMPT_EXPIRED: { status: 410, retryable: false, nextAction: "reauthenticate" },
108
- OPERATION_EXPIRED: { status: 410, retryable: false, nextAction: "none" },
109
- RESULT_EXPIRED: { status: 410, retryable: false, nextAction: "none" },
110
- RESYNC_REQUIRED: { status: 410, retryable: false, nextAction: "resync_streams" },
111
- USER_PROOF_EXPIRED: { status: 410, retryable: false, nextAction: "sign_user_request" },
112
- CAPABILITY_UNAVAILABLE: { status: 422, retryable: false, nextAction: "none" },
113
- RECOVERY_UNAVAILABLE: { status: 422, retryable: false, nextAction: "none" },
114
- PAYLOAD_NOT_SUPPORTED: { status: 422, retryable: false, nextAction: "none" },
115
- RATE_LIMITED: { status: 429, retryable: true, nextAction: "retry_same_request" },
116
- DEPENDENCY_UNAVAILABLE: { status: 503, retryable: true, nextAction: "retry_same_request" },
117
- NETWORK_FEE_TOO_HIGH: { status: 503, retryable: true, nextAction: "retry_same_request" },
118
- TENANT_AUTH_UNAVAILABLE: { status: 503, retryable: true, nextAction: "retry_same_request" },
119
- AUDIT_UNAVAILABLE: { status: 503, retryable: true, nextAction: "retry_same_request" },
120
- ADAPTER_INTEGRITY_CONFLICT: { status: 503, retryable: false, nextAction: "none" },
121
- INTERNAL_ERROR: { status: 500, retryable: true, nextAction: "retry_same_request" },
122
- });
123
- export function isAuthorizationErrorCode(value) {
124
- return typeof value === "string" && Object.prototype.hasOwnProperty.call(errorCatalog, value);
125
- }
126
- const possibleCommitCodes = new Set(["DEPENDENCY_UNAVAILABLE", "TENANT_AUTH_UNAVAILABLE", "AUDIT_UNAVAILABLE", "INTERNAL_ERROR"]);
127
- const operationIdCodes = new Set(["IDEMPOTENCY_CONFLICT", "USER_PROOF_REPLAYED", "RESULT_NOT_READY", "OPERATION_EXPIRED", "RESULT_EXPIRED", "OPERATION_NOT_AUTHORIZED", "ADAPTER_INTEGRITY_CONFLICT"]);
128
102
  function opaqueCursor(value) {
129
103
  return typeof value === "string" && value.length > 0;
130
104
  }
package/dist/client.d.ts CHANGED
@@ -1,162 +1,53 @@
1
1
  import { type ClientChannel, type IdentityMethod } from "./auth.ts";
2
- import { type AccountIdentity, type ConfirmationChallenge, type HostedIdentityFlow, type IdentityVerificationMethod, type LocalOperation, type LocalOperationCreate, type LocalOperationResult, type PasskeyBootstrapResult, type ServiceReadScope, type VerifiedIdentityResult } from "./slice4.ts";
2
+ import { type Session } from "./credentials.ts";
3
+ import { type ClientConfiguration, type ClientSettings, type PublicClientConfiguration } from "./configuration.ts";
4
+ import { type SessionProjection, type WalletProjection } from "./accountLists.ts";
5
+ import { type ServiceGrantInput, type ServiceGrantPage, type ServiceGrantTarget } from "./serviceGrants.ts";
6
+ import { type AccountIdentity, type ConfirmationChallenge, type HostedIdentityFlow, type IdentityVerificationMethod, type LocalOperation, type LocalOperationCreate, type LocalOperationResult, type PasskeyBootstrapResult, type VerifiedIdentityResult } from "./slice4.ts";
7
+ import { type MeProjection } from "./me.ts";
8
+ import { type HostedSignIn } from "./redirects.ts";
9
+ import { type MobileBrowserBridge, type MobileSecureStorage } from "./mobile.ts";
10
+ export type { MobileAssociationInput, MobileAssociationVerification, MobileBrowserBridge, MobileSecureStorage } from "./mobile.ts";
3
11
  import { StreamsReads } from "./streams.ts";
4
12
  import { LinkedWallets } from "./linkedWallets.ts";
5
- export { LinkedWallets, eventOfTransaction, isWalletLimitRefusal, resumeCursor, sendEvents, transferFinal, WalletLimitRefusals } from "./linkedWallets.ts";
6
- export type { AssetBalance, LinkedWalletBalances, NetworkBalanceStatus, NetworkBalances, ListedSend, SendPage, TransferOutcome, TransferState, TransferStatus, WalletConnection, LinkedWallet, WalletLinkChallenge, WalletLinkAssertion, LinkedRegistrationCreate, LinkedRegistrationOperation, LinkedRegistrationDisplay, LinkedRegistrationPurgedDisplay, LinkedRegistrationResult, LinkedRegistrationListOptions, LinkedEventsOptions, LinkedStreamsRegistration, LinkedStreamsRegistrationList, LinkedSendInput, LinkedReplaceInput, LinkedSendDisplay, ReplaceAction, LinkedTransportKey, LimitAsset, WalletCeiling, WalletLimitRefusal, WalletLimits, WalletLimitsDisplay, WalletLimitsInput } from "./linkedWallets.ts";
13
+ export { DebitPermissions, LinkedWallets, MaxDebitAssets, MaxDebitRecipients, eventOfTransaction, isWalletLimitRefusal, resumeCursor, sendEvents, transferFinal, WalletLimitRefusals } from "./linkedWallets.ts";
14
+ export type { AssetBalance, LinkedWalletBalances, NetworkBalanceStatus, NetworkBalances, ListedSend, SendPage, TransferOutcome, TransferState, TransferStatus, WalletConnection, LinkedWallet, WalletLinkChallenge, WalletLinkAssertion, LinkedRegistrationCreate, LinkedRegistrationOperation, LinkedRegistrationDisplay, LinkedRegistrationPurgedDisplay, LinkedRegistrationResult, LinkedRegistrationListOptions, LinkedEventsOptions, LinkedStreamsRegistration, LinkedStreamsRegistrationList, LinkedSendInput, LinkedReplaceInput, LinkedSendDisplay, ReplaceAction, LinkedTransportKey, LimitAsset, WalletCeiling, WalletLimitRefusal, WalletLimits, WalletLimitsDisplay, WalletLimitsInput, DebitAsset, DebitAssetBound, DebitPermission, DebitPermissionDisplay, DebitPermissionInput, DebitPermissionList, DebitPermissionRevokeDisplay, DebitPermissionState, DebitShareKeys } from "./linkedWallets.ts";
7
15
  import { type UserWalletOperation, type UserWalletOperationCreate, type WalletResult } from "./walletOperations.ts";
16
+ import { type WalletCreateInput } from "./walletCreateGrant.ts";
17
+ export type { ConsentDebitOutcome, DebitTerms } from "./consentDebit.ts";
18
+ export type { WalletCreateGrant, WalletCreateGrantOutcome, WalletCreateInput } from "./walletCreateGrant.ts";
8
19
  import { type PageOptions } from "./pages.ts";
9
20
  export type { PageOptions } from "./pages.ts";
10
- export { AuthorizationError, ClientFlowError } from "./auth.ts";
21
+ export type { ClientConfiguration, ClientSettings, PublicClientConfiguration } from "./configuration.ts";
22
+ export type { SessionProjection, WalletProjection } from "./accountLists.ts";
23
+ export type { AccountServiceGrant, ServiceGrantInput, ServiceGrantPage, ServiceGrantState, ServiceGrantTarget } from "./serviceGrants.ts";
24
+ export { AuthorizationErrorCodes, AuthorizationErrorContracts, ModeCRefusals, isAuthorizationErrorCode, isModeCRefusal } from "./errors.ts";
25
+ export type { AuthorizationErrorCode, AuthorizationErrorContract, ModeCRefusal } from "./errors.ts";
26
+ export type { MeProjection, MeWallet } from "./me.ts";
27
+ export { AuthorizationError, ClientFlowError, isAuthorizationError } from "./auth.ts";
28
+ export { webRenewalRequiresNavigation } from "./webRenewal.ts";
11
29
  export type { AuthIntent, ClientChannel, IdentityMethod, NextAction } from "./auth.ts";
30
+ export type { HostedSignIn } from "./redirects.ts";
12
31
  export { pollAuthoritative } from "./poll.ts";
13
32
  export type { PollDisposition, PollOptions, PollResult } from "./poll.ts";
14
33
  export type { AccountIdentity, ConfirmationChallenge, HostedIdentityFlow, IdentityVerificationMethod, LocalOperation, LocalOperationCreate, LocalOperationResult, PasskeyBootstrapResult, ResultRecipient, ServiceReadScope, VerifiedIdentityResult, } from "./slice4.ts";
15
34
  export { MaxTransferCommentBytes, MaxWalletMessageBytes, ReplaceActions, transferComment, walletMaterialPurged } from "./walletOperations.ts";
16
- export type { UserWalletAuthorizationBasis, UserWalletDisplay, UserWalletEffectState, UserWalletOperation, UserWalletOperationCreate, UserWalletOperationKind, UserWalletPurgedDisplay, UserWalletState, WalletResult, WalletResultKind, } from "./walletOperations.ts";
17
- export interface ClientConfiguration {
18
- mode: "mode_b";
19
- channel: ClientChannel;
20
- authorizationOrigin: string;
21
- applicationOrigin?: string;
22
- redirectUri: string;
23
- publishableClientId: string;
24
- tenantId: string;
25
- applicationId: string;
26
- environmentId: string;
27
- methods: readonly IdentityMethod[];
28
- mobileApplicationIdentifier?: string;
29
- }
30
- export interface PublicClientConfiguration {
31
- requestId: string;
32
- id: string;
33
- name: string;
34
- environmentId: string;
35
- methods: readonly IdentityMethod[];
36
- providerOrigin: string;
37
- rpId: string;
38
- redirects: readonly string[];
39
- platform: ClientChannel;
40
- }
41
- export interface FetchRequest {
42
- url: string;
43
- method?: string;
44
- headers?: Record<string, string>;
45
- body?: string;
46
- credentials?: "include" | "omit";
47
- cache?: "no-store";
48
- signal?: AbortSignal;
49
- }
50
- export interface FetchResponse {
51
- status: number;
52
- ok: boolean;
53
- json(): Promise<unknown>;
54
- /** The answer as it arrives and its headers; only a signal stream reads them. */
55
- body?: ReadableStream<Uint8Array> | null;
56
- headers?: {
57
- get(name: string): string | null;
58
- };
59
- }
60
- export type FetchLike = (url: string, init?: Omit<FetchRequest, "url">) => Promise<FetchResponse>;
61
- export interface MobileSecureStorage {
62
- get(key: string): Promise<string | null>;
63
- set(key: string, value: string): Promise<void>;
64
- delete(key: string): Promise<void>;
65
- }
66
- export interface MobileAssociationInput {
67
- redirectUri: string;
68
- applicationIdentifier: string;
69
- }
70
- export interface MobileAssociationVerification {
71
- source: "os_verified_https_association";
72
- redirectUri: string;
73
- applicationIdentifier: string;
74
- }
75
- /**
76
- * Host/native trust boundary. Implementations must ask the operating system to
77
- * verify the configured HTTPS app/universal-link association. This result is a
78
- * port contract, not cryptographic proof produced by this TypeScript package.
79
- */
80
- export interface MobileBrowserBridge {
81
- verifyAssociatedRedirect(input: MobileAssociationInput): Promise<MobileAssociationVerification | null>;
82
- openSystemBrowser(url: string): Promise<void> | void;
83
- }
84
- interface CommonDependencies {
85
- fetch?: FetchLike;
86
- crypto?: Crypto;
87
- now?: () => number;
88
- }
89
- export interface WebDependencies extends CommonDependencies {
90
- currentOrigin: () => string;
91
- /**
92
- * Opens a separate top-level browsing context. Restore requires the host to
93
- * return the final registered app redirect while this caller stays alive so
94
- * its state and PKCE verifier remain only in memory.
95
- */
96
- openHosted: (url: string) => Promise<string | void> | string | void;
97
- }
98
- export interface MobileDependencies extends CommonDependencies {
99
- browserBridge: MobileBrowserBridge;
100
- secureStorage: MobileSecureStorage;
101
- }
102
- export type ClientDependencies = WebDependencies | MobileDependencies;
103
- export interface AuthAttempt {
104
- requestId: string;
105
- attemptId: string;
106
- launchUrl: string;
107
- expiresAt: number;
108
- }
109
- export interface Session {
110
- requestId: string;
111
- accessExpiresAt: number;
112
- accountId: string;
113
- sessionId: string;
114
- setupRequired?: boolean;
115
- }
116
- export interface MeProjection {
117
- requestId: string;
118
- account: {
119
- accountId: string;
120
- version: string;
121
- setupRequired: boolean;
122
- };
123
- sessionId: string;
124
- serverTime: number;
125
- }
126
- export interface SessionProjection {
127
- requestId: string;
128
- items: Array<{
129
- sessionId: string;
130
- clientId: string;
131
- state: string;
132
- createdAt: string;
133
- expiresAt: string;
134
- current: boolean;
135
- }>;
136
- hasMore: boolean;
137
- nextCursor?: string;
138
- }
139
- export interface WalletProjection {
140
- requestId: string;
141
- items: Array<{
142
- walletId: string;
143
- network: string;
144
- address: string;
145
- state: string;
146
- generation: string;
147
- mappingVersion: string;
148
- }>;
149
- hasMore: boolean;
150
- nextCursor?: string;
151
- }
35
+ export type { UserWalletAuthorizationBasis, UserWalletDisplay, UserWalletEffectState, UserWalletOperation, UserWalletOperationCreate, UserWalletOperationKind, UserWalletPurgedDisplay, UserWalletState, WalletResult, WalletResultKind, DeviceSharePackage, } from "./walletOperations.ts";
36
+ export type { AuthAttempt, ClientDependencies, FetchLike, FetchRequest, FetchResponse, MobileDependencies, WebDependencies } from "./clientTypes.ts";
37
+ import { type DeviceShareStore } from "./deviceShares.ts";
38
+ export type { DeviceRecoveryOptions, DeviceShareRecord, DeviceShareStore } from "./deviceShares.ts";
39
+ import type { ClientDependencies, FetchLike, AuthAttempt } from "./clientTypes.ts";
40
+ export type { Session } from "./credentials.ts";
152
41
  type NormalizedDependencies = {
153
42
  fetch: FetchLike;
154
43
  crypto: Crypto;
155
44
  now: () => number;
156
- launch: (url: string) => Promise<string | void>;
45
+ launch: (url: string, signal?: AbortSignal) => Promise<string | void>;
157
46
  secureStorage?: MobileSecureStorage;
47
+ browserBridge?: MobileBrowserBridge;
48
+ deviceShares?: DeviceShareStore;
158
49
  };
159
- export declare function initializeAuthorizationClient(configuration: ClientConfiguration, dependencies: ClientDependencies): Promise<AuthorizationClient>;
50
+ export declare function initializeAuthorizationClient(settings: ClientSettings, dependencies: ClientDependencies): Promise<AuthorizationClient>;
160
51
  export declare class AuthorizationClient {
161
52
  #private;
162
53
  readonly capabilities: {
@@ -167,7 +58,13 @@ export declare class AuthorizationClient {
167
58
  readonly publicConfiguration?: PublicClientConfiguration;
168
59
  constructor(configuration: ClientConfiguration, dependencies: NormalizedDependencies, publicConfiguration?: PublicClientConfiguration);
169
60
  get hasSession(): boolean;
61
+ /**
62
+ * signup and login open the hosted sign-in page (on mobile: verify the app link, open the system browser,
63
+ * exchange what it hands back and resolve with the session). Given a method, they begin that attempt.
64
+ */
65
+ signup(): Promise<HostedSignIn>;
170
66
  signup(method: IdentityMethod): Promise<AuthAttempt>;
67
+ login(): Promise<HostedSignIn>;
171
68
  login(method: IdentityMethod): Promise<AuthAttempt>;
172
69
  bootstrapPasskey(signal?: AbortSignal): Promise<HostedIdentityFlow>;
173
70
  verifyIdentity(method: IdentityVerificationMethod, signal?: AbortSignal): Promise<HostedIdentityFlow>;
@@ -179,26 +76,19 @@ export declare class AuthorizationClient {
179
76
  createIdentityLink(verifiedIdentityHandle: string, idempotencyKey: string, signal?: AbortSignal): Promise<LocalOperation>;
180
77
  createIdentityUnlink(identityId: string, idempotencyKey: string, signal?: AbortSignal): Promise<LocalOperation>;
181
78
  createSessionRevocation(sessionId: string, idempotencyKey: string, signal?: AbortSignal): Promise<LocalOperation>;
182
- createServiceGrant(input: {
183
- walletId: string;
184
- servicePrincipalId: string;
185
- enabled: boolean;
186
- scopes: ServiceReadScope[];
187
- externalRef?: string;
188
- }, idempotencyKey: string, signal?: AbortSignal): Promise<LocalOperation>;
79
+ /** createServiceGrant asks to give one service read access to one of the account's wallets, or to change it; the person confirms it with a passkey. */
80
+ createServiceGrant(input: ServiceGrantInput, idempotencyKey: string, signal?: AbortSignal): Promise<LocalOperation>;
81
+ /** revokeServiceGrant asks to withdraw the grant of one service on one wallet (`enabled: false`); the person confirms it with a passkey. */
82
+ revokeServiceGrant(target: ServiceGrantTarget, idempotencyKey: string, signal?: AbortSignal): Promise<LocalOperation>;
83
+ /** serviceGrants lists the grants the account gave services, in every state, newest first. */
84
+ serviceGrants(input?: AbortSignal | PageOptions): Promise<ServiceGrantPage>;
189
85
  operation(operationId: string, signal?: AbortSignal): Promise<LocalOperation>;
190
86
  challengeOperation(operationId: string, credentialId: string, signal?: AbortSignal): Promise<ConfirmationChallenge>;
191
87
  completeOperationConfirmation(callbackUri: string, signal?: AbortSignal): Promise<LocalOperation>;
192
- /**
193
- * createWalletOperation admits one Mode B wallet intent on POST /v1/operations.
194
- * The closed body is validated locally against the current session account
195
- * before the request leaves the client (source §1.3, §2.2).
196
- */
88
+ /** createWalletOperation admits one Mode B wallet intent, its closed body checked locally first (source §1.3, §2.2). */
197
89
  createWalletOperation(create: UserWalletOperationCreate, idempotencyKey: string, signal?: AbortSignal): Promise<UserWalletOperation>;
198
- createWallet(input: {
199
- network: string;
200
- recipientPublicKey: string;
201
- }, idempotencyKey: string, signal?: AbortSignal): Promise<UserWalletOperation>;
90
+ /** Without recipientPublicKey the SDK makes the device key and keeps the share (deviceShares.ts); grant opens the wallet to a service in the same confirmation (walletCreateGrant.ts). */
91
+ createWallet(input: WalletCreateInput, idempotencyKey: string, signal?: AbortSignal): Promise<UserWalletOperation>;
202
92
  signWithWallet(input: {
203
93
  walletId: string;
204
94
  network: string;
@@ -222,17 +112,10 @@ export declare class AuthorizationClient {
222
112
  }, idempotencyKey: string, signal?: AbortSignal): Promise<UserWalletOperation>;
223
113
  /** walletOperation reads the safe wallet status on GET /v1/operations/{operation_id}. */
224
114
  walletOperation(operationId: string, signal?: AbortSignal): Promise<UserWalletOperation>;
225
- /**
226
- * challengeWalletOperation reuses the shared confirmation challenge route and
227
- * pending-state bookkeeping; the wallet and local challenge contracts are the
228
- * same closed response.
229
- */
115
+ /** challengeWalletOperation is challengeOperation: the wallet and local challenges are one closed response. */
230
116
  challengeWalletOperation(operationId: string, credentialId: string, signal?: AbortSignal): Promise<ConfirmationChallenge>;
231
117
  completeWalletOperationConfirmation(callbackUri: string, signal?: AbortSignal): Promise<UserWalletOperation>;
232
- /**
233
- * executeWalletOperation claims one confirmed wallet effect. The first claim
234
- * answers 202 and an exact replay answers 200; both carry the same operation.
235
- */
118
+ /** executeWalletOperation claims one confirmed wallet effect: 202, or 200 for an exact replay, with the same operation. */
236
119
  executeWalletOperation(operationId: string, version: string, idempotencyKey: string, signal?: AbortSignal): Promise<UserWalletOperation>;
237
120
  /** walletOperationResult reads the protected wallet output for its frozen recipient. */
238
121
  walletOperationResult(operationId: string, signal?: AbortSignal): Promise<WalletResult>;
@@ -240,25 +123,30 @@ export declare class AuthorizationClient {
240
123
  /** HTTP-only Auth-owned links and session-authorized Streams registration. */
241
124
  linkedWallets(): LinkedWallets;
242
125
  /**
243
- * streams binds the two authorized Streams reads of source §2.6 to this
244
- * session's protected GET, so the account caller reuses the one access-token
245
- * and refresh path. The read contract, its types and its bounds live in the
246
- * `./streams` entry point, which this file deliberately does not re-export; a
247
- * service caller constructs `StreamsReads` there with its own credentialed
248
- * GET. The caller supplies the stable `idempotencyKey` in each read's options;
249
- * it is forwarded unchanged on the original GET and any protected 401 retry.
126
+ * streams binds the authorized Streams reads (source §2.6, `./streams`) to this session's protected GET;
127
+ * each read's `idempotencyKey` is forwarded unchanged on the GET and any 401 retry.
250
128
  */
251
129
  streams(): StreamsReads;
252
130
  operationResult(operationId: string, signal?: AbortSignal): Promise<LocalOperationResult>;
253
131
  cancel(attemptId: string): "local_canceled";
132
+ /** exchangeHandoff exchanges the redirect back for the session; a signal ends only this caller's wait, never the exchange. */
254
133
  exchangeHandoff(callbackUri: string, signal?: AbortSignal): Promise<Session>;
134
+ /** restoreSession is the top-level restore on the web (webRenewal.ts); on mobile it is refreshSession. */
255
135
  restoreSession(signal?: AbortSignal): Promise<Session>;
136
+ /** refreshSession renews in the background: on the web from the provider's cookie, on mobile with the stored refresh token. */
256
137
  refreshSession(signal?: AbortSignal): Promise<Session>;
138
+ /** logout ends the session here at once and asks the provider to end it; a signal ends only this caller's wait, never the revocation. */
257
139
  logout(signal?: AbortSignal): Promise<{
258
140
  localCleared: true;
259
141
  serverDisposition: "server_revoked" | "server_unconfirmed";
260
142
  }>;
143
+ /**
144
+ * accessToken is the session's access token for the app's own backend, renewed first when it has
145
+ * less than 30 seconds to live or a read was refused with it. Never store it or put it in a URL.
146
+ */
147
+ accessToken(signal?: AbortSignal): Promise<string>;
261
148
  me(signal?: AbortSignal): Promise<MeProjection>;
262
149
  sessions(input?: AbortSignal | PageOptions): Promise<SessionProjection>;
150
+ /** wallets pages the account's own wallets, kind "wallet" in me(), which lists them with the linked ones. */
263
151
  wallets(input?: AbortSignal | PageOptions): Promise<WalletProjection>;
264
152
  }