@seams/wallet-server 0.23.0 → 0.24.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.
- package/THIRD_PARTY_NOTICES.md +182 -5
- package/artifact-manifest.json +23 -13
- package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
- package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
- package/dist/esm/authorization/voiceIdDeviceProof.js +32 -0
- package/dist/esm/core/ThresholdService/validation.js +17 -1
- package/dist/esm/core/d1WalletAuthMethodStore.js +42 -1
- package/dist/esm/core/deviceLinking/linkedDeviceManagement.js +5 -0
- package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +11 -2
- package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +23 -6
- package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +5 -5
- package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.js +1 -1
- package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyEnvelopeStore.js +6 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1VoiceIdActivation.js +139 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1VoiceIdSessions.js +138 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1VoiceIdWalletSessionChallenges.js +88 -0
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +12 -4
- package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +14 -0
- package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +1 -0
- package/dist/esm/router/cloudflare.js +576 -10
- package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +5 -0
- package/dist/esm/router/domains/passkeyCustody/walletRecoveryFinalization.js +1 -0
- package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmissionCore.js +1 -0
- package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +1 -0
- package/dist/esm/router/domains/voiceId/voiceIdActivation.js +12 -0
- package/dist/esm/router/domains/voiceId/voiceIdSessions.js +0 -0
- package/dist/esm/router/framework/routeDefinitions.js +13 -0
- package/dist/esm/router/transport/fetch/createFetchRouter.js +5 -0
- package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +12 -1
- package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +1 -0
- package/dist/esm/router/transport/fetch/routes/walletVoiceIdActivation.js +139 -0
- package/dist/esm/router/transport/fetch/routes/walletVoiceIdNear.js +36 -0
- package/dist/esm/router/transport/fetch/routes/walletVoiceIdSessions.js +127 -0
- package/dist/esm/shared-ts/src/authorization/voiceIdDeviceAssertion.js +110 -0
- package/dist/esm/shared-ts/src/device-linking/authorityActivation.js +1 -0
- package/dist/esm/shared-ts/src/device-linking/committedSignerPackages.js +1 -1
- package/dist/esm/shared-ts/src/passkey-custody/custodyEnvelope.js +30 -3
- package/dist/esm/shared-ts/src/passkey-custody/custodySecretBinding.js +1 -1
- package/dist/esm/shared-ts/src/signing-lanes/recordParsers.js +15 -1
- package/dist/esm/shared-ts/src/threshold/sessionPolicy.js +2 -1
- package/dist/esm/shared-ts/src/utils/registrationIntent.js +1 -3
- package/dist/esm/shared-ts/src/utils/walletAuthAuthority.js +46 -2
- package/dist/esm/shared-ts/src/utils/walletAuthMethodRecord.js +116 -7
- package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryCommittedProjection.js +1 -0
- package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
- package/dist/types/shared-ts/src/authorization/voiceIdDeviceAssertion.d.ts +32 -0
- package/dist/types/shared-ts/src/device-linking/committedSignerPackages.d.ts +3 -1
- package/dist/types/shared-ts/src/device-linking/contracts.d.ts +8 -0
- package/dist/types/shared-ts/src/passkey-custody/custodyEnvelope.d.ts +29 -0
- package/dist/types/shared-ts/src/passkey-custody/custodySecretBinding.d.ts +1 -0
- package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +2 -2
- package/dist/types/shared-ts/src/signing-lanes/recordParsers.d.ts +2 -1
- package/dist/types/shared-ts/src/signing-lanes/records.d.ts +10 -2
- package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +2 -2
- package/dist/types/shared-ts/src/threshold/sessionPolicy.d.ts +9 -0
- package/dist/types/shared-ts/src/utils/addWalletAuthMethod.d.ts +3 -3
- package/dist/types/shared-ts/src/utils/domainIds.d.ts +4 -5
- package/dist/types/shared-ts/src/utils/registrationIntent.d.ts +0 -1
- package/dist/types/shared-ts/src/utils/signerDomain.d.ts +3 -0
- package/dist/types/shared-ts/src/utils/walletAuthAuthority.d.ts +32 -2
- package/dist/types/shared-ts/src/utils/walletAuthMethodRecord.d.ts +15 -1
- package/dist/types/shared-ts/src/utils/walletCapabilityBindings.d.ts +20 -0
- package/dist/types/wallet-server/src/authorization/voiceIdDeviceProof.d.ts +29 -0
- package/dist/types/wallet-server/src/core/d1WalletAuthMethodStore.d.ts +13 -2
- package/dist/types/wallet-server/src/core/registrationContracts.d.ts +8 -0
- package/dist/types/wallet-server/src/core/signingLanes/WalletExecutionLaneProjection.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyEnvelopeStore.d.ts +4 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1VoiceIdActivation.d.ts +14 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1VoiceIdSessions.d.ts +19 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1VoiceIdWalletSessionChallenges.d.ts +26 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +1 -0
- package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts +25 -0
- package/dist/types/wallet-server/src/router/domains/voiceId/voiceIdActivation.d.ts +29 -0
- package/dist/types/wallet-server/src/router/domains/voiceId/voiceIdSessions.d.ts +35 -0
- package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +3 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/walletVoiceIdActivation.d.ts +12 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/walletVoiceIdNear.d.ts +14 -0
- package/dist/types/wallet-server/src/router/transport/fetch/routes/walletVoiceIdSessions.d.ts +19 -0
- package/migrations/d1-signer/0083_voiceid_wallet_session_challenges.sql +29 -0
- package/migrations/d1-signer/0084_voiceid_wallet_auth_methods.sql +373 -0
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DigestB64u } from './canonicalPrimitives';
|
|
1
2
|
import { type EmailOtpProviderUserId, type WalletAuthorityBindingDigest, type WalletAuthMethodId, type WalletId, type WebAuthnCredentialIdB64u, type WebAuthnRpId } from './domainIds';
|
|
2
3
|
export type EmailOtpProvider = 'google' | 'email';
|
|
3
4
|
export type PasskeyFactorIdentity = {
|
|
@@ -6,6 +7,7 @@ export type PasskeyFactorIdentity = {
|
|
|
6
7
|
rpId?: never;
|
|
7
8
|
provider?: never;
|
|
8
9
|
providerUserId?: never;
|
|
10
|
+
deviceKeyId?: never;
|
|
9
11
|
};
|
|
10
12
|
export type EmailOtpFactorIdentity = {
|
|
11
13
|
kind: 'email_otp';
|
|
@@ -13,8 +15,17 @@ export type EmailOtpFactorIdentity = {
|
|
|
13
15
|
providerUserId: EmailOtpProviderUserId;
|
|
14
16
|
rpId?: never;
|
|
15
17
|
credentialIdB64u?: never;
|
|
18
|
+
deviceKeyId?: never;
|
|
16
19
|
};
|
|
17
|
-
export type
|
|
20
|
+
export type VoiceIdFactorIdentity = {
|
|
21
|
+
kind: 'voiceid';
|
|
22
|
+
deviceKeyId: DigestB64u;
|
|
23
|
+
rpId?: never;
|
|
24
|
+
credentialIdB64u?: never;
|
|
25
|
+
provider?: never;
|
|
26
|
+
providerUserId?: never;
|
|
27
|
+
};
|
|
28
|
+
export type AuthFactorIdentity = PasskeyFactorIdentity | EmailOtpFactorIdentity | VoiceIdFactorIdentity;
|
|
18
29
|
export type PasskeyWalletAuthAuthority = {
|
|
19
30
|
walletId: WalletId;
|
|
20
31
|
factor: PasskeyFactorIdentity;
|
|
@@ -43,7 +54,26 @@ export type EmailOtpWalletAuthAuthority = {
|
|
|
43
54
|
provider?: never;
|
|
44
55
|
providerUserId?: never;
|
|
45
56
|
};
|
|
46
|
-
export type
|
|
57
|
+
export type VoiceIdWalletAuthAuthority = {
|
|
58
|
+
walletId: WalletId;
|
|
59
|
+
factor: VoiceIdFactorIdentity;
|
|
60
|
+
verifier: {
|
|
61
|
+
kind: 'device_signature';
|
|
62
|
+
};
|
|
63
|
+
bindingId: WalletAuthMethodId;
|
|
64
|
+
kind?: never;
|
|
65
|
+
rpId?: never;
|
|
66
|
+
credentialIdB64u?: never;
|
|
67
|
+
provider?: never;
|
|
68
|
+
providerUserId?: never;
|
|
69
|
+
};
|
|
70
|
+
export type WalletAuthAuthority = PasskeyWalletAuthAuthority | EmailOtpWalletAuthAuthority | VoiceIdWalletAuthAuthority;
|
|
71
|
+
export declare function buildVoiceIdWalletAuthAuthority(input: {
|
|
72
|
+
walletId: WalletId;
|
|
73
|
+
walletAuthMethodId: WalletAuthMethodId;
|
|
74
|
+
deviceKeyId: DigestB64u;
|
|
75
|
+
}): VoiceIdWalletAuthAuthority;
|
|
76
|
+
export declare function isVoiceIdWalletAuthAuthority(authority: WalletAuthAuthority): authority is VoiceIdWalletAuthAuthority;
|
|
47
77
|
export declare function isPasskeyWalletAuthAuthority(authority: WalletAuthAuthority): authority is PasskeyWalletAuthAuthority;
|
|
48
78
|
export declare function isEmailOtpWalletAuthAuthority(authority: WalletAuthAuthority): authority is EmailOtpWalletAuthAuthority;
|
|
49
79
|
export declare function walletAuthAuthoritiesMatch(left: WalletAuthAuthority, right: WalletAuthAuthority): boolean;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type VoiceIdDevicePublicKeyB64u } from '../authorization/voiceIdDeviceAssertion';
|
|
1
2
|
import { type DigestB64u } from './canonicalPrimitives';
|
|
2
3
|
import { type WalletAuthMethodId, type WalletAuthorityId, type WalletId, type WebAuthnCredentialIdB64u, type WebAuthnRpId } from './domainIds';
|
|
3
4
|
import type { Variant, ReadonlyExclusiveUnion } from './variant';
|
|
@@ -77,6 +78,17 @@ export type EmailOtpWalletAuthMethodDraftV1 = WalletAuthMethodDraftCommonV1 & {
|
|
|
77
78
|
readonly credentialPublicKeyB64u?: never;
|
|
78
79
|
readonly counter?: never;
|
|
79
80
|
};
|
|
81
|
+
export type VoiceIdWalletAuthMethodDraftV1 = WalletAuthMethodDraftCommonV1 & {
|
|
82
|
+
readonly kind: 'voiceid';
|
|
83
|
+
readonly deviceKeyId: DigestB64u;
|
|
84
|
+
readonly devicePublicKeyB64u: VoiceIdDevicePublicKeyB64u;
|
|
85
|
+
readonly rpId?: never;
|
|
86
|
+
readonly credentialIdB64u?: never;
|
|
87
|
+
readonly credentialPublicKeyB64u?: never;
|
|
88
|
+
readonly counter?: never;
|
|
89
|
+
readonly emailHashHex?: never;
|
|
90
|
+
readonly registrationAuthorityId?: never;
|
|
91
|
+
};
|
|
80
92
|
type WalletAuthMethodCommonV1 = {
|
|
81
93
|
readonly version: 'wallet_auth_method_v2';
|
|
82
94
|
readonly walletAuthMethodId: WalletAuthMethodId;
|
|
@@ -85,14 +97,16 @@ type WalletAuthMethodCommonV1 = {
|
|
|
85
97
|
readonly createdAtMs: number;
|
|
86
98
|
readonly updatedAtMs: number;
|
|
87
99
|
};
|
|
88
|
-
export type WalletAuthMethodRecordV2 = WalletAuthMethodCommonV1 & ((PasskeyWalletAuthMethodDraftV1 & WalletAuthMethodLifecycleV1) | (EmailOtpWalletAuthMethodDraftV1 & WalletAuthMethodLifecycleV1));
|
|
100
|
+
export type WalletAuthMethodRecordV2 = WalletAuthMethodCommonV1 & ((PasskeyWalletAuthMethodDraftV1 & WalletAuthMethodLifecycleV1) | (EmailOtpWalletAuthMethodDraftV1 & WalletAuthMethodLifecycleV1) | (VoiceIdWalletAuthMethodDraftV1 & WalletAuthMethodLifecycleV1));
|
|
89
101
|
export type PasskeyWalletAuthMethodRecordV2 = Variant<WalletAuthMethodRecordV2, 'kind', 'passkey'>;
|
|
90
102
|
export type EmailOtpWalletAuthMethodRecordV2 = Variant<WalletAuthMethodRecordV2, 'kind', 'email_otp'>;
|
|
103
|
+
export type VoiceIdWalletAuthMethodRecordV2 = Variant<WalletAuthMethodRecordV2, 'kind', 'voiceid'>;
|
|
91
104
|
export type PendingWalletAuthMethodRecordV2 = Variant<WalletAuthMethodRecordV2, 'status', 'pending_local_install'>;
|
|
92
105
|
export type ActiveWalletAuthMethodRecordV2 = Variant<WalletAuthMethodRecordV2, 'status', 'active'>;
|
|
93
106
|
export type RevokedWalletAuthMethodRecordV2 = Variant<WalletAuthMethodRecordV2, 'status', 'revoked'>;
|
|
94
107
|
export type ActivePasskeyWalletAuthMethodRecordV2 = Variant<ActiveWalletAuthMethodRecordV2, 'kind', 'passkey'>;
|
|
95
108
|
export type ActiveEmailOtpWalletAuthMethodRecordV2 = Variant<ActiveWalletAuthMethodRecordV2, 'kind', 'email_otp'>;
|
|
109
|
+
export type ActiveVoiceIdWalletAuthMethodRecordV2 = Variant<ActiveWalletAuthMethodRecordV2, 'kind', 'voiceid'>;
|
|
96
110
|
export declare function sameWalletAuthMethodRecordV2(left: WalletAuthMethodRecordV2, right: WalletAuthMethodRecordV2): boolean;
|
|
97
111
|
export declare function buildWalletAuthMethodRecordV2(input: WalletAuthMethodRecordV2): WalletAuthMethodRecordV2;
|
|
98
112
|
export declare function parseWalletAuthMethodRecordV2(raw: unknown): WalletAuthMethodRecordV2 | null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type WalletAuthMethodId, type WalletId, type WebAuthnRpId } from './domainIds';
|
|
2
2
|
import { type ImplicitNearAccountId, type NamedNearAccountId } from './near';
|
|
3
3
|
import { type NearEd25519SigningKeyId } from './registrationIds';
|
|
4
|
+
import { type DigestB64u } from './canonicalPrimitives';
|
|
4
5
|
export type { WebAuthnRpId };
|
|
5
6
|
export type RpId = WebAuthnRpId;
|
|
6
7
|
export type WalletIdentity = {
|
|
@@ -15,6 +16,7 @@ export type WalletAuthMethodBinding = {
|
|
|
15
16
|
readonly walletAuthMethodId: WalletAuthMethodId;
|
|
16
17
|
readonly scope: PasskeyAuthScope;
|
|
17
18
|
readonly credentialIdB64u: string;
|
|
19
|
+
readonly deviceKeyId?: never;
|
|
18
20
|
} | {
|
|
19
21
|
readonly kind: 'email_otp';
|
|
20
22
|
readonly walletAuthMethodId: WalletAuthMethodId;
|
|
@@ -22,6 +24,17 @@ export type WalletAuthMethodBinding = {
|
|
|
22
24
|
readonly emailHashHex: string;
|
|
23
25
|
readonly registrationAuthorityId: string;
|
|
24
26
|
readonly rpId?: never;
|
|
27
|
+
readonly deviceKeyId?: never;
|
|
28
|
+
} | {
|
|
29
|
+
readonly kind: 'voiceid';
|
|
30
|
+
readonly walletAuthMethodId: WalletAuthMethodId;
|
|
31
|
+
readonly wallet: WalletIdentity;
|
|
32
|
+
readonly deviceKeyId: DigestB64u;
|
|
33
|
+
readonly scope?: never;
|
|
34
|
+
readonly credentialIdB64u?: never;
|
|
35
|
+
readonly emailHashHex?: never;
|
|
36
|
+
readonly registrationAuthorityId?: never;
|
|
37
|
+
readonly rpId?: never;
|
|
25
38
|
};
|
|
26
39
|
export type CurrentWalletAuthMethod = {
|
|
27
40
|
readonly kind: 'none';
|
|
@@ -74,6 +87,13 @@ export declare function buildEmailOtpWalletAuthMethodBinding(args: {
|
|
|
74
87
|
emailHashHex: string;
|
|
75
88
|
registrationAuthorityId: string;
|
|
76
89
|
}): WalletAuthMethodBinding;
|
|
90
|
+
export declare function buildVoiceIdWalletAuthMethodBinding(args: {
|
|
91
|
+
walletAuthMethodId: WalletAuthMethodId;
|
|
92
|
+
wallet: WalletIdentity;
|
|
93
|
+
deviceKeyId: DigestB64u;
|
|
94
|
+
}): Extract<WalletAuthMethodBinding, {
|
|
95
|
+
kind: 'voiceid';
|
|
96
|
+
}>;
|
|
77
97
|
export declare function walletAuthMethodBindingFromRaw(raw: unknown): WalletCapabilityBindingParseResult<WalletAuthMethodBinding>;
|
|
78
98
|
export declare function buildNoCurrentWalletAuthMethod(): Extract<CurrentWalletAuthMethod, {
|
|
79
99
|
kind: 'none';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type VoiceIdDevicePublicKeyB64u, type VoiceIdWalletSessionChallenge } from '../../../shared-ts/src/authorization/voiceIdDeviceAssertion';
|
|
2
|
+
import { type DigestB64u } from '../../../shared-ts/src/utils/canonicalPrimitives';
|
|
3
|
+
import type { WalletAuthMethodId, WalletAuthorityId, WalletId } from '../../../shared-ts/src/utils/domainIds';
|
|
4
|
+
export type RegisteredVoiceIdDeviceKey = Readonly<{
|
|
5
|
+
walletId: WalletId;
|
|
6
|
+
walletAuthMethodId: WalletAuthMethodId;
|
|
7
|
+
walletAuthorityId: WalletAuthorityId;
|
|
8
|
+
deviceKeyId: DigestB64u;
|
|
9
|
+
publicKeyB64u: VoiceIdDevicePublicKeyB64u;
|
|
10
|
+
status: 'active';
|
|
11
|
+
}>;
|
|
12
|
+
declare class VerifiedVoiceIdWalletSessionProof {
|
|
13
|
+
readonly challenge: VoiceIdWalletSessionChallenge;
|
|
14
|
+
readonly deviceKeyId: DigestB64u;
|
|
15
|
+
private readonly proofBrand;
|
|
16
|
+
constructor(challenge: VoiceIdWalletSessionChallenge, deviceKeyId: DigestB64u);
|
|
17
|
+
}
|
|
18
|
+
export type VerifiedVoiceIdSessionProof = VerifiedVoiceIdWalletSessionProof;
|
|
19
|
+
export type ConsumeVoiceIdChallenge = (challenge: VoiceIdWalletSessionChallenge, nowMs: number) => Promise<boolean>;
|
|
20
|
+
/** Only this server boundary turns a signed device result into verified proof. */
|
|
21
|
+
export declare function verifyVoiceIdWalletSessionAssertion(input: {
|
|
22
|
+
registered: RegisteredVoiceIdDeviceKey;
|
|
23
|
+
expectedChallenge: VoiceIdWalletSessionChallenge;
|
|
24
|
+
assertion: unknown;
|
|
25
|
+
nowMs: number;
|
|
26
|
+
consumeChallenge: ConsumeVoiceIdChallenge;
|
|
27
|
+
}): Promise<VerifiedVoiceIdSessionProof>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=voiceIdDeviceProof.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type WalletAuthMethodId, type WalletAuthorityId, type WalletId } from '../../../shared-ts/src/utils/domainIds';
|
|
2
2
|
import type { DigestB64u } from '../../../shared-ts/src/utils/canonicalPrimitives';
|
|
3
|
-
import { type ActiveWalletAuthMethodRecordV2, type WalletAuthMethodRecord as SharedWalletAuthMethodRecord, type WalletAuthMethodRecordV2 } from '../../../shared-ts/src/utils/walletAuthMethodRecord';
|
|
3
|
+
import { type ActiveWalletAuthMethodRecordV2, type ActiveVoiceIdWalletAuthMethodRecordV2, type WalletAuthMethodRecord as SharedWalletAuthMethodRecord, type WalletAuthMethodRecordV2 } from '../../../shared-ts/src/utils/walletAuthMethodRecord';
|
|
4
4
|
import type { D1DatabaseLike, D1PreparedStatementLike } from '../storage/tenantRoute';
|
|
5
5
|
import { type D1SchemaOptions, type D1TenantScope, type D1TenantStoreOptions } from './d1TenantStore';
|
|
6
6
|
export type WalletAuthMethodRecord = SharedWalletAuthMethodRecord;
|
|
@@ -27,6 +27,11 @@ export type WalletAuthMethodV2Store = {
|
|
|
27
27
|
readByIdV2(input: {
|
|
28
28
|
readonly walletAuthMethodId: WalletAuthMethodId;
|
|
29
29
|
}): Promise<WalletAuthMethodRecordV2 | null>;
|
|
30
|
+
getActiveVoiceIdV2(input: {
|
|
31
|
+
readonly walletId: WalletId;
|
|
32
|
+
readonly walletAuthMethodId: WalletAuthMethodId;
|
|
33
|
+
readonly walletAuthorityId: WalletAuthorityId;
|
|
34
|
+
}): Promise<ActiveVoiceIdWalletAuthMethodRecordV2 | null>;
|
|
30
35
|
getPasskeyV2(input: {
|
|
31
36
|
readonly rpId: string;
|
|
32
37
|
readonly credentialIdB64u: string;
|
|
@@ -70,7 +75,7 @@ export declare const WALLET_AUTH_METHOD_STORE_D1_SCHEMA_SQL: readonly ["\n CR
|
|
|
70
75
|
* statements; keeping the SQL here lets focused D1 tests provision the V2
|
|
71
76
|
* table without copying migration text into a test.
|
|
72
77
|
*/
|
|
73
|
-
export declare const WALLET_AUTH_METHOD_STORE_D1_SCHEMA_V2_SQL: readonly ["\n CREATE TABLE IF NOT EXISTS wallet_auth_methods (\n namespace TEXT NOT NULL,\n org_id TEXT NOT NULL,\n project_id TEXT NOT NULL,\n env_id TEXT NOT NULL,\n wallet_id TEXT NOT NULL,\n wallet_authority_id TEXT NOT NULL,\n rp_id TEXT NOT NULL DEFAULT '',\n kind TEXT NOT NULL,\n status TEXT NOT NULL,\n wallet_auth_method_id TEXT NOT NULL,\n auth_identifier_key TEXT NOT NULL,\n credential_id_b64u TEXT,\n credential_public_key_b64u TEXT,\n email_hash_hex TEXT,\n registration_authority_id TEXT,\n record_json TEXT NOT NULL,\n created_at_ms INTEGER NOT NULL,\n updated_at_ms INTEGER NOT NULL,\n activated_at_ms INTEGER,\n revoked_at_ms INTEGER,\n PRIMARY KEY (namespace, org_id, project_id, env_id, wallet_auth_method_id),\n FOREIGN KEY (\n namespace,\n org_id,\n project_id,\n env_id,\n wallet_authority_id\n ) REFERENCES wallet_authorities(\n namespace,\n org_id,\n project_id,\n env_id,\n authority_id\n ),\n CHECK (length(wallet_id) > 0),\n CHECK (length(wallet_authority_id) > 0),\n CHECK (kind IN ('passkey', 'email_otp')),\n CHECK (status IN ('pending_local_install', 'active', 'revoked')),\n CHECK (length(wallet_auth_method_id) > 0),\n CHECK (length(auth_identifier_key) > 0),\n CHECK (json_valid(record_json)),\n CHECK (created_at_ms >= 0),\n CHECK (updated_at_ms >= created_at_ms),\n CHECK (\n (status = 'pending_local_install' AND activated_at_ms IS NULL AND revoked_at_ms IS NULL)\n OR\n (status = 'active' AND activated_at_ms IS NOT NULL AND revoked_at_ms IS NULL)\n OR\n (status = 'revoked' AND activated_at_ms IS NOT NULL AND revoked_at_ms IS NOT NULL)\n ),\n CHECK (\n (kind = 'passkey'\n AND length(rp_id) > 0\n AND credential_id_b64u IS NOT NULL\n AND length(credential_id_b64u) > 0\n AND credential_public_key_b64u IS NOT NULL\n AND length(credential_public_key_b64u) > 0\n AND email_hash_hex IS NULL\n AND registration_authority_id IS NULL\n AND auth_identifier_key = credential_id_b64u)\n OR\n (kind = 'email_otp'\n AND rp_id = ''\n AND credential_id_b64u IS NULL\n AND credential_public_key_b64u IS NULL\n AND email_hash_hex IS NOT NULL\n AND length(email_hash_hex) > 0\n AND registration_authority_id IS NOT NULL\n AND length(registration_authority_id) > 0\n AND auth_identifier_key = email_hash_hex)\n ),\n CHECK (json_extract(record_json, '$.version') = 'wallet_auth_method_v2'),\n CHECK (json_extract(record_json, '$.walletAuthMethodId') = wallet_auth_method_id),\n CHECK (json_extract(record_json, '$.walletId') = wallet_id),\n CHECK (json_extract(record_json, '$.walletAuthorityId') = wallet_authority_id),\n CHECK (json_extract(record_json, '$.kind') = kind),\n CHECK (json_extract(record_json, '$.status') = status),\n CHECK (json_extract(record_json, '$.createdAtMs') = created_at_ms),\n CHECK (json_extract(record_json, '$.updatedAtMs') = updated_at_ms),\n CHECK (\n (kind = 'passkey'\n AND json_extract(record_json, '$.rpId') = rp_id\n AND json_extract(record_json, '$.credentialIdB64u') = credential_id_b64u\n AND json_extract(record_json, '$.credentialPublicKeyB64u') = credential_public_key_b64u\n AND json_extract(record_json, '$.counter') >= 0)\n OR\n (kind = 'email_otp'\n AND json_extract(record_json, '$.emailHashHex') = email_hash_hex\n AND json_extract(record_json, '$.registrationAuthorityId') = registration_authority_id)\n )\n )\n ", "\n CREATE INDEX IF NOT EXISTS wallet_auth_methods_wallet_authority_status_idx\n ON wallet_auth_methods (\n namespace,\n org_id,\n project_id,\n env_id,\n wallet_id,\n wallet_authority_id,\n status\n )\n ", "\n CREATE UNIQUE INDEX IF NOT EXISTS wallet_auth_methods_v2_passkey_uidx\n ON wallet_auth_methods (\n namespace,\n org_id,\n project_id,\n env_id,\n rp_id,\n credential_id_b64u\n )\n WHERE kind = 'passkey' AND credential_id_b64u IS NOT NULL\n "];
|
|
78
|
+
export declare const WALLET_AUTH_METHOD_STORE_D1_SCHEMA_V2_SQL: readonly ["\n CREATE TABLE IF NOT EXISTS wallet_auth_methods (\n namespace TEXT NOT NULL,\n org_id TEXT NOT NULL,\n project_id TEXT NOT NULL,\n env_id TEXT NOT NULL,\n wallet_id TEXT NOT NULL,\n wallet_authority_id TEXT NOT NULL,\n rp_id TEXT NOT NULL DEFAULT '',\n kind TEXT NOT NULL,\n status TEXT NOT NULL,\n wallet_auth_method_id TEXT NOT NULL,\n auth_identifier_key TEXT NOT NULL,\n credential_id_b64u TEXT,\n credential_public_key_b64u TEXT,\n email_hash_hex TEXT,\n registration_authority_id TEXT,\n record_json TEXT NOT NULL,\n created_at_ms INTEGER NOT NULL,\n updated_at_ms INTEGER NOT NULL,\n activated_at_ms INTEGER,\n revoked_at_ms INTEGER,\n provider TEXT,\n provider_user_id TEXT,\n PRIMARY KEY (namespace, org_id, project_id, env_id, wallet_auth_method_id),\n FOREIGN KEY (\n namespace,\n org_id,\n project_id,\n env_id,\n wallet_authority_id\n ) REFERENCES wallet_authorities(\n namespace,\n org_id,\n project_id,\n env_id,\n authority_id\n ),\n CHECK (length(wallet_id) > 0),\n CHECK (length(wallet_authority_id) > 0),\n CHECK (kind IN ('passkey', 'email_otp', 'voiceid')),\n CHECK (status IN ('pending_local_install', 'active', 'revoked')),\n CHECK (length(wallet_auth_method_id) > 0),\n CHECK (length(auth_identifier_key) > 0),\n CHECK (json_valid(record_json)),\n CHECK (created_at_ms >= 0),\n CHECK (updated_at_ms >= created_at_ms),\n CHECK (\n (status = 'pending_local_install' AND activated_at_ms IS NULL AND revoked_at_ms IS NULL)\n OR\n (status = 'active' AND activated_at_ms IS NOT NULL AND revoked_at_ms IS NULL)\n OR\n (status = 'revoked' AND activated_at_ms IS NOT NULL AND revoked_at_ms IS NOT NULL)\n ),\n CHECK (\n (kind = 'passkey'\n AND length(rp_id) > 0\n AND credential_id_b64u IS NOT NULL\n AND length(credential_id_b64u) > 0\n AND credential_public_key_b64u IS NOT NULL\n AND length(credential_public_key_b64u) > 0\n AND email_hash_hex IS NULL\n AND registration_authority_id IS NULL\n AND auth_identifier_key = credential_id_b64u)\n OR\n (kind = 'email_otp'\n AND rp_id = ''\n AND credential_id_b64u IS NULL\n AND credential_public_key_b64u IS NULL\n AND email_hash_hex IS NOT NULL\n AND length(email_hash_hex) > 0\n AND registration_authority_id IS NOT NULL\n AND length(registration_authority_id) > 0\n AND auth_identifier_key = email_hash_hex)\n OR\n (kind = 'voiceid'\n AND rp_id = ''\n AND credential_id_b64u IS NULL\n AND credential_public_key_b64u IS NOT NULL\n AND length(credential_public_key_b64u) = 43\n AND email_hash_hex IS NULL\n AND registration_authority_id IS NULL\n AND provider IS NULL\n AND provider_user_id IS NULL\n AND length(auth_identifier_key) = 43\n AND COALESCE(auth_identifier_key = json_extract(record_json, '$.deviceKeyId'), 0))\n ),\n CHECK (json_extract(record_json, '$.version') = 'wallet_auth_method_v2'),\n CHECK (json_extract(record_json, '$.walletAuthMethodId') = wallet_auth_method_id),\n CHECK (json_extract(record_json, '$.walletId') = wallet_id),\n CHECK (json_extract(record_json, '$.walletAuthorityId') = wallet_authority_id),\n CHECK (json_extract(record_json, '$.kind') = kind),\n CHECK (json_extract(record_json, '$.status') = status),\n CHECK (json_extract(record_json, '$.createdAtMs') = created_at_ms),\n CHECK (json_extract(record_json, '$.updatedAtMs') = updated_at_ms),\n CHECK (\n (kind = 'passkey'\n AND json_extract(record_json, '$.rpId') = rp_id\n AND json_extract(record_json, '$.credentialIdB64u') = credential_id_b64u\n AND json_extract(record_json, '$.credentialPublicKeyB64u') = credential_public_key_b64u\n AND json_extract(record_json, '$.counter') >= 0)\n OR\n (kind = 'email_otp'\n AND json_extract(record_json, '$.emailHashHex') = email_hash_hex\n AND json_extract(record_json, '$.registrationAuthorityId') = registration_authority_id)\n OR\n (kind = 'voiceid'\n AND COALESCE(json_extract(record_json, '$.deviceKeyId') = auth_identifier_key, 0)\n AND COALESCE(json_extract(record_json, '$.devicePublicKeyB64u') = credential_public_key_b64u, 0))\n )\n )\n ", "\n CREATE INDEX IF NOT EXISTS wallet_auth_methods_wallet_authority_status_idx\n ON wallet_auth_methods (\n namespace,\n org_id,\n project_id,\n env_id,\n wallet_id,\n wallet_authority_id,\n status\n )\n ", "\n CREATE UNIQUE INDEX IF NOT EXISTS wallet_auth_methods_v2_voiceid_key_uidx\n ON wallet_auth_methods (\n namespace, org_id, project_id, env_id, auth_identifier_key\n )\n WHERE kind = 'voiceid'\n ", "\n CREATE UNIQUE INDEX IF NOT EXISTS wallet_auth_methods_v2_passkey_uidx\n ON wallet_auth_methods (\n namespace,\n org_id,\n project_id,\n env_id,\n rp_id,\n credential_id_b64u\n )\n WHERE kind = 'passkey' AND credential_id_b64u IS NOT NULL\n "];
|
|
74
79
|
export declare function ensureWalletAuthMethodStoreD1Schema(options: D1WalletAuthMethodStoreSchemaOptions): Promise<void>;
|
|
75
80
|
export declare function walletAuthMethodId(record: WalletAuthMethodRecord): WalletAuthMethodId;
|
|
76
81
|
export declare function normalizeWalletAuthMethod(raw: unknown): WalletAuthMethodRecord | null;
|
|
@@ -178,6 +183,12 @@ export declare class D1WalletAuthMethodStore implements WalletAuthMethodStore, W
|
|
|
178
183
|
readByIdV2(input: {
|
|
179
184
|
readonly walletAuthMethodId: WalletAuthMethodId;
|
|
180
185
|
}): Promise<WalletAuthMethodRecordV2 | null>;
|
|
186
|
+
/** Checks the method record. Session issuance must also check its parent authority. */
|
|
187
|
+
getActiveVoiceIdV2(input: {
|
|
188
|
+
readonly walletId: WalletId;
|
|
189
|
+
readonly walletAuthMethodId: WalletAuthMethodId;
|
|
190
|
+
readonly walletAuthorityId: WalletAuthorityId;
|
|
191
|
+
}): Promise<ActiveVoiceIdWalletAuthMethodRecordV2 | null>;
|
|
181
192
|
getPasskeyV2(input: {
|
|
182
193
|
rpId: string;
|
|
183
194
|
credentialIdB64u: string;
|
|
@@ -276,6 +276,14 @@ export type WalletRevokeAuthMethodResponse = {
|
|
|
276
276
|
kind: typeof WALLET_AUTH_METHODS.emailOtp;
|
|
277
277
|
};
|
|
278
278
|
rpId?: never;
|
|
279
|
+
} | {
|
|
280
|
+
ok: true;
|
|
281
|
+
walletId: WalletId;
|
|
282
|
+
authMethod: {
|
|
283
|
+
kind: 'voiceid';
|
|
284
|
+
status: 'revoked';
|
|
285
|
+
};
|
|
286
|
+
rpId?: never;
|
|
279
287
|
} | {
|
|
280
288
|
ok: false;
|
|
281
289
|
code: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type OwnerWalletExecutionLaneProjectionV1 } from '../../../../shared-ts/src/signing-lanes';
|
|
2
|
+
import { type DigestB64u } from '../../../../shared-ts/src/utils/canonicalPrimitives';
|
|
2
3
|
import type { MpcMaterialActivationRef, ProviderSubject, WalletAuthMethodId, WalletId } from '../../../../shared-ts/src/utils/domainIds';
|
|
3
4
|
import { type WalletAuthMethodRecordV2 } from '../../../../shared-ts/src/utils/walletAuthMethodRecord';
|
|
4
5
|
import { type WalletAuthAuthorityRef } from '../../../../shared-ts/src/utils/walletAuthAuthority';
|
|
@@ -21,6 +22,9 @@ export interface WalletExecutionLaneProjectionSource {
|
|
|
21
22
|
}): Promise<readonly WalletSignerRecord[]>;
|
|
22
23
|
}
|
|
23
24
|
export type WalletExecutionLaneAuthSource = {
|
|
25
|
+
readonly kind: 'voiceid';
|
|
26
|
+
readonly deviceKeyId: DigestB64u;
|
|
27
|
+
} | {
|
|
24
28
|
readonly kind: 'passkey';
|
|
25
29
|
readonly credentialIdB64u: string;
|
|
26
30
|
} | {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DigestB64u } from '../../../../../../shared-ts/src/utils/canonicalPrimitives';
|
|
1
2
|
import { type PasskeyDeviceEnvelopeIndexRecord, type PasskeyCustodyEnvelopeRecord, type WalletCustodyEnvelopeOwnership } from '../../../../../../shared-ts/src/passkey-custody';
|
|
2
3
|
import { type WalletCredentialActivityRecordV1 } from '../../../../../../shared-ts/src/passkey-custody/credentialActivity';
|
|
3
4
|
import type { PasskeyEnvelopeId, WalletId, WebAuthnCredentialIdB64u, WebAuthnRpId, WalletAuthMethodId } from '../../../../../../shared-ts/src/utils/domainIds';
|
|
@@ -45,6 +46,9 @@ export type WalletCustodyFactorRef = {
|
|
|
45
46
|
readonly kind: 'email_otp';
|
|
46
47
|
readonly enrollmentId: string;
|
|
47
48
|
readonly enrollmentSealKeyVersion: string;
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: 'voiceid';
|
|
51
|
+
readonly deviceKeyId: DigestB64u;
|
|
48
52
|
};
|
|
49
53
|
export type PasskeyCustodyEnvelopeLocator = {
|
|
50
54
|
readonly walletId: WalletId;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { D1WalletAuthMethodStore } from '../../../../core/d1WalletAuthMethodStore';
|
|
2
|
+
import type { D1TenantScope } from '../../../../core/d1TenantStore';
|
|
3
|
+
import type { D1DatabaseLike } from '../../../../storage/tenantRoute';
|
|
4
|
+
import type { CloudflareD1PasskeyCustodyEnvelopeStore } from '../passkeyCustody/d1PasskeyCustodyEnvelopeStore';
|
|
5
|
+
import type { VoiceIdActivationCommand, VoiceIdActivationResult } from '../../../domains/voiceId/voiceIdActivation';
|
|
6
|
+
export declare class D1VoiceIdActivation {
|
|
7
|
+
private readonly database;
|
|
8
|
+
private readonly scope;
|
|
9
|
+
private readonly authMethods;
|
|
10
|
+
private readonly envelopes;
|
|
11
|
+
constructor(database: D1DatabaseLike, scope: D1TenantScope, authMethods: D1WalletAuthMethodStore, envelopes: CloudflareD1PasskeyCustodyEnvelopeStore);
|
|
12
|
+
activate(input: VoiceIdActivationCommand): Promise<VoiceIdActivationResult>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=d1VoiceIdActivation.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AuthorizationService } from '../../../../authorization/service';
|
|
2
|
+
import type { D1WalletAuthMethodStore } from '../../../../core/d1WalletAuthMethodStore';
|
|
3
|
+
import type { CloudflareD1PasskeyCustodyEnvelopeStore } from '../passkeyCustody/d1PasskeyCustodyEnvelopeStore';
|
|
4
|
+
import type { D1WalletAuthorityStore } from './d1WalletAuthorityStore';
|
|
5
|
+
import type { VoiceIdChallengeRequest, VoiceIdChallengeResult, VoiceIdVerifyRequest, VoiceIdVerifyResult } from '../../../domains/voiceId/voiceIdSessions';
|
|
6
|
+
import { D1VoiceIdWalletSessionChallenges } from './d1VoiceIdWalletSessionChallenges';
|
|
7
|
+
export declare class D1VoiceIdSessions {
|
|
8
|
+
private readonly authMethods;
|
|
9
|
+
private readonly authorities;
|
|
10
|
+
private readonly envelopes;
|
|
11
|
+
private readonly challenges;
|
|
12
|
+
private readonly authorization;
|
|
13
|
+
private readonly tenantId;
|
|
14
|
+
constructor(authMethods: D1WalletAuthMethodStore, authorities: D1WalletAuthorityStore, envelopes: CloudflareD1PasskeyCustodyEnvelopeStore, challenges: D1VoiceIdWalletSessionChallenges, authorization: Pick<AuthorizationService, 'issueDirectWalletSessionAuthorizationV2'>, orgId: string);
|
|
15
|
+
private resolveActiveMethod;
|
|
16
|
+
issueChallenge(input: VoiceIdChallengeRequest): Promise<VoiceIdChallengeResult>;
|
|
17
|
+
verifyAndIssue(input: VoiceIdVerifyRequest): Promise<VoiceIdVerifyResult>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=d1VoiceIdSessions.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type WalletSessionMintId } from '../../../../../../shared-ts/src/authorization/capabilityKinds';
|
|
2
|
+
import { type VoiceIdWalletSessionChallenge } from '../../../../../../shared-ts/src/authorization/voiceIdDeviceAssertion';
|
|
3
|
+
import type { RegisteredVoiceIdDeviceKey } from '../../../../authorization/voiceIdDeviceProof';
|
|
4
|
+
import type { D1TenantScope } from '../../../../core/d1TenantStore';
|
|
5
|
+
import type { D1DatabaseLike } from '../../../../storage/tenantRoute';
|
|
6
|
+
export declare class D1VoiceIdWalletSessionChallenges {
|
|
7
|
+
private readonly database;
|
|
8
|
+
private readonly scope;
|
|
9
|
+
constructor(database: D1DatabaseLike, scope: D1TenantScope);
|
|
10
|
+
issue(input: {
|
|
11
|
+
readonly registered: RegisteredVoiceIdDeviceKey;
|
|
12
|
+
readonly requestOrigin: string;
|
|
13
|
+
readonly audience: string;
|
|
14
|
+
readonly nowMs: number;
|
|
15
|
+
}): Promise<VoiceIdWalletSessionChallenge>;
|
|
16
|
+
read(input: {
|
|
17
|
+
readonly challengeId: WalletSessionMintId;
|
|
18
|
+
readonly requestOrigin: string;
|
|
19
|
+
readonly audience: string;
|
|
20
|
+
readonly nowMs: number;
|
|
21
|
+
}): Promise<VoiceIdWalletSessionChallenge | null>;
|
|
22
|
+
consume(challenge: VoiceIdWalletSessionChallenge, nowMs: number): Promise<boolean>;
|
|
23
|
+
private pruneExpired;
|
|
24
|
+
private scopeValues;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=d1VoiceIdWalletSessionChallenges.d.ts.map
|
package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts
CHANGED
|
@@ -92,6 +92,7 @@ type WalletAuthMethodAuthorityResult = {
|
|
|
92
92
|
type Sha256Bytes = (input: Uint8Array) => Promise<Uint8Array>;
|
|
93
93
|
type RegistrationCeremonyStoreProvider = () => CloudflareD1RegistrationCeremonyIntentStore;
|
|
94
94
|
type WalletAuthMethodStoreProvider = () => D1WalletAuthMethodStore;
|
|
95
|
+
export declare function isFullOwnerAuthorityV1(authority: ActiveWalletAuthorityV1): boolean;
|
|
95
96
|
export declare class CloudflareD1WalletAuthMethodService {
|
|
96
97
|
private readonly emailOtpChallengeVerifier;
|
|
97
98
|
private readonly emailOtpEnrollmentChallengeIssuer;
|
package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts
CHANGED
|
@@ -60,6 +60,31 @@ export declare function readWalletRelocationOwner(database: D1DatabaseLike, scop
|
|
|
60
60
|
readonly status: 'active';
|
|
61
61
|
readonly activatedAtMs: number;
|
|
62
62
|
readonly revokedAtMs?: undefined;
|
|
63
|
+
}) | ({
|
|
64
|
+
readonly version: 'wallet_auth_method_v2';
|
|
65
|
+
readonly walletAuthMethodId: import("../../../../../../shared-ts/src/utils").WalletAuthMethodId;
|
|
66
|
+
readonly walletId: import("../../../../../../shared-ts/src/utils").WalletId;
|
|
67
|
+
readonly walletAuthorityId: import("../../../../../../shared-ts/src/utils").WalletAuthorityId;
|
|
68
|
+
readonly createdAtMs: number;
|
|
69
|
+
readonly updatedAtMs: number;
|
|
70
|
+
} & {
|
|
71
|
+
readonly walletAuthMethodId: import("../../../../../../shared-ts/src/utils").WalletAuthMethodId;
|
|
72
|
+
readonly walletId: import("../../../../../../shared-ts/src/utils").WalletId;
|
|
73
|
+
readonly createdAtMs: number;
|
|
74
|
+
} & {
|
|
75
|
+
readonly kind: 'voiceid';
|
|
76
|
+
readonly deviceKeyId: DigestB64u;
|
|
77
|
+
readonly devicePublicKeyB64u: import("../../../../../../shared-ts/src/authorization/voiceIdDeviceAssertion").VoiceIdDevicePublicKeyB64u;
|
|
78
|
+
readonly rpId?: never;
|
|
79
|
+
readonly credentialIdB64u?: never;
|
|
80
|
+
readonly credentialPublicKeyB64u?: never;
|
|
81
|
+
readonly counter?: never;
|
|
82
|
+
readonly emailHashHex?: never;
|
|
83
|
+
readonly registrationAuthorityId?: never;
|
|
84
|
+
} & {
|
|
85
|
+
readonly status: 'active';
|
|
86
|
+
readonly activatedAtMs: number;
|
|
87
|
+
readonly revokedAtMs?: undefined;
|
|
63
88
|
});
|
|
64
89
|
authority: {
|
|
65
90
|
readonly kind: 'wallet_authority_v1';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ActiveWalletAuthorityV1 } from '../../../../../shared-ts/src/authorization/walletAuthority';
|
|
2
|
+
import type { VoiceIdDevicePublicKeyB64u } from '../../../../../shared-ts/src/authorization/voiceIdDeviceAssertion';
|
|
3
|
+
import type { WalletAuthMethodId } from '../../../../../shared-ts/src/utils/domainIds';
|
|
4
|
+
import type { ActiveEmailOtpWalletAuthMethodRecordV2, ActivePasskeyWalletAuthMethodRecordV2, ActiveVoiceIdWalletAuthMethodRecordV2 } from '../../../../../shared-ts/src/utils/walletAuthMethodRecord';
|
|
5
|
+
import { type VoiceIdSeedEnvelope } from '../../../../../shared-ts/src/passkey-custody/custodyEnvelope';
|
|
6
|
+
import type { IssuedWalletSessionAuthorizationV2 } from '../../../authorization/domain';
|
|
7
|
+
export type VoiceIdActivationEnvelope = VoiceIdSeedEnvelope;
|
|
8
|
+
export type VoiceIdActivationOwnerSession = Readonly<{
|
|
9
|
+
authorization: IssuedWalletSessionAuthorizationV2;
|
|
10
|
+
authority: ActiveWalletAuthorityV1;
|
|
11
|
+
authMethod: ActivePasskeyWalletAuthMethodRecordV2 | ActiveEmailOtpWalletAuthMethodRecordV2;
|
|
12
|
+
}>;
|
|
13
|
+
export type VoiceIdActivationCommand = Readonly<{
|
|
14
|
+
source: VoiceIdActivationOwnerSession;
|
|
15
|
+
targetWalletAuthMethodId: WalletAuthMethodId;
|
|
16
|
+
devicePublicKeyB64u: VoiceIdDevicePublicKeyB64u;
|
|
17
|
+
envelope: VoiceIdActivationEnvelope;
|
|
18
|
+
nowMs: number;
|
|
19
|
+
}>;
|
|
20
|
+
export type VoiceIdActivationResult = {
|
|
21
|
+
readonly kind: 'activated';
|
|
22
|
+
readonly authMethod: ActiveVoiceIdWalletAuthMethodRecordV2;
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: 'rejected';
|
|
25
|
+
readonly code: 'invalid_source' | 'invalid_target' | 'conflict';
|
|
26
|
+
};
|
|
27
|
+
/** Accepts only a method-bound owner seed envelope for the new VoiceID method. */
|
|
28
|
+
export declare function parseVoiceIdActivationEnvelope(raw: unknown): VoiceIdActivationEnvelope;
|
|
29
|
+
//# sourceMappingURL=voiceIdActivation.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { VoiceIdDeviceAssertion, VoiceIdWalletSessionChallenge } from '../../../../../shared-ts/src/authorization/voiceIdDeviceAssertion';
|
|
2
|
+
import type { WalletAuthMethodId, WalletId } from '../../../../../shared-ts/src/utils/domainIds';
|
|
3
|
+
import type { VoiceIdSeedEnvelope } from '../../../../../shared-ts/src/passkey-custody/custodyEnvelope';
|
|
4
|
+
import type { DirectV2IssueResult, IssuedWalletSessionAuthorizationV2 } from '../../../authorization/domain';
|
|
5
|
+
import type { SessionOrigin } from '../../../authorization/domain';
|
|
6
|
+
export type VoiceIdChallengeRequest = Readonly<{
|
|
7
|
+
walletId: WalletId;
|
|
8
|
+
walletAuthMethodId: WalletAuthMethodId;
|
|
9
|
+
requestOrigin: SessionOrigin;
|
|
10
|
+
nowMs: number;
|
|
11
|
+
}>;
|
|
12
|
+
export type VoiceIdChallengeResult = {
|
|
13
|
+
readonly kind: 'issued';
|
|
14
|
+
readonly challenge: VoiceIdWalletSessionChallenge;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: 'rejected';
|
|
17
|
+
readonly code: 'method_unavailable';
|
|
18
|
+
};
|
|
19
|
+
export type VoiceIdVerifyRequest = Readonly<{
|
|
20
|
+
assertion: VoiceIdDeviceAssertion;
|
|
21
|
+
requestOrigin: SessionOrigin;
|
|
22
|
+
nowMs: number;
|
|
23
|
+
}>;
|
|
24
|
+
export type VoiceIdVerifyResult = {
|
|
25
|
+
readonly kind: 'issued';
|
|
26
|
+
readonly authorization: IssuedWalletSessionAuthorizationV2;
|
|
27
|
+
readonly operationCredential: Extract<DirectV2IssueResult, {
|
|
28
|
+
readonly kind: 'issued';
|
|
29
|
+
}>['operationCredential'];
|
|
30
|
+
readonly custodyEnvelope: VoiceIdSeedEnvelope;
|
|
31
|
+
} | {
|
|
32
|
+
readonly kind: 'rejected';
|
|
33
|
+
readonly code: 'challenge_unavailable' | 'method_unavailable' | 'invalid_assertion' | 'issuance_unavailable';
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=voiceIdSessions.d.ts.map
|
|
@@ -1075,6 +1075,7 @@ interface RouterApiWalletAuthVerificationService {
|
|
|
1075
1075
|
verifyWebAuthnAuthenticationLite(input: RouterApiMethodTypes['verifyWebAuthnAuthenticationLite']['input']): Promise<RouterApiMethodTypes['verifyWebAuthnAuthenticationLite']['result']>;
|
|
1076
1076
|
}
|
|
1077
1077
|
export interface RouterApiWalletAuthMethodService {
|
|
1078
|
+
activateVoiceId(input: import('../domains/voiceId/voiceIdActivation').VoiceIdActivationCommand): Promise<import('../domains/voiceId/voiceIdActivation').VoiceIdActivationResult>;
|
|
1078
1079
|
resolveActiveWalletSessionAuthority(input: {
|
|
1079
1080
|
readonly walletId: WalletId;
|
|
1080
1081
|
readonly authorityRef: WalletAuthAuthorityRef;
|
|
@@ -1204,6 +1205,8 @@ export interface RouterApiWalletRegistrationRouteService extends RouterApiWallet
|
|
|
1204
1205
|
listWalletEcdsaKeyFactsInventory(input: RouterApiMethodTypes['listWalletEcdsaKeyFactsInventory']['input']): Promise<RouterApiMethodTypes['listWalletEcdsaKeyFactsInventory']['result']>;
|
|
1205
1206
|
}
|
|
1206
1207
|
export interface RouterApiWalletUnlockService {
|
|
1208
|
+
issueVoiceIdChallenge(input: import('../domains/voiceId/voiceIdSessions').VoiceIdChallengeRequest): Promise<import('../domains/voiceId/voiceIdSessions').VoiceIdChallengeResult>;
|
|
1209
|
+
verifyAndIssueVoiceId(input: import('../domains/voiceId/voiceIdSessions').VoiceIdVerifyRequest): Promise<import('../domains/voiceId/voiceIdSessions').VoiceIdVerifyResult>;
|
|
1207
1210
|
createEmailOtpUnlockChallenge(input: RouterApiMethodTypes['createEmailOtpUnlockChallenge']['input']): Promise<RouterApiMethodTypes['createEmailOtpUnlockChallenge']['result']>;
|
|
1208
1211
|
createWebAuthnLoginOptions(input: RouterApiMethodTypes['createWebAuthnLoginOptions']['input']): Promise<RouterApiMethodTypes['createWebAuthnLoginOptions']['result']>;
|
|
1209
1212
|
markEmailOtpStrongAuthSatisfied(input: RouterApiMethodTypes['markEmailOtpStrongAuthSatisfied']['input']): Promise<RouterApiMethodTypes['markEmailOtpStrongAuthSatisfied']['result']>;
|
package/dist/types/wallet-server/src/router/transport/fetch/routes/walletVoiceIdActivation.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RouterApiAuthorizationSessionService, RouterApiWalletAuthMethodService } from '../../../framework/authServicePort';
|
|
2
|
+
import type { FetchRouterApiContext } from '../createFetchRouter';
|
|
3
|
+
export declare function hostedWalletOriginAllowed(request: Request, allowedOrigins: readonly (string | undefined)[]): boolean;
|
|
4
|
+
export type VoiceIdActivationRouteDependencies = Readonly<{
|
|
5
|
+
tenantId: RouterApiAuthorizationSessionService['tenantId'];
|
|
6
|
+
readWalletSessionAuthorizationV2ByOperationCredential: RouterApiAuthorizationSessionService['readWalletSessionAuthorizationV2ByOperationCredential'];
|
|
7
|
+
activateVoiceId: RouterApiWalletAuthMethodService['activateVoiceId'];
|
|
8
|
+
hostedWalletOrigins: readonly (string | undefined)[];
|
|
9
|
+
}>;
|
|
10
|
+
export declare function handleWalletVoiceIdActivation(ctx: FetchRouterApiContext): Promise<Response | null>;
|
|
11
|
+
export declare function handleVoiceIdActivationRequest(request: Request, deps: VoiceIdActivationRouteDependencies): Promise<Response>;
|
|
12
|
+
//# sourceMappingURL=walletVoiceIdActivation.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FetchRouterApiContext } from '../createFetchRouter';
|
|
2
|
+
import type { VoiceIdVerifyResult } from '../../../domains/voiceId/voiceIdSessions';
|
|
3
|
+
import type { RouterAbEd25519YaoActiveCapabilityDescriptorV1 } from '../../../domains/ed25519Yao/recovery/routerAbEd25519YaoRecovery';
|
|
4
|
+
export type VoiceIdNearInstallation = {
|
|
5
|
+
readonly kind: 'unavailable';
|
|
6
|
+
} | {
|
|
7
|
+
readonly kind: 'ready';
|
|
8
|
+
readonly capability: RouterAbEd25519YaoActiveCapabilityDescriptorV1;
|
|
9
|
+
readonly remainingUses: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function prepareVoiceIdNearInstallation(ctx: FetchRouterApiContext, verified: Extract<VoiceIdVerifyResult, {
|
|
12
|
+
kind: 'issued';
|
|
13
|
+
}>): Promise<VoiceIdNearInstallation>;
|
|
14
|
+
//# sourceMappingURL=walletVoiceIdNear.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RouterApiWalletUnlockService } from '../../../framework/authServicePort';
|
|
2
|
+
import type { FetchRouterApiContext } from '../createFetchRouter';
|
|
3
|
+
import { type VoiceIdNearInstallation } from './walletVoiceIdNear';
|
|
4
|
+
import type { VoiceIdVerifyResult } from '../../../domains/voiceId/voiceIdSessions';
|
|
5
|
+
type HostedVoiceIdRoute = Readonly<{
|
|
6
|
+
hostedWalletOrigins: readonly (string | undefined)[];
|
|
7
|
+
}>;
|
|
8
|
+
export type VoiceIdChallengeRouteDependencies = HostedVoiceIdRoute & Pick<RouterApiWalletUnlockService, 'issueVoiceIdChallenge'>;
|
|
9
|
+
export type VoiceIdVerifyRouteDependencies = HostedVoiceIdRoute & Pick<RouterApiWalletUnlockService, 'verifyAndIssueVoiceId'> & {
|
|
10
|
+
prepareNear(verified: Extract<VoiceIdVerifyResult, {
|
|
11
|
+
kind: 'issued';
|
|
12
|
+
}>): Promise<VoiceIdNearInstallation>;
|
|
13
|
+
};
|
|
14
|
+
export declare function handleWalletVoiceIdChallenge(ctx: FetchRouterApiContext): Promise<Response | null>;
|
|
15
|
+
export declare function handleWalletVoiceIdVerify(ctx: FetchRouterApiContext): Promise<Response | null>;
|
|
16
|
+
export declare function handleVoiceIdChallengeRequest(request: Request, deps: VoiceIdChallengeRouteDependencies): Promise<Response>;
|
|
17
|
+
export declare function handleVoiceIdVerifyRequest(request: Request, deps: VoiceIdVerifyRouteDependencies): Promise<Response>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=walletVoiceIdSessions.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
CREATE TABLE voiceid_wallet_session_challenges (
|
|
2
|
+
namespace TEXT NOT NULL,
|
|
3
|
+
org_id TEXT NOT NULL,
|
|
4
|
+
project_id TEXT NOT NULL,
|
|
5
|
+
env_id TEXT NOT NULL,
|
|
6
|
+
challenge_id TEXT NOT NULL,
|
|
7
|
+
wallet_id TEXT NOT NULL,
|
|
8
|
+
wallet_auth_method_id TEXT NOT NULL,
|
|
9
|
+
challenge_json TEXT NOT NULL CHECK(json_valid(challenge_json)),
|
|
10
|
+
issued_at_ms INTEGER NOT NULL CHECK(issued_at_ms > 0 AND issued_at_ms <= 9007199254740991),
|
|
11
|
+
expires_at_ms INTEGER NOT NULL,
|
|
12
|
+
consumed_at_ms INTEGER,
|
|
13
|
+
PRIMARY KEY(namespace, org_id, project_id, env_id, challenge_id),
|
|
14
|
+
CHECK(length(challenge_id) > 0 AND length(wallet_id) > 0 AND length(wallet_auth_method_id) > 0),
|
|
15
|
+
CHECK(expires_at_ms > issued_at_ms AND expires_at_ms - issued_at_ms <= 60000),
|
|
16
|
+
CHECK(consumed_at_ms IS NULL OR
|
|
17
|
+
(consumed_at_ms >= issued_at_ms AND consumed_at_ms < expires_at_ms)),
|
|
18
|
+
CHECK(COALESCE(json_extract(challenge_json, '$.kind') = 'voiceid_wallet_session_challenge_v1', 0)),
|
|
19
|
+
CHECK(COALESCE(json_extract(challenge_json, '$.challengeId') = challenge_id, 0)),
|
|
20
|
+
CHECK(COALESCE(json_extract(challenge_json, '$.walletId') = wallet_id, 0)),
|
|
21
|
+
CHECK(COALESCE(json_extract(challenge_json, '$.walletAuthMethodId') = wallet_auth_method_id, 0)),
|
|
22
|
+
CHECK(COALESCE(json_extract(challenge_json, '$.issuedAtMs') = issued_at_ms, 0)),
|
|
23
|
+
CHECK(COALESCE(json_extract(challenge_json, '$.expiresAtMs') = expires_at_ms, 0))
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
CREATE INDEX voiceid_wallet_session_challenges_expiry
|
|
27
|
+
ON voiceid_wallet_session_challenges(
|
|
28
|
+
namespace, org_id, project_id, env_id, expires_at_ms
|
|
29
|
+
);
|