@seams/wallet-server 0.23.0 → 0.25.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 (86) hide show
  1. package/THIRD_PARTY_NOTICES.md +182 -5
  2. package/artifact-manifest.json +23 -13
  3. package/cloudflare-router-ab/build/deriver-a/build-stamp.json +1 -1
  4. package/cloudflare-router-ab/build/deriver-b/build-stamp.json +1 -1
  5. package/cloudflare-router-ab/build/local-tools/darwin-arm64/router_ab_local_init +0 -0
  6. package/cloudflare-router-ab/build/local-tools/darwin-x64/router_ab_local_init +0 -0
  7. package/cloudflare-router-ab/build/router/build-stamp.json +1 -1
  8. package/cloudflare-router-ab/build/signing-worker/build-stamp.json +1 -1
  9. package/cloudflare-router-ab/build/tenant-root-control-plane/build-stamp.json +1 -1
  10. package/dist/esm/authorization/voiceIdDeviceProof.js +32 -0
  11. package/dist/esm/core/ThresholdService/validation.js +17 -1
  12. package/dist/esm/core/d1WalletAuthMethodStore.js +42 -1
  13. package/dist/esm/core/deviceLinking/linkedDeviceManagement.js +5 -0
  14. package/dist/esm/core/signingLanes/WalletExecutionLaneProjection.js +11 -2
  15. package/dist/esm/router/cloudflare/d1/auth/d1RouterApiAuthService.js +23 -6
  16. package/dist/esm/router/cloudflare/d1/deviceLinking/d1LinkedDeviceAuthorityInstallService.js +5 -5
  17. package/dist/esm/router/cloudflare/d1/emailOtp/d1GoogleEmailOtpRegistrationAttemptStore.js +1 -1
  18. package/dist/esm/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyEnvelopeStore.js +6 -0
  19. package/dist/esm/router/cloudflare/d1/wallet/d1VoiceIdActivation.js +139 -0
  20. package/dist/esm/router/cloudflare/d1/wallet/d1VoiceIdSessions.js +138 -0
  21. package/dist/esm/router/cloudflare/d1/wallet/d1VoiceIdWalletSessionChallenges.js +88 -0
  22. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthMethodService.js +12 -4
  23. package/dist/esm/router/cloudflare/d1/wallet/d1WalletAuthorityStore.js +14 -0
  24. package/dist/esm/router/cloudflare/d1/webauthn/d1WebAuthnRecords.js +1 -0
  25. package/dist/esm/router/cloudflare.js +576 -10
  26. package/dist/esm/router/domains/ed25519Yao/export/routerAbEd25519YaoExport.js +5 -0
  27. package/dist/esm/router/domains/passkeyCustody/walletRecoveryFinalization.js +1 -0
  28. package/dist/esm/router/domains/signingOperations/routerAbNormalSigningAdmissionCore.js +1 -0
  29. package/dist/esm/router/domains/signingOperations/walletExecutionAdmission.js +1 -0
  30. package/dist/esm/router/domains/voiceId/voiceIdActivation.js +12 -0
  31. package/dist/esm/router/domains/voiceId/voiceIdSessions.js +0 -0
  32. package/dist/esm/router/framework/routeDefinitions.js +13 -0
  33. package/dist/esm/router/transport/fetch/createFetchRouter.js +5 -0
  34. package/dist/esm/router/transport/fetch/routes/deviceLinkingOwnerAuthorization.js +12 -1
  35. package/dist/esm/router/transport/fetch/routes/walletExecutionLanePreflight.js +1 -0
  36. package/dist/esm/router/transport/fetch/routes/walletVoiceIdActivation.js +139 -0
  37. package/dist/esm/router/transport/fetch/routes/walletVoiceIdNear.js +36 -0
  38. package/dist/esm/router/transport/fetch/routes/walletVoiceIdSessions.js +127 -0
  39. package/dist/esm/shared-ts/src/authorization/voiceIdDeviceAssertion.js +110 -0
  40. package/dist/esm/shared-ts/src/device-linking/authorityActivation.js +1 -0
  41. package/dist/esm/shared-ts/src/device-linking/committedSignerPackages.js +1 -1
  42. package/dist/esm/shared-ts/src/passkey-custody/custodyEnvelope.js +30 -3
  43. package/dist/esm/shared-ts/src/passkey-custody/custodySecretBinding.js +1 -1
  44. package/dist/esm/shared-ts/src/signing-lanes/recordParsers.js +15 -1
  45. package/dist/esm/shared-ts/src/threshold/sessionPolicy.js +2 -1
  46. package/dist/esm/shared-ts/src/utils/registrationIntent.js +1 -3
  47. package/dist/esm/shared-ts/src/utils/walletAuthAuthority.js +46 -2
  48. package/dist/esm/shared-ts/src/utils/walletAuthMethodRecord.js +116 -7
  49. package/dist/esm/shared-ts/src/wallet-recovery/walletRecoveryCommittedProjection.js +1 -0
  50. package/dist/esm/wasm/near_signer/pkg/wasm_signer_worker_bg.wasm +0 -0
  51. package/dist/types/shared-ts/src/authorization/voiceIdDeviceAssertion.d.ts +32 -0
  52. package/dist/types/shared-ts/src/device-linking/committedSignerPackages.d.ts +3 -1
  53. package/dist/types/shared-ts/src/device-linking/contracts.d.ts +8 -0
  54. package/dist/types/shared-ts/src/passkey-custody/custodyEnvelope.d.ts +29 -0
  55. package/dist/types/shared-ts/src/passkey-custody/custodySecretBinding.d.ts +1 -0
  56. package/dist/types/shared-ts/src/signing-lanes/execution.d.ts +2 -2
  57. package/dist/types/shared-ts/src/signing-lanes/recordParsers.d.ts +2 -1
  58. package/dist/types/shared-ts/src/signing-lanes/records.d.ts +10 -2
  59. package/dist/types/shared-ts/src/signing-lanes/rotation.d.ts +2 -2
  60. package/dist/types/shared-ts/src/threshold/sessionPolicy.d.ts +9 -0
  61. package/dist/types/shared-ts/src/utils/addWalletAuthMethod.d.ts +3 -3
  62. package/dist/types/shared-ts/src/utils/domainIds.d.ts +4 -5
  63. package/dist/types/shared-ts/src/utils/registrationIntent.d.ts +0 -1
  64. package/dist/types/shared-ts/src/utils/signerDomain.d.ts +3 -0
  65. package/dist/types/shared-ts/src/utils/walletAuthAuthority.d.ts +32 -2
  66. package/dist/types/shared-ts/src/utils/walletAuthMethodRecord.d.ts +15 -1
  67. package/dist/types/shared-ts/src/utils/walletCapabilityBindings.d.ts +20 -0
  68. package/dist/types/wallet-server/src/authorization/voiceIdDeviceProof.d.ts +29 -0
  69. package/dist/types/wallet-server/src/core/d1WalletAuthMethodStore.d.ts +13 -2
  70. package/dist/types/wallet-server/src/core/registrationContracts.d.ts +8 -0
  71. package/dist/types/wallet-server/src/core/signingLanes/WalletExecutionLaneProjection.d.ts +4 -0
  72. package/dist/types/wallet-server/src/router/cloudflare/d1/passkeyCustody/d1PasskeyCustodyEnvelopeStore.d.ts +4 -0
  73. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1VoiceIdActivation.d.ts +14 -0
  74. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1VoiceIdSessions.d.ts +19 -0
  75. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1VoiceIdWalletSessionChallenges.d.ts +26 -0
  76. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletAuthMethodService.d.ts +1 -0
  77. package/dist/types/wallet-server/src/router/cloudflare/d1/wallet/d1WalletRelocationOwner.d.ts +25 -0
  78. package/dist/types/wallet-server/src/router/domains/voiceId/voiceIdActivation.d.ts +29 -0
  79. package/dist/types/wallet-server/src/router/domains/voiceId/voiceIdSessions.d.ts +35 -0
  80. package/dist/types/wallet-server/src/router/framework/authServicePort.d.ts +3 -0
  81. package/dist/types/wallet-server/src/router/transport/fetch/routes/walletVoiceIdActivation.d.ts +12 -0
  82. package/dist/types/wallet-server/src/router/transport/fetch/routes/walletVoiceIdNear.d.ts +14 -0
  83. package/dist/types/wallet-server/src/router/transport/fetch/routes/walletVoiceIdSessions.d.ts +19 -0
  84. package/migrations/d1-signer/0083_voiceid_wallet_session_challenges.sql +29 -0
  85. package/migrations/d1-signer/0084_voiceid_wallet_auth_methods.sql +373 -0
  86. 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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seams/wallet-server",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "type": "module",
5
5
  "description": "Seams server TypeScript SDK for NEAR and EVM-family wallets",
6
6
  "main": "./dist/esm/index.js",