@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,66 @@
1
+ import { SqlExpression, TableModel } from "../query-operations.mjs";
2
+ import { PersistenceMappingError } from "../mapping-error.mjs";
3
+ import "./common.mjs";
4
+ import { D1SessionClockMapping, SessionAuthorityTables, SessionConstraintClassifier, SessionIdCodec, SignedSessionValidityTables, StatefulSessionTables } from "./session-model.mjs";
5
+ import { DateTime, Effect } from "effect";
6
+ import { SecurityRevision, SessionStepUpIntent } from "@yielded/auth/Sessions";
7
+ //#region src/internal/models/step-up-model.d.ts
8
+ type ColumnKey<T extends TableModel> = T["column"];
9
+ /** Distinct from login-pending storage. Snapshot is TEXT encoded by the core's
10
+ * SessionStepUpIntent schema; it contains no Claims and needs no consumer decoder. */
11
+ export interface SessionStepUpIntentTables<Intent extends TableModel, NativeSubjectId> {
12
+ readonly intent: {
13
+ readonly table: Intent["table"];
14
+ readonly digest: ColumnKey<Intent>;
15
+ readonly version: ColumnKey<Intent>;
16
+ readonly flowId: ColumnKey<Intent>;
17
+ readonly subjectId: ColumnKey<Intent>;
18
+ readonly bindingDigest: ColumnKey<Intent>;
19
+ readonly snapshot: ColumnKey<Intent>;
20
+ readonly expiresAt: ColumnKey<Intent>;
21
+ readonly attemptLimit: ColumnKey<Intent>;
22
+ readonly failedAttempts: ColumnKey<Intent>;
23
+ readonly consumed: ColumnKey<Intent>;
24
+ readonly encodeInstant: (instant: DateTime.Utc) => unknown;
25
+ /** Consumer fields/defaults; the adapter sets all mapped security columns. */
26
+ readonly encodeInsert: (intent: SessionStepUpIntent, input: {
27
+ readonly subjectId: NativeSubjectId;
28
+ }) => Intent["insert"];
29
+ readonly allocateVersion?: Effect.Effect<SecurityRevision, PersistenceMappingError>;
30
+ readonly allocateVersionSync?: () => SecurityRevision;
31
+ };
32
+ }
33
+ export interface RequiredSessionStepUpConstraints {
34
+ readonly intentDigest: "unique(intent.digest)";
35
+ readonly intentFlow: "unique(intent.flowId)";
36
+ }
37
+ export declare const requiredSessionStepUpConstraints: RequiredSessionStepUpConstraints;
38
+ /** Fixed source discriminator is checked against every stored intent. A minimal
39
+ * pure-signed installation does not provide dummy session or tombstone tables. */
40
+ export type SessionStepUpSourceTables<Claims, Session extends TableModel, Tombstone extends TableModel, NativeSubjectId, NativeSessionId> = {
41
+ readonly kind: "StatelessSigned";
42
+ } | ({
43
+ readonly kind: "StateAssistedSigned";
44
+ readonly constraints: {
45
+ readonly tombstoneOwner: "unique(tombstone.subjectId,tombstone.sessionId)";
46
+ };
47
+ } & SignedSessionValidityTables<Tombstone, NativeSubjectId, NativeSessionId>) | {
48
+ readonly kind: "Stateful";
49
+ readonly constraints: {
50
+ readonly sessionDigest: "unique(session.digest)";
51
+ };
52
+ readonly sessionId: SessionIdCodec<NativeSessionId>;
53
+ /** encodeRotation must replace Claims, provenance, and the queryable security
54
+ * fields together; it must not retain the old proof payload. */
55
+ readonly session: StatefulSessionTables<Claims, Session, TableModel, NativeSubjectId, NativeSessionId>["session"] & {
56
+ readonly credentialVersion: ColumnKey<Session>;
57
+ readonly authenticatedAt: ColumnKey<Session>;
58
+ };
59
+ };
60
+ export type SessionStepUpMapping<Claims, Subject extends TableModel, Credential extends TableModel, Intent extends TableModel, Session extends TableModel, Tombstone extends TableModel, NativeSubjectId, NativeSessionId> = SessionAuthorityTables<Subject, Credential, NativeSubjectId> & SessionStepUpIntentTables<Intent, NativeSubjectId> & SessionConstraintClassifier & {
61
+ readonly source: SessionStepUpSourceTables<Claims, Session, Tombstone, NativeSubjectId, NativeSessionId>;
62
+ readonly constraints: RequiredSessionStepUpConstraints;
63
+ };
64
+ export type D1SessionStepUpMapping<Claims, Subject extends TableModel, Credential extends TableModel, Intent extends TableModel, Session extends TableModel, Tombstone extends TableModel, NativeSubjectId, NativeSessionId, Expression extends SqlExpression = SqlExpression> = SessionStepUpMapping<Claims, Subject, Credential, Intent, Session, Tombstone, NativeSubjectId, NativeSessionId> & D1SessionClockMapping<Expression>;
65
+ //#endregion
66
+ //# sourceMappingURL=step-up-model.d.mts.map
@@ -0,0 +1,9 @@
1
+ //#region src/internal/models/step-up-model.ts
2
+ const requiredSessionStepUpConstraints = {
3
+ intentDigest: "unique(intent.digest)",
4
+ intentFlow: "unique(intent.flowId)"
5
+ };
6
+ //#endregion
7
+ export { requiredSessionStepUpConstraints };
8
+
9
+ //# sourceMappingURL=step-up-model.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-up-model.mjs","names":[],"sources":["../../../src/internal/models/step-up-model.ts"],"sourcesContent":["import type { SecurityRevision, SessionStepUpIntent } from \"@yielded/auth/Sessions\";\nimport type { DateTime, Effect } from \"effect\";\n\nimport type { TableModel as Table, SqlExpression } from \"../query-operations\";\nimport type { PersistenceMappingError } from \"./common\";\nimport type {\n D1SessionClockMapping,\n SessionAuthorityTables,\n SessionConstraintClassifier,\n SessionIdCodec,\n SignedSessionValidityTables,\n StatefulSessionTables,\n} from \"./session-model\";\n\ntype ColumnKey<T extends Table> = T[\"column\"];\n\n/** Distinct from login-pending storage. Snapshot is TEXT encoded by the core's\n * SessionStepUpIntent schema; it contains no Claims and needs no consumer decoder. */\nexport interface SessionStepUpIntentTables<Intent extends Table, NativeSubjectId> {\n readonly intent: {\n readonly table: Intent[\"table\"];\n readonly digest: ColumnKey<Intent>;\n readonly version: ColumnKey<Intent>;\n readonly flowId: ColumnKey<Intent>;\n readonly subjectId: ColumnKey<Intent>;\n readonly bindingDigest: ColumnKey<Intent>;\n readonly snapshot: ColumnKey<Intent>;\n readonly expiresAt: ColumnKey<Intent>;\n readonly attemptLimit: ColumnKey<Intent>;\n readonly failedAttempts: ColumnKey<Intent>;\n readonly consumed: ColumnKey<Intent>;\n readonly encodeInstant: (instant: DateTime.Utc) => unknown;\n /** Consumer fields/defaults; the adapter sets all mapped security columns. */\n readonly encodeInsert: (\n intent: SessionStepUpIntent,\n input: {\n readonly subjectId: NativeSubjectId;\n },\n ) => Intent[\"insert\"];\n readonly allocateVersion?: Effect.Effect<SecurityRevision, PersistenceMappingError>;\n readonly allocateVersionSync?: () => SecurityRevision;\n };\n}\n\nexport interface RequiredSessionStepUpConstraints {\n readonly intentDigest: \"unique(intent.digest)\";\n readonly intentFlow: \"unique(intent.flowId)\";\n}\n\nexport const requiredSessionStepUpConstraints: RequiredSessionStepUpConstraints = {\n intentDigest: \"unique(intent.digest)\",\n intentFlow: \"unique(intent.flowId)\",\n};\n\n/** Fixed source discriminator is checked against every stored intent. A minimal\n * pure-signed installation does not provide dummy session or tombstone tables. */\nexport type SessionStepUpSourceTables<\n Claims,\n Session extends Table,\n Tombstone extends Table,\n NativeSubjectId,\n NativeSessionId,\n> =\n | {\n readonly kind: \"StatelessSigned\";\n }\n | ({\n readonly kind: \"StateAssistedSigned\";\n readonly constraints: {\n readonly tombstoneOwner: \"unique(tombstone.subjectId,tombstone.sessionId)\";\n };\n } & SignedSessionValidityTables<Tombstone, NativeSubjectId, NativeSessionId>)\n | {\n readonly kind: \"Stateful\";\n readonly constraints: {\n readonly sessionDigest: \"unique(session.digest)\";\n };\n readonly sessionId: SessionIdCodec<NativeSessionId>;\n /** encodeRotation must replace Claims, provenance, and the queryable security\n * fields together; it must not retain the old proof payload. */\n readonly session: StatefulSessionTables<\n Claims,\n Session,\n Table,\n NativeSubjectId,\n NativeSessionId\n >[\"session\"] & {\n readonly credentialVersion: ColumnKey<Session>;\n readonly authenticatedAt: ColumnKey<Session>;\n };\n };\n\nexport type SessionStepUpMapping<\n Claims,\n Subject extends Table,\n Credential extends Table,\n Intent extends Table,\n Session extends Table,\n Tombstone extends Table,\n NativeSubjectId,\n NativeSessionId,\n> = SessionAuthorityTables<Subject, Credential, NativeSubjectId> &\n SessionStepUpIntentTables<Intent, NativeSubjectId> &\n SessionConstraintClassifier & {\n readonly source: SessionStepUpSourceTables<\n Claims,\n Session,\n Tombstone,\n NativeSubjectId,\n NativeSessionId\n >;\n readonly constraints: RequiredSessionStepUpConstraints;\n };\n\nexport type D1SessionStepUpMapping<\n Claims,\n Subject extends Table,\n Credential extends Table,\n Intent extends Table,\n Session extends Table,\n Tombstone extends Table,\n NativeSubjectId,\n NativeSessionId,\n Expression extends SqlExpression = SqlExpression,\n> = SessionStepUpMapping<\n Claims,\n Subject,\n Credential,\n Intent,\n Session,\n Tombstone,\n NativeSubjectId,\n NativeSessionId\n> &\n D1SessionClockMapping<Expression>;\n"],"mappings":";AAiDA,MAAa,mCAAqE;CAChF,cAAc;CACd,YAAY;AACd"}
@@ -0,0 +1,11 @@
1
+ import { Layer } from "effect";
2
+ import { SqlClient } from "effect/unstable/sql";
3
+ import { OAuthUnavailable } from "@yielded/auth/OAuth";
4
+ import { Persistence } from "@yielded/auth/OAuthApp";
5
+ //#region src/internal/oauth-app.d.ts
6
+ export declare const OAuthAppPersistence: {
7
+ layer: Layer.Layer<Persistence, OAuthUnavailable, SqlClient.SqlClient>;
8
+ migration: string;
9
+ };
10
+ //#endregion
11
+ //# sourceMappingURL=oauth-app.d.mts.map
@@ -0,0 +1,57 @@
1
+ import { requireStandalone } from "./standalone.mjs";
2
+ import { Effect, Layer, Schema } from "effect";
3
+ import { SqlClient } from "effect/unstable/sql";
4
+ import { OAuthUnavailable } from "@yielded/auth/OAuth";
5
+ import { Persistence, Record } from "@yielded/auth/OAuthApp";
6
+ //#region src/internal/oauth-app.ts
7
+ const codec = Schema.fromJsonString(Record);
8
+ const Row = Schema.Struct({
9
+ payload: Schema.String,
10
+ version: Schema.String
11
+ });
12
+ const OAuthAppPersistence = {
13
+ layer: Layer.effect(Persistence, Effect.gen(function* () {
14
+ const sql = yield* SqlClient.SqlClient;
15
+ if (!sql.onDialectOrElse({
16
+ sqlite: () => true,
17
+ pg: () => true,
18
+ orElse: () => false
19
+ })) return yield* OAuthUnavailable.make({});
20
+ const noTransaction = requireStandalone(() => OAuthUnavailable.make({}), sql);
21
+ const failure = (effect) => effect.pipe(Effect.mapError(() => OAuthUnavailable.make({})));
22
+ return Persistence.of({
23
+ get: Effect.fn("OAuthAppPersistence.get")(function* (namespace, key) {
24
+ yield* noTransaction;
25
+ const rows = yield* sql`SELECT payload, version FROM yielded_oauth_app WHERE namespace = ${namespace} AND record_key = ${key}`;
26
+ if (rows.length === 0) return void 0;
27
+ if (rows.length !== 1) return yield* OAuthUnavailable.make({});
28
+ const row = yield* Schema.decodeEffect(Row)(rows[0]);
29
+ const value = yield* Schema.decodeEffect(codec)(row.payload);
30
+ if (value.version !== row.version) return yield* OAuthUnavailable.make({});
31
+ return value;
32
+ }, failure),
33
+ insert: Effect.fn("OAuthAppPersistence.insert")(function* (namespace, key, value) {
34
+ yield* noTransaction;
35
+ const payload = yield* Schema.encodeEffect(codec)(value);
36
+ return (yield* sql`INSERT INTO yielded_oauth_app (namespace, record_key, version, payload) VALUES (${namespace}, ${key}, ${value.version}, ${payload}) ON CONFLICT (namespace, record_key) DO NOTHING RETURNING version`).length === 1;
37
+ }, failure),
38
+ compareAndSet: Effect.fn("OAuthAppPersistence.compareAndSet")(function* (namespace, key, version, value) {
39
+ yield* noTransaction;
40
+ if (value.version === version) return yield* OAuthUnavailable.make({});
41
+ const payload = yield* Schema.encodeEffect(codec)(value);
42
+ return (yield* sql`UPDATE yielded_oauth_app SET version = ${value.version}, payload = ${payload} WHERE namespace = ${namespace} AND record_key = ${key} AND version = ${version} RETURNING version`).length === 1;
43
+ }, failure)
44
+ });
45
+ })),
46
+ migration: `CREATE TABLE yielded_oauth_app (
47
+ namespace TEXT NOT NULL,
48
+ record_key TEXT NOT NULL,
49
+ version TEXT NOT NULL,
50
+ payload TEXT NOT NULL,
51
+ PRIMARY KEY (namespace, record_key)
52
+ )`
53
+ };
54
+ //#endregion
55
+ export { OAuthAppPersistence };
56
+
57
+ //# sourceMappingURL=oauth-app.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-app.mjs","names":[],"sources":["../../src/internal/oauth-app.ts"],"sourcesContent":["import { OAuthUnavailable } from \"@yielded/auth/OAuth\";\nimport { Persistence, Record } from \"@yielded/auth/OAuthApp\";\nimport { Effect, Layer, Schema } from \"effect\";\nimport { SqlClient } from \"effect/unstable/sql\";\n\nimport { requireStandalone } from \"./standalone\";\n\nconst codec = Schema.fromJsonString(Record);\nconst Row = Schema.Struct({ payload: Schema.String, version: Schema.String });\n\n/** Apply with the application's migrations. SQLite (including D1) and PostgreSQL.\n * Each transition is one conditional statement, so D1 needs no interactive\n * transaction and parallel workers share the same refresh/code claim.\n */\nconst migration = `CREATE TABLE yielded_oauth_app (\n namespace TEXT NOT NULL,\n record_key TEXT NOT NULL,\n version TEXT NOT NULL,\n payload TEXT NOT NULL,\n PRIMARY KEY (namespace, record_key)\n)`;\n\nconst layer = Layer.effect(\n Persistence,\n Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n\n if (!sql.onDialectOrElse({ sqlite: () => true, pg: () => true, orElse: () => false }))\n return yield* OAuthUnavailable.make({});\n\n const noTransaction = requireStandalone(() => OAuthUnavailable.make({}), sql);\n\n const failure = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n effect.pipe(Effect.mapError(() => OAuthUnavailable.make({})));\n\n return Persistence.of({\n get: Effect.fn(\"OAuthAppPersistence.get\")(function* (namespace, key) {\n yield* noTransaction;\n\n const rows = yield* sql<{\n payload: string;\n version: string;\n }>`SELECT payload, version FROM yielded_oauth_app WHERE namespace = ${namespace} AND record_key = ${key}`;\n\n if (rows.length === 0) return undefined;\n if (rows.length !== 1) return yield* OAuthUnavailable.make({});\n const row = yield* Schema.decodeEffect(Row)(rows[0]);\n const value = yield* Schema.decodeEffect(codec)(row.payload);\n\n if (value.version !== row.version) return yield* OAuthUnavailable.make({});\n\n return value;\n }, failure),\n insert: Effect.fn(\"OAuthAppPersistence.insert\")(function* (namespace, key, value) {\n yield* noTransaction;\n const payload = yield* Schema.encodeEffect(codec)(value);\n\n const rows =\n yield* sql`INSERT INTO yielded_oauth_app (namespace, record_key, version, payload) VALUES (${namespace}, ${key}, ${value.version}, ${payload}) ON CONFLICT (namespace, record_key) DO NOTHING RETURNING version`;\n\n return rows.length === 1;\n }, failure),\n compareAndSet: Effect.fn(\"OAuthAppPersistence.compareAndSet\")(function* (\n namespace,\n key,\n version,\n value,\n ) {\n yield* noTransaction;\n if (value.version === version) return yield* OAuthUnavailable.make({});\n const payload = yield* Schema.encodeEffect(codec)(value);\n\n const rows =\n yield* sql`UPDATE yielded_oauth_app SET version = ${value.version}, payload = ${payload} WHERE namespace = ${namespace} AND record_key = ${key} AND version = ${version} RETURNING version`;\n\n return rows.length === 1;\n }, failure),\n });\n }),\n);\n\nexport const OAuthAppPersistence = { layer, migration };\n"],"mappings":";;;;;;AAOA,MAAM,QAAQ,OAAO,eAAe,MAAM;AAC1C,MAAM,MAAM,OAAO,OAAO;CAAE,SAAS,OAAO;CAAQ,SAAS,OAAO;AAAO,CAAC;AAyE5E,MAAa,sBAAsB;CAAE,OA3DvB,MAAM,OAClB,aACA,OAAO,IAAI,aAAa;EACtB,MAAM,MAAM,OAAO,UAAU;EAE7B,IAAI,CAAC,IAAI,gBAAgB;GAAE,cAAc;GAAM,UAAU;GAAM,cAAc;EAAM,CAAC,GAClF,OAAO,OAAO,iBAAiB,KAAK,CAAC,CAAC;EAExC,MAAM,gBAAgB,wBAAwB,iBAAiB,KAAK,CAAC,CAAC,GAAG,GAAG;EAE5E,MAAM,WAAoB,WACxB,OAAO,KAAK,OAAO,eAAe,iBAAiB,KAAK,CAAC,CAAC,CAAC,CAAC;EAE9D,OAAO,YAAY,GAAG;GACpB,KAAK,OAAO,GAAG,yBAAyB,CAAC,CAAC,WAAW,WAAW,KAAK;IACnE,OAAO;IAEP,MAAM,OAAO,OAAO,GAGlB,oEAAoE,UAAU,oBAAoB;IAEpG,IAAI,KAAK,WAAW,GAAG,OAAO,KAAA;IAC9B,IAAI,KAAK,WAAW,GAAG,OAAO,OAAO,iBAAiB,KAAK,CAAC,CAAC;IAC7D,MAAM,MAAM,OAAO,OAAO,aAAa,GAAG,CAAC,CAAC,KAAK,EAAE;IACnD,MAAM,QAAQ,OAAO,OAAO,aAAa,KAAK,CAAC,CAAC,IAAI,OAAO;IAE3D,IAAI,MAAM,YAAY,IAAI,SAAS,OAAO,OAAO,iBAAiB,KAAK,CAAC,CAAC;IAEzE,OAAO;GACT,GAAG,OAAO;GACV,QAAQ,OAAO,GAAG,4BAA4B,CAAC,CAAC,WAAW,WAAW,KAAK,OAAO;IAChF,OAAO;IACP,MAAM,UAAU,OAAO,OAAO,aAAa,KAAK,CAAC,CAAC,KAAK;IAKvD,QAAO,OAFE,GAAG,mFAAmF,UAAU,IAAI,IAAI,IAAI,MAAM,QAAQ,IAAI,QAAQ,oEAAA,CAEnI,WAAW;GACzB,GAAG,OAAO;GACV,eAAe,OAAO,GAAG,mCAAmC,CAAC,CAAC,WAC5D,WACA,KACA,SACA,OACA;IACA,OAAO;IACP,IAAI,MAAM,YAAY,SAAS,OAAO,OAAO,iBAAiB,KAAK,CAAC,CAAC;IACrE,MAAM,UAAU,OAAO,OAAO,aAAa,KAAK,CAAC,CAAC,KAAK;IAKvD,QAAO,OAFE,GAAG,0CAA0C,MAAM,QAAQ,cAAc,QAAQ,qBAAqB,UAAU,oBAAoB,IAAI,iBAAiB,QAAQ,oBAAA,CAE9J,WAAW;GACzB,GAAG,OAAO;EACZ,CAAC;CACH,CAAC,CAGkC;CAAO;;;;;;;AAAU"}
@@ -0,0 +1,10 @@
1
+ import { Layer } from "effect";
2
+ import { SqlClient } from "effect/unstable/sql";
3
+ import { Persistence, Unavailable } from "@yielded/auth/OAuthServer";
4
+ //#region src/internal/oauth-server.d.ts
5
+ export declare const OAuthServerPersistence: {
6
+ migration: string;
7
+ layer: Layer.Layer<Persistence, Unavailable, SqlClient.SqlClient>;
8
+ };
9
+ //#endregion
10
+ //# sourceMappingURL=oauth-server.d.mts.map
@@ -0,0 +1,66 @@
1
+ import { requireStandalone } from "./standalone.mjs";
2
+ import { Effect, Layer, Schema } from "effect";
3
+ import { SqlClient } from "effect/unstable/sql";
4
+ import { Persistence, Record, Unavailable } from "@yielded/auth/OAuthServer";
5
+ //#region src/internal/oauth-server.ts
6
+ const codec = Schema.fromJsonString(Record);
7
+ const Row = Schema.Struct({
8
+ payload: Schema.String,
9
+ version: Schema.String,
10
+ revoked: Schema.Literals([0, 1])
11
+ });
12
+ const OAuthServerPersistence = {
13
+ migration: `CREATE TABLE yielded_oauth_server (
14
+ namespace TEXT NOT NULL,
15
+ grant_id TEXT NOT NULL,
16
+ version TEXT NOT NULL,
17
+ revoked INTEGER NOT NULL DEFAULT 0,
18
+ expires_at_millis BIGINT NOT NULL,
19
+ payload TEXT NOT NULL,
20
+ PRIMARY KEY (namespace, grant_id)
21
+ )`,
22
+ layer: Layer.effect(Persistence, Effect.gen(function* () {
23
+ const sql = yield* SqlClient.SqlClient;
24
+ if (!sql.onDialectOrElse({
25
+ sqlite: () => true,
26
+ pg: () => true,
27
+ orElse: () => false
28
+ })) return yield* Unavailable.make({});
29
+ const standalone = requireStandalone(() => Unavailable.make({}), sql);
30
+ const failure = (effect) => effect.pipe(Effect.mapError(() => Unavailable.make({})));
31
+ return Persistence.of({
32
+ get: Effect.fn("OAuthServerPersistence.get")(function* (namespace, id) {
33
+ yield* standalone;
34
+ const rows = yield* sql`SELECT payload, version, revoked FROM yielded_oauth_server WHERE namespace = ${namespace} AND grant_id = ${id}`;
35
+ if (rows.length === 0) return void 0;
36
+ if (rows.length !== 1) return yield* Unavailable.make({});
37
+ const row = yield* Schema.decodeUnknownEffect(Row)(rows[0]);
38
+ const record = yield* Schema.decodeEffect(codec)(row.payload);
39
+ if (record.version !== row.version) return yield* Unavailable.make({});
40
+ return row.revoked === 1 ? {
41
+ ...record,
42
+ status: "Revoked"
43
+ } : record;
44
+ }, failure),
45
+ insert: Effect.fn("OAuthServerPersistence.insert")(function* (namespace, id, record) {
46
+ yield* standalone;
47
+ const payload = yield* Schema.encodeEffect(codec)(record);
48
+ return (yield* sql`INSERT INTO yielded_oauth_server (namespace, grant_id, version, revoked, expires_at_millis, payload) VALUES (${namespace}, ${id}, ${record.version}, ${record.status === "Revoked" ? 1 : 0}, ${record.expiresAtMillis}, ${payload}) ON CONFLICT (namespace, grant_id) DO NOTHING RETURNING version`).length === 1;
49
+ }, failure),
50
+ compareAndSet: Effect.fn("OAuthServerPersistence.compareAndSet")(function* (namespace, id, version, record) {
51
+ yield* standalone;
52
+ if (version === record.version) return yield* Unavailable.make({});
53
+ const payload = yield* Schema.encodeEffect(codec)(record);
54
+ return (yield* sql`UPDATE yielded_oauth_server SET version = ${record.version}, revoked = ${record.status === "Revoked" ? 1 : 0}, expires_at_millis = ${record.expiresAtMillis}, payload = ${payload} WHERE namespace = ${namespace} AND grant_id = ${id} AND version = ${version} AND revoked = 0 RETURNING version`).length === 1;
55
+ }, failure),
56
+ revoke: Effect.fn("OAuthServerPersistence.revoke")(function* (namespace, id) {
57
+ yield* standalone;
58
+ yield* sql`UPDATE yielded_oauth_server SET revoked = 1 WHERE namespace = ${namespace} AND grant_id = ${id}`;
59
+ }, failure)
60
+ });
61
+ }))
62
+ };
63
+ //#endregion
64
+ export { OAuthServerPersistence };
65
+
66
+ //# sourceMappingURL=oauth-server.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-server.mjs","names":[],"sources":["../../src/internal/oauth-server.ts"],"sourcesContent":["import { Persistence, Record, Unavailable } from \"@yielded/auth/OAuthServer\";\nimport { Effect, Layer, Schema } from \"effect\";\nimport { SqlClient } from \"effect/unstable/sql\";\n\nimport { requireStandalone } from \"./standalone\";\n\nconst codec = Schema.fromJsonString(Record);\n\nconst Row = Schema.Struct({\n payload: Schema.String,\n version: Schema.String,\n revoked: Schema.Literals([0, 1]),\n});\n\n/** SQLite (including D1) and PostgreSQL. Apply once through application migrations.\n * Expired records may be deleted when expires_at_millis <= the current time.\n * Revocation has its own monotonic column so it cannot lose a race with rotation.\n */\nconst migration = `CREATE TABLE yielded_oauth_server (\n namespace TEXT NOT NULL,\n grant_id TEXT NOT NULL,\n version TEXT NOT NULL,\n revoked INTEGER NOT NULL DEFAULT 0,\n expires_at_millis BIGINT NOT NULL,\n payload TEXT NOT NULL,\n PRIMARY KEY (namespace, grant_id)\n)`;\n\nconst layer = Layer.effect(\n Persistence,\n Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n\n if (!sql.onDialectOrElse({ sqlite: () => true, pg: () => true, orElse: () => false }))\n return yield* Unavailable.make({});\n const standalone = requireStandalone(() => Unavailable.make({}), sql);\n\n const failure = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n effect.pipe(Effect.mapError(() => Unavailable.make({})));\n\n return Persistence.of({\n get: Effect.fn(\"OAuthServerPersistence.get\")(function* (namespace, id) {\n yield* standalone;\n\n const rows =\n yield* sql`SELECT payload, version, revoked FROM yielded_oauth_server WHERE namespace = ${namespace} AND grant_id = ${id}`;\n\n if (rows.length === 0) return undefined;\n if (rows.length !== 1) return yield* Unavailable.make({});\n const row = yield* Schema.decodeUnknownEffect(Row)(rows[0]);\n const record = yield* Schema.decodeEffect(codec)(row.payload);\n\n if (record.version !== row.version) return yield* Unavailable.make({});\n\n return row.revoked === 1 ? { ...record, status: \"Revoked\" as const } : record;\n }, failure),\n insert: Effect.fn(\"OAuthServerPersistence.insert\")(function* (namespace, id, record) {\n yield* standalone;\n const payload = yield* Schema.encodeEffect(codec)(record);\n\n const rows =\n yield* sql`INSERT INTO yielded_oauth_server (namespace, grant_id, version, revoked, expires_at_millis, payload) VALUES (${namespace}, ${id}, ${record.version}, ${record.status === \"Revoked\" ? 1 : 0}, ${record.expiresAtMillis}, ${payload}) ON CONFLICT (namespace, grant_id) DO NOTHING RETURNING version`;\n\n return rows.length === 1;\n }, failure),\n compareAndSet: Effect.fn(\"OAuthServerPersistence.compareAndSet\")(function* (\n namespace,\n id,\n version,\n record,\n ) {\n yield* standalone;\n if (version === record.version) return yield* Unavailable.make({});\n const payload = yield* Schema.encodeEffect(codec)(record);\n\n const rows =\n yield* sql`UPDATE yielded_oauth_server SET version = ${record.version}, revoked = ${record.status === \"Revoked\" ? 1 : 0}, expires_at_millis = ${record.expiresAtMillis}, payload = ${payload} WHERE namespace = ${namespace} AND grant_id = ${id} AND version = ${version} AND revoked = 0 RETURNING version`;\n\n return rows.length === 1;\n }, failure),\n revoke: Effect.fn(\"OAuthServerPersistence.revoke\")(function* (namespace, id) {\n yield* standalone;\n yield* sql`UPDATE yielded_oauth_server SET revoked = 1 WHERE namespace = ${namespace} AND grant_id = ${id}`;\n }, failure),\n });\n }),\n);\n\nexport const OAuthServerPersistence = { migration, layer };\n"],"mappings":";;;;;AAMA,MAAM,QAAQ,OAAO,eAAe,MAAM;AAE1C,MAAM,MAAM,OAAO,OAAO;CACxB,SAAS,OAAO;CAChB,SAAS,OAAO;CAChB,SAAS,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;AACjC,CAAC;AA4ED,MAAa,yBAAyB;CAAE;;;;;;;;;CAAW,OA5DrC,MAAM,OAClB,aACA,OAAO,IAAI,aAAa;EACtB,MAAM,MAAM,OAAO,UAAU;EAE7B,IAAI,CAAC,IAAI,gBAAgB;GAAE,cAAc;GAAM,UAAU;GAAM,cAAc;EAAM,CAAC,GAClF,OAAO,OAAO,YAAY,KAAK,CAAC,CAAC;EACnC,MAAM,aAAa,wBAAwB,YAAY,KAAK,CAAC,CAAC,GAAG,GAAG;EAEpE,MAAM,WAAoB,WACxB,OAAO,KAAK,OAAO,eAAe,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC;EAEzD,OAAO,YAAY,GAAG;GACpB,KAAK,OAAO,GAAG,4BAA4B,CAAC,CAAC,WAAW,WAAW,IAAI;IACrE,OAAO;IAEP,MAAM,OACJ,OAAO,GAAG,gFAAgF,UAAU,kBAAkB;IAExH,IAAI,KAAK,WAAW,GAAG,OAAO,KAAA;IAC9B,IAAI,KAAK,WAAW,GAAG,OAAO,OAAO,YAAY,KAAK,CAAC,CAAC;IACxD,MAAM,MAAM,OAAO,OAAO,oBAAoB,GAAG,CAAC,CAAC,KAAK,EAAE;IAC1D,MAAM,SAAS,OAAO,OAAO,aAAa,KAAK,CAAC,CAAC,IAAI,OAAO;IAE5D,IAAI,OAAO,YAAY,IAAI,SAAS,OAAO,OAAO,YAAY,KAAK,CAAC,CAAC;IAErE,OAAO,IAAI,YAAY,IAAI;KAAE,GAAG;KAAQ,QAAQ;IAAmB,IAAI;GACzE,GAAG,OAAO;GACV,QAAQ,OAAO,GAAG,+BAA+B,CAAC,CAAC,WAAW,WAAW,IAAI,QAAQ;IACnF,OAAO;IACP,MAAM,UAAU,OAAO,OAAO,aAAa,KAAK,CAAC,CAAC,MAAM;IAKxD,QAAO,OAFE,GAAG,gHAAgH,UAAU,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,OAAO,WAAW,YAAY,IAAI,EAAE,IAAI,OAAO,gBAAgB,IAAI,QAAQ,kEAAA,CAEnO,WAAW;GACzB,GAAG,OAAO;GACV,eAAe,OAAO,GAAG,sCAAsC,CAAC,CAAC,WAC/D,WACA,IACA,SACA,QACA;IACA,OAAO;IACP,IAAI,YAAY,OAAO,SAAS,OAAO,OAAO,YAAY,KAAK,CAAC,CAAC;IACjE,MAAM,UAAU,OAAO,OAAO,aAAa,KAAK,CAAC,CAAC,MAAM;IAKxD,QAAO,OAFE,GAAG,6CAA6C,OAAO,QAAQ,cAAc,OAAO,WAAW,YAAY,IAAI,EAAE,wBAAwB,OAAO,gBAAgB,cAAc,QAAQ,qBAAqB,UAAU,kBAAkB,GAAG,iBAAiB,QAAQ,oCAAA,CAEhQ,WAAW;GACzB,GAAG,OAAO;GACV,QAAQ,OAAO,GAAG,+BAA+B,CAAC,CAAC,WAAW,WAAW,IAAI;IAC3E,OAAO;IACP,OAAO,GAAG,iEAAiE,UAAU,kBAAkB;GACzG,GAAG,OAAO;EACZ,CAAC;CACH,CAAC,CAGgD;AAAM"}
@@ -0,0 +1,6 @@
1
+ import "../query-operations.mjs";
2
+ import "../models/passkey-model.mjs";
3
+ import "../transaction-kernel.mjs";
4
+ import "./state.mjs";
5
+ import { Effect } from "effect";
6
+ import { PasskeyCeremony, PasskeyMethodPolicy } from "@yielded/auth/Passkey";
@@ -0,0 +1,216 @@
1
+ import { CurrentPasskeyTransaction } from "./state.mjs";
2
+ import { Effect } from "effect";
3
+ //#region src/internal/passkey/admission.ts
4
+ const makePasskeyAdmissionKernel = (operations, state, transactions) => {
5
+ const { sql } = operations;
6
+ const { col, equal, existsExact, key, mappedColumns, subjectScope, targetScope } = state;
7
+ const invariant = state.invariant;
8
+ const { both } = transactions;
9
+ const chargeRetentionMillis = 864e5;
10
+ const chargeScopes = (ceremony, subjectId) => {
11
+ const scopes = [{
12
+ kind: "global",
13
+ scope: key("global", [ceremony.moduleId])
14
+ }];
15
+ if (subjectId !== void 0) scopes.push({
16
+ kind: "subject",
17
+ scope: subjectScope(subjectId)
18
+ });
19
+ const target = targetScope(ceremony);
20
+ if (target !== null) scopes.push({
21
+ kind: "target",
22
+ scope: target
23
+ });
24
+ return scopes;
25
+ };
26
+ const lockAdmission = Effect.fn("passkey.lockAdmission")(function* (mapping) {
27
+ const owner = yield* CurrentPasskeyTransaction;
28
+ const table = mapping.admission;
29
+ const identity = {
30
+ [table.authorityScope]: mapping.authorityScope,
31
+ [table.moduleId]: mapping.moduleId
32
+ };
33
+ const found = yield* owner.read(table.table, equal(table.table, identity), {
34
+ limit: 1,
35
+ observe: false,
36
+ columns: [table.authorityScope, table.moduleId]
37
+ });
38
+ invariant(found.rows.length === 1);
39
+ invariant(found.rows[0][table.authorityScope] === mapping.authorityScope && found.rows[0][table.moduleId] === mapping.moduleId);
40
+ const marked = {
41
+ ...identity,
42
+ [table.version]: owner.marker,
43
+ [table.ownerMarker]: owner.marker
44
+ };
45
+ yield* owner.updateGuarded(table.table, owner.exact(table.table, identity), {
46
+ [table.version]: owner.marker,
47
+ [table.ownerMarker]: owner.marker,
48
+ [table.admittedAt]: null
49
+ }, {
50
+ rows: 1,
51
+ postcondition: yield* existsExact(table.table, marked)
52
+ });
53
+ });
54
+ const pendingCount = (mapping, scope) => {
55
+ const table = mapping.flow;
56
+ return sql`(select count(*) from ${table.table} where ${both(equal(table.table, { [table.moduleId]: mapping.moduleId }), sql`${col(table.table, table.state)} in (${table.states.Pending}, ${table.states.Claimed})`, scope === void 0 ? void 0 : equal(table.table, { [table.subjectScope]: scope }))})`;
57
+ };
58
+ const chargedCount = (mapping, kind, scope, window) => {
59
+ const table = mapping.charge;
60
+ const clock = mapping.clock;
61
+ return sql`(select count(*) from ${table.table} where ${both(equal(table.table, {
62
+ [table.moduleId]: mapping.moduleId,
63
+ [table.kind]: kind
64
+ }), kind === "global" ? void 0 : equal(table.table, { [table.scope]: scope }), sql`${col(table.table, table.admittedAt)} is not null`, sql`${clock.toMillis(sql`${col(table.table, table.admittedAt)}`)} > ${clock.engineNowMillis} - ${window}`)})`;
65
+ };
66
+ const admissionCondition = (mapping, policies, ceremony, subjectId, added, newFlow, resolvedSubject) => both(...policies.flatMap((policy) => [
67
+ sql`${pendingCount(mapping)} + ${newFlow ? 1 : 0} <= ${policy.maximumPending}`,
68
+ subjectId === void 0 ? void 0 : sql`${pendingCount(mapping, subjectScope(subjectId))} + ${newFlow || resolvedSubject ? 1 : 0} <= ${policy.maximumPendingPerSubject}`,
69
+ ...chargeScopes(ceremony, subjectId).map(({ kind, scope }) => sql`${chargedCount(mapping, kind, scope, policy.admission[kind].windowMillis)} + ${added.includes(kind) ? 1 : 0} <= ${policy.admission[kind].limit}`)
70
+ ]));
71
+ const guardAdmission = (mapping, policies, ceremony, subjectId) => Effect.map(CurrentPasskeyTransaction, (owner) => {
72
+ owner.postconditions.push(admissionCondition(mapping, policies, ceremony, subjectId, [], false, false));
73
+ });
74
+ const readCharges = Effect.fn("passkey.readCharges")(function* (mapping, ceremony, policy, subjectId) {
75
+ const owner = yield* CurrentPasskeyTransaction;
76
+ const table = mapping.charge;
77
+ const where = equal(table.table, {
78
+ [table.moduleId]: ceremony.moduleId,
79
+ [table.flowId]: ceremony.flowId
80
+ });
81
+ const found = yield* owner.read(table.table, where, {
82
+ limit: 3,
83
+ observe: false,
84
+ columns: mappedColumns(table)
85
+ });
86
+ const scopes = chargeScopes(ceremony, subjectId);
87
+ invariant(found.rows.length === scopes.length);
88
+ for (const { kind, scope } of scopes) {
89
+ const rows = found.rows.filter((row) => row[table.kind] === kind);
90
+ invariant(rows.length === 1);
91
+ const row = rows[0];
92
+ const admitted = mapping.clock.decodeInstant(row[table.admittedAt]);
93
+ const retained = mapping.clock.decodeInstant(row[table.retainUntil]);
94
+ invariant(Number.isSafeInteger(admitted) && admitted >= 0 && retained === admitted + chargeRetentionMillis);
95
+ invariant(row[table.moduleId] === ceremony.moduleId && row[table.flowId] === ceremony.flowId && row[table.purpose] === ceremony.purpose);
96
+ invariant(row[table.scope] === scope && row[table.originalWindowMillis] === policy.admission[kind].windowMillis);
97
+ owner.observations.push({
98
+ table: table.table,
99
+ where: equal(table.table, {
100
+ [table.moduleId]: ceremony.moduleId,
101
+ [table.flowId]: ceremony.flowId,
102
+ [table.kind]: kind
103
+ }),
104
+ rows: [row]
105
+ });
106
+ }
107
+ });
108
+ const guardChargeSet = (mapping, ceremony, subjectId) => Effect.flatMap(CurrentPasskeyTransaction, (owner) => Effect.gen(function* () {
109
+ const table = mapping.charge;
110
+ const scopes = chargeScopes(ceremony, subjectId);
111
+ const where = equal(table.table, {
112
+ [table.moduleId]: ceremony.moduleId,
113
+ [table.flowId]: ceremony.flowId
114
+ });
115
+ owner.postconditions.push(sql`(select count(*) from ${table.table} where ${where}) = ${scopes.length}`);
116
+ for (const { kind, scope } of scopes) owner.postconditions.push(yield* existsExact(table.table, {
117
+ [table.moduleId]: ceremony.moduleId,
118
+ [table.flowId]: ceremony.flowId,
119
+ [table.purpose]: ceremony.purpose,
120
+ [table.kind]: kind,
121
+ [table.scope]: scope
122
+ }));
123
+ }));
124
+ return {
125
+ chargeRetentionMillis,
126
+ chargeScopes,
127
+ lockAdmission,
128
+ admissionCondition,
129
+ guardAdmission,
130
+ readCharges,
131
+ guardChargeSet,
132
+ insertCharges: Effect.fn("passkey.insertCharges")(function* (mapping, ceremony, policy, kinds, subjectId) {
133
+ const owner = yield* CurrentPasskeyTransaction;
134
+ if (kinds.length === 0) return;
135
+ const table = mapping.charge;
136
+ const anchor = mapping.admission;
137
+ const clock = mapping.clock;
138
+ const earliest = yield* owner.now(clock);
139
+ const identities = [];
140
+ for (const { kind, scope } of chargeScopes(ceremony, subjectId).filter((item) => kinds.includes(item.kind))) {
141
+ const identity = {
142
+ [table.moduleId]: ceremony.moduleId,
143
+ [table.flowId]: ceremony.flowId,
144
+ [table.kind]: kind
145
+ };
146
+ const values = {
147
+ ...table.encodeInsert({
148
+ moduleId: ceremony.moduleId,
149
+ flowId: ceremony.flowId,
150
+ purpose: ceremony.purpose,
151
+ kind,
152
+ scope,
153
+ originalWindowMillis: policy.admission[kind].windowMillis,
154
+ marker: owner.marker
155
+ }),
156
+ ...identity,
157
+ [table.purpose]: ceremony.purpose,
158
+ [table.scope]: scope,
159
+ [table.originalWindowMillis]: policy.admission[kind].windowMillis,
160
+ [table.admittedAt]: null,
161
+ [table.retainUntil]: null,
162
+ [table.version]: owner.marker,
163
+ [table.ownerMarker]: owner.marker
164
+ };
165
+ const observation = yield* owner.insert(table.table, values, identity);
166
+ observation.rows = observation.rows.map((row) => Object.fromEntries(Object.entries(row).filter(([name]) => name !== table.admittedAt && name !== table.retainUntil)));
167
+ identities.push(identity);
168
+ }
169
+ invariant(identities.length === kinds.length);
170
+ const anchorIdentity = {
171
+ [anchor.authorityScope]: mapping.authorityScope,
172
+ [anchor.moduleId]: mapping.moduleId,
173
+ [anchor.version]: owner.marker,
174
+ [anchor.ownerMarker]: owner.marker
175
+ };
176
+ const stamp = sql`(select ${col(anchor.table, anchor.admittedAt)} from ${anchor.table} where ${owner.exact(anchor.table, anchorIdentity)})`;
177
+ const stampMillis = clock.toMillis(stamp);
178
+ const validStamp = both(yield* existsExact(anchor.table, anchorIdentity), sql`${stamp} is not null`, sql`${stampMillis} >= ${earliest}`, sql`${stampMillis} <= ${clock.engineNowMillis}`, sql`${stampMillis} <= ${86399999136e5}`);
179
+ yield* owner.finalUpdate(anchor.table, owner.exact(anchor.table, {
180
+ ...anchorIdentity,
181
+ [anchor.admittedAt]: null
182
+ }), { [anchor.admittedAt]: clock.fromMillis(clock.engineNowMillis) }, {
183
+ rows: 1,
184
+ postcondition: validStamp
185
+ });
186
+ for (const identity of identities) {
187
+ const expected = {
188
+ ...identity,
189
+ [table.version]: owner.marker,
190
+ [table.ownerMarker]: owner.marker
191
+ };
192
+ const postcondition = yield* existsExact(table.table, expected, both(sql`${clock.toMillis(sql`${col(table.table, table.admittedAt)}`)} = ${stampMillis}`, sql`${clock.toMillis(sql`${col(table.table, table.retainUntil)}`)} = ${stampMillis} + ${chargeRetentionMillis}`));
193
+ yield* owner.finalUpdate(table.table, owner.exact(table.table, {
194
+ ...expected,
195
+ [table.admittedAt]: null,
196
+ [table.retainUntil]: null
197
+ }), {
198
+ [table.admittedAt]: stamp,
199
+ [table.retainUntil]: clock.fromMillis(sql`${stampMillis} + ${chargeRetentionMillis}`)
200
+ }, {
201
+ rows: 1,
202
+ postcondition
203
+ });
204
+ }
205
+ owner.postconditions.push(sql`(select count(*) from ${table.table} where ${owner.exact(table.table, {
206
+ [table.moduleId]: ceremony.moduleId,
207
+ [table.flowId]: ceremony.flowId,
208
+ [table.ownerMarker]: owner.marker
209
+ })}) = ${identities.length}`);
210
+ })
211
+ };
212
+ };
213
+ //#endregion
214
+ export { makePasskeyAdmissionKernel };
215
+
216
+ //# sourceMappingURL=admission.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admission.mjs","names":[],"sources":["../../../src/internal/passkey/admission.ts"],"sourcesContent":["/* oxlint-disable no-explicit-any -- existing mapped-row bridge; public adapters preserve table, ID, and Effect types. */\n\nimport type { PasskeyCeremony, PasskeyMethodPolicy } from \"@yielded/auth/Passkey\";\nimport { Effect } from \"effect\";\n\nimport type { PasskeyChargeKind } from \"../models/passkey-model\";\nimport type { SqlExpression as SQL, QueryOperations } from \"../query-operations\";\nimport type { makeTransactionKernel } from \"../transaction-kernel\";\nimport { CurrentPasskeyTransaction } from \"./state\";\nimport type { makePasskeyStateKernel } from \"./state\";\n\nexport const makePasskeyAdmissionKernel = (\n operations: QueryOperations,\n state: Pick<\n ReturnType<typeof makePasskeyStateKernel>,\n | \"col\"\n | \"equal\"\n | \"existsExact\"\n | \"invariant\"\n | \"key\"\n | \"mappedColumns\"\n | \"subjectScope\"\n | \"targetScope\"\n >,\n transactions: Pick<ReturnType<typeof makeTransactionKernel>, \"both\">,\n) => {\n const { sql } = operations;\n const { col, equal, existsExact, key, mappedColumns, subjectScope, targetScope } = state;\n const invariant: (value: unknown) => asserts value = state.invariant;\n const { both } = transactions;\n\n const chargeRetentionMillis = 86_400_000;\n\n const chargeScopes = (ceremony: PasskeyCeremony, subjectId?: string) => {\n const scopes: { kind: PasskeyChargeKind; scope: string }[] = [\n { kind: \"global\", scope: key(\"global\", [ceremony.moduleId]) },\n ];\n\n if (subjectId !== undefined) scopes.push({ kind: \"subject\", scope: subjectScope(subjectId) });\n const target = targetScope(ceremony);\n\n if (target !== null) scopes.push({ kind: \"target\", scope: target });\n\n return scopes;\n };\n\n const lockAdmission = Effect.fn(\"passkey.lockAdmission\")(function* (mapping: any) {\n const owner = yield* CurrentPasskeyTransaction;\n const table = mapping.admission;\n\n const identity = {\n [table.authorityScope]: mapping.authorityScope,\n [table.moduleId]: mapping.moduleId,\n };\n\n // The previous marker/time is telemetry, not an authentication CAS. Actual\n // engine predicates serialize admission, including separately planned D1 batches.\n const found = yield* owner.read(table.table, equal(table.table, identity), {\n limit: 1,\n observe: false,\n columns: [table.authorityScope, table.moduleId],\n });\n\n invariant(found.rows.length === 1);\n invariant(\n found.rows[0]![table.authorityScope] === mapping.authorityScope &&\n found.rows[0]![table.moduleId] === mapping.moduleId,\n );\n\n const marked = {\n ...identity,\n [table.version]: owner.marker,\n [table.ownerMarker]: owner.marker,\n };\n\n yield* owner.updateGuarded(\n table.table,\n owner.exact(table.table, identity),\n {\n [table.version]: owner.marker,\n [table.ownerMarker]: owner.marker,\n [table.admittedAt]: null,\n },\n { rows: 1, postcondition: yield* existsExact(table.table, marked) },\n );\n });\n\n const pendingCount = (mapping: any, scope?: string) => {\n const table = mapping.flow;\n\n return sql`(select count(*) from ${table.table} where ${both(\n equal(table.table, { [table.moduleId]: mapping.moduleId }),\n sql`${col(table.table, table.state)} in (${table.states.Pending}, ${table.states.Claimed})`,\n scope === undefined ? undefined : equal(table.table, { [table.subjectScope]: scope }),\n )})`;\n };\n\n const chargedCount = (mapping: any, kind: PasskeyChargeKind, scope: string, window: number) => {\n const table = mapping.charge;\n const clock = mapping.clock;\n\n return sql`(select count(*) from ${table.table} where ${both(\n equal(table.table, { [table.moduleId]: mapping.moduleId, [table.kind]: kind }),\n kind === \"global\" ? undefined : equal(table.table, { [table.scope]: scope }),\n sql`${col(table.table, table.admittedAt)} is not null`,\n sql`${clock.toMillis(sql`${col(table.table, table.admittedAt)}`)} > ${clock.engineNowMillis} - ${window}`,\n )})`;\n };\n\n const admissionCondition = (\n mapping: any,\n policies: ReadonlyArray<PasskeyMethodPolicy>,\n ceremony: PasskeyCeremony,\n subjectId: string | undefined,\n added: ReadonlyArray<PasskeyChargeKind>,\n newFlow: boolean,\n resolvedSubject: boolean,\n ) =>\n both(\n ...policies.flatMap((policy) => [\n sql`${pendingCount(mapping)} + ${newFlow ? 1 : 0} <= ${policy.maximumPending}`,\n subjectId === undefined\n ? undefined\n : sql`${pendingCount(mapping, subjectScope(subjectId))} + ${newFlow || resolvedSubject ? 1 : 0} <= ${policy.maximumPendingPerSubject}`,\n ...chargeScopes(ceremony, subjectId).map(\n ({ kind, scope }) =>\n sql`${chargedCount(mapping, kind, scope, policy.admission[kind].windowMillis)} + ${added.includes(kind) ? 1 : 0} <= ${policy.admission[kind].limit}`,\n ),\n ]),\n );\n\n const guardAdmission = (\n mapping: any,\n policies: ReadonlyArray<PasskeyMethodPolicy>,\n ceremony: PasskeyCeremony,\n subjectId?: string,\n ) =>\n Effect.map(CurrentPasskeyTransaction, (owner) => {\n owner.postconditions.push(\n admissionCondition(mapping, policies, ceremony, subjectId, [], false, false),\n );\n });\n\n const readCharges = Effect.fn(\"passkey.readCharges\")(function* (\n mapping: any,\n ceremony: PasskeyCeremony,\n policy: PasskeyMethodPolicy,\n subjectId?: string,\n ) {\n const owner = yield* CurrentPasskeyTransaction;\n const table = mapping.charge;\n\n const where = equal(table.table, {\n [table.moduleId]: ceremony.moduleId,\n [table.flowId]: ceremony.flowId,\n });\n\n const found = yield* owner.read(table.table, where, {\n limit: 3,\n observe: false,\n columns: mappedColumns(table),\n });\n\n const scopes = chargeScopes(ceremony, subjectId);\n\n invariant(found.rows.length === scopes.length);\n for (const { kind, scope } of scopes) {\n const rows = found.rows.filter((row) => row[table.kind] === kind);\n\n invariant(rows.length === 1);\n const row = rows[0]!;\n const admitted = mapping.clock.decodeInstant(row[table.admittedAt]);\n const retained = mapping.clock.decodeInstant(row[table.retainUntil]);\n\n invariant(\n Number.isSafeInteger(admitted) &&\n admitted >= 0 &&\n retained === admitted + chargeRetentionMillis,\n );\n invariant(\n row[table.moduleId] === ceremony.moduleId &&\n row[table.flowId] === ceremony.flowId &&\n row[table.purpose] === ceremony.purpose,\n );\n invariant(\n row[table.scope] === scope &&\n row[table.originalWindowMillis] === policy.admission[kind].windowMillis,\n );\n owner.observations.push({\n table: table.table,\n where: equal(table.table, {\n [table.moduleId]: ceremony.moduleId,\n [table.flowId]: ceremony.flowId,\n [table.kind]: kind,\n }),\n rows: [row],\n });\n }\n });\n\n const guardChargeSet = (mapping: any, ceremony: PasskeyCeremony, subjectId?: string) =>\n Effect.flatMap(CurrentPasskeyTransaction, (owner) =>\n Effect.gen(function* () {\n const table = mapping.charge;\n const scopes = chargeScopes(ceremony, subjectId);\n\n const where = equal(table.table, {\n [table.moduleId]: ceremony.moduleId,\n [table.flowId]: ceremony.flowId,\n });\n\n owner.postconditions.push(\n sql`(select count(*) from ${table.table} where ${where}) = ${scopes.length}`,\n );\n for (const { kind, scope } of scopes)\n owner.postconditions.push(\n yield* existsExact(table.table, {\n [table.moduleId]: ceremony.moduleId,\n [table.flowId]: ceremony.flowId,\n [table.purpose]: ceremony.purpose,\n [table.kind]: kind,\n [table.scope]: scope,\n }),\n );\n }),\n );\n\n const insertCharges = Effect.fn(\"passkey.insertCharges\")(function* (\n mapping: any,\n ceremony: PasskeyCeremony,\n policy: PasskeyMethodPolicy,\n kinds: ReadonlyArray<PasskeyChargeKind>,\n subjectId?: string,\n ) {\n const owner = yield* CurrentPasskeyTransaction;\n\n if (kinds.length === 0) return;\n const table = mapping.charge;\n const anchor = mapping.admission;\n const clock = mapping.clock;\n const earliest = yield* owner.now(clock);\n const identities: Record<string, unknown>[] = [];\n\n for (const { kind, scope } of chargeScopes(ceremony, subjectId).filter((item) =>\n kinds.includes(item.kind),\n )) {\n const identity = {\n [table.moduleId]: ceremony.moduleId,\n [table.flowId]: ceremony.flowId,\n [table.kind]: kind,\n };\n\n const values = {\n ...table.encodeInsert({\n moduleId: ceremony.moduleId,\n flowId: ceremony.flowId,\n purpose: ceremony.purpose,\n kind,\n scope,\n originalWindowMillis: policy.admission[kind].windowMillis,\n marker: owner.marker,\n }),\n ...identity,\n [table.purpose]: ceremony.purpose,\n [table.scope]: scope,\n [table.originalWindowMillis]: policy.admission[kind].windowMillis,\n [table.admittedAt]: null,\n [table.retainUntil]: null,\n [table.version]: owner.marker,\n [table.ownerMarker]: owner.marker,\n };\n\n const observation = yield* owner.insert(table.table, values, identity);\n\n observation.rows = observation.rows.map((row) =>\n Object.fromEntries(\n Object.entries(row).filter(\n ([name]) => name !== table.admittedAt && name !== table.retainUntil,\n ),\n ),\n );\n identities.push(identity);\n }\n invariant(identities.length === kinds.length);\n\n const anchorIdentity = {\n [anchor.authorityScope]: mapping.authorityScope,\n [anchor.moduleId]: mapping.moduleId,\n [anchor.version]: owner.marker,\n [anchor.ownerMarker]: owner.marker,\n };\n\n const stamp = sql`(select ${col(anchor.table, anchor.admittedAt)} from ${anchor.table} where ${owner.exact(anchor.table, anchorIdentity)})`;\n const stampMillis = clock.toMillis(stamp);\n\n const validStamp: SQL = both(\n yield* existsExact(anchor.table, anchorIdentity),\n sql`${stamp} is not null`,\n sql`${stampMillis} >= ${earliest}`,\n sql`${stampMillis} <= ${clock.engineNowMillis}`,\n sql`${stampMillis} <= ${8640000000000000 - chargeRetentionMillis}`,\n );\n\n yield* owner.finalUpdate(\n anchor.table,\n owner.exact(anchor.table, { ...anchorIdentity, [anchor.admittedAt]: null }),\n {\n [anchor.admittedAt]: clock.fromMillis(clock.engineNowMillis),\n },\n { rows: 1, postcondition: validStamp },\n );\n for (const identity of identities) {\n const expected = {\n ...identity,\n [table.version]: owner.marker,\n [table.ownerMarker]: owner.marker,\n };\n\n const postcondition = yield* existsExact(\n table.table,\n expected,\n both(\n sql`${clock.toMillis(sql`${col(table.table, table.admittedAt)}`)} = ${stampMillis}`,\n sql`${clock.toMillis(sql`${col(table.table, table.retainUntil)}`)} = ${stampMillis} + ${chargeRetentionMillis}`,\n ),\n );\n\n yield* owner.finalUpdate(\n table.table,\n owner.exact(table.table, {\n ...expected,\n [table.admittedAt]: null,\n [table.retainUntil]: null,\n }),\n {\n [table.admittedAt]: stamp,\n [table.retainUntil]: clock.fromMillis(sql`${stampMillis} + ${chargeRetentionMillis}`),\n },\n { rows: 1, postcondition },\n );\n }\n owner.postconditions.push(\n sql`(select count(*) from ${table.table} where ${owner.exact(table.table, {\n [table.moduleId]: ceremony.moduleId,\n [table.flowId]: ceremony.flowId,\n [table.ownerMarker]: owner.marker,\n })}) = ${identities.length}`,\n );\n });\n\n return {\n chargeRetentionMillis,\n chargeScopes,\n lockAdmission,\n admissionCondition,\n guardAdmission,\n readCharges,\n guardChargeSet,\n insertCharges,\n };\n};\n"],"mappings":";;;AAWA,MAAa,8BACX,YACA,OAWA,iBACG;CACH,MAAM,EAAE,QAAQ;CAChB,MAAM,EAAE,KAAK,OAAO,aAAa,KAAK,eAAe,cAAc,gBAAgB;CACnF,MAAM,YAA+C,MAAM;CAC3D,MAAM,EAAE,SAAS;CAEjB,MAAM,wBAAwB;CAE9B,MAAM,gBAAgB,UAA2B,cAAuB;EACtE,MAAM,SAAuD,CAC3D;GAAE,MAAM;GAAU,OAAO,IAAI,UAAU,CAAC,SAAS,QAAQ,CAAC;EAAE,CAC9D;EAEA,IAAI,cAAc,KAAA,GAAW,OAAO,KAAK;GAAE,MAAM;GAAW,OAAO,aAAa,SAAS;EAAE,CAAC;EAC5F,MAAM,SAAS,YAAY,QAAQ;EAEnC,IAAI,WAAW,MAAM,OAAO,KAAK;GAAE,MAAM;GAAU,OAAO;EAAO,CAAC;EAElE,OAAO;CACT;CAEA,MAAM,gBAAgB,OAAO,GAAG,uBAAuB,CAAC,CAAC,WAAW,SAAc;EAChF,MAAM,QAAQ,OAAO;EACrB,MAAM,QAAQ,QAAQ;EAEtB,MAAM,WAAW;IACd,MAAM,iBAAiB,QAAQ;IAC/B,MAAM,WAAW,QAAQ;EAC5B;EAIA,MAAM,QAAQ,OAAO,MAAM,KAAK,MAAM,OAAO,MAAM,MAAM,OAAO,QAAQ,GAAG;GACzE,OAAO;GACP,SAAS;GACT,SAAS,CAAC,MAAM,gBAAgB,MAAM,QAAQ;EAChD,CAAC;EAED,UAAU,MAAM,KAAK,WAAW,CAAC;EACjC,UACE,MAAM,KAAK,EAAE,CAAE,MAAM,oBAAoB,QAAQ,kBAC/C,MAAM,KAAK,EAAE,CAAE,MAAM,cAAc,QAAQ,QAC/C;EAEA,MAAM,SAAS;GACb,GAAG;IACF,MAAM,UAAU,MAAM;IACtB,MAAM,cAAc,MAAM;EAC7B;EAEA,OAAO,MAAM,cACX,MAAM,OACN,MAAM,MAAM,MAAM,OAAO,QAAQ,GACjC;IACG,MAAM,UAAU,MAAM;IACtB,MAAM,cAAc,MAAM;IAC1B,MAAM,aAAa;EACtB,GACA;GAAE,MAAM;GAAG,eAAe,OAAO,YAAY,MAAM,OAAO,MAAM;EAAE,CACpE;CACF,CAAC;CAED,MAAM,gBAAgB,SAAc,UAAmB;EACrD,MAAM,QAAQ,QAAQ;EAEtB,OAAO,GAAG,yBAAyB,MAAM,MAAM,SAAS,KACtD,MAAM,MAAM,OAAO,GAAG,MAAM,WAAW,QAAQ,SAAS,CAAC,GACzD,GAAG,GAAG,IAAI,MAAM,OAAO,MAAM,KAAK,EAAE,OAAO,MAAM,OAAO,QAAQ,IAAI,MAAM,OAAO,QAAQ,IACzF,UAAU,KAAA,IAAY,KAAA,IAAY,MAAM,MAAM,OAAO,GAAG,MAAM,eAAe,MAAM,CAAC,CACtF,EAAE;CACJ;CAEA,MAAM,gBAAgB,SAAc,MAAyB,OAAe,WAAmB;EAC7F,MAAM,QAAQ,QAAQ;EACtB,MAAM,QAAQ,QAAQ;EAEtB,OAAO,GAAG,yBAAyB,MAAM,MAAM,SAAS,KACtD,MAAM,MAAM,OAAO;IAAG,MAAM,WAAW,QAAQ;IAAW,MAAM,OAAO;EAAK,CAAC,GAC7E,SAAS,WAAW,KAAA,IAAY,MAAM,MAAM,OAAO,GAAG,MAAM,QAAQ,MAAM,CAAC,GAC3E,GAAG,GAAG,IAAI,MAAM,OAAO,MAAM,UAAU,EAAE,eACzC,GAAG,GAAG,MAAM,SAAS,GAAG,GAAG,IAAI,MAAM,OAAO,MAAM,UAAU,GAAG,EAAE,KAAK,MAAM,gBAAgB,KAAK,QACnG,EAAE;CACJ;CAEA,MAAM,sBACJ,SACA,UACA,UACA,WACA,OACA,SACA,oBAEA,KACE,GAAG,SAAS,SAAS,WAAW;EAC9B,GAAG,GAAG,aAAa,OAAO,EAAE,KAAK,UAAU,IAAI,EAAE,MAAM,OAAO;EAC9D,cAAc,KAAA,IACV,KAAA,IACA,GAAG,GAAG,aAAa,SAAS,aAAa,SAAS,CAAC,EAAE,KAAK,WAAW,kBAAkB,IAAI,EAAE,MAAM,OAAO;EAC9G,GAAG,aAAa,UAAU,SAAS,CAAC,CAAC,KAClC,EAAE,MAAM,YACP,GAAG,GAAG,aAAa,SAAS,MAAM,OAAO,OAAO,UAAU,KAAK,CAAC,YAAY,EAAE,KAAK,MAAM,SAAS,IAAI,IAAI,IAAI,EAAE,MAAM,OAAO,UAAU,KAAK,CAAC,OACjJ;CACF,CAAC,CACH;CAEF,MAAM,kBACJ,SACA,UACA,UACA,cAEA,OAAO,IAAI,4BAA4B,UAAU;EAC/C,MAAM,eAAe,KACnB,mBAAmB,SAAS,UAAU,UAAU,WAAW,CAAC,GAAG,OAAO,KAAK,CAC7E;CACF,CAAC;CAEH,MAAM,cAAc,OAAO,GAAG,qBAAqB,CAAC,CAAC,WACnD,SACA,UACA,QACA,WACA;EACA,MAAM,QAAQ,OAAO;EACrB,MAAM,QAAQ,QAAQ;EAEtB,MAAM,QAAQ,MAAM,MAAM,OAAO;IAC9B,MAAM,WAAW,SAAS;IAC1B,MAAM,SAAS,SAAS;EAC3B,CAAC;EAED,MAAM,QAAQ,OAAO,MAAM,KAAK,MAAM,OAAO,OAAO;GAClD,OAAO;GACP,SAAS;GACT,SAAS,cAAc,KAAK;EAC9B,CAAC;EAED,MAAM,SAAS,aAAa,UAAU,SAAS;EAE/C,UAAU,MAAM,KAAK,WAAW,OAAO,MAAM;EAC7C,KAAK,MAAM,EAAE,MAAM,WAAW,QAAQ;GACpC,MAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ,IAAI,MAAM,UAAU,IAAI;GAEhE,UAAU,KAAK,WAAW,CAAC;GAC3B,MAAM,MAAM,KAAK;GACjB,MAAM,WAAW,QAAQ,MAAM,cAAc,IAAI,MAAM,WAAW;GAClE,MAAM,WAAW,QAAQ,MAAM,cAAc,IAAI,MAAM,YAAY;GAEnE,UACE,OAAO,cAAc,QAAQ,KAC3B,YAAY,KACZ,aAAa,WAAW,qBAC5B;GACA,UACE,IAAI,MAAM,cAAc,SAAS,YAC/B,IAAI,MAAM,YAAY,SAAS,UAC/B,IAAI,MAAM,aAAa,SAAS,OACpC;GACA,UACE,IAAI,MAAM,WAAW,SACnB,IAAI,MAAM,0BAA0B,OAAO,UAAU,KAAK,CAAC,YAC/D;GACA,MAAM,aAAa,KAAK;IACtB,OAAO,MAAM;IACb,OAAO,MAAM,MAAM,OAAO;MACvB,MAAM,WAAW,SAAS;MAC1B,MAAM,SAAS,SAAS;MACxB,MAAM,OAAO;IAChB,CAAC;IACD,MAAM,CAAC,GAAG;GACZ,CAAC;EACH;CACF,CAAC;CAED,MAAM,kBAAkB,SAAc,UAA2B,cAC/D,OAAO,QAAQ,4BAA4B,UACzC,OAAO,IAAI,aAAa;EACtB,MAAM,QAAQ,QAAQ;EACtB,MAAM,SAAS,aAAa,UAAU,SAAS;EAE/C,MAAM,QAAQ,MAAM,MAAM,OAAO;IAC9B,MAAM,WAAW,SAAS;IAC1B,MAAM,SAAS,SAAS;EAC3B,CAAC;EAED,MAAM,eAAe,KACnB,GAAG,yBAAyB,MAAM,MAAM,SAAS,MAAM,MAAM,OAAO,QACtE;EACA,KAAK,MAAM,EAAE,MAAM,WAAW,QAC5B,MAAM,eAAe,KACnB,OAAO,YAAY,MAAM,OAAO;IAC7B,MAAM,WAAW,SAAS;IAC1B,MAAM,SAAS,SAAS;IACxB,MAAM,UAAU,SAAS;IACzB,MAAM,OAAO;IACb,MAAM,QAAQ;EACjB,CAAC,CACH;CACJ,CAAC,CACH;CA6HF,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAnIoB,OAAO,GAAG,uBAAuB,CAAC,CAAC,WACvD,SACA,UACA,QACA,OACA,WACA;GACA,MAAM,QAAQ,OAAO;GAErB,IAAI,MAAM,WAAW,GAAG;GACxB,MAAM,QAAQ,QAAQ;GACtB,MAAM,SAAS,QAAQ;GACvB,MAAM,QAAQ,QAAQ;GACtB,MAAM,WAAW,OAAO,MAAM,IAAI,KAAK;GACvC,MAAM,aAAwC,CAAC;GAE/C,KAAK,MAAM,EAAE,MAAM,WAAW,aAAa,UAAU,SAAS,CAAC,CAAC,QAAQ,SACtE,MAAM,SAAS,KAAK,IAAI,CAC1B,GAAG;IACD,MAAM,WAAW;MACd,MAAM,WAAW,SAAS;MAC1B,MAAM,SAAS,SAAS;MACxB,MAAM,OAAO;IAChB;IAEA,MAAM,SAAS;KACb,GAAG,MAAM,aAAa;MACpB,UAAU,SAAS;MACnB,QAAQ,SAAS;MACjB,SAAS,SAAS;MAClB;MACA;MACA,sBAAsB,OAAO,UAAU,KAAK,CAAC;MAC7C,QAAQ,MAAM;KAChB,CAAC;KACD,GAAG;MACF,MAAM,UAAU,SAAS;MACzB,MAAM,QAAQ;MACd,MAAM,uBAAuB,OAAO,UAAU,KAAK,CAAC;MACpD,MAAM,aAAa;MACnB,MAAM,cAAc;MACpB,MAAM,UAAU,MAAM;MACtB,MAAM,cAAc,MAAM;IAC7B;IAEA,MAAM,cAAc,OAAO,MAAM,OAAO,MAAM,OAAO,QAAQ,QAAQ;IAErE,YAAY,OAAO,YAAY,KAAK,KAAK,QACvC,OAAO,YACL,OAAO,QAAQ,GAAG,CAAC,CAAC,QACjB,CAAC,UAAU,SAAS,MAAM,cAAc,SAAS,MAAM,WAC1D,CACF,CACF;IACA,WAAW,KAAK,QAAQ;GAC1B;GACA,UAAU,WAAW,WAAW,MAAM,MAAM;GAE5C,MAAM,iBAAiB;KACpB,OAAO,iBAAiB,QAAQ;KAChC,OAAO,WAAW,QAAQ;KAC1B,OAAO,UAAU,MAAM;KACvB,OAAO,cAAc,MAAM;GAC9B;GAEA,MAAM,QAAQ,GAAG,WAAW,IAAI,OAAO,OAAO,OAAO,UAAU,EAAE,QAAQ,OAAO,MAAM,SAAS,MAAM,MAAM,OAAO,OAAO,cAAc,EAAE;GACzI,MAAM,cAAc,MAAM,SAAS,KAAK;GAExC,MAAM,aAAkB,KACtB,OAAO,YAAY,OAAO,OAAO,cAAc,GAC/C,GAAG,GAAG,MAAM,eACZ,GAAG,GAAG,YAAY,MAAM,YACxB,GAAG,GAAG,YAAY,MAAM,MAAM,mBAC9B,GAAG,GAAG,YAAY,MAAM,eAC1B;GAEA,OAAO,MAAM,YACX,OAAO,OACP,MAAM,MAAM,OAAO,OAAO;IAAE,GAAG;KAAiB,OAAO,aAAa;GAAK,CAAC,GAC1E,GACG,OAAO,aAAa,MAAM,WAAW,MAAM,eAAe,EAC7D,GACA;IAAE,MAAM;IAAG,eAAe;GAAW,CACvC;GACA,KAAK,MAAM,YAAY,YAAY;IACjC,MAAM,WAAW;KACf,GAAG;MACF,MAAM,UAAU,MAAM;MACtB,MAAM,cAAc,MAAM;IAC7B;IAEA,MAAM,gBAAgB,OAAO,YAC3B,MAAM,OACN,UACA,KACE,GAAG,GAAG,MAAM,SAAS,GAAG,GAAG,IAAI,MAAM,OAAO,MAAM,UAAU,GAAG,EAAE,KAAK,eACtE,GAAG,GAAG,MAAM,SAAS,GAAG,GAAG,IAAI,MAAM,OAAO,MAAM,WAAW,GAAG,EAAE,KAAK,YAAY,KAAK,uBAC1F,CACF;IAEA,OAAO,MAAM,YACX,MAAM,OACN,MAAM,MAAM,MAAM,OAAO;KACvB,GAAG;MACF,MAAM,aAAa;MACnB,MAAM,cAAc;IACvB,CAAC,GACD;MACG,MAAM,aAAa;MACnB,MAAM,cAAc,MAAM,WAAW,GAAG,GAAG,YAAY,KAAK,uBAAuB;IACtF,GACA;KAAE,MAAM;KAAG;IAAc,CAC3B;GACF;GACA,MAAM,eAAe,KACnB,GAAG,yBAAyB,MAAM,MAAM,SAAS,MAAM,MAAM,MAAM,OAAO;KACvE,MAAM,WAAW,SAAS;KAC1B,MAAM,SAAS,SAAS;KACxB,MAAM,cAAc,MAAM;GAC7B,CAAC,EAAE,MAAM,WAAW,QACtB;EACF,CAUc;CACd;AACF"}
@@ -0,0 +1,14 @@
1
+ import "../query-operations.mjs";
2
+ import "../transaction-kernel.mjs";
3
+ import "./state.mjs";
4
+ import { Effect } from "effect";
5
+ import { PasskeyCredential, PasskeyRevision } from "@yielded/auth/Passkey";
6
+ import { SubjectId } from "@yielded/auth/Schema";
7
+ //#region src/internal/passkey/credentials.d.ts
8
+ export interface SubjectRead {
9
+ readonly nativeId: unknown;
10
+ readonly subjectId: SubjectId;
11
+ readonly securityRevision: typeof PasskeyRevision.Type.securityRevision;
12
+ }
13
+ //#endregion
14
+ //# sourceMappingURL=credentials.d.mts.map