@seams/wallet-server 0.22.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 +186 -6
- 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
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
-- Rebuild the canonical method table to admit wallet-bound VoiceID device keys.
|
|
2
|
+
-- Copy every existing row before replacing the table. Child foreign keys remain
|
|
3
|
+
-- valid after the original name is restored.
|
|
4
|
+
PRAGMA defer_foreign_keys = ON;
|
|
5
|
+
|
|
6
|
+
CREATE TABLE wallet_auth_methods_next (
|
|
7
|
+
namespace TEXT NOT NULL,
|
|
8
|
+
org_id TEXT NOT NULL,
|
|
9
|
+
project_id TEXT NOT NULL,
|
|
10
|
+
env_id TEXT NOT NULL,
|
|
11
|
+
wallet_id TEXT NOT NULL,
|
|
12
|
+
wallet_authority_id TEXT NOT NULL,
|
|
13
|
+
rp_id TEXT NOT NULL DEFAULT '',
|
|
14
|
+
kind TEXT NOT NULL,
|
|
15
|
+
status TEXT NOT NULL,
|
|
16
|
+
wallet_auth_method_id TEXT NOT NULL,
|
|
17
|
+
auth_identifier_key TEXT NOT NULL,
|
|
18
|
+
credential_id_b64u TEXT,
|
|
19
|
+
credential_public_key_b64u TEXT,
|
|
20
|
+
email_hash_hex TEXT,
|
|
21
|
+
registration_authority_id TEXT,
|
|
22
|
+
record_json TEXT NOT NULL,
|
|
23
|
+
created_at_ms INTEGER NOT NULL,
|
|
24
|
+
updated_at_ms INTEGER NOT NULL,
|
|
25
|
+
activated_at_ms INTEGER,
|
|
26
|
+
revoked_at_ms INTEGER,
|
|
27
|
+
provider TEXT,
|
|
28
|
+
provider_user_id TEXT,
|
|
29
|
+
PRIMARY KEY (namespace, org_id, project_id, env_id, wallet_auth_method_id),
|
|
30
|
+
FOREIGN KEY (
|
|
31
|
+
namespace,
|
|
32
|
+
org_id,
|
|
33
|
+
project_id,
|
|
34
|
+
env_id,
|
|
35
|
+
wallet_authority_id
|
|
36
|
+
) REFERENCES wallet_authorities(
|
|
37
|
+
namespace,
|
|
38
|
+
org_id,
|
|
39
|
+
project_id,
|
|
40
|
+
env_id,
|
|
41
|
+
authority_id
|
|
42
|
+
),
|
|
43
|
+
CHECK (length(wallet_id) > 0),
|
|
44
|
+
CHECK (length(wallet_authority_id) > 0),
|
|
45
|
+
CHECK (kind IN ('passkey', 'email_otp', 'voiceid')),
|
|
46
|
+
CHECK (status IN ('pending_local_install', 'active', 'revoked')),
|
|
47
|
+
CHECK (length(wallet_auth_method_id) > 0),
|
|
48
|
+
CHECK (length(auth_identifier_key) > 0),
|
|
49
|
+
CHECK (json_valid(record_json)),
|
|
50
|
+
CHECK (created_at_ms >= 0),
|
|
51
|
+
CHECK (updated_at_ms >= created_at_ms),
|
|
52
|
+
CHECK (
|
|
53
|
+
(status = 'pending_local_install' AND activated_at_ms IS NULL AND revoked_at_ms IS NULL)
|
|
54
|
+
OR
|
|
55
|
+
(status = 'active' AND activated_at_ms IS NOT NULL AND revoked_at_ms IS NULL)
|
|
56
|
+
OR
|
|
57
|
+
(status = 'revoked' AND activated_at_ms IS NOT NULL AND revoked_at_ms IS NOT NULL)
|
|
58
|
+
),
|
|
59
|
+
CHECK (
|
|
60
|
+
(kind = 'passkey'
|
|
61
|
+
AND length(rp_id) > 0
|
|
62
|
+
AND credential_id_b64u IS NOT NULL
|
|
63
|
+
AND length(credential_id_b64u) > 0
|
|
64
|
+
AND credential_public_key_b64u IS NOT NULL
|
|
65
|
+
AND length(credential_public_key_b64u) > 0
|
|
66
|
+
AND email_hash_hex IS NULL
|
|
67
|
+
AND registration_authority_id IS NULL
|
|
68
|
+
AND auth_identifier_key = credential_id_b64u)
|
|
69
|
+
OR
|
|
70
|
+
(kind = 'email_otp'
|
|
71
|
+
AND rp_id = ''
|
|
72
|
+
AND credential_id_b64u IS NULL
|
|
73
|
+
AND credential_public_key_b64u IS NULL
|
|
74
|
+
AND email_hash_hex IS NOT NULL
|
|
75
|
+
AND length(email_hash_hex) > 0
|
|
76
|
+
AND registration_authority_id IS NOT NULL
|
|
77
|
+
AND length(registration_authority_id) > 0
|
|
78
|
+
AND auth_identifier_key = email_hash_hex)
|
|
79
|
+
OR
|
|
80
|
+
(kind = 'voiceid'
|
|
81
|
+
AND rp_id = ''
|
|
82
|
+
AND credential_id_b64u IS NULL
|
|
83
|
+
AND credential_public_key_b64u IS NOT NULL
|
|
84
|
+
AND length(credential_public_key_b64u) = 43
|
|
85
|
+
AND email_hash_hex IS NULL
|
|
86
|
+
AND registration_authority_id IS NULL
|
|
87
|
+
AND provider IS NULL
|
|
88
|
+
AND provider_user_id IS NULL
|
|
89
|
+
AND length(auth_identifier_key) = 43
|
|
90
|
+
AND COALESCE(auth_identifier_key = json_extract(record_json, '$.deviceKeyId'), 0))
|
|
91
|
+
),
|
|
92
|
+
CHECK (json_extract(record_json, '$.version') = 'wallet_auth_method_v2'),
|
|
93
|
+
CHECK (json_extract(record_json, '$.walletAuthMethodId') = wallet_auth_method_id),
|
|
94
|
+
CHECK (json_extract(record_json, '$.walletId') = wallet_id),
|
|
95
|
+
CHECK (json_extract(record_json, '$.walletAuthorityId') = wallet_authority_id),
|
|
96
|
+
CHECK (json_extract(record_json, '$.kind') = kind),
|
|
97
|
+
CHECK (json_extract(record_json, '$.status') = status),
|
|
98
|
+
CHECK (json_extract(record_json, '$.createdAtMs') = created_at_ms),
|
|
99
|
+
CHECK (json_extract(record_json, '$.updatedAtMs') = updated_at_ms),
|
|
100
|
+
CHECK (
|
|
101
|
+
(kind = 'passkey'
|
|
102
|
+
AND json_extract(record_json, '$.rpId') = rp_id
|
|
103
|
+
AND json_extract(record_json, '$.credentialIdB64u') = credential_id_b64u
|
|
104
|
+
AND json_extract(record_json, '$.credentialPublicKeyB64u') = credential_public_key_b64u
|
|
105
|
+
AND json_extract(record_json, '$.counter') >= 0)
|
|
106
|
+
OR
|
|
107
|
+
(kind = 'email_otp'
|
|
108
|
+
AND json_extract(record_json, '$.emailHashHex') = email_hash_hex
|
|
109
|
+
AND json_extract(record_json, '$.registrationAuthorityId') = registration_authority_id)
|
|
110
|
+
OR
|
|
111
|
+
(kind = 'voiceid'
|
|
112
|
+
AND COALESCE(json_extract(record_json, '$.deviceKeyId') = auth_identifier_key, 0)
|
|
113
|
+
AND COALESCE(json_extract(record_json, '$.devicePublicKeyB64u') = credential_public_key_b64u, 0))
|
|
114
|
+
)
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
INSERT INTO wallet_auth_methods_next (
|
|
118
|
+
namespace, org_id, project_id, env_id, wallet_id, wallet_authority_id,
|
|
119
|
+
rp_id, kind, status, wallet_auth_method_id, auth_identifier_key,
|
|
120
|
+
credential_id_b64u, credential_public_key_b64u, email_hash_hex,
|
|
121
|
+
registration_authority_id, record_json, created_at_ms, updated_at_ms,
|
|
122
|
+
activated_at_ms, revoked_at_ms, provider, provider_user_id
|
|
123
|
+
)
|
|
124
|
+
SELECT
|
|
125
|
+
namespace, org_id, project_id, env_id, wallet_id, wallet_authority_id,
|
|
126
|
+
rp_id, kind, status, wallet_auth_method_id, auth_identifier_key,
|
|
127
|
+
credential_id_b64u, credential_public_key_b64u, email_hash_hex,
|
|
128
|
+
registration_authority_id, record_json, created_at_ms, updated_at_ms,
|
|
129
|
+
activated_at_ms, revoked_at_ms, provider, provider_user_id
|
|
130
|
+
FROM wallet_auth_methods;
|
|
131
|
+
|
|
132
|
+
DROP TRIGGER authorized_operation_owner_grant_claim_atomic;
|
|
133
|
+
DROP TABLE wallet_auth_methods;
|
|
134
|
+
ALTER TABLE wallet_auth_methods_next RENAME TO wallet_auth_methods;
|
|
135
|
+
|
|
136
|
+
CREATE INDEX wallet_auth_methods_wallet_authority_status_idx
|
|
137
|
+
ON wallet_auth_methods (
|
|
138
|
+
namespace, org_id, project_id, env_id, wallet_id, wallet_authority_id, status
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
CREATE UNIQUE INDEX wallet_auth_methods_v2_passkey_uidx
|
|
142
|
+
ON wallet_auth_methods (
|
|
143
|
+
namespace, org_id, project_id, env_id, rp_id, credential_id_b64u
|
|
144
|
+
)
|
|
145
|
+
WHERE kind = 'passkey' AND credential_id_b64u IS NOT NULL;
|
|
146
|
+
|
|
147
|
+
CREATE UNIQUE INDEX wallet_auth_methods_v2_voiceid_key_uidx
|
|
148
|
+
ON wallet_auth_methods (
|
|
149
|
+
namespace, org_id, project_id, env_id, auth_identifier_key
|
|
150
|
+
)
|
|
151
|
+
WHERE kind = 'voiceid';
|
|
152
|
+
|
|
153
|
+
CREATE UNIQUE INDEX wallet_auth_methods_authority_identity_uidx
|
|
154
|
+
ON wallet_auth_methods (
|
|
155
|
+
namespace, org_id, project_id, env_id,
|
|
156
|
+
wallet_auth_method_id, wallet_id, wallet_authority_id
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
CREATE UNIQUE INDEX wallet_auth_methods_v2_authority_email_uidx
|
|
160
|
+
ON wallet_auth_methods (
|
|
161
|
+
namespace, org_id, project_id, env_id, wallet_id, wallet_authority_id
|
|
162
|
+
)
|
|
163
|
+
WHERE kind = 'email_otp' AND status = 'active';
|
|
164
|
+
|
|
165
|
+
CREATE INDEX wallet_auth_methods_v2_email_provider_idx
|
|
166
|
+
ON wallet_auth_methods (
|
|
167
|
+
namespace, org_id, project_id, env_id, provider, provider_user_id
|
|
168
|
+
)
|
|
169
|
+
WHERE kind = 'email_otp' AND provider_user_id IS NOT NULL;
|
|
170
|
+
|
|
171
|
+
CREATE TRIGGER wallet_auth_methods_frozen_insert
|
|
172
|
+
BEFORE INSERT ON wallet_auth_methods
|
|
173
|
+
WHEN EXISTS (
|
|
174
|
+
SELECT 1 FROM wallet_relocation_authorization_fences AS fence
|
|
175
|
+
WHERE fence.namespace = NEW.namespace AND fence.org_id = NEW.org_id
|
|
176
|
+
AND fence.project_id = NEW.project_id AND fence.env_id = NEW.env_id
|
|
177
|
+
AND fence.wallet_id = NEW.wallet_id
|
|
178
|
+
)
|
|
179
|
+
BEGIN
|
|
180
|
+
SELECT RAISE(ABORT, 'wallet_authorization_history_frozen');
|
|
181
|
+
END;
|
|
182
|
+
|
|
183
|
+
CREATE TRIGGER wallet_auth_methods_frozen_update
|
|
184
|
+
BEFORE UPDATE ON wallet_auth_methods
|
|
185
|
+
WHEN EXISTS (
|
|
186
|
+
SELECT 1 FROM wallet_relocation_authorization_fences AS fence
|
|
187
|
+
WHERE fence.namespace = OLD.namespace AND fence.org_id = OLD.org_id
|
|
188
|
+
AND fence.project_id = OLD.project_id AND fence.env_id = OLD.env_id
|
|
189
|
+
AND fence.wallet_id = OLD.wallet_id
|
|
190
|
+
) OR EXISTS (
|
|
191
|
+
SELECT 1 FROM wallet_relocation_authorization_fences AS fence
|
|
192
|
+
WHERE fence.namespace = NEW.namespace AND fence.org_id = NEW.org_id
|
|
193
|
+
AND fence.project_id = NEW.project_id AND fence.env_id = NEW.env_id
|
|
194
|
+
AND fence.wallet_id = NEW.wallet_id
|
|
195
|
+
)
|
|
196
|
+
BEGIN
|
|
197
|
+
SELECT RAISE(ABORT, 'wallet_authorization_history_frozen');
|
|
198
|
+
END;
|
|
199
|
+
|
|
200
|
+
CREATE TRIGGER wallet_auth_methods_frozen_delete
|
|
201
|
+
BEFORE DELETE ON wallet_auth_methods
|
|
202
|
+
WHEN EXISTS (
|
|
203
|
+
SELECT 1 FROM wallet_relocation_authorization_fences AS fence
|
|
204
|
+
WHERE fence.namespace = OLD.namespace AND fence.org_id = OLD.org_id
|
|
205
|
+
AND fence.project_id = OLD.project_id AND fence.env_id = OLD.env_id AND fence.wallet_id = OLD.wallet_id
|
|
206
|
+
AND NOT EXISTS (SELECT 1 FROM wallet_relocation_authorization_cleanups AS cleanup
|
|
207
|
+
WHERE cleanup.namespace = fence.namespace AND cleanup.org_id = fence.org_id
|
|
208
|
+
AND cleanup.project_id = fence.project_id AND cleanup.env_id = fence.env_id
|
|
209
|
+
AND cleanup.wallet_id = fence.wallet_id AND cleanup.move_id = fence.move_id
|
|
210
|
+
AND cleanup.request_digest_hex = fence.request_digest_hex AND cleanup.source_generation = fence.source_generation
|
|
211
|
+
AND cleanup.state = 'cleaning')
|
|
212
|
+
)
|
|
213
|
+
BEGIN SELECT RAISE(ABORT, 'wallet_authorization_history_frozen'); END;
|
|
214
|
+
|
|
215
|
+
CREATE TRIGGER wallet_auth_methods_inactive_import_insert
|
|
216
|
+
BEFORE INSERT ON wallet_auth_methods
|
|
217
|
+
WHEN (EXISTS (SELECT 1 FROM wallet_relocation_authorization_imports AS destination
|
|
218
|
+
WHERE destination.namespace = NEW.namespace AND destination.org_id = NEW.org_id
|
|
219
|
+
AND destination.project_id = NEW.project_id AND destination.env_id = NEW.env_id
|
|
220
|
+
AND destination.wallet_id = NEW.wallet_id AND destination.state != 'activated') AND NOT EXISTS (
|
|
221
|
+
SELECT 1 FROM wallet_relocation_authorization_import_context AS context
|
|
222
|
+
JOIN wallet_relocation_authorization_imports AS destination
|
|
223
|
+
ON destination.namespace = context.namespace AND destination.org_id = context.org_id
|
|
224
|
+
AND destination.project_id = context.project_id AND destination.env_id = context.env_id
|
|
225
|
+
AND destination.wallet_id = context.wallet_id AND destination.move_id = context.move_id
|
|
226
|
+
AND destination.request_digest_hex = context.request_digest_hex
|
|
227
|
+
AND destination.source_generation = context.source_generation AND destination.state = 'importing'
|
|
228
|
+
WHERE context.namespace = NEW.namespace AND context.wallet_id = NEW.wallet_id
|
|
229
|
+
AND context.table_name = 'wallet_auth_methods'
|
|
230
|
+
AND context.record_key = json_array(NEW.env_id, NEW.namespace, NEW.org_id, NEW.project_id, NEW.wallet_auth_method_id)
|
|
231
|
+
))
|
|
232
|
+
BEGIN SELECT RAISE(ABORT, 'wallet_authorization_destination_inactive'); END;
|
|
233
|
+
|
|
234
|
+
CREATE TRIGGER wallet_auth_methods_inactive_import_update
|
|
235
|
+
BEFORE UPDATE ON wallet_auth_methods
|
|
236
|
+
WHEN (EXISTS (SELECT 1 FROM wallet_relocation_authorization_imports AS destination
|
|
237
|
+
WHERE destination.namespace = OLD.namespace AND destination.org_id = OLD.org_id
|
|
238
|
+
AND destination.project_id = OLD.project_id AND destination.env_id = OLD.env_id
|
|
239
|
+
AND destination.wallet_id = OLD.wallet_id AND destination.state != 'activated')) OR (EXISTS (SELECT 1 FROM wallet_relocation_authorization_imports AS destination
|
|
240
|
+
WHERE destination.namespace = NEW.namespace AND destination.org_id = NEW.org_id
|
|
241
|
+
AND destination.project_id = NEW.project_id AND destination.env_id = NEW.env_id
|
|
242
|
+
AND destination.wallet_id = NEW.wallet_id AND destination.state != 'activated'))
|
|
243
|
+
BEGIN SELECT RAISE(ABORT, 'wallet_authorization_destination_inactive'); END;
|
|
244
|
+
|
|
245
|
+
CREATE TRIGGER wallet_auth_methods_inactive_import_delete
|
|
246
|
+
BEFORE DELETE ON wallet_auth_methods
|
|
247
|
+
WHEN (EXISTS (SELECT 1 FROM wallet_relocation_authorization_imports AS destination
|
|
248
|
+
WHERE destination.namespace = OLD.namespace AND destination.org_id = OLD.org_id
|
|
249
|
+
AND destination.project_id = OLD.project_id AND destination.env_id = OLD.env_id
|
|
250
|
+
AND destination.wallet_id = OLD.wallet_id AND destination.state != 'activated'))
|
|
251
|
+
BEGIN SELECT RAISE(ABORT, 'wallet_authorization_destination_inactive'); END;
|
|
252
|
+
|
|
253
|
+
-- Restore the operation claim guard after the canonical method name exists again.
|
|
254
|
+
CREATE TRIGGER authorized_operation_owner_grant_claim_atomic
|
|
255
|
+
AFTER INSERT ON authorized_operations
|
|
256
|
+
WHEN NEW.lifecycle_kind = 'claimed'
|
|
257
|
+
AND NEW.authorization_source_kind = 'authorization_grant'
|
|
258
|
+
AND NEW.authorization_grant_kind = 'wallet_session_authorization'
|
|
259
|
+
BEGIN
|
|
260
|
+
SELECT CASE
|
|
261
|
+
WHEN NOT EXISTS (
|
|
262
|
+
SELECT 1
|
|
263
|
+
FROM wallet_session_authorizations_v2 AS session
|
|
264
|
+
JOIN authorization_wallet_session_quotas AS quota
|
|
265
|
+
ON quota.namespace = session.namespace
|
|
266
|
+
AND quota.tenant_id = session.tenant_id
|
|
267
|
+
AND quota.quota_id = session.quota_id
|
|
268
|
+
AND quota.wallet_session_id = session.wallet_session_id
|
|
269
|
+
AND quota.principal_id = session.principal_id
|
|
270
|
+
JOIN wallet_authorities AS authority
|
|
271
|
+
ON authority.namespace = session.namespace
|
|
272
|
+
AND authority.org_id = session.org_id
|
|
273
|
+
AND authority.project_id = session.project_id
|
|
274
|
+
AND authority.env_id = session.env_id
|
|
275
|
+
AND authority.authority_id = session.authority_id
|
|
276
|
+
AND authority.wallet_id = session.wallet_id
|
|
277
|
+
JOIN wallet_auth_methods AS auth_method
|
|
278
|
+
ON auth_method.namespace = session.namespace
|
|
279
|
+
AND auth_method.org_id = session.org_id
|
|
280
|
+
AND auth_method.project_id = session.project_id
|
|
281
|
+
AND auth_method.env_id = session.env_id
|
|
282
|
+
AND auth_method.wallet_auth_method_id = session.wallet_auth_method_id
|
|
283
|
+
AND auth_method.wallet_id = session.wallet_id
|
|
284
|
+
AND auth_method.wallet_authority_id = session.authority_id
|
|
285
|
+
WHERE session.namespace = NEW.namespace
|
|
286
|
+
AND session.org_id = NEW.owner_scope_org_id
|
|
287
|
+
AND session.project_id = NEW.owner_scope_project_id
|
|
288
|
+
AND session.env_id = NEW.owner_scope_env_id
|
|
289
|
+
AND session.tenant_id = NEW.tenant_id
|
|
290
|
+
AND session.authorization_id = NEW.authorization_id
|
|
291
|
+
AND session.principal_id = NEW.principal_id
|
|
292
|
+
AND (NEW.quota_kind = 'quota_neutral' OR session.quota_id = NEW.quota_id)
|
|
293
|
+
AND session.operation_credential_hash IS NOT NULL
|
|
294
|
+
AND session.retired_at_ms IS NULL
|
|
295
|
+
AND session.expires_at_ms > NEW.claimed_at_ms
|
|
296
|
+
AND authority.lifecycle_state = 'active'
|
|
297
|
+
AND authority.authority_digest_b64u = session.authority_digest_b64u
|
|
298
|
+
AND authority.revocation_epoch = session.authority_revocation_epoch
|
|
299
|
+
AND auth_method.status = 'active'
|
|
300
|
+
)
|
|
301
|
+
THEN RAISE(ABORT, 'authorization_wallet_session_rejected')
|
|
302
|
+
END;
|
|
303
|
+
|
|
304
|
+
UPDATE authorization_wallet_session_quotas
|
|
305
|
+
SET remaining_uses = remaining_uses - 1,
|
|
306
|
+
lifecycle_kind = CASE WHEN remaining_uses = 1 THEN 'exhausted' ELSE 'active' END
|
|
307
|
+
WHERE NEW.quota_kind = 'consume_reusable_wallet_session'
|
|
308
|
+
AND namespace = NEW.namespace
|
|
309
|
+
AND tenant_id = NEW.tenant_id
|
|
310
|
+
AND quota_id = NEW.quota_id
|
|
311
|
+
AND principal_id = NEW.principal_id
|
|
312
|
+
AND lifecycle_kind = 'active'
|
|
313
|
+
AND remaining_uses > 0
|
|
314
|
+
AND expires_at_ms > NEW.claimed_at_ms
|
|
315
|
+
AND wallet_session_id = (
|
|
316
|
+
SELECT session.wallet_session_id
|
|
317
|
+
FROM wallet_session_authorizations_v2 AS session
|
|
318
|
+
JOIN authorization_wallet_session_quotas AS quota
|
|
319
|
+
ON quota.namespace = session.namespace
|
|
320
|
+
AND quota.tenant_id = session.tenant_id
|
|
321
|
+
AND quota.quota_id = session.quota_id
|
|
322
|
+
AND quota.wallet_session_id = session.wallet_session_id
|
|
323
|
+
AND quota.principal_id = session.principal_id
|
|
324
|
+
JOIN wallet_authorities AS authority
|
|
325
|
+
ON authority.namespace = session.namespace
|
|
326
|
+
AND authority.org_id = session.org_id
|
|
327
|
+
AND authority.project_id = session.project_id
|
|
328
|
+
AND authority.env_id = session.env_id
|
|
329
|
+
AND authority.authority_id = session.authority_id
|
|
330
|
+
AND authority.wallet_id = session.wallet_id
|
|
331
|
+
JOIN wallet_auth_methods AS auth_method
|
|
332
|
+
ON auth_method.namespace = session.namespace
|
|
333
|
+
AND auth_method.org_id = session.org_id
|
|
334
|
+
AND auth_method.project_id = session.project_id
|
|
335
|
+
AND auth_method.env_id = session.env_id
|
|
336
|
+
AND auth_method.wallet_auth_method_id = session.wallet_auth_method_id
|
|
337
|
+
AND auth_method.wallet_id = session.wallet_id
|
|
338
|
+
AND auth_method.wallet_authority_id = session.authority_id
|
|
339
|
+
WHERE session.namespace = NEW.namespace
|
|
340
|
+
AND session.org_id = NEW.owner_scope_org_id
|
|
341
|
+
AND session.project_id = NEW.owner_scope_project_id
|
|
342
|
+
AND session.env_id = NEW.owner_scope_env_id
|
|
343
|
+
AND session.tenant_id = NEW.tenant_id
|
|
344
|
+
AND session.authorization_id = NEW.authorization_id
|
|
345
|
+
AND session.principal_id = NEW.principal_id
|
|
346
|
+
AND session.quota_id = NEW.quota_id
|
|
347
|
+
AND session.operation_credential_hash IS NOT NULL
|
|
348
|
+
AND session.retired_at_ms IS NULL
|
|
349
|
+
AND session.expires_at_ms > NEW.claimed_at_ms
|
|
350
|
+
AND authority.lifecycle_state = 'active'
|
|
351
|
+
AND authority.authority_digest_b64u = session.authority_digest_b64u
|
|
352
|
+
AND authority.revocation_epoch = session.authority_revocation_epoch
|
|
353
|
+
AND auth_method.status = 'active'
|
|
354
|
+
LIMIT 1
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
SELECT CASE
|
|
358
|
+
WHEN NEW.quota_kind = 'consume_reusable_wallet_session' AND changes() != 1
|
|
359
|
+
THEN RAISE(ABORT, 'authorization_wallet_session_quota_rejected')
|
|
360
|
+
END;
|
|
361
|
+
END;
|
|
362
|
+
|
|
363
|
+
-- Abort if a referenced method was lost during the rebuild.
|
|
364
|
+
CREATE TABLE voiceid_wallet_auth_method_fk_guard (
|
|
365
|
+
guard_id INTEGER PRIMARY KEY CHECK (guard_id = 1)
|
|
366
|
+
);
|
|
367
|
+
INSERT INTO voiceid_wallet_auth_method_fk_guard (guard_id)
|
|
368
|
+
SELECT 0 FROM pragma_foreign_key_check LIMIT 1;
|
|
369
|
+
DROP TABLE voiceid_wallet_auth_method_fk_guard;
|
|
370
|
+
|
|
371
|
+
-- SQLite remembers deferred DROP TABLE violations until this switch. The guard
|
|
372
|
+
-- above verifies that all references point to the restored canonical table.
|
|
373
|
+
PRAGMA defer_foreign_keys = OFF;
|