@yielded/auth-persistence 0.1.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/README.md +27 -0
  2. package/dist/Adapter.d.mts +30 -0
  3. package/dist/Adapter.mjs +25 -0
  4. package/dist/index.d.mts +7 -0
  5. package/dist/index.mjs +7 -0
  6. package/dist/internal/PasswordPreparedPostconditions.d.mts +22 -0
  7. package/dist/internal/PasswordPreparedPostconditions.mjs +12 -0
  8. package/dist/internal/PasswordPreparedPostconditions.mjs.map +1 -0
  9. package/dist/internal/configuration.d.mts +174 -0
  10. package/dist/internal/configuration.mjs +7 -0
  11. package/dist/internal/configuration.mjs.map +1 -0
  12. package/dist/internal/email-kernel.d.mts +275 -0
  13. package/dist/internal/email-kernel.mjs +487 -0
  14. package/dist/internal/email-kernel.mjs.map +1 -0
  15. package/dist/internal/mapping-error.d.mts +10 -0
  16. package/dist/internal/mapping-error.mjs +30 -0
  17. package/dist/internal/mapping-error.mjs.map +1 -0
  18. package/dist/internal/models/common.d.mts +12 -0
  19. package/dist/internal/models/email-model.d.mts +353 -0
  20. package/dist/internal/models/email-model.mjs +21 -0
  21. package/dist/internal/models/email-model.mjs.map +1 -0
  22. package/dist/internal/models/passkey-model.d.mts +266 -0
  23. package/dist/internal/models/passkey-model.mjs +34 -0
  24. package/dist/internal/models/passkey-model.mjs.map +1 -0
  25. package/dist/internal/models/passkey-registration-ceremony-model.d.mts +49 -0
  26. package/dist/internal/models/passkey-registration-ceremony-model.mjs +18 -0
  27. package/dist/internal/models/passkey-registration-ceremony-model.mjs.map +1 -0
  28. package/dist/internal/models/passkey-write-model.d.mts +189 -0
  29. package/dist/internal/models/passkey-write-model.mjs +13 -0
  30. package/dist/internal/models/passkey-write-model.mjs.map +1 -0
  31. package/dist/internal/models/password-model.d.mts +328 -0
  32. package/dist/internal/models/password-model.mjs +23 -0
  33. package/dist/internal/models/password-model.mjs.map +1 -0
  34. package/dist/internal/models/proof-model.d.mts +285 -0
  35. package/dist/internal/models/proof-model.mjs +17 -0
  36. package/dist/internal/models/proof-model.mjs.map +1 -0
  37. package/dist/internal/models/session-model.d.mts +199 -0
  38. package/dist/internal/models/session-model.mjs +20 -0
  39. package/dist/internal/models/session-model.mjs.map +1 -0
  40. package/dist/internal/models/step-up-model.d.mts +66 -0
  41. package/dist/internal/models/step-up-model.mjs +9 -0
  42. package/dist/internal/models/step-up-model.mjs.map +1 -0
  43. package/dist/internal/oauth-app.d.mts +11 -0
  44. package/dist/internal/oauth-app.mjs +57 -0
  45. package/dist/internal/oauth-app.mjs.map +1 -0
  46. package/dist/internal/oauth-server.d.mts +10 -0
  47. package/dist/internal/oauth-server.mjs +66 -0
  48. package/dist/internal/oauth-server.mjs.map +1 -0
  49. package/dist/internal/passkey/admission.d.mts +6 -0
  50. package/dist/internal/passkey/admission.mjs +216 -0
  51. package/dist/internal/passkey/admission.mjs.map +1 -0
  52. package/dist/internal/passkey/credentials.d.mts +14 -0
  53. package/dist/internal/passkey/credentials.mjs +249 -0
  54. package/dist/internal/passkey/credentials.mjs.map +1 -0
  55. package/dist/internal/passkey/enrollment.mjs +138 -0
  56. package/dist/internal/passkey/enrollment.mjs.map +1 -0
  57. package/dist/internal/passkey/flow.d.mts +21 -0
  58. package/dist/internal/passkey/flow.mjs +452 -0
  59. package/dist/internal/passkey/flow.mjs.map +1 -0
  60. package/dist/internal/passkey/management.mjs +231 -0
  61. package/dist/internal/passkey/management.mjs.map +1 -0
  62. package/dist/internal/passkey/registration-ceremony.d.mts +9 -0
  63. package/dist/internal/passkey/registration-ceremony.mjs +129 -0
  64. package/dist/internal/passkey/registration-ceremony.mjs.map +1 -0
  65. package/dist/internal/passkey/registration-custody.d.mts +2 -0
  66. package/dist/internal/passkey/registration-custody.mjs +52 -0
  67. package/dist/internal/passkey/registration-custody.mjs.map +1 -0
  68. package/dist/internal/passkey/registration-write.mjs +211 -0
  69. package/dist/internal/passkey/registration-write.mjs.map +1 -0
  70. package/dist/internal/passkey/state.d.mts +10 -0
  71. package/dist/internal/passkey/state.mjs +234 -0
  72. package/dist/internal/passkey/state.mjs.map +1 -0
  73. package/dist/internal/passkey/target.d.mts +19 -0
  74. package/dist/internal/passkey/target.mjs +190 -0
  75. package/dist/internal/passkey/target.mjs.map +1 -0
  76. package/dist/internal/passkey/write-state.d.mts +17 -0
  77. package/dist/internal/passkey/write-state.mjs +345 -0
  78. package/dist/internal/passkey/write-state.mjs.map +1 -0
  79. package/dist/internal/passkey/write-target.mjs +192 -0
  80. package/dist/internal/passkey/write-target.mjs.map +1 -0
  81. package/dist/internal/passkey-kernel.d.mts +5592 -0
  82. package/dist/internal/passkey-kernel.mjs +49 -0
  83. package/dist/internal/passkey-kernel.mjs.map +1 -0
  84. package/dist/internal/passkeys.d.mts +7 -0
  85. package/dist/internal/passkeys.mjs +368 -0
  86. package/dist/internal/passkeys.mjs.map +1 -0
  87. package/dist/internal/password-kernel.d.mts +290 -0
  88. package/dist/internal/password-kernel.mjs +704 -0
  89. package/dist/internal/password-kernel.mjs.map +1 -0
  90. package/dist/internal/persistence.d.mts +25 -0
  91. package/dist/internal/persistence.mjs +291 -0
  92. package/dist/internal/persistence.mjs.map +1 -0
  93. package/dist/internal/phone-kernel.d.mts +162 -0
  94. package/dist/internal/phone-kernel.mjs +434 -0
  95. package/dist/internal/phone-kernel.mjs.map +1 -0
  96. package/dist/internal/proof-kernel.d.mts +93 -0
  97. package/dist/internal/proof-kernel.mjs +619 -0
  98. package/dist/internal/proof-kernel.mjs.map +1 -0
  99. package/dist/internal/query-operations.d.mts +61 -0
  100. package/dist/internal/registration-contract.d.mts +16 -0
  101. package/dist/internal/registration.mjs +66 -0
  102. package/dist/internal/registration.mjs.map +1 -0
  103. package/dist/internal/session-kernel.d.mts +48 -0
  104. package/dist/internal/session-kernel.mjs +737 -0
  105. package/dist/internal/session-kernel.mjs.map +1 -0
  106. package/dist/internal/sql-persistence.d.mts +10 -0
  107. package/dist/internal/sql-persistence.mjs +37 -0
  108. package/dist/internal/sql-persistence.mjs.map +1 -0
  109. package/dist/internal/sql-query.mjs +207 -0
  110. package/dist/internal/sql-query.mjs.map +1 -0
  111. package/dist/internal/sql-table.d.mts +36 -0
  112. package/dist/internal/sql-table.mjs +81 -0
  113. package/dist/internal/sql-table.mjs.map +1 -0
  114. package/dist/internal/standalone.d.mts +9 -0
  115. package/dist/internal/standalone.mjs +13 -0
  116. package/dist/internal/standalone.mjs.map +1 -0
  117. package/dist/internal/step-up-state.d.mts +49 -0
  118. package/dist/internal/step-up-state.mjs +32 -0
  119. package/dist/internal/step-up-state.mjs.map +1 -0
  120. package/dist/internal/storage-mapping.mjs +686 -0
  121. package/dist/internal/storage-mapping.mjs.map +1 -0
  122. package/dist/internal/storage-tables.d.mts +913 -0
  123. package/dist/internal/storage-tables.mjs +387 -0
  124. package/dist/internal/storage-tables.mjs.map +1 -0
  125. package/dist/internal/storage-validation.mjs +58 -0
  126. package/dist/internal/storage-validation.mjs.map +1 -0
  127. package/dist/internal/transaction-execution-kernel.d.mts +38 -0
  128. package/dist/internal/transaction-execution-kernel.mjs +116 -0
  129. package/dist/internal/transaction-execution-kernel.mjs.map +1 -0
  130. package/dist/internal/transaction-kernel.d.mts +77 -0
  131. package/dist/internal/transaction-kernel.mjs +260 -0
  132. package/dist/internal/transaction-kernel.mjs.map +1 -0
  133. package/package.json +1 -0
  134. package/src/Adapter.ts +291 -0
  135. package/src/index.ts +6 -0
  136. package/src/internal/PasswordPreparedPostconditions.ts +30 -0
  137. package/src/internal/configuration.ts +282 -0
  138. package/src/internal/email-kernel.ts +1535 -0
  139. package/src/internal/mapping-error.ts +36 -0
  140. package/src/internal/models/common.ts +11 -0
  141. package/src/internal/models/email-model.ts +559 -0
  142. package/src/internal/models/passkey-model.ts +390 -0
  143. package/src/internal/models/passkey-registration-ceremony-model.ts +72 -0
  144. package/src/internal/models/passkey-write-model.ts +297 -0
  145. package/src/internal/models/password-model.ts +513 -0
  146. package/src/internal/models/proof-model.ts +424 -0
  147. package/src/internal/models/session-model.ts +375 -0
  148. package/src/internal/models/step-up-model.ts +135 -0
  149. package/src/internal/oauth-app.ts +82 -0
  150. package/src/internal/oauth-server.ts +89 -0
  151. package/src/internal/passkey/admission.ts +361 -0
  152. package/src/internal/passkey/credentials.ts +511 -0
  153. package/src/internal/passkey/enrollment.ts +326 -0
  154. package/src/internal/passkey/flow.ts +1062 -0
  155. package/src/internal/passkey/management.ts +421 -0
  156. package/src/internal/passkey/registration-ceremony.ts +283 -0
  157. package/src/internal/passkey/registration-custody.ts +91 -0
  158. package/src/internal/passkey/registration-write.ts +426 -0
  159. package/src/internal/passkey/state.ts +353 -0
  160. package/src/internal/passkey/target.ts +586 -0
  161. package/src/internal/passkey/write-state.ts +681 -0
  162. package/src/internal/passkey/write-target.ts +452 -0
  163. package/src/internal/passkey-kernel.ts +104 -0
  164. package/src/internal/passkeys.ts +606 -0
  165. package/src/internal/password-kernel.ts +2124 -0
  166. package/src/internal/persistence.ts +588 -0
  167. package/src/internal/phone-kernel.ts +846 -0
  168. package/src/internal/proof-kernel.ts +1954 -0
  169. package/src/internal/query-operations.ts +81 -0
  170. package/src/internal/registration-contract.ts +22 -0
  171. package/src/internal/registration.ts +161 -0
  172. package/src/internal/session-kernel.ts +2217 -0
  173. package/src/internal/sql-persistence.ts +45 -0
  174. package/src/internal/sql-query.ts +298 -0
  175. package/src/internal/sql-table.ts +104 -0
  176. package/src/internal/standalone.ts +30 -0
  177. package/src/internal/step-up-state.ts +139 -0
  178. package/src/internal/storage-mapping.ts +708 -0
  179. package/src/internal/storage-tables.ts +408 -0
  180. package/src/internal/storage-validation.ts +117 -0
  181. package/src/internal/transaction-execution-kernel.ts +313 -0
  182. package/src/internal/transaction-kernel.ts +593 -0
@@ -0,0 +1,390 @@
1
+ import {
2
+ type PasskeyCeremony,
3
+ type PasskeyCredential,
4
+ type PasskeyMethodPolicy,
5
+ PasskeyCredentials,
6
+ PasskeyEnrollmentContext,
7
+ PasskeyPersistence,
8
+ } from "@yielded/auth/Passkey";
9
+ import type { SubjectId } from "@yielded/auth/Schema";
10
+ import { Effect, Layer } from "effect";
11
+
12
+ import type { TableModel as Table, SqlExpression } from "../query-operations";
13
+ import type { PersistenceMappingError } from "./common";
14
+
15
+ export type PasskeyColumn<T extends Table> = T["column"];
16
+
17
+ export type PasskeyMappingSource<M, RSetup = never> =
18
+ | M
19
+ | Effect.Effect<M, PersistenceMappingError, RSetup>;
20
+
21
+ export interface PasskeyCredentialServices {
22
+ readonly passkeyCredentials: PasskeyCredentials["Service"];
23
+ }
24
+
25
+ export interface PasskeyPersistenceServices {
26
+ readonly passkeyPersistence: PasskeyPersistence["Service"];
27
+ }
28
+
29
+ export interface PasskeyEnrollmentContextServices {
30
+ readonly passkeyEnrollmentContext: PasskeyEnrollmentContext["Service"];
31
+ }
32
+
33
+ export const passkeyCredentialsLayer = <E, R>(
34
+ services: Effect.Effect<PasskeyCredentialServices, E, R>,
35
+ ): Layer.Layer<PasskeyCredentials, E, R> =>
36
+ Layer.effect(
37
+ PasskeyCredentials,
38
+ Effect.map(services, (value) => value.passkeyCredentials),
39
+ );
40
+
41
+ export const passkeyPersistenceLayer = <E, R>(
42
+ services: Effect.Effect<PasskeyPersistenceServices, E, R>,
43
+ ): Layer.Layer<PasskeyPersistence, E, R> =>
44
+ Layer.effect(
45
+ PasskeyPersistence,
46
+ Effect.map(services, (value) => value.passkeyPersistence),
47
+ );
48
+
49
+ export const passkeyEnrollmentContextLayer = <E, R>(
50
+ services: Effect.Effect<PasskeyEnrollmentContextServices, E, R>,
51
+ ): Layer.Layer<PasskeyEnrollmentContext, E, R> =>
52
+ Layer.effect(
53
+ PasskeyEnrollmentContext,
54
+ Effect.map(services, (value) => value.passkeyEnrollmentContext),
55
+ );
56
+
57
+ /** Native IDs roundtrip exactly; protocol IDs and authentication references are
58
+ * different identities. These callbacks never suspend inside an owner. */
59
+ export interface PasskeySubjectIdCodec<N> {
60
+ readonly toNative: (id: SubjectId) => N;
61
+ readonly toSubject: (id: N) => SubjectId;
62
+ readonly equals: (left: N, right: N) => boolean;
63
+ }
64
+
65
+ export interface PasskeyClock<Expression extends SqlExpression = SqlExpression> {
66
+ readonly encodeInstant: (millis: number) => unknown;
67
+ readonly decodeInstant: (value: unknown) => number;
68
+ readonly engineNowMillis: Expression;
69
+ readonly toMillis: (expression: Expression) => Expression;
70
+ readonly fromMillis: (expression: Expression) => Expression;
71
+ }
72
+
73
+ export interface PasskeySubjectReadTable<
74
+ T extends Table,
75
+ N,
76
+ Expression extends SqlExpression = SqlExpression,
77
+ > {
78
+ readonly table: T["table"];
79
+ readonly id: PasskeyColumn<T>;
80
+ readonly status: PasskeyColumn<T>;
81
+ readonly securityRevision: PasskeyColumn<T>;
82
+ readonly decodeId: (row: Readonly<Partial<T["select"]>>) => N;
83
+ readonly isActiveStatus: (value: unknown) => boolean;
84
+ readonly activeCondition: Expression;
85
+ }
86
+
87
+ export interface PasskeyFactorReadTable<
88
+ T extends Table,
89
+ Expression extends SqlExpression = SqlExpression,
90
+ > {
91
+ readonly table: T["table"];
92
+ readonly subjectId: PasskeyColumn<T>;
93
+ readonly credentialId: PasskeyColumn<T>;
94
+ readonly revision: PasskeyColumn<T>;
95
+ readonly status: PasskeyColumn<T>;
96
+ readonly isActiveStatus: (value: unknown) => boolean;
97
+ readonly activeCondition: Expression;
98
+ }
99
+
100
+ /** decode uses only these declared columns. Counter columns are native integral
101
+ * numbers; BS may use a consumer enum. Name/creation metadata is not required. */
102
+ export interface PasskeyCredentialReadTable<
103
+ T extends Table,
104
+ N,
105
+ Expression extends SqlExpression = SqlExpression,
106
+ > {
107
+ readonly table: T["table"];
108
+ readonly credentialId: PasskeyColumn<T>;
109
+ readonly subjectId: PasskeyColumn<T>;
110
+ readonly rpId: PasskeyColumn<T>;
111
+ readonly protocolCredentialId: PasskeyColumn<T>;
112
+ readonly credentialKey: PasskeyColumn<T>;
113
+ readonly handleKey: PasskeyColumn<T>;
114
+ readonly userHandle: PasskeyColumn<T>;
115
+ readonly publicKey: PasskeyColumn<T>;
116
+ readonly algorithm: PasskeyColumn<T>;
117
+ readonly profile: PasskeyColumn<T>;
118
+ readonly credentialRevision: PasskeyColumn<T>;
119
+ readonly status: PasskeyColumn<T>;
120
+ readonly primarySignIn: PasskeyColumn<T>;
121
+ readonly enrollmentUserVerified: PasskeyColumn<T>;
122
+ readonly backupEligible: PasskeyColumn<T>;
123
+ readonly backupState: PasskeyColumn<T>;
124
+ readonly counter: PasskeyColumn<T>;
125
+ readonly maximumCounter: PasskeyColumn<T>;
126
+ readonly decode: (
127
+ row: Readonly<Partial<T["select"]>>,
128
+ ) => Omit<PasskeyCredential, "revision" | "active">;
129
+ readonly decodeSubjectId: (row: Readonly<Partial<T["select"]>>) => N;
130
+ readonly isActiveStatus: (value: unknown) => boolean;
131
+ readonly activeCondition: Expression;
132
+ }
133
+
134
+ export interface PasskeyCredentialOwnershipTable<
135
+ T extends Table,
136
+ N,
137
+ Expression extends SqlExpression = SqlExpression,
138
+ > {
139
+ readonly table: T["table"];
140
+ readonly credentialKey: PasskeyColumn<T>;
141
+ readonly rpId: PasskeyColumn<T>;
142
+ readonly protocolCredentialId: PasskeyColumn<T>;
143
+ readonly subjectId: PasskeyColumn<T>;
144
+ readonly credentialId: PasskeyColumn<T>;
145
+ readonly state: PasskeyColumn<T>;
146
+ readonly version: PasskeyColumn<T>;
147
+ readonly reservationId: PasskeyColumn<T>;
148
+ readonly ownedCondition: Expression;
149
+ readonly isOwnedState: (value: unknown) => boolean;
150
+ readonly decodeSubjectId: (row: Readonly<Partial<T["select"]>>) => N;
151
+ }
152
+
153
+ /** Reservations do not manufacture a subject; bound handles are RP-global. */
154
+ export interface PasskeyHandleReadTable<T extends Table> {
155
+ readonly table: T["table"];
156
+ readonly handleKey: PasskeyColumn<T>;
157
+ readonly rpId: PasskeyColumn<T>;
158
+ readonly userHandle: PasskeyColumn<T>;
159
+ readonly state: PasskeyColumn<T>;
160
+ readonly version: PasskeyColumn<T>;
161
+ readonly reservationId: PasskeyColumn<T>;
162
+ }
163
+
164
+ export interface PasskeyHandleReservationTable<
165
+ T extends Table,
166
+ Expression extends SqlExpression = SqlExpression,
167
+ > extends PasskeyHandleReadTable<T> {
168
+ readonly reservedCondition: Expression;
169
+ readonly isReservedState: (value: unknown) => boolean;
170
+ }
171
+
172
+ export interface PasskeyHandleOwnershipTable<
173
+ T extends Table,
174
+ N,
175
+ Expression extends SqlExpression = SqlExpression,
176
+ > extends PasskeyHandleReadTable<T> {
177
+ readonly subjectId: PasskeyColumn<T>;
178
+ readonly ownedCondition: Expression;
179
+ readonly isOwnedState: (value: unknown) => boolean;
180
+ readonly decodeSubjectId: (row: Readonly<Partial<T["select"]>>) => N;
181
+ }
182
+
183
+ export const requiredPasskeyCredentialConstraints = {
184
+ credentialId: ["credentialId"],
185
+ factor: ["subjectId", "credentialId"],
186
+ credentialOwnership: ["credentialKey"],
187
+ handleOwnership: ["handleKey"],
188
+ boundSubjectHandle: ["rpId", "subjectId"],
189
+ } as const;
190
+
191
+ export interface PasskeyCredentialMapping<
192
+ S extends Table,
193
+ C extends Table,
194
+ F extends Table,
195
+ Ownership extends Table,
196
+ Handle extends Table,
197
+ N,
198
+ Expression extends SqlExpression = SqlExpression,
199
+ > {
200
+ readonly subject: PasskeySubjectReadTable<S, N, Expression>;
201
+ readonly credential: PasskeyCredentialReadTable<C, N, Expression>;
202
+ readonly authority: PasskeyFactorReadTable<F, Expression>;
203
+ readonly credentialOwnership: PasskeyCredentialOwnershipTable<Ownership, N, Expression>;
204
+ readonly handleOwnership: PasskeyHandleOwnershipTable<Handle, N, Expression>;
205
+ readonly subjectIds: PasskeySubjectIdCodec<N>;
206
+ readonly constraints: typeof requiredPasskeyCredentialConstraints;
207
+ }
208
+
209
+ /** A stable additional policy row, acquired before RP/credential locks. The
210
+ * factory checks column names without erasing the consumer table at its input. */
211
+ const PasskeyPolicyGuardTypeId: unique symbol = Symbol("effect-auth/drizzle/PasskeyPolicyGuard");
212
+
213
+ export interface PasskeyPolicyGuard<Expression extends SqlExpression = SqlExpression> {
214
+ readonly [PasskeyPolicyGuardTypeId]: true;
215
+ readonly scope: string;
216
+ readonly table: object;
217
+ readonly columns: ReadonlyArray<string>;
218
+ readonly where: (moduleId: string) => Expression;
219
+ readonly condition: (moduleId: string) => Expression;
220
+ }
221
+
222
+ export const passkeyPolicyGuard = <
223
+ T extends Table,
224
+ Expression extends SqlExpression = SqlExpression,
225
+ >(input: {
226
+ readonly scope: string;
227
+ readonly table: T["table"];
228
+ readonly columns: ReadonlyArray<PasskeyColumn<T>>;
229
+ readonly where: (moduleId: string) => Expression;
230
+ readonly condition: (moduleId: string) => Expression;
231
+ }): PasskeyPolicyGuard<Expression> => ({ ...input, [PasskeyPolicyGuardTypeId]: true });
232
+
233
+ export interface PasskeyModuleTable<
234
+ T extends Table,
235
+ Expression extends SqlExpression = SqlExpression,
236
+ > {
237
+ readonly table: T["table"];
238
+ readonly moduleId: PasskeyColumn<T>;
239
+ readonly status: PasskeyColumn<T>;
240
+ readonly policyRevision: PasskeyColumn<T>;
241
+ /** All physical fields used by decodeMethodPolicy, including policyRevision. */
242
+ readonly policyColumns: ReadonlyArray<PasskeyColumn<T>>;
243
+ readonly isActiveStatus: (value: unknown) => boolean;
244
+ readonly activeCondition: Expression;
245
+ readonly decodeMethodPolicy: (row: Readonly<Partial<T["select"]>>) => PasskeyMethodPolicy;
246
+ readonly guards?: ReadonlyArray<PasskeyPolicyGuard<Expression>>;
247
+ }
248
+
249
+ export type PasskeyFlowState =
250
+ | "Pending"
251
+ | "Claimed"
252
+ | "Verified"
253
+ | "Rejected"
254
+ | "Ambiguous"
255
+ | "RegistrationAccepted"
256
+ | "ProvisioningPending";
257
+
258
+ export interface PasskeyFlowInsert {
259
+ readonly ceremony: PasskeyCeremony;
260
+ readonly policy: PasskeyMethodPolicy;
261
+ readonly marker: string;
262
+ }
263
+
264
+ export interface PasskeyFlowTable<T extends Table> {
265
+ readonly table: T["table"];
266
+ readonly moduleId: PasskeyColumn<T>;
267
+ readonly flowId: PasskeyColumn<T>;
268
+ readonly commandId: PasskeyColumn<T>;
269
+ readonly purpose: PasskeyColumn<T>;
270
+ readonly state: PasskeyColumn<T>;
271
+ readonly version: PasskeyColumn<T>;
272
+ readonly generation: PasskeyColumn<T>;
273
+ readonly snapshot: PasskeyColumn<T>;
274
+ readonly policySnapshot: PasskeyColumn<T>;
275
+ readonly requestBindingVerifier: PasskeyColumn<T>;
276
+ readonly requestBindingExpiresAt: PasskeyColumn<T>;
277
+ readonly issuedAt: PasskeyColumn<T>;
278
+ readonly expiresAt: PasskeyColumn<T>;
279
+ readonly retentionUntil: PasskeyColumn<T>;
280
+ readonly claimId: PasskeyColumn<T>;
281
+ readonly claimedAt: PasskeyColumn<T>;
282
+ readonly claimExpiresAt: PasskeyColumn<T>;
283
+ readonly credentialSnapshot: PasskeyColumn<T>;
284
+ /** Core SubjectId scope text, not a consumer's native subject ID. */
285
+ readonly subjectScope: PasskeyColumn<T>;
286
+ readonly targetScope: PasskeyColumn<T>;
287
+ readonly states: Readonly<Record<PasskeyFlowState, unknown>>;
288
+ readonly encodeInsert: (input: PasskeyFlowInsert) => T["insert"];
289
+ }
290
+
291
+ export interface PasskeyAdmissionTable<T extends Table> {
292
+ readonly table: T["table"];
293
+ readonly authorityScope: PasskeyColumn<T>;
294
+ readonly moduleId: PasskeyColumn<T>;
295
+ readonly version: PasskeyColumn<T>;
296
+ readonly ownerMarker: PasskeyColumn<T>;
297
+ /** One physical clock sample, reused by every charge of this decision. */
298
+ readonly admittedAt: PasskeyColumn<T>;
299
+ }
300
+
301
+ export type PasskeyChargeKind = "global" | "subject" | "target";
302
+
303
+ export interface PasskeyChargeInsert {
304
+ readonly moduleId: string;
305
+ readonly flowId: string;
306
+ readonly purpose: PasskeyCeremony["purpose"];
307
+ readonly kind: PasskeyChargeKind;
308
+ readonly scope: string;
309
+ readonly originalWindowMillis: number;
310
+ readonly marker: string;
311
+ }
312
+
313
+ /** Charge scope is canonical core identity text; this subject-free descriptor
314
+ * can count all purposes without decoding any unrelated native subject. */
315
+ export interface PasskeyChargeTable<T extends Table> {
316
+ readonly table: T["table"];
317
+ readonly moduleId: PasskeyColumn<T>;
318
+ readonly flowId: PasskeyColumn<T>;
319
+ readonly purpose: PasskeyColumn<T>;
320
+ readonly kind: PasskeyColumn<T>;
321
+ readonly scope: PasskeyColumn<T>;
322
+ readonly originalWindowMillis: PasskeyColumn<T>;
323
+ readonly admittedAt: PasskeyColumn<T>;
324
+ readonly retainUntil: PasskeyColumn<T>;
325
+ readonly version: PasskeyColumn<T>;
326
+ readonly ownerMarker: PasskeyColumn<T>;
327
+ readonly encodeInsert: (input: PasskeyChargeInsert) => T["insert"];
328
+ }
329
+
330
+ export const requiredPasskeyPersistenceConstraints = {
331
+ flow: ["moduleId", "flowId"],
332
+ command: ["moduleId", "commandId"],
333
+ admission: ["authorityScope", "moduleId"],
334
+ charge: ["moduleId", "flowId", "kind"],
335
+ } as const;
336
+
337
+ export interface PasskeyCeremonyMapping<
338
+ Module extends Table,
339
+ Flow extends Table,
340
+ Admission extends Table,
341
+ Charge extends Table,
342
+ Expression extends SqlExpression = SqlExpression,
343
+ > {
344
+ readonly moduleId: string;
345
+ readonly authorityScope: string;
346
+ readonly module: PasskeyModuleTable<Module, Expression>;
347
+ readonly flow: PasskeyFlowTable<Flow>;
348
+ readonly admission: PasskeyAdmissionTable<Admission>;
349
+ readonly charge: PasskeyChargeTable<Charge>;
350
+ readonly clock: PasskeyClock<Expression>;
351
+ readonly constraints: typeof requiredPasskeyPersistenceConstraints;
352
+ }
353
+
354
+ export interface PasskeyPersistenceMapping<
355
+ Read,
356
+ Module extends Table,
357
+ Flow extends Table,
358
+ Admission extends Table,
359
+ Charge extends Table,
360
+ N,
361
+ Expression extends SqlExpression = SqlExpression,
362
+ Credential extends Table = Table,
363
+ > extends PasskeyCeremonyMapping<Module, Flow, Admission, Charge, Expression> {
364
+ readonly read: Read & {
365
+ readonly subjectIds: PasskeySubjectIdCodec<N>;
366
+ };
367
+ readonly telemetry: {
368
+ readonly lastUsedAt: PasskeyColumn<Credential>;
369
+ readonly encodeBackupState: (value: boolean) => unknown;
370
+ };
371
+ }
372
+
373
+ export interface PasskeyEnrollmentContextMapping<
374
+ Read,
375
+ Module extends Table,
376
+ N,
377
+ Expression extends SqlExpression = SqlExpression,
378
+ > {
379
+ readonly moduleId: string;
380
+ readonly read: Read & {
381
+ readonly subjectIds: PasskeySubjectIdCodec<N>;
382
+ };
383
+ readonly module: PasskeyModuleTable<Module, Expression>;
384
+ }
385
+
386
+ export interface D1PasskeyMapping {
387
+ readonly d1: {
388
+ readonly primary: true;
389
+ };
390
+ }
@@ -0,0 +1,72 @@
1
+ import type { TableModel as Table, SqlExpression } from "../query-operations";
2
+ import type {
3
+ PasskeyCeremonyMapping,
4
+ PasskeyChargeTable,
5
+ PasskeyColumn,
6
+ PasskeyFlowTable,
7
+ PasskeyHandleReservationTable,
8
+ PasskeyPersistenceServices,
9
+ } from "./passkey-model";
10
+
11
+ export interface PasskeyRegistrationCeremonyCapabilities {
12
+ readonly purposes: readonly ["registration"];
13
+ readonly issue: "registration-authority";
14
+ readonly assertionSettlement: false;
15
+ }
16
+
17
+ export interface PasskeyRegistrationCeremonyServices extends PasskeyPersistenceServices {
18
+ readonly capabilities: PasskeyRegistrationCeremonyCapabilities;
19
+ }
20
+
21
+ /** Read-only custody supplied by a separate registration issuance authority.
22
+ * No application payload codec, subject codec or provisioning callback runs here. */
23
+ export interface PasskeyRegistrationIntentReadTable<
24
+ T extends Table,
25
+ Expression extends SqlExpression = SqlExpression,
26
+ > {
27
+ readonly table: T["table"];
28
+ readonly moduleId: PasskeyColumn<T>;
29
+ readonly flowId: PasskeyColumn<T>;
30
+ readonly commandId: PasskeyColumn<T>;
31
+ readonly state: PasskeyColumn<T>;
32
+ readonly version: PasskeyColumn<T>;
33
+ readonly fingerprint: PasskeyColumn<T>;
34
+ readonly handleKey: PasskeyColumn<T>;
35
+ readonly reservationId: PasskeyColumn<T>;
36
+ readonly ceremonySnapshot: PasskeyColumn<T>;
37
+ /** Already validated by the issuing authority; compare opaque bytes only. */
38
+ readonly applicationSnapshot: PasskeyColumn<T>;
39
+ readonly pendingCondition: Expression;
40
+ readonly isPendingState: (value: unknown) => boolean;
41
+ /** Any unresolved initial intent or provisioning job; cleanup never releases it. */
42
+ readonly custodyCondition: Expression;
43
+ }
44
+
45
+ export const requiredPasskeyRegistrationCeremonyConstraints = {
46
+ flow: ["moduleId", "flowId"],
47
+ command: ["moduleId", "commandId"],
48
+ admission: ["authorityScope", "moduleId"],
49
+ charge: ["moduleId", "flowId", "kind"],
50
+ intentFlow: ["moduleId", "flowId"],
51
+ intentCommand: ["moduleId", "commandId"],
52
+ handle: ["handleKey"],
53
+ } as const;
54
+
55
+ export interface PasskeyRegistrationCeremonyMapping<
56
+ Module extends Table,
57
+ Flow extends Table,
58
+ Admission extends Table,
59
+ Charge extends Table,
60
+ Intent extends Table,
61
+ Handle extends Table,
62
+ Expression extends SqlExpression = SqlExpression,
63
+ > extends Omit<
64
+ PasskeyCeremonyMapping<Module, Flow, Admission, Charge, Expression>,
65
+ "constraints" | "flow" | "charge"
66
+ > {
67
+ readonly flow: Omit<PasskeyFlowTable<Flow>, "encodeInsert">;
68
+ readonly charge: Omit<PasskeyChargeTable<Charge>, "encodeInsert">;
69
+ readonly intent: PasskeyRegistrationIntentReadTable<Intent, Expression>;
70
+ readonly handle: PasskeyHandleReservationTable<Handle, Expression>;
71
+ readonly constraints: typeof requiredPasskeyRegistrationCeremonyConstraints;
72
+ }