@yielded/auth-persistence-drizzle 0.1.0-beta.18 → 0.1.0-beta.19

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 (130) hide show
  1. package/README.md +8 -1
  2. package/dist/D1.d.mts +8 -8
  3. package/dist/Libsql.d.mts +44 -44
  4. package/dist/Mysql2.d.mts +44 -44
  5. package/dist/Pglite.d.mts +44 -44
  6. package/dist/Postgres.d.mts +44 -44
  7. package/dist/SqliteBun.d.mts +44 -44
  8. package/dist/SqliteDo.d.mts +112 -134
  9. package/dist/SqliteDo.mjs +30 -45
  10. package/dist/SqliteDo.mjs.map +1 -1
  11. package/dist/SqliteNode.d.mts +38 -38
  12. package/dist/SqliteWasm.d.mts +38 -38
  13. package/dist/drizzle/crypto.mjs +11 -0
  14. package/dist/drizzle/crypto.mjs.map +1 -0
  15. package/dist/drizzle/d1-identity.mjs +2 -2
  16. package/dist/drizzle/d1-identity.mjs.map +1 -1
  17. package/dist/drizzle/d1-oauth.d.mts +11 -11
  18. package/dist/drizzle/d1-oauth.mjs.map +1 -1
  19. package/dist/drizzle/d1-passkey.d.mts +6 -6
  20. package/dist/drizzle/d1-passkey.mjs.map +1 -1
  21. package/dist/drizzle/d1-passwords.d.mts +1 -1
  22. package/dist/drizzle/d1-phone.d.mts +3 -3
  23. package/dist/drizzle/d1-phone.mjs.map +1 -1
  24. package/dist/drizzle/d1-proofs.d.mts +1 -1
  25. package/dist/drizzle/d1-sessions.d.mts +1 -1
  26. package/dist/drizzle/d1-totp.d.mts +3 -3
  27. package/dist/drizzle/d1-totp.mjs.map +1 -1
  28. package/dist/drizzle/mysql-identity.mjs +2 -2
  29. package/dist/drizzle/mysql-identity.mjs.map +1 -1
  30. package/dist/drizzle/oauth-accounts.mjs +9 -8
  31. package/dist/drizzle/oauth-accounts.mjs.map +1 -1
  32. package/dist/drizzle/oauth-connected-collection.mjs +1 -1
  33. package/dist/drizzle/oauth-connected-collection.mjs.map +1 -1
  34. package/dist/drizzle/oauth-connected-custody.mjs +5 -4
  35. package/dist/drizzle/oauth-connected-custody.mjs.map +1 -1
  36. package/dist/drizzle/oauth-connected-drivers.mjs.map +1 -1
  37. package/dist/drizzle/oauth-connected-flow.mjs +8 -7
  38. package/dist/drizzle/oauth-connected-flow.mjs.map +1 -1
  39. package/dist/drizzle/oauth-connected-management.mjs +3 -2
  40. package/dist/drizzle/oauth-connected-management.mjs.map +1 -1
  41. package/dist/drizzle/oauth-connected-reference.mjs +8 -4
  42. package/dist/drizzle/oauth-connected-reference.mjs.map +1 -1
  43. package/dist/drizzle/oauth-connected-settlement.mjs +4 -4
  44. package/dist/drizzle/oauth-connected-settlement.mjs.map +1 -1
  45. package/dist/drizzle/oauth-connected-sign-in.mjs +11 -10
  46. package/dist/drizzle/oauth-connected-sign-in.mjs.map +1 -1
  47. package/dist/drizzle/oauth-connected-state.d.mts +13 -13
  48. package/dist/drizzle/oauth-connected-state.mjs +23 -20
  49. package/dist/drizzle/oauth-connected-state.mjs.map +1 -1
  50. package/dist/drizzle/oauth-connected-target.d.mts +7 -7
  51. package/dist/drizzle/oauth-connected-target.mjs.map +1 -1
  52. package/dist/drizzle/oauth-drivers.mjs.map +1 -1
  53. package/dist/drizzle/oauth-flow.mjs +1 -1
  54. package/dist/drizzle/oauth-flow.mjs.map +1 -1
  55. package/dist/drizzle/oauth-model.d.mts +4 -4
  56. package/dist/drizzle/oauth-model.mjs.map +1 -1
  57. package/dist/drizzle/oauth-registration.mjs +2 -2
  58. package/dist/drizzle/oauth-registration.mjs.map +1 -1
  59. package/dist/drizzle/oauth-state.mjs +11 -12
  60. package/dist/drizzle/oauth-state.mjs.map +1 -1
  61. package/dist/drizzle/oauth-target.d.mts +4 -4
  62. package/dist/drizzle/oauth-target.mjs.map +1 -1
  63. package/dist/drizzle/passkey-drivers.mjs.map +1 -1
  64. package/dist/drizzle/passkey-write-drivers.mjs.map +1 -1
  65. package/dist/drizzle/passkey-write-target.d.mts +1 -1
  66. package/dist/drizzle/password-prepared-state.mjs +1 -1
  67. package/dist/drizzle/pg-identity.mjs +2 -2
  68. package/dist/drizzle/pg-identity.mjs.map +1 -1
  69. package/dist/drizzle/phone-model.d.mts +2 -2
  70. package/dist/drizzle/phone-model.mjs +3 -3
  71. package/dist/drizzle/phone-model.mjs.map +1 -1
  72. package/dist/drizzle/phone-target.d.mts +1 -1
  73. package/dist/drizzle/phone-target.mjs +2 -2
  74. package/dist/drizzle/phone-target.mjs.map +1 -1
  75. package/dist/drizzle/sqlite-do-database.d.mts +29 -0
  76. package/dist/drizzle/sqlite-do-database.mjs +45 -0
  77. package/dist/drizzle/sqlite-do-database.mjs.map +1 -0
  78. package/dist/drizzle/sqlite-emails.mjs.map +1 -1
  79. package/dist/drizzle/sqlite-identity.mjs +2 -2
  80. package/dist/drizzle/sqlite-identity.mjs.map +1 -1
  81. package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
  82. package/dist/drizzle/sqlite-proofs.mjs.map +1 -1
  83. package/dist/drizzle/sqlite-sessions.mjs.map +1 -1
  84. package/dist/drizzle/storage-validation.mjs +17 -9
  85. package/dist/drizzle/storage-validation.mjs.map +1 -1
  86. package/dist/drizzle/totp-state.mjs +8 -8
  87. package/dist/drizzle/totp-state.mjs.map +1 -1
  88. package/dist/drizzle/totp-target.d.mts +1 -1
  89. package/dist/drizzle/totp-target.mjs +2 -2
  90. package/dist/drizzle/totp-target.mjs.map +1 -1
  91. package/package.json +1 -1
  92. package/src/SqliteDo.ts +63 -70
  93. package/src/drizzle/crypto.ts +14 -0
  94. package/src/drizzle/d1-identity.ts +2 -2
  95. package/src/drizzle/d1-oauth.ts +14 -5
  96. package/src/drizzle/d1-passkey.ts +5 -1
  97. package/src/drizzle/d1-phone.ts +2 -1
  98. package/src/drizzle/d1-totp.ts +6 -2
  99. package/src/drizzle/mysql-identity.ts +2 -2
  100. package/src/drizzle/oauth-accounts.ts +14 -13
  101. package/src/drizzle/oauth-connected-collection.ts +1 -1
  102. package/src/drizzle/oauth-connected-custody.ts +8 -6
  103. package/src/drizzle/oauth-connected-drivers.ts +9 -3
  104. package/src/drizzle/oauth-connected-flow.ts +6 -6
  105. package/src/drizzle/oauth-connected-management.ts +1 -1
  106. package/src/drizzle/oauth-connected-reference.ts +14 -9
  107. package/src/drizzle/oauth-connected-settlement.ts +4 -4
  108. package/src/drizzle/oauth-connected-sign-in.ts +11 -10
  109. package/src/drizzle/oauth-connected-state.ts +40 -25
  110. package/src/drizzle/oauth-connected-target.ts +9 -5
  111. package/src/drizzle/oauth-drivers.ts +13 -5
  112. package/src/drizzle/oauth-flow.ts +1 -1
  113. package/src/drizzle/oauth-model.ts +4 -4
  114. package/src/drizzle/oauth-registration.ts +2 -2
  115. package/src/drizzle/oauth-state.ts +17 -15
  116. package/src/drizzle/oauth-target.ts +11 -3
  117. package/src/drizzle/passkey-drivers.ts +7 -3
  118. package/src/drizzle/passkey-write-drivers.ts +11 -2
  119. package/src/drizzle/pg-identity.ts +2 -2
  120. package/src/drizzle/phone-model.ts +3 -3
  121. package/src/drizzle/phone-target.ts +11 -4
  122. package/src/drizzle/sqlite-do-database.ts +87 -0
  123. package/src/drizzle/sqlite-emails.ts +1 -1
  124. package/src/drizzle/sqlite-identity.ts +2 -2
  125. package/src/drizzle/sqlite-passwords.ts +1 -1
  126. package/src/drizzle/sqlite-proofs.ts +2 -2
  127. package/src/drizzle/sqlite-sessions.ts +2 -2
  128. package/src/drizzle/storage-validation.ts +15 -6
  129. package/src/drizzle/totp-state.ts +8 -8
  130. package/src/drizzle/totp-target.ts +11 -5
@@ -1,6 +1,6 @@
1
1
  import { OAuthTargetConfiguration } from "./oauth-target.mjs";
2
2
  import { Mapping, Revocations, oauth_connected_state_d_exports } from "./oauth-connected-state.mjs";
3
- import { Effect, Layer, Schema } from "effect";
3
+ import { Crypto, Effect, Layer, Schema } from "effect";
4
4
  import * as M from "@yielded/auth/OAuth";
5
5
  import { OAuthConnectedPersistence, OAuthConnectedRevocationDecision, OAuthConnectedRevocations, OAuthExternalIdentity, PrepareOAuthCommit } from "@yielded/auth/OAuth";
6
6
  import { Statement } from "effect/sql/Statement";
@@ -21,10 +21,10 @@ export declare const makeTargetOAuthConnectedServices: (mapping: Mapping, config
21
21
  readonly outcome: M.OAuthSignInAccessOutcome;
22
22
  }, prepare: PrepareOAuthCommit<{
23
23
  readonly _tag: "Rejected";
24
- } | {
25
- readonly _tag: "Ambiguous";
26
24
  } | {
27
25
  readonly _tag: "Cancelled";
26
+ } | {
27
+ readonly _tag: "Ambiguous";
28
28
  } | {
29
29
  readonly _tag: "Connected";
30
30
  readonly grant: {
@@ -477,10 +477,10 @@ export declare const makeTargetOAuthConnectedServices: (mapping: Mapping, config
477
477
  readonly nowMillis: number;
478
478
  }, prepare: PrepareOAuthCommit<{
479
479
  readonly _tag: "Rejected";
480
- } | {
481
- readonly _tag: "Ambiguous";
482
480
  } | {
483
481
  readonly _tag: "Cancelled";
482
+ } | {
483
+ readonly _tag: "Ambiguous";
484
484
  } | {
485
485
  readonly _tag: "Connected";
486
486
  readonly grant: {
@@ -971,7 +971,7 @@ export declare const makeTargetOAuthConnectedServices: (mapping: Mapping, config
971
971
  readonly hasMore: boolean;
972
972
  }, A>) => Effect.Effect<import("@yielded/auth/Hooks").PreparedCommit<A>, M.OAuthUnavailable, never>;
973
973
  };
974
- }, M.OAuthUnavailable, import("@yielded/auth/Hooks").LifecycleHooks | import("@yielded/auth-persistence/Adapter").NativeDatabase>;
974
+ }, M.OAuthUnavailable, Crypto.Crypto | import("@yielded/auth/Hooks").LifecycleHooks | import("@yielded/auth-persistence/Adapter").NativeDatabase>;
975
975
  export declare const makeTargetOAuthConnectedRevocationServices: (mapping: Revocations, configuration: OAuthTargetConfiguration) => Effect.Effect<{
976
976
  oauthConnectedRevocations: {
977
977
  readonly claim: <A>(input: {
@@ -986,7 +986,7 @@ export declare const makeTargetOAuthConnectedRevocationServices: (mapping: Revoc
986
986
  readonly settled: boolean;
987
987
  }, A>) => Effect.Effect<import("@yielded/auth/Hooks").PreparedCommit<A>, M.OAuthUnavailable>;
988
988
  };
989
- }, M.OAuthUnavailable, import("@yielded/auth/Hooks").LifecycleHooks | import("@yielded/auth-persistence/Adapter").NativeDatabase>;
989
+ }, M.OAuthUnavailable, Crypto.Crypto | import("@yielded/auth/Hooks").LifecycleHooks | import("@yielded/auth-persistence/Adapter").NativeDatabase>;
990
990
  export declare const oauthConnectedPersistenceLayer: <E, R>(services: Effect.Effect<Effect.Success<ReturnType<typeof makeTargetOAuthConnectedServices>>, E, R>) => Layer.Layer<OAuthConnectedPersistence, E, Exclude<R, import("effect/Scope").Scope>>;
991
991
  export declare const oauthConnectedRevocationsLayer: <E, R>(services: Effect.Effect<Effect.Success<ReturnType<typeof makeTargetOAuthConnectedRevocationServices>>, E, R>) => Layer.Layer<OAuthConnectedRevocations, E, Exclude<R, import("effect/Scope").Scope>>;
992
992
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-connected-target.mjs","names":["S.nativeCopy","SignIn.claimSignIn","SignIn.inspectSignIn","SignIn.settleSignIn","F.capture","F.issue","F.prepare","F.inspectPrepared","F.preflight","F.claim","F.inspectGrant","Management.list","Management.inspectDisconnect","Management.disconnect","A.inspectAccess","A.claimRefresh","A.settleRefresh","A.admitUse","Maintenance.cleanup","Maintenance.claimRevocation","Maintenance.settleRevocation"],"sources":["../../src/drizzle/oauth-connected-target.ts"],"sourcesContent":["import * as M from \"@yielded/auth/OAuth\";\nimport {\n OAuthConnectedPersistence,\n OAuthConnectedRevocations,\n OAuthConnectedRevocationDecision,\n OAuthExternalIdentity,\n snapshotOAuthSync,\n type PrepareOAuthCommit,\n} from \"@yielded/auth/OAuth\";\n/* oxlint-disable no-explicit-any -- concrete adapters retain the native database, table and ID types. */\nimport { Effect, Layer, Schema } from \"effect\";\nimport type { Statement } from \"effect/sql/Statement\";\n\nimport type { PersistenceMappingError } from \"./model\";\nimport * as A from \"./oauth-connected-access\";\nimport * as F from \"./oauth-connected-flow\";\nimport { connectedInputs, connectedRevocationInputs } from \"./oauth-connected-input\";\nimport * as Maintenance from \"./oauth-connected-maintenance\";\nimport * as Management from \"./oauth-connected-management\";\nimport { settle } from \"./oauth-connected-settlement\";\nimport * as SignIn from \"./oauth-connected-sign-in\";\nimport * as S from \"./oauth-connected-state\";\nimport { capturedOAuthService } from \"./oauth-input\";\nimport { CurrentOAuthTransaction } from \"./oauth-owner\";\nimport { captureOAuthMapping } from \"./oauth-state\";\nimport {\n coordinateOAuthOwner,\n makeOAuthExecution,\n type OAuthExecution,\n type OAuthTargetConfiguration,\n} from \"./oauth-target\";\n\nconst captured = <T extends S.Authority>(mapping: T): T => {\n const retained = captureOAuthMapping(mapping),\n codec = retained.subjectId;\n\n const subjectId = {\n ...codec,\n toNative: (subject: Parameters<typeof codec.toNative>[0]) =>\n Effect.map(codec.toNative(subject), S.nativeCopy),\n toSubject: (native: unknown) => codec.toSubject(S.nativeCopy(native)),\n equals: (a: unknown, b: unknown) => codec.equals(S.nativeCopy(a), S.nativeCopy(b)),\n };\n\n const ownership = retained.ownership;\n\n if (ownership.mode === \"separate\" && \"encodeInsert\" in ownership.external) {\n const encode = ownership.external.encodeInsert as (input: {\n readonly identity: typeof OAuthExternalIdentity.Type;\n readonly identityKey: string;\n readonly subjectId: unknown;\n }) => import(\"./oauth-owner\").Row;\n\n return captureOAuthMapping({\n ...retained,\n subjectId,\n ownership: {\n ...ownership,\n external: {\n ...ownership.external,\n encodeInsert: (input: Parameters<typeof encode>[0]) =>\n encode({\n ...input,\n identity: snapshotOAuthSync(OAuthExternalIdentity, input.identity),\n subjectId: S.nativeCopy(input.subjectId),\n }),\n },\n },\n });\n }\n\n return captureOAuthMapping({ ...retained, subjectId });\n};\n\nconst prepare = <Value, Encoded, A>(\n schema: Schema.Codec<Value, Encoded, never, never>,\n value: Value,\n callback: PrepareOAuthCommit<Value, A>,\n) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.sync(() => {\n owner.guards.push(owner.journal.prepare(undefined));\n\n return callback(snapshotOAuthSync(schema, value), owner.journal);\n }),\n );\n\nconst mutation =\n <Input, Value, Encoded>(\n mapping: S.Mapping,\n execute: OAuthExecution,\n body: (\n mapping: S.Mapping,\n input: Input,\n ) => Effect.Effect<\n Value,\n import(\"@yielded/auth/OAuth\").OAuthUnavailable | PersistenceMappingError,\n CurrentOAuthTransaction\n >,\n schema: Schema.Codec<Value, Encoded, never, never>,\n ) =>\n <A>(input: Input, callback: PrepareOAuthCommit<Value, A>) =>\n execute.run(Effect.flatMap(body(mapping, input), (value) => prepare(schema, value, callback)));\n\nconst read =\n <Input, Value>(\n mapping: S.Mapping,\n execute: OAuthExecution,\n body: (\n mapping: S.Mapping,\n input: Input,\n ) => Effect.Effect<\n Value,\n import(\"@yielded/auth/OAuth\").OAuthUnavailable | PersistenceMappingError,\n CurrentOAuthTransaction\n >,\n ) =>\n (input: Input) =>\n execute.run(body(mapping, input), false);\n\nexport const makeConnected = (\n mapping: S.Mapping,\n execute: OAuthExecution,\n): OAuthConnectedPersistence[\"Service\"] =>\n capturedOAuthService<OAuthConnectedPersistence[\"Service\"]>(\n {\n claimSignIn: mutation(mapping, execute, SignIn.claimSignIn, M.OAuthSignInAccessClaim),\n inspectSignIn: read(mapping, execute, SignIn.inspectSignIn),\n settleSignIn: mutation(\n mapping,\n execute,\n SignIn.settleSignIn,\n M.OAuthConnectedSettlementDecision,\n ),\n capture: read(mapping, execute, F.capture),\n issue: mutation(mapping, execute, F.issue, M.OAuthConnectedIssueDecision),\n prepare: mutation(mapping, execute, F.prepare, M.OAuthConnectedIssueDecision),\n inspectPrepared: read(mapping, execute, F.inspectPrepared),\n preflight: read(mapping, execute, F.preflight),\n claim: mutation(mapping, execute, F.claim, M.OAuthConnectedClaimDecision),\n inspectGrant: read(mapping, execute, F.inspectGrant),\n settle: mutation(mapping, execute, settle, M.OAuthConnectedSettlementDecision),\n list: read(mapping, execute, Management.list),\n inspectDisconnect: read(mapping, execute, Management.inspectDisconnect),\n disconnect: mutation(\n mapping,\n execute,\n Management.disconnect,\n M.OAuthConnectedDisconnectDecision,\n ),\n inspectAccess: read(mapping, execute, A.inspectAccess),\n claimRefresh: mutation(mapping, execute, A.claimRefresh, M.OAuthConnectedRefreshDecision),\n settleRefresh: mutation(mapping, execute, A.settleRefresh, M.OAuthConnectedRefreshSettlement),\n admitUse: mutation(mapping, execute, A.admitUse, M.OAuthConnectedUseAdmission),\n cleanup: mutation(mapping, execute, Maintenance.cleanup, M.OAuthConnectedCleanupResult),\n },\n connectedInputs,\n execute.active,\n execute.poison,\n );\n\nconst settled = Schema.Struct({ settled: Schema.Boolean });\n\nexport const makeRevocations = (\n mapping: S.Revocations,\n execute: OAuthExecution,\n): OAuthConnectedRevocations[\"Service\"] =>\n capturedOAuthService<OAuthConnectedRevocations[\"Service\"]>(\n {\n claim: (input, callback) =>\n execute.run(\n Effect.flatMap(Maintenance.claimRevocation(mapping, input), (value) =>\n prepare(OAuthConnectedRevocationDecision, value, callback),\n ),\n ),\n settle: (input, callback) =>\n execute.run(\n Effect.flatMap(Maintenance.settleRevocation(mapping, input), (value) =>\n prepare(settled, value, callback),\n ),\n ),\n },\n connectedRevocationInputs,\n execute.active,\n execute.poison,\n );\n\nexport const makeTargetOAuthConnectedServices = (\n mapping: S.Mapping,\n configuration: OAuthTargetConfiguration,\n) => {\n const retained = captured(mapping);\n\n return Effect.map(makeOAuthExecution(configuration, retained), (execution) => ({\n oauthConnectedPersistence: makeConnected(retained, execution),\n }));\n};\n\nexport const makeTargetOAuthConnectedRevocationServices = (\n mapping: S.Revocations,\n configuration: OAuthTargetConfiguration,\n) => {\n const retained = captured(mapping);\n\n return Effect.map(makeOAuthExecution(configuration, retained), (execution) => ({\n oauthConnectedRevocations: makeRevocations(retained, execution),\n }));\n};\n\nexport const coordinateTargetOAuthConnected = <Transaction, A, E, R>(\n database: any,\n mapping: S.Mapping,\n configuration: OAuthTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly oauthConnectedPersistence: OAuthConnectedPersistence[\"Service\"] },\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateOAuthOwner(\n database,\n captured(mapping),\n configuration,\n () => Effect.void,\n (value: S.Mapping, execution) => ({\n oauthConnectedPersistence: makeConnected(value, execution),\n }),\n owner,\n );\n\nexport const coordinateTargetOAuthConnectedRevocations = <Transaction, A, E, R>(\n database: any,\n mapping: S.Revocations,\n configuration: OAuthTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly oauthConnectedRevocations: OAuthConnectedRevocations[\"Service\"] },\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateOAuthOwner(\n database,\n captured(mapping),\n configuration,\n () => Effect.void,\n (value: S.Revocations, execution) => ({\n oauthConnectedRevocations: makeRevocations(value, execution),\n }),\n owner,\n );\n\nexport const oauthConnectedPersistenceLayer = <E, R>(\n services: Effect.Effect<\n Effect.Success<ReturnType<typeof makeTargetOAuthConnectedServices>>,\n E,\n R\n >,\n) =>\n Layer.effect(\n OAuthConnectedPersistence,\n Effect.map(services, (value) => value.oauthConnectedPersistence),\n );\n\nexport const oauthConnectedRevocationsLayer = <E, R>(\n services: Effect.Effect<\n Effect.Success<ReturnType<typeof makeTargetOAuthConnectedRevocationServices>>,\n E,\n R\n >,\n) =>\n Layer.effect(\n OAuthConnectedRevocations,\n Effect.map(services, (value) => value.oauthConnectedRevocations),\n );\n"],"mappings":"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"}
1
+ {"version":3,"file":"oauth-connected-target.mjs","names":["S.nativeCopy","SignIn.claimSignIn","SignIn.inspectSignIn","SignIn.settleSignIn","F.capture","F.issue","F.prepare","F.inspectPrepared","F.preflight","F.claim","F.inspectGrant","Management.list","Management.inspectDisconnect","Management.disconnect","A.inspectAccess","A.claimRefresh","A.settleRefresh","A.admitUse","Maintenance.cleanup","Maintenance.claimRevocation","Maintenance.settleRevocation"],"sources":["../../src/drizzle/oauth-connected-target.ts"],"sourcesContent":["import * as M from \"@yielded/auth/OAuth\";\nimport {\n OAuthConnectedPersistence,\n OAuthConnectedRevocations,\n OAuthConnectedRevocationDecision,\n OAuthExternalIdentity,\n snapshotOAuthSync,\n type PrepareOAuthCommit,\n} from \"@yielded/auth/OAuth\";\n/* oxlint-disable no-explicit-any -- concrete adapters retain the native database, table and ID types. */\nimport { type Crypto, Effect, Layer, type PlatformError, Schema } from \"effect\";\nimport type { Statement } from \"effect/sql/Statement\";\n\nimport type { PersistenceMappingError } from \"./model\";\nimport * as A from \"./oauth-connected-access\";\nimport * as F from \"./oauth-connected-flow\";\nimport { connectedInputs, connectedRevocationInputs } from \"./oauth-connected-input\";\nimport * as Maintenance from \"./oauth-connected-maintenance\";\nimport * as Management from \"./oauth-connected-management\";\nimport { settle } from \"./oauth-connected-settlement\";\nimport * as SignIn from \"./oauth-connected-sign-in\";\nimport * as S from \"./oauth-connected-state\";\nimport { capturedOAuthService } from \"./oauth-input\";\nimport { CurrentOAuthTransaction } from \"./oauth-owner\";\nimport { captureOAuthMapping } from \"./oauth-state\";\nimport {\n coordinateOAuthOwner,\n makeOAuthExecution,\n type OAuthExecution,\n type OAuthTargetConfiguration,\n} from \"./oauth-target\";\n\nconst captured = <T extends S.Authority>(mapping: T): T => {\n const retained = captureOAuthMapping(mapping),\n codec = retained.subjectId;\n\n const subjectId = {\n ...codec,\n toNative: (subject: Parameters<typeof codec.toNative>[0]) =>\n Effect.map(codec.toNative(subject), S.nativeCopy),\n toSubject: (native: unknown) => codec.toSubject(S.nativeCopy(native)),\n equals: (a: unknown, b: unknown) => codec.equals(S.nativeCopy(a), S.nativeCopy(b)),\n };\n\n const ownership = retained.ownership;\n\n if (ownership.mode === \"separate\" && \"encodeInsert\" in ownership.external) {\n const encode = ownership.external.encodeInsert as (input: {\n readonly identity: typeof OAuthExternalIdentity.Type;\n readonly identityKey: string;\n readonly subjectId: unknown;\n }) => import(\"./oauth-owner\").Row;\n\n return captureOAuthMapping({\n ...retained,\n subjectId,\n ownership: {\n ...ownership,\n external: {\n ...ownership.external,\n encodeInsert: (input: Parameters<typeof encode>[0]) =>\n encode({\n ...input,\n identity: snapshotOAuthSync(OAuthExternalIdentity, input.identity),\n subjectId: S.nativeCopy(input.subjectId),\n }),\n },\n },\n });\n }\n\n return captureOAuthMapping({ ...retained, subjectId });\n};\n\nconst prepare = <Value, Encoded, A>(\n schema: Schema.Codec<Value, Encoded, never, never>,\n value: Value,\n callback: PrepareOAuthCommit<Value, A>,\n) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.sync(() => {\n owner.guards.push(owner.journal.prepare(undefined));\n\n return callback(snapshotOAuthSync(schema, value), owner.journal);\n }),\n );\n\nconst mutation =\n <Input, Value, Encoded>(\n mapping: S.Mapping,\n execute: OAuthExecution,\n body: (\n mapping: S.Mapping,\n input: Input,\n ) => Effect.Effect<\n Value,\n | import(\"@yielded/auth/OAuth\").OAuthUnavailable\n | PersistenceMappingError\n | PlatformError.PlatformError,\n CurrentOAuthTransaction | Crypto.Crypto\n >,\n schema: Schema.Codec<Value, Encoded, never, never>,\n ) =>\n <A>(input: Input, callback: PrepareOAuthCommit<Value, A>) =>\n execute.run(Effect.flatMap(body(mapping, input), (value) => prepare(schema, value, callback)));\n\nconst read =\n <Input, Value>(\n mapping: S.Mapping,\n execute: OAuthExecution,\n body: (\n mapping: S.Mapping,\n input: Input,\n ) => Effect.Effect<\n Value,\n | import(\"@yielded/auth/OAuth\").OAuthUnavailable\n | PersistenceMappingError\n | PlatformError.PlatformError,\n CurrentOAuthTransaction | Crypto.Crypto\n >,\n ) =>\n (input: Input) =>\n execute.run(body(mapping, input), false);\n\nexport const makeConnected = (\n mapping: S.Mapping,\n execute: OAuthExecution,\n): OAuthConnectedPersistence[\"Service\"] =>\n capturedOAuthService<OAuthConnectedPersistence[\"Service\"]>(\n {\n claimSignIn: mutation(mapping, execute, SignIn.claimSignIn, M.OAuthSignInAccessClaim),\n inspectSignIn: read(mapping, execute, SignIn.inspectSignIn),\n settleSignIn: mutation(\n mapping,\n execute,\n SignIn.settleSignIn,\n M.OAuthConnectedSettlementDecision,\n ),\n capture: read(mapping, execute, F.capture),\n issue: mutation(mapping, execute, F.issue, M.OAuthConnectedIssueDecision),\n prepare: mutation(mapping, execute, F.prepare, M.OAuthConnectedIssueDecision),\n inspectPrepared: read(mapping, execute, F.inspectPrepared),\n preflight: read(mapping, execute, F.preflight),\n claim: mutation(mapping, execute, F.claim, M.OAuthConnectedClaimDecision),\n inspectGrant: read(mapping, execute, F.inspectGrant),\n settle: mutation(mapping, execute, settle, M.OAuthConnectedSettlementDecision),\n list: read(mapping, execute, Management.list),\n inspectDisconnect: read(mapping, execute, Management.inspectDisconnect),\n disconnect: mutation(\n mapping,\n execute,\n Management.disconnect,\n M.OAuthConnectedDisconnectDecision,\n ),\n inspectAccess: read(mapping, execute, A.inspectAccess),\n claimRefresh: mutation(mapping, execute, A.claimRefresh, M.OAuthConnectedRefreshDecision),\n settleRefresh: mutation(mapping, execute, A.settleRefresh, M.OAuthConnectedRefreshSettlement),\n admitUse: mutation(mapping, execute, A.admitUse, M.OAuthConnectedUseAdmission),\n cleanup: mutation(mapping, execute, Maintenance.cleanup, M.OAuthConnectedCleanupResult),\n },\n connectedInputs,\n execute.active,\n execute.poison,\n );\n\nconst settled = Schema.Struct({ settled: Schema.Boolean });\n\nexport const makeRevocations = (\n mapping: S.Revocations,\n execute: OAuthExecution,\n): OAuthConnectedRevocations[\"Service\"] =>\n capturedOAuthService<OAuthConnectedRevocations[\"Service\"]>(\n {\n claim: (input, callback) =>\n execute.run(\n Effect.flatMap(Maintenance.claimRevocation(mapping, input), (value) =>\n prepare(OAuthConnectedRevocationDecision, value, callback),\n ),\n ),\n settle: (input, callback) =>\n execute.run(\n Effect.flatMap(Maintenance.settleRevocation(mapping, input), (value) =>\n prepare(settled, value, callback),\n ),\n ),\n },\n connectedRevocationInputs,\n execute.active,\n execute.poison,\n );\n\nexport const makeTargetOAuthConnectedServices = (\n mapping: S.Mapping,\n configuration: OAuthTargetConfiguration,\n) => {\n const retained = captured(mapping);\n\n return Effect.map(makeOAuthExecution(configuration, retained), (execution) => ({\n oauthConnectedPersistence: makeConnected(retained, execution),\n }));\n};\n\nexport const makeTargetOAuthConnectedRevocationServices = (\n mapping: S.Revocations,\n configuration: OAuthTargetConfiguration,\n) => {\n const retained = captured(mapping);\n\n return Effect.map(makeOAuthExecution(configuration, retained), (execution) => ({\n oauthConnectedRevocations: makeRevocations(retained, execution),\n }));\n};\n\nexport const coordinateTargetOAuthConnected = <Transaction, A, E, R>(\n database: any,\n mapping: S.Mapping,\n configuration: OAuthTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly oauthConnectedPersistence: OAuthConnectedPersistence[\"Service\"] },\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateOAuthOwner(\n database,\n captured(mapping),\n configuration,\n () => Effect.void,\n (value: S.Mapping, execution) => ({\n oauthConnectedPersistence: makeConnected(value, execution),\n }),\n owner,\n );\n\nexport const coordinateTargetOAuthConnectedRevocations = <Transaction, A, E, R>(\n database: any,\n mapping: S.Revocations,\n configuration: OAuthTargetConfiguration,\n owner: (\n transaction: Transaction,\n services: { readonly oauthConnectedRevocations: OAuthConnectedRevocations[\"Service\"] },\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateOAuthOwner(\n database,\n captured(mapping),\n configuration,\n () => Effect.void,\n (value: S.Revocations, execution) => ({\n oauthConnectedRevocations: makeRevocations(value, execution),\n }),\n owner,\n );\n\nexport const oauthConnectedPersistenceLayer = <E, R>(\n services: Effect.Effect<\n Effect.Success<ReturnType<typeof makeTargetOAuthConnectedServices>>,\n E,\n R\n >,\n) =>\n Layer.effect(\n OAuthConnectedPersistence,\n Effect.map(services, (value) => value.oauthConnectedPersistence),\n );\n\nexport const oauthConnectedRevocationsLayer = <E, R>(\n services: Effect.Effect<\n Effect.Success<ReturnType<typeof makeTargetOAuthConnectedRevocationServices>>,\n E,\n R\n >,\n) =>\n Layer.effect(\n OAuthConnectedRevocations,\n Effect.map(services, (value) => value.oauthConnectedRevocations),\n );\n"],"mappings":";;;;;;;;;;;;;;;;AAgCA,MAAM,YAAmC,YAAkB;CACzD,MAAM,WAAW,oBAAoB,OAAO,GAC1C,QAAQ,SAAS;CAEnB,MAAM,YAAY;EAChB,GAAG;EACH,WAAW,YACT,OAAO,IAAI,MAAM,SAAS,OAAO,GAAGA,UAAY;EAClD,YAAY,WAAoB,MAAM,UAAUA,WAAa,MAAM,CAAC;EACpE,SAAS,GAAY,MAAe,MAAM,OAAOA,WAAa,CAAC,GAAGA,WAAa,CAAC,CAAC;CACnF;CAEA,MAAM,YAAY,SAAS;CAE3B,IAAI,UAAU,SAAS,cAAc,kBAAkB,UAAU,UAAU;EACzE,MAAM,SAAS,UAAU,SAAS;EAMlC,OAAO,oBAAoB;GACzB,GAAG;GACH;GACA,WAAW;IACT,GAAG;IACH,UAAU;KACR,GAAG,UAAU;KACb,eAAe,UACb,OAAO;MACL,GAAG;MACH,UAAU,kBAAkB,uBAAuB,MAAM,QAAQ;MACjE,WAAWA,WAAa,MAAM,SAAS;KACzC,CAAC;IACL;GACF;EACF,CAAC;CACH;CAEA,OAAO,oBAAoB;EAAE,GAAG;EAAU;CAAU,CAAC;AACvD;AAEA,MAAM,WACJ,QACA,OACA,aAEA,OAAO,QAAQ,0BAA0B,UACvC,OAAO,WAAW;CAChB,MAAM,OAAO,KAAK,MAAM,QAAQ,QAAQ,KAAA,CAAS,CAAC;CAElD,OAAO,SAAS,kBAAkB,QAAQ,KAAK,GAAG,MAAM,OAAO;AACjE,CAAC,CACH;AAEF,MAAM,YAEF,SACA,SACA,MAUA,YAEE,OAAc,aAChB,QAAQ,IAAI,OAAO,QAAQ,KAAK,SAAS,KAAK,IAAI,UAAU,QAAQ,QAAQ,OAAO,QAAQ,CAAC,CAAC;AAEjG,MAAM,QAEF,SACA,SACA,UAWD,UACC,QAAQ,IAAI,KAAK,SAAS,KAAK,GAAG,KAAK;AAE3C,MAAa,iBACX,SACA,YAEA,qBACE;CACE,aAAa,SAAS,SAAS,SAASC,aAAoB,EAAE,sBAAsB;CACpF,eAAe,KAAK,SAAS,SAASC,aAAoB;CAC1D,cAAc,SACZ,SACA,SACAC,cACA,EAAE,gCACJ;CACA,SAAS,KAAK,SAAS,SAASC,OAAS;CACzC,OAAO,SAAS,SAAS,SAASC,OAAS,EAAE,2BAA2B;CACxE,SAAS,SAAS,SAAS,SAASC,WAAW,EAAE,2BAA2B;CAC5E,iBAAiB,KAAK,SAAS,SAASC,eAAiB;CACzD,WAAW,KAAK,SAAS,SAASC,SAAW;CAC7C,OAAO,SAAS,SAAS,SAASC,OAAS,EAAE,2BAA2B;CACxE,cAAc,KAAK,SAAS,SAASC,YAAc;CACnD,QAAQ,SAAS,SAAS,SAAS,QAAQ,EAAE,gCAAgC;CAC7E,MAAM,KAAK,SAAS,SAASC,IAAe;CAC5C,mBAAmB,KAAK,SAAS,SAASC,iBAA4B;CACtE,YAAY,SACV,SACA,SACAC,YACA,EAAE,gCACJ;CACA,eAAe,KAAK,SAAS,SAASC,aAAe;CACrD,cAAc,SAAS,SAAS,SAASC,cAAgB,EAAE,6BAA6B;CACxF,eAAe,SAAS,SAAS,SAASC,eAAiB,EAAE,+BAA+B;CAC5F,UAAU,SAAS,SAAS,SAASC,UAAY,EAAE,0BAA0B;CAC7E,SAAS,SAAS,SAAS,SAASC,SAAqB,EAAE,2BAA2B;AACxF,GACA,iBACA,QAAQ,QACR,QAAQ,MACV;AAEF,MAAM,UAAU,OAAO,OAAO,EAAE,SAAS,OAAO,QAAQ,CAAC;AAEzD,MAAa,mBACX,SACA,YAEA,qBACE;CACE,QAAQ,OAAO,aACb,QAAQ,IACN,OAAO,QAAQC,gBAA4B,SAAS,KAAK,IAAI,UAC3D,QAAQ,kCAAkC,OAAO,QAAQ,CAC3D,CACF;CACF,SAAS,OAAO,aACd,QAAQ,IACN,OAAO,QAAQC,iBAA6B,SAAS,KAAK,IAAI,UAC5D,QAAQ,SAAS,OAAO,QAAQ,CAClC,CACF;AACJ,GACA,2BACA,QAAQ,QACR,QAAQ,MACV;AAEF,MAAa,oCACX,SACA,kBACG;CACH,MAAM,WAAW,SAAS,OAAO;CAEjC,OAAO,OAAO,IAAI,mBAAmB,eAAe,QAAQ,IAAI,eAAe,EAC7E,2BAA2B,cAAc,UAAU,SAAS,EAC9D,EAAE;AACJ;AAEA,MAAa,8CACX,SACA,kBACG;CACH,MAAM,WAAW,SAAS,OAAO;CAEjC,OAAO,OAAO,IAAI,mBAAmB,eAAe,QAAQ,IAAI,eAAe,EAC7E,2BAA2B,gBAAgB,UAAU,SAAS,EAChE,EAAE;AACJ;AAEA,MAAa,kCACX,UACA,SACA,eACA,UAMA,qBACE,UACA,SAAS,OAAO,GAChB,qBACM,OAAO,OACZ,OAAkB,eAAe,EAChC,2BAA2B,cAAc,OAAO,SAAS,EAC3D,IACA,KACF;AAEF,MAAa,6CACX,UACA,SACA,eACA,UAMA,qBACE,UACA,SAAS,OAAO,GAChB,qBACM,OAAO,OACZ,OAAsB,eAAe,EACpC,2BAA2B,gBAAgB,OAAO,SAAS,EAC7D,IACA,KACF;AAEF,MAAa,kCACX,aAMA,MAAM,OACJ,2BACA,OAAO,IAAI,WAAW,UAAU,MAAM,yBAAyB,CACjE;AAEF,MAAa,kCACX,aAMA,MAAM,OACJ,2BACA,OAAO,IAAI,WAAW,UAAU,MAAM,yBAAyB,CACjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-drivers.mjs","names":[],"sources":["../../src/drizzle/oauth-drivers.ts"],"sourcesContent":["import { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport {\n OAuthAccountsPersistence,\n OAuthRegistrationIntents,\n OAuthSignInPersistence,\n} from \"@yielded/auth/OAuth\";\nimport type { Table } from \"drizzle-orm\";\nimport { Effect, Context } from \"effect\";\n\nimport { nativeDatabase } from \"./native-database\";\nimport { makeOAuthConnectedTarget } from \"./oauth-connected-drivers\";\nimport type {\n OAuthAccountsMapping,\n OAuthRegistrationAuthority,\n OAuthRegistrationIntentMapping,\n OAuthRegistrationMapping,\n OAuthSignInMapping,\n} from \"./oauth-model\";\nimport {\n type OAuthCoordinatorError,\n coordinateTargetOAuthAccounts,\n coordinateTargetOAuthSignIn,\n coordinateTargetOAuthRegistrationIntents,\n coordinateTargetOAuthRegistration,\n makeTargetOAuthRegistrationIntentServices,\n makeTargetOAuthRegistrationServices,\n makeTargetOAuthSignInServices,\n makeTargetOAuthAccountsServices,\n type OAuthTargetConfiguration,\n} from \"./oauth-target\";\nimport type { SuppliedService } from \"./SuppliedService\";\n\n// oxlint-disable-next-line no-explicit-any -- inspect the installed generic transaction signature without erasing its callback parameter.\ntype TransactionOf<D> = D extends { readonly transaction: (...args: any[]) => any }\n ? Parameters<Parameters<D[\"transaction\"]>[0]>[0]\n : never;\n\n/** Driver-specific entry points instantiate both the database and table family. */\nexport const makeOAuthTarget = <\n DatabaseId,\n D,\n T extends Table,\n Synchronous extends boolean = false,\n>(\n databaseService: Context.Service<DatabaseId, D>,\n configuration: OAuthTargetConfiguration,\n) => {\n function coordinateOAuthSignIn<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthSignInMapping<S, O, C, AC, F, N>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthSignInPersistence> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthSignInPersistence>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthSignIn<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthSignInMapping<S, O, C, AC, F, N>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthSignInPersistence | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthSignInPersistence | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthSignIn<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthSignInMapping<S, O, C, AC, F, N>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthSignInPersistence> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthSignIn<\n TransactionOf<Database>,\n A,\n E,\n Exclude<R, OAuthSignInPersistence>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services: { readonly oauthSignInPersistence: OAuthSignInPersistence[\"Service\"] },\n ) => {\n const provided = Context.make(OAuthSignInPersistence, services.oauthSignInPersistence);\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthRegistrationIntents<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n I extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationIntentMapping<S, O, C, AC, F, TA, I, N>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthRegistrationIntents> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthRegistrationIntents>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthRegistrationIntents<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n I extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationIntentMapping<S, O, C, AC, F, TA, I, N>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthRegistrationIntents | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthRegistrationIntents | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthRegistrationIntents<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n I extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationIntentMapping<S, O, C, AC, F, TA, I, N>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthRegistrationIntents> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthRegistrationIntents<\n TransactionOf<Database>,\n A,\n E,\n Exclude<R, OAuthRegistrationIntents>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services: { readonly oauthRegistrationIntents: OAuthRegistrationIntents[\"Service\"] },\n ) => {\n const provided = Context.make(\n OAuthRegistrationIntents,\n services.oauthRegistrationIntents,\n );\n\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthAccounts<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n U extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthAccountsMapping<S, O, C, AC, F, TA, U, N>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthAccountsPersistence> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthAccountsPersistence>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthAccounts<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n U extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthAccountsMapping<S, O, C, AC, F, TA, U, N>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthAccountsPersistence | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthAccountsPersistence | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthAccounts<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n U extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthAccountsMapping<S, O, C, AC, F, TA, U, N>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthAccountsPersistence> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthAccounts<\n TransactionOf<Database>,\n A,\n E,\n Exclude<R, OAuthAccountsPersistence>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services: { readonly oauthAccountsPersistence: OAuthAccountsPersistence[\"Service\"] },\n ) => {\n const provided = Context.make(\n OAuthAccountsPersistence,\n services.oauthAccountsPersistence,\n );\n\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthRegistration<\n Database extends D,\n TargetId,\n Registration,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n TA extends T,\n I extends T,\n Rq extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationMapping<NoInfer<Registration>, S, O, C, AC, TA, I, Rq, N>;\n readonly target: SuppliedService<TargetId, OAuthRegistrationAuthority<Registration>>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TargetId> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthRegistration<\n Database extends D,\n TargetId,\n Registration,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n TA extends T,\n I extends T,\n Rq extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationMapping<NoInfer<Registration>, S, O, C, AC, TA, I, Rq, N>;\n readonly target: SuppliedService<TargetId, OAuthRegistrationAuthority<Registration>>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TargetId | TxId> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthRegistration<\n Database extends D,\n TargetId,\n Registration,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n TA extends T,\n I extends T,\n Rq extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationMapping<NoInfer<Registration>, S, O, C, AC, TA, I, Rq, N>;\n readonly target: SuppliedService<TargetId, OAuthRegistrationAuthority<Registration>>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, TargetId> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthRegistration<\n Registration,\n TransactionOf<Database>,\n A,\n E,\n Exclude<R, TargetId>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services: { readonly registrationAuthority: OAuthRegistrationAuthority<Registration> },\n ) => {\n const provided = Context.make(options.target, services.registrationAuthority);\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n\n return {\n ...makeOAuthConnectedTarget<DatabaseId, D, T, {}, Synchronous>(databaseService, configuration),\n coordinateOAuthSignIn,\n coordinateOAuthRegistrationIntents,\n coordinateOAuthAccounts,\n makeOAuthAccountsServices: <\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n U extends T,\n N,\n >(\n mapping: OAuthAccountsMapping<S, O, C, AC, F, TA, U, N>,\n ) =>\n makeTargetOAuthAccountsServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeOAuthSignInServices: <S extends T, O extends T, C extends T, AC extends T, F extends T, N>(\n mapping: OAuthSignInMapping<S, O, C, AC, F, N>,\n ) =>\n makeTargetOAuthSignInServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeOAuthRegistrationIntentServices: <\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n I extends T,\n N,\n >(\n mapping: OAuthRegistrationIntentMapping<S, O, C, AC, F, TA, I, N>,\n ) =>\n makeTargetOAuthRegistrationIntentServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeOAuthRegistrationServices: <\n Registration,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n TA extends T,\n I extends T,\n R extends T,\n N,\n >(\n mapping: OAuthRegistrationMapping<Registration, S, O, C, AC, TA, I, R, N>,\n ) =>\n makeTargetOAuthRegistrationServices<Registration>(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateOAuthRegistration,\n };\n};\n"],"mappings":";;;;;;;;AAuCA,MAAa,mBAMX,iBACA,kBACG;CA6DH,SAAS,sBAgBP,SACA,SAIA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,4BAME,UACA,QAAQ,SACR,gBAEE,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KAAK,wBAAwB,SAAS,sBAAsB;GACrF,MAAM,OAAO,OAAO,eAAe,MAAM,QAAQ;GAEjD,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;EAC1F,CACF,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC,CACxD;CACF;CAiEA,SAAS,mCAkBP,SACA,SAIA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,yCAME,UACA,QAAQ,SACR,gBAEE,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KACvB,0BACA,SAAS,wBACX;GAEA,MAAM,OAAO,OAAO,eAAe,MAAM,QAAQ;GAEjD,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;EAC1F,CACF,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC,CACxD;CACF;CAiEA,SAAS,wBAkBP,SACA,SAIA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,8BAME,UACA,QAAQ,SACR,gBAEE,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KACvB,0BACA,SAAS,wBACX;GAEA,MAAM,OAAO,OAAO,eAAe,MAAM,QAAQ;GAEjD,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;EAC1F,CACF,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC,CACxD;CACF;CAmEA,SAAS,4BAoBP,SACA,SAKA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,kCAOE,UACA,QAAQ,SACR,gBAEE,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KAAK,QAAQ,QAAQ,SAAS,qBAAqB;GAC5E,MAAM,OAAO,OAAO,eAAe,MAAM,QAAQ;GAEjD,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;EAC1F,CACF,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC,CACxD;CACF;CAEA,OAAO;EACL,GAAG,yBAA4D,iBAAiB,aAAa;EAC7F;EACA;EACA;EACA,4BAUE,YAEA,gCAAgC,SAAS,aAAa,CAAC,CAAC,KACtD,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,0BACE,YAEA,8BAA8B,SAAS,aAAa,CAAC,CAAC,KACpD,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,sCAUE,YAEA,0CAA0C,SAAS,aAAa,CAAC,CAAC,KAChE,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,gCAWE,YAEA,oCAAkD,SAAS,aAAa,CAAC,CAAC,KACxE,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF;CACF;AACF"}
1
+ {"version":3,"file":"oauth-drivers.mjs","names":[],"sources":["../../src/drizzle/oauth-drivers.ts"],"sourcesContent":["import { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport {\n OAuthAccountsPersistence,\n OAuthRegistrationIntents,\n OAuthSignInPersistence,\n} from \"@yielded/auth/OAuth\";\nimport type { Table } from \"drizzle-orm\";\nimport { type Crypto, Effect, Context } from \"effect\";\n\nimport { nativeDatabase } from \"./native-database\";\nimport { makeOAuthConnectedTarget } from \"./oauth-connected-drivers\";\nimport type {\n OAuthAccountsMapping,\n OAuthRegistrationAuthority,\n OAuthRegistrationIntentMapping,\n OAuthRegistrationMapping,\n OAuthSignInMapping,\n} from \"./oauth-model\";\nimport {\n type OAuthCoordinatorError,\n coordinateTargetOAuthAccounts,\n coordinateTargetOAuthSignIn,\n coordinateTargetOAuthRegistrationIntents,\n coordinateTargetOAuthRegistration,\n makeTargetOAuthRegistrationIntentServices,\n makeTargetOAuthRegistrationServices,\n makeTargetOAuthSignInServices,\n makeTargetOAuthAccountsServices,\n type OAuthTargetConfiguration,\n} from \"./oauth-target\";\nimport type { SuppliedService } from \"./SuppliedService\";\n\n// oxlint-disable-next-line no-explicit-any -- inspect the installed generic transaction signature without erasing its callback parameter.\ntype TransactionOf<D> = D extends { readonly transaction: (...args: any[]) => any }\n ? Parameters<Parameters<D[\"transaction\"]>[0]>[0]\n : never;\n\n/** Driver-specific entry points instantiate both the database and table family. */\nexport const makeOAuthTarget = <\n DatabaseId,\n D,\n T extends Table,\n Synchronous extends boolean = false,\n>(\n databaseService: Context.Service<DatabaseId, D>,\n configuration: OAuthTargetConfiguration,\n) => {\n function coordinateOAuthSignIn<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthSignInMapping<S, O, C, AC, F, N>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthSignInPersistence> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthSignInPersistence>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthSignIn<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthSignInMapping<S, O, C, AC, F, N>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthSignInPersistence | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthSignInPersistence | TxId>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthSignIn<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthSignInMapping<S, O, C, AC, F, N>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthSignInPersistence> | Crypto.Crypto | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthSignIn<\n TransactionOf<Database>,\n A,\n E,\n Exclude<R, OAuthSignInPersistence>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services: { readonly oauthSignInPersistence: OAuthSignInPersistence[\"Service\"] },\n ) => {\n const provided = Context.make(OAuthSignInPersistence, services.oauthSignInPersistence);\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthRegistrationIntents<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n I extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationIntentMapping<S, O, C, AC, F, TA, I, N>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthRegistrationIntents> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthRegistrationIntents>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthRegistrationIntents<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n I extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationIntentMapping<S, O, C, AC, F, TA, I, N>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthRegistrationIntents | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthRegistrationIntents | TxId>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthRegistrationIntents<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n I extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationIntentMapping<S, O, C, AC, F, TA, I, N>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthRegistrationIntents> | Crypto.Crypto | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthRegistrationIntents<\n TransactionOf<Database>,\n A,\n E,\n Exclude<R, OAuthRegistrationIntents>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services: { readonly oauthRegistrationIntents: OAuthRegistrationIntents[\"Service\"] },\n ) => {\n const provided = Context.make(\n OAuthRegistrationIntents,\n services.oauthRegistrationIntents,\n );\n\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthAccounts<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n U extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthAccountsMapping<S, O, C, AC, F, TA, U, N>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<OAuthAccountsPersistence> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthAccountsPersistence>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthAccounts<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n U extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthAccountsMapping<S, O, C, AC, F, TA, U, N>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<OAuthAccountsPersistence | TxId> : R\n >,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, OAuthAccountsPersistence | TxId>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthAccounts<\n Database extends D,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n U extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthAccountsMapping<S, O, C, AC, F, TA, U, N>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, OAuthAccountsPersistence> | Crypto.Crypto | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthAccounts<\n TransactionOf<Database>,\n A,\n E,\n Exclude<R, OAuthAccountsPersistence>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services: { readonly oauthAccountsPersistence: OAuthAccountsPersistence[\"Service\"] },\n ) => {\n const provided = Context.make(\n OAuthAccountsPersistence,\n services.oauthAccountsPersistence,\n );\n\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n function coordinateOAuthRegistration<\n Database extends D,\n TargetId,\n Registration,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n TA extends T,\n I extends T,\n Rq extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationMapping<NoInfer<Registration>, S, O, C, AC, TA, I, Rq, N>;\n readonly target: SuppliedService<TargetId, OAuthRegistrationAuthority<Registration>>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TargetId> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthRegistration<\n Database extends D,\n TargetId,\n Registration,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n TA extends T,\n I extends T,\n Rq extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationMapping<NoInfer<Registration>, S, O, C, AC, TA, I, Rq, N>;\n readonly target: SuppliedService<TargetId, OAuthRegistrationAuthority<Registration>>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TargetId | TxId> : R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId | TxId>)\n | Crypto.Crypto\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateOAuthRegistration<\n Database extends D,\n TargetId,\n Registration,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n TA extends T,\n I extends T,\n Rq extends T,\n N,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n TxId,\n TxShape,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: OAuthRegistrationMapping<NoInfer<Registration>, S, O, C, AC, TA, I, Rq, N>;\n readonly target: SuppliedService<TargetId, OAuthRegistrationAuthority<Registration>>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n OAuthCoordinatorError<E> | DatabaseError,\n Exclude<R, TargetId> | Crypto.Crypto | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetOAuthRegistration<\n Registration,\n TransactionOf<Database>,\n A,\n E,\n Exclude<R, TargetId>\n >(\n database,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services: { readonly registrationAuthority: OAuthRegistrationAuthority<Registration> },\n ) => {\n const provided = Context.make(options.target, services.registrationAuthority);\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n\n return {\n ...makeOAuthConnectedTarget<DatabaseId, D, T, {}, Synchronous>(databaseService, configuration),\n coordinateOAuthSignIn,\n coordinateOAuthRegistrationIntents,\n coordinateOAuthAccounts,\n makeOAuthAccountsServices: <\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n U extends T,\n N,\n >(\n mapping: OAuthAccountsMapping<S, O, C, AC, F, TA, U, N>,\n ) =>\n makeTargetOAuthAccountsServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeOAuthSignInServices: <S extends T, O extends T, C extends T, AC extends T, F extends T, N>(\n mapping: OAuthSignInMapping<S, O, C, AC, F, N>,\n ) =>\n makeTargetOAuthSignInServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeOAuthRegistrationIntentServices: <\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n F extends T,\n TA extends T,\n I extends T,\n N,\n >(\n mapping: OAuthRegistrationIntentMapping<S, O, C, AC, F, TA, I, N>,\n ) =>\n makeTargetOAuthRegistrationIntentServices(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeOAuthRegistrationServices: <\n Registration,\n S extends T,\n O extends T,\n C extends T,\n AC extends T,\n TA extends T,\n I extends T,\n R extends T,\n N,\n >(\n mapping: OAuthRegistrationMapping<Registration, S, O, C, AC, TA, I, R, N>,\n ) =>\n makeTargetOAuthRegistrationServices<Registration>(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateOAuthRegistration,\n };\n};\n"],"mappings":";;;;;;;;AAuCA,MAAa,mBAMX,iBACA,kBACG;CA+DH,SAAS,sBAgBP,SACA,SAIA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,4BAME,UACA,QAAQ,SACR,gBAEE,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KAAK,wBAAwB,SAAS,sBAAsB;GACrF,MAAM,OAAO,OAAO,eAAe,MAAM,QAAQ;GAEjD,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;EAC1F,CACF,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC,CACxD;CACF;CAmEA,SAAS,mCAkBP,SACA,SAIA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,yCAME,UACA,QAAQ,SACR,gBAEE,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KACvB,0BACA,SAAS,wBACX;GAEA,MAAM,OAAO,OAAO,eAAe,MAAM,QAAQ;GAEjD,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;EAC1F,CACF,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC,CACxD;CACF;CAmEA,SAAS,wBAkBP,SACA,SAIA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,8BAME,UACA,QAAQ,SACR,gBAEE,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KACvB,0BACA,SAAS,wBACX;GAEA,MAAM,OAAO,OAAO,eAAe,MAAM,QAAQ;GAEjD,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;EAC1F,CACF,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC,CACxD;CACF;CAqEA,SAAS,4BAoBP,SACA,SAKA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,kCAOE,UACA,QAAQ,SACR,gBAEE,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KAAK,QAAQ,QAAQ,SAAS,qBAAqB;GAC5E,MAAM,OAAO,OAAO,eAAe,MAAM,QAAQ;GAEjD,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;EAC1F,CACF,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC,CACxD;CACF;CAEA,OAAO;EACL,GAAG,yBAA4D,iBAAiB,aAAa;EAC7F;EACA;EACA;EACA,4BAUE,YAEA,gCAAgC,SAAS,aAAa,CAAC,CAAC,KACtD,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,0BACE,YAEA,8BAA8B,SAAS,aAAa,CAAC,CAAC,KACpD,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,sCAUE,YAEA,0CAA0C,SAAS,aAAa,CAAC,CAAC,KAChE,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,gCAWE,YAEA,oCAAkD,SAAS,aAAa,CAAC,CAAC,KACxE,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF;CACF;AACF"}
@@ -158,7 +158,7 @@ const currentSubject = (mapping, nativeId) => Effect.flatMap(CurrentOAuthTransac
158
158
  };
159
159
  }));
160
160
  const discoverOwned = (mapping, identity) => Effect.flatMap(CurrentOAuthTransaction, (owner) => Effect.gen(function* () {
161
- const key = oauthIdentityKey(identity), o = mapping.ownership;
161
+ const key = yield* oauthIdentityKey(identity), o = mapping.ownership;
162
162
  const where = both(eq(col(o.table, o.identityKey), key), o.ownedCondition);
163
163
  const row = (yield* owner.read(o.table, where, {
164
164
  lock: false,
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-flow.mjs","names":[],"sources":["../../src/drizzle/oauth-flow.ts"],"sourcesContent":["import {\n type OAuthLinkClaim,\n type OAuthClaim,\n OAuthCleanupInput,\n OAuthCredentialSnapshot,\n OAuthPendingFlow,\n OAuthModuleId,\n type OAuthVerifiedExternalIdentity,\n OAuthAccountRevision,\n OAuthLinkPendingFlow,\n snapshotOAuthSync,\n} from \"@yielded/auth/OAuth\";\n/* oxlint-disable no-explicit-any -- private kernel shared by concrete driver mappings. */\nimport { eq, sql } from \"drizzle-orm\";\nimport { Effect } from \"effect\";\n\nimport type { SubjectIdCodec } from \"./model\";\nimport { CurrentOAuthTransaction, type Row, both, col, copiedRow, equal } from \"./oauth-owner\";\nimport { invariant, oauthIdentityKey, storage } from \"./oauth-state\";\n\nexport const pendingStorage = storage(OAuthPendingFlow);\nexport const linkStorage = storage(OAuthLinkPendingFlow);\nexport const credentialStorage = storage(OAuthCredentialSnapshot);\nexport const revisionStorage = storage(OAuthAccountRevision);\nexport type Flow = typeof OAuthPendingFlow.Type | typeof OAuthLinkPendingFlow.Type;\nexport type Claim = typeof OAuthClaim.Type | typeof OAuthLinkClaim.Type;\n\nexport const flowKey = (mapping: any, context: Flow[\"context\"]) => ({\n [mapping.moduleId]: context.moduleId,\n [mapping.flowId]: context.flowId,\n});\n\nexport const flowStorage = (purpose: \"sign-in\" | \"link\") =>\n purpose === \"link\" ? linkStorage : pendingStorage;\n\nconst instant = (mapping: any, value: unknown): number => {\n const millis = mapping.clock.decodeInstant(value);\n\n invariant(Number.isSafeInteger(millis) && millis >= 0);\n\n return millis;\n};\n\nexport const readFlow = (\n mapping: any,\n input: { readonly moduleId: string; readonly flowId: string },\n purpose: \"sign-in\" | \"link\",\n) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const f = mapping.flow;\n\n const observation = yield* owner.read(\n f.table,\n equal(f.table, {\n [f.moduleId]: input.moduleId,\n [f.flowId]: input.flowId,\n }),\n { limit: 1 },\n );\n\n const row = observation.rows[0];\n\n if (row === undefined || row[f.purpose] !== purpose || row[f.snapshot] === null)\n return { observation };\n const flow = flowStorage(purpose).decode(row[f.snapshot]) as Flow;\n const c = flow.context;\n\n invariant(\n row[f.moduleId] === c.moduleId &&\n row[f.flowId] === c.flowId &&\n row[f.commandId] === c.commandId &&\n row[f.generation] === c.generation &&\n row[f.stateDigest] === c.stateDigest &&\n row[f.binderVerifier] === c.requestBindingVerifier &&\n instant(mapping, row[f.binderExpiresAt]) === c.requestBindingExpiresAtMillis &&\n instant(mapping, row[f.issuedAt]) === c.issuedAtMillis &&\n instant(mapping, row[f.expiresAt]) === c.expiresAtMillis &&\n instant(mapping, row[f.retentionUntil]) === flow.retentionUntilMillis,\n );\n\n return { observation, row, flow };\n }),\n );\n\nexport const liveFlow = (flow: Flow, now: number) =>\n flow.context.issuedAtMillis <= now &&\n now < flow.context.expiresAtMillis &&\n flow.context.expiresAtMillis <= flow.context.requestBindingExpiresAtMillis &&\n flow.retentionUntilMillis >= flow.context.expiresAtMillis + flow.context.claimLifetimeMillis;\n\nexport const issueFlow = (mapping: any, original: Flow, purpose: \"sign-in\" | \"link\") =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const codec = flowStorage(purpose);\n const flow = codec.decode(codec.encode(original as never)) as Flow;\n\n const f = mapping.flow,\n c = flow.context,\n now = yield* owner.now(mapping.clock);\n\n if (!liveFlow(flow, now)) return { _tag: \"Rejected\" } as const;\n const byFlow = yield* owner.read(f.table, equal(f.table, flowKey(f, c)), { limit: 1 });\n\n const byCommand = yield* owner.read(\n f.table,\n equal(f.table, {\n [f.moduleId]: c.moduleId,\n [f.commandId]: c.commandId,\n }),\n { limit: 1 },\n );\n\n if (byFlow.rows.length || byCommand.rows.length) return { _tag: \"Rejected\" } as const;\n const encode = mapping.clock.encodeInstant;\n\n const values = {\n ...f.encodeInsert({ moduleId: c.moduleId, flowId: c.flowId, purpose }),\n ...flowKey(f, c),\n [f.commandId]: c.commandId,\n [f.purpose]: purpose,\n [f.generation]: c.generation,\n [f.state]: \"Pending\",\n [f.version]: owner.marker,\n [f.stateDigest]: c.stateDigest,\n [f.binderVerifier]: c.requestBindingVerifier,\n [f.binderExpiresAt]: encode(c.requestBindingExpiresAtMillis),\n [f.snapshot]: codec.encode(flow as never),\n [f.issuedAt]: encode(c.issuedAtMillis),\n [f.expiresAt]: encode(c.expiresAtMillis),\n [f.claimId]: null,\n [f.claimedAt]: null,\n [f.claimExpiresAt]: null,\n [f.retentionUntil]: encode(flow.retentionUntilMillis),\n };\n\n const inserted = yield* owner.insert(f.table, values, flowKey(f, c), true);\n\n byFlow.rows = inserted.rows;\n byCommand.rows = inserted.rows;\n if (inserted.rows[0]?.[f.version] !== owner.marker) return { _tag: \"Rejected\" } as const;\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${c.issuedAtMillis}\n and ${mapping.clock.engineNowMillis} < ${c.expiresAtMillis}`);\n\n return { _tag: \"Issued\", flow } as const;\n }),\n );\n\nexport const matchesAccess = (flow: Flow, input: any) => {\n const c = flow.context;\n\n return (\n c.moduleId === input.moduleId &&\n c.generation === input.generation &&\n c.flowId === input.flowId &&\n c.provider === input.provider &&\n c.callbackId === input.callbackId &&\n c.stateDigest === input.stateDigest &&\n c.requestBindingVerifier === input.requestBindingVerifier &&\n c.requestBindingExpiresAtMillis === input.requestBindingExpiresAtMillis &&\n (c.responseIssuerMode === \"required\"\n ? input.responseIssuer === c.issuer\n : input.responseIssuer === undefined)\n );\n};\n\nexport const claimFlow = (mapping: any, inspected: { row: Row; flow: Flow }, claimId: string) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const now = yield* owner.now(mapping.clock),\n flow = inspected.flow,\n c = flow.context;\n\n if (inspected.row[mapping.flow.state] !== \"Pending\" || !liveFlow(flow, now)) return undefined;\n\n const claim = {\n flow,\n claimId,\n claimedAtMillis: now,\n claimExpiresAtMillis: now + c.claimLifetimeMillis,\n };\n\n invariant(\n Number.isSafeInteger(claim.claimExpiresAtMillis) &&\n claim.claimExpiresAtMillis <= flow.retentionUntilMillis,\n );\n\n const f = mapping.flow,\n encode = mapping.clock.encodeInstant;\n\n yield* owner.update(f.table, flowKey(f, c), {\n [f.state]: \"Claimed\",\n [f.version]: owner.marker,\n [f.claimId]: claimId,\n [f.claimedAt]: encode(now),\n [f.claimExpiresAt]: encode(claim.claimExpiresAtMillis),\n });\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${now} and\n ${mapping.clock.engineNowMillis} < ${Math.min(c.expiresAtMillis, claim.claimExpiresAtMillis)}`);\n\n return claim;\n }),\n );\n\nexport const exactClaim = (mapping: any, claim: Claim, purpose: \"sign-in\" | \"link\") =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const read = yield* readFlow(mapping, claim.flow.context, purpose);\n\n const now = yield* owner.now(mapping.clock),\n f = mapping.flow,\n row = read.row;\n\n if (\n row === undefined ||\n read.flow === undefined ||\n row[f.state] !== \"Claimed\" ||\n row[f.claimId] !== claim.claimId ||\n instant(mapping, row[f.claimedAt]) !== claim.claimedAtMillis ||\n instant(mapping, row[f.claimExpiresAt]) !== claim.claimExpiresAtMillis ||\n claim.claimExpiresAtMillis !==\n claim.claimedAtMillis + claim.flow.context.claimLifetimeMillis ||\n now < claim.claimedAtMillis ||\n now >= claim.claimExpiresAtMillis ||\n flowStorage(purpose).encode(read.flow as never) !==\n flowStorage(purpose).encode(claim.flow as never)\n )\n return undefined;\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${claim.claimedAtMillis} and\n ${mapping.clock.engineNowMillis} < ${claim.claimExpiresAtMillis}`);\n\n return { ...read, now };\n }),\n );\n\nexport const terminalFlow = (mapping: any, flow: Flow, state: string) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n owner.update(mapping.flow.table, flowKey(mapping.flow, flow.context), {\n [mapping.flow.state]: state,\n [mapping.flow.version]: owner.marker,\n [mapping.flow.snapshot]: null,\n }),\n );\n\n/** Subject precedes credentials; the complete active credential vector is retained. */\nexport const currentSubject = (mapping: any, nativeId: unknown) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const s = mapping.subject,\n a = mapping.authority;\n\n const subject = yield* owner.read(s.table, eq(col(s.table, s.id), nativeId), { limit: 1 });\n const row = subject.rows[0];\n const subjectActive = sql`exists(select 1 from ${s.table} where ${both(eq(col(s.table, s.id), nativeId), s.activeCondition)})`;\n\n if (\n row === undefined ||\n !s.isActiveStatus(row[s.status]) ||\n !(yield* owner.check(subjectActive))\n )\n return undefined;\n owner.postconditions.push(subjectActive);\n\n const authorities = yield* owner.read(a.table, eq(col(a.table, a.subjectId), nativeId), {\n orderBy: col(a.table, a.credentialId),\n });\n\n const active = authorities.rows.filter((item) => a.isActiveStatus(item[a.status]));\n\n const activeGuard = sql`(select count(*) from ${a.table} where ${both(\n eq(col(a.table, a.subjectId), nativeId),\n a.activeCondition,\n )}) = ${active.length}`;\n\n invariant(yield* owner.check(activeGuard));\n owner.postconditions.push(\n () => sql`(select count(*) from ${a.table} where ${both(\n eq(col(a.table, a.subjectId), nativeId),\n a.activeCondition,\n )}) =\n ${authorities.rows.filter((item) => a.isActiveStatus(item[a.status])).length}`,\n );\n\n const credentials = active\n .map((item) => ({ credentialId: item[a.credentialId], revision: item[a.revision] }))\n .sort((left, right) => left.credentialId.localeCompare(right.credentialId));\n\n invariant(new Set(credentials.map((item) => item.credentialId)).size === credentials.length);\n const subjectId = yield* (mapping.subjectId as SubjectIdCodec<unknown>).toSubject(nativeId);\n\n const revision = snapshotOAuthSync(OAuthAccountRevision, {\n subjectId,\n securityRevision: row[s.securityRevision],\n credentials,\n });\n\n return { subject, row, authorities, revision, nativeId };\n }),\n );\n\nexport const discoverOwned = (mapping: any, identity: OAuthVerifiedExternalIdentity[\"identity\"]) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const key = oauthIdentityKey(identity),\n o = mapping.ownership;\n\n const where = both(eq(col(o.table, o.identityKey), key), o.ownedCondition);\n\n const discovered = yield* owner.read(o.table, where, {\n lock: false,\n observe: false,\n limit: 1,\n });\n\n const row = discovered.rows[0];\n\n if (row === undefined) return { key };\n invariant(\n row[o.provider] === identity.provider &&\n row[o.issuer] === identity.issuer &&\n row[o.externalSubject] === identity.subject,\n );\n const nativeId = o.decodeSubjectId(copiedRow(row));\n const current = yield* currentSubject(mapping, nativeId);\n const owned = yield* owner.read(o.table, where, { limit: 1 });\n const final = owned.rows[0];\n\n if (\n current === undefined ||\n final === undefined ||\n !mapping.subjectId.equals(nativeId, o.decodeSubjectId(copiedRow(final)))\n )\n return { key, owned: true as const };\n invariant(\n final[o.provider] === identity.provider &&\n final[o.issuer] === identity.issuer &&\n final[o.externalSubject] === identity.subject,\n );\n const c = mapping.credential;\n\n const credential = yield* owner.read(c.table, eq(col(c.table, c.identityKey), key), {\n limit: 1,\n });\n\n let login: Row | undefined = credential.rows[0];\n\n if (login !== undefined && c.isActiveStatus(login[c.status])) {\n const usable = sql`exists(select 1 from ${c.table} where ${both(\n eq(col(c.table, c.identityKey), key),\n c.activeCondition,\n )})`;\n\n if (yield* owner.check(usable)) owner.postconditions.push(usable);\n else login = undefined;\n }\n\n return { key, owned: true as const, current, credential, login };\n }),\n );\n\nexport const resolveOwned = (\n mapping: any,\n moduleId: string,\n identity: OAuthVerifiedExternalIdentity[\"identity\"],\n found: any,\n) => {\n const login = found.login,\n current = found.current,\n c = mapping.credential;\n\n if (\n login === undefined ||\n current === undefined ||\n login[c.moduleId] !== moduleId ||\n !mapping.subjectId.equals(login[c.subjectId], current.nativeId) ||\n !c.isActiveStatus(login[c.status])\n )\n return undefined;\n\n const shared = current.revision.credentials.find(\n (item: any) => item.credentialId === login[c.credentialId],\n );\n\n if (shared?.revision !== login[c.credentialRevision]) return undefined;\n\n return snapshotOAuthSync(OAuthCredentialSnapshot, {\n moduleId: OAuthModuleId.make(moduleId),\n identity,\n credentialId: login[c.credentialId],\n credentialRevision: login[c.credentialRevision],\n revision: current.revision,\n });\n};\n\nexport const cleanupFlows = (\n mapping: any,\n original: typeof OAuthCleanupInput.Type,\n purpose: \"sign-in\" | \"link\",\n) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const input = snapshotOAuthSync(OAuthCleanupInput, original),\n f = mapping.flow;\n\n const now = yield* owner.now(mapping.clock);\n\n const candidates = yield* owner.read(\n f.table,\n both(\n eq(col(f.table, f.moduleId), input.moduleId),\n eq(col(f.table, f.purpose), purpose),\n sql`((${col(f.table, f.state)} = 'Pending' and ${col(f.table, f.expiresAt)} <= ${mapping.clock.encodeInstant(now)})\n or (${col(f.table, f.state)} = 'Claimed' and ${col(f.table, f.claimExpiresAt)} <= ${mapping.clock.encodeInstant(now)})\n or (${col(f.table, f.state)} not in ('Pending','Claimed') and ${col(f.table, f.retentionUntil)} < ${mapping.clock.encodeInstant(now)}))`,\n ),\n { limit: input.limit, observe: false, takeOnly: true },\n );\n\n let terminalized = 0,\n removed = 0;\n\n for (const candidate of candidates.rows) {\n const key = { [f.moduleId]: candidate[f.moduleId], [f.flowId]: candidate[f.flowId] };\n const current = yield* owner.read(f.table, equal(f.table, key), { limit: 1 });\n\n if (current.rows.length !== 1) continue;\n\n const row = current.rows[0]!,\n transitionNow = yield* owner.now(mapping.clock);\n\n const state = row[f.state];\n\n if (state === \"Pending\" || state === \"Claimed\") {\n const deadline = instant(\n mapping,\n row[state === \"Pending\" ? f.expiresAt : f.claimExpiresAt],\n );\n\n if (transitionNow < deadline) continue;\n yield* owner.update(f.table, key, {\n [f.state]: state === \"Pending\" ? \"Rejected\" : \"Ambiguous\",\n [f.snapshot]: null,\n [f.version]: owner.marker,\n });\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${deadline}`);\n terminalized++;\n } else {\n const retainUntil = Math.max(\n instant(mapping, row[f.retentionUntil]),\n row[f.claimExpiresAt] === null ? 0 : instant(mapping, row[f.claimExpiresAt]),\n );\n\n if (transitionNow <= retainUntil) continue;\n yield* owner.remove(f.table, key);\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} > ${retainUntil}`);\n removed++;\n }\n }\n\n return { terminalized, removed, hasMore: candidates.rows.length === input.limit };\n }),\n );\n"],"mappings":"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"}
1
+ {"version":3,"file":"oauth-flow.mjs","names":[],"sources":["../../src/drizzle/oauth-flow.ts"],"sourcesContent":["import {\n type OAuthLinkClaim,\n type OAuthClaim,\n OAuthCleanupInput,\n OAuthCredentialSnapshot,\n OAuthPendingFlow,\n OAuthModuleId,\n type OAuthVerifiedExternalIdentity,\n OAuthAccountRevision,\n OAuthLinkPendingFlow,\n snapshotOAuthSync,\n} from \"@yielded/auth/OAuth\";\n/* oxlint-disable no-explicit-any -- private kernel shared by concrete driver mappings. */\nimport { eq, sql } from \"drizzle-orm\";\nimport { Effect } from \"effect\";\n\nimport type { SubjectIdCodec } from \"./model\";\nimport { CurrentOAuthTransaction, type Row, both, col, copiedRow, equal } from \"./oauth-owner\";\nimport { invariant, oauthIdentityKey, storage } from \"./oauth-state\";\n\nexport const pendingStorage = storage(OAuthPendingFlow);\nexport const linkStorage = storage(OAuthLinkPendingFlow);\nexport const credentialStorage = storage(OAuthCredentialSnapshot);\nexport const revisionStorage = storage(OAuthAccountRevision);\nexport type Flow = typeof OAuthPendingFlow.Type | typeof OAuthLinkPendingFlow.Type;\nexport type Claim = typeof OAuthClaim.Type | typeof OAuthLinkClaim.Type;\n\nexport const flowKey = (mapping: any, context: Flow[\"context\"]) => ({\n [mapping.moduleId]: context.moduleId,\n [mapping.flowId]: context.flowId,\n});\n\nexport const flowStorage = (purpose: \"sign-in\" | \"link\") =>\n purpose === \"link\" ? linkStorage : pendingStorage;\n\nconst instant = (mapping: any, value: unknown): number => {\n const millis = mapping.clock.decodeInstant(value);\n\n invariant(Number.isSafeInteger(millis) && millis >= 0);\n\n return millis;\n};\n\nexport const readFlow = (\n mapping: any,\n input: { readonly moduleId: string; readonly flowId: string },\n purpose: \"sign-in\" | \"link\",\n) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const f = mapping.flow;\n\n const observation = yield* owner.read(\n f.table,\n equal(f.table, {\n [f.moduleId]: input.moduleId,\n [f.flowId]: input.flowId,\n }),\n { limit: 1 },\n );\n\n const row = observation.rows[0];\n\n if (row === undefined || row[f.purpose] !== purpose || row[f.snapshot] === null)\n return { observation };\n const flow = flowStorage(purpose).decode(row[f.snapshot]) as Flow;\n const c = flow.context;\n\n invariant(\n row[f.moduleId] === c.moduleId &&\n row[f.flowId] === c.flowId &&\n row[f.commandId] === c.commandId &&\n row[f.generation] === c.generation &&\n row[f.stateDigest] === c.stateDigest &&\n row[f.binderVerifier] === c.requestBindingVerifier &&\n instant(mapping, row[f.binderExpiresAt]) === c.requestBindingExpiresAtMillis &&\n instant(mapping, row[f.issuedAt]) === c.issuedAtMillis &&\n instant(mapping, row[f.expiresAt]) === c.expiresAtMillis &&\n instant(mapping, row[f.retentionUntil]) === flow.retentionUntilMillis,\n );\n\n return { observation, row, flow };\n }),\n );\n\nexport const liveFlow = (flow: Flow, now: number) =>\n flow.context.issuedAtMillis <= now &&\n now < flow.context.expiresAtMillis &&\n flow.context.expiresAtMillis <= flow.context.requestBindingExpiresAtMillis &&\n flow.retentionUntilMillis >= flow.context.expiresAtMillis + flow.context.claimLifetimeMillis;\n\nexport const issueFlow = (mapping: any, original: Flow, purpose: \"sign-in\" | \"link\") =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const codec = flowStorage(purpose);\n const flow = codec.decode(codec.encode(original as never)) as Flow;\n\n const f = mapping.flow,\n c = flow.context,\n now = yield* owner.now(mapping.clock);\n\n if (!liveFlow(flow, now)) return { _tag: \"Rejected\" } as const;\n const byFlow = yield* owner.read(f.table, equal(f.table, flowKey(f, c)), { limit: 1 });\n\n const byCommand = yield* owner.read(\n f.table,\n equal(f.table, {\n [f.moduleId]: c.moduleId,\n [f.commandId]: c.commandId,\n }),\n { limit: 1 },\n );\n\n if (byFlow.rows.length || byCommand.rows.length) return { _tag: \"Rejected\" } as const;\n const encode = mapping.clock.encodeInstant;\n\n const values = {\n ...f.encodeInsert({ moduleId: c.moduleId, flowId: c.flowId, purpose }),\n ...flowKey(f, c),\n [f.commandId]: c.commandId,\n [f.purpose]: purpose,\n [f.generation]: c.generation,\n [f.state]: \"Pending\",\n [f.version]: owner.marker,\n [f.stateDigest]: c.stateDigest,\n [f.binderVerifier]: c.requestBindingVerifier,\n [f.binderExpiresAt]: encode(c.requestBindingExpiresAtMillis),\n [f.snapshot]: codec.encode(flow as never),\n [f.issuedAt]: encode(c.issuedAtMillis),\n [f.expiresAt]: encode(c.expiresAtMillis),\n [f.claimId]: null,\n [f.claimedAt]: null,\n [f.claimExpiresAt]: null,\n [f.retentionUntil]: encode(flow.retentionUntilMillis),\n };\n\n const inserted = yield* owner.insert(f.table, values, flowKey(f, c), true);\n\n byFlow.rows = inserted.rows;\n byCommand.rows = inserted.rows;\n if (inserted.rows[0]?.[f.version] !== owner.marker) return { _tag: \"Rejected\" } as const;\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${c.issuedAtMillis}\n and ${mapping.clock.engineNowMillis} < ${c.expiresAtMillis}`);\n\n return { _tag: \"Issued\", flow } as const;\n }),\n );\n\nexport const matchesAccess = (flow: Flow, input: any) => {\n const c = flow.context;\n\n return (\n c.moduleId === input.moduleId &&\n c.generation === input.generation &&\n c.flowId === input.flowId &&\n c.provider === input.provider &&\n c.callbackId === input.callbackId &&\n c.stateDigest === input.stateDigest &&\n c.requestBindingVerifier === input.requestBindingVerifier &&\n c.requestBindingExpiresAtMillis === input.requestBindingExpiresAtMillis &&\n (c.responseIssuerMode === \"required\"\n ? input.responseIssuer === c.issuer\n : input.responseIssuer === undefined)\n );\n};\n\nexport const claimFlow = (mapping: any, inspected: { row: Row; flow: Flow }, claimId: string) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const now = yield* owner.now(mapping.clock),\n flow = inspected.flow,\n c = flow.context;\n\n if (inspected.row[mapping.flow.state] !== \"Pending\" || !liveFlow(flow, now)) return undefined;\n\n const claim = {\n flow,\n claimId,\n claimedAtMillis: now,\n claimExpiresAtMillis: now + c.claimLifetimeMillis,\n };\n\n invariant(\n Number.isSafeInteger(claim.claimExpiresAtMillis) &&\n claim.claimExpiresAtMillis <= flow.retentionUntilMillis,\n );\n\n const f = mapping.flow,\n encode = mapping.clock.encodeInstant;\n\n yield* owner.update(f.table, flowKey(f, c), {\n [f.state]: \"Claimed\",\n [f.version]: owner.marker,\n [f.claimId]: claimId,\n [f.claimedAt]: encode(now),\n [f.claimExpiresAt]: encode(claim.claimExpiresAtMillis),\n });\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${now} and\n ${mapping.clock.engineNowMillis} < ${Math.min(c.expiresAtMillis, claim.claimExpiresAtMillis)}`);\n\n return claim;\n }),\n );\n\nexport const exactClaim = (mapping: any, claim: Claim, purpose: \"sign-in\" | \"link\") =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const read = yield* readFlow(mapping, claim.flow.context, purpose);\n\n const now = yield* owner.now(mapping.clock),\n f = mapping.flow,\n row = read.row;\n\n if (\n row === undefined ||\n read.flow === undefined ||\n row[f.state] !== \"Claimed\" ||\n row[f.claimId] !== claim.claimId ||\n instant(mapping, row[f.claimedAt]) !== claim.claimedAtMillis ||\n instant(mapping, row[f.claimExpiresAt]) !== claim.claimExpiresAtMillis ||\n claim.claimExpiresAtMillis !==\n claim.claimedAtMillis + claim.flow.context.claimLifetimeMillis ||\n now < claim.claimedAtMillis ||\n now >= claim.claimExpiresAtMillis ||\n flowStorage(purpose).encode(read.flow as never) !==\n flowStorage(purpose).encode(claim.flow as never)\n )\n return undefined;\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${claim.claimedAtMillis} and\n ${mapping.clock.engineNowMillis} < ${claim.claimExpiresAtMillis}`);\n\n return { ...read, now };\n }),\n );\n\nexport const terminalFlow = (mapping: any, flow: Flow, state: string) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n owner.update(mapping.flow.table, flowKey(mapping.flow, flow.context), {\n [mapping.flow.state]: state,\n [mapping.flow.version]: owner.marker,\n [mapping.flow.snapshot]: null,\n }),\n );\n\n/** Subject precedes credentials; the complete active credential vector is retained. */\nexport const currentSubject = (mapping: any, nativeId: unknown) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const s = mapping.subject,\n a = mapping.authority;\n\n const subject = yield* owner.read(s.table, eq(col(s.table, s.id), nativeId), { limit: 1 });\n const row = subject.rows[0];\n const subjectActive = sql`exists(select 1 from ${s.table} where ${both(eq(col(s.table, s.id), nativeId), s.activeCondition)})`;\n\n if (\n row === undefined ||\n !s.isActiveStatus(row[s.status]) ||\n !(yield* owner.check(subjectActive))\n )\n return undefined;\n owner.postconditions.push(subjectActive);\n\n const authorities = yield* owner.read(a.table, eq(col(a.table, a.subjectId), nativeId), {\n orderBy: col(a.table, a.credentialId),\n });\n\n const active = authorities.rows.filter((item) => a.isActiveStatus(item[a.status]));\n\n const activeGuard = sql`(select count(*) from ${a.table} where ${both(\n eq(col(a.table, a.subjectId), nativeId),\n a.activeCondition,\n )}) = ${active.length}`;\n\n invariant(yield* owner.check(activeGuard));\n owner.postconditions.push(\n () => sql`(select count(*) from ${a.table} where ${both(\n eq(col(a.table, a.subjectId), nativeId),\n a.activeCondition,\n )}) =\n ${authorities.rows.filter((item) => a.isActiveStatus(item[a.status])).length}`,\n );\n\n const credentials = active\n .map((item) => ({ credentialId: item[a.credentialId], revision: item[a.revision] }))\n .sort((left, right) => left.credentialId.localeCompare(right.credentialId));\n\n invariant(new Set(credentials.map((item) => item.credentialId)).size === credentials.length);\n const subjectId = yield* (mapping.subjectId as SubjectIdCodec<unknown>).toSubject(nativeId);\n\n const revision = snapshotOAuthSync(OAuthAccountRevision, {\n subjectId,\n securityRevision: row[s.securityRevision],\n credentials,\n });\n\n return { subject, row, authorities, revision, nativeId };\n }),\n );\n\nexport const discoverOwned = (mapping: any, identity: OAuthVerifiedExternalIdentity[\"identity\"]) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const key = yield* oauthIdentityKey(identity),\n o = mapping.ownership;\n\n const where = both(eq(col(o.table, o.identityKey), key), o.ownedCondition);\n\n const discovered = yield* owner.read(o.table, where, {\n lock: false,\n observe: false,\n limit: 1,\n });\n\n const row = discovered.rows[0];\n\n if (row === undefined) return { key };\n invariant(\n row[o.provider] === identity.provider &&\n row[o.issuer] === identity.issuer &&\n row[o.externalSubject] === identity.subject,\n );\n const nativeId = o.decodeSubjectId(copiedRow(row));\n const current = yield* currentSubject(mapping, nativeId);\n const owned = yield* owner.read(o.table, where, { limit: 1 });\n const final = owned.rows[0];\n\n if (\n current === undefined ||\n final === undefined ||\n !mapping.subjectId.equals(nativeId, o.decodeSubjectId(copiedRow(final)))\n )\n return { key, owned: true as const };\n invariant(\n final[o.provider] === identity.provider &&\n final[o.issuer] === identity.issuer &&\n final[o.externalSubject] === identity.subject,\n );\n const c = mapping.credential;\n\n const credential = yield* owner.read(c.table, eq(col(c.table, c.identityKey), key), {\n limit: 1,\n });\n\n let login: Row | undefined = credential.rows[0];\n\n if (login !== undefined && c.isActiveStatus(login[c.status])) {\n const usable = sql`exists(select 1 from ${c.table} where ${both(\n eq(col(c.table, c.identityKey), key),\n c.activeCondition,\n )})`;\n\n if (yield* owner.check(usable)) owner.postconditions.push(usable);\n else login = undefined;\n }\n\n return { key, owned: true as const, current, credential, login };\n }),\n );\n\nexport const resolveOwned = (\n mapping: any,\n moduleId: string,\n identity: OAuthVerifiedExternalIdentity[\"identity\"],\n found: any,\n) => {\n const login = found.login,\n current = found.current,\n c = mapping.credential;\n\n if (\n login === undefined ||\n current === undefined ||\n login[c.moduleId] !== moduleId ||\n !mapping.subjectId.equals(login[c.subjectId], current.nativeId) ||\n !c.isActiveStatus(login[c.status])\n )\n return undefined;\n\n const shared = current.revision.credentials.find(\n (item: any) => item.credentialId === login[c.credentialId],\n );\n\n if (shared?.revision !== login[c.credentialRevision]) return undefined;\n\n return snapshotOAuthSync(OAuthCredentialSnapshot, {\n moduleId: OAuthModuleId.make(moduleId),\n identity,\n credentialId: login[c.credentialId],\n credentialRevision: login[c.credentialRevision],\n revision: current.revision,\n });\n};\n\nexport const cleanupFlows = (\n mapping: any,\n original: typeof OAuthCleanupInput.Type,\n purpose: \"sign-in\" | \"link\",\n) =>\n Effect.flatMap(CurrentOAuthTransaction, (owner) =>\n Effect.gen(function* () {\n const input = snapshotOAuthSync(OAuthCleanupInput, original),\n f = mapping.flow;\n\n const now = yield* owner.now(mapping.clock);\n\n const candidates = yield* owner.read(\n f.table,\n both(\n eq(col(f.table, f.moduleId), input.moduleId),\n eq(col(f.table, f.purpose), purpose),\n sql`((${col(f.table, f.state)} = 'Pending' and ${col(f.table, f.expiresAt)} <= ${mapping.clock.encodeInstant(now)})\n or (${col(f.table, f.state)} = 'Claimed' and ${col(f.table, f.claimExpiresAt)} <= ${mapping.clock.encodeInstant(now)})\n or (${col(f.table, f.state)} not in ('Pending','Claimed') and ${col(f.table, f.retentionUntil)} < ${mapping.clock.encodeInstant(now)}))`,\n ),\n { limit: input.limit, observe: false, takeOnly: true },\n );\n\n let terminalized = 0,\n removed = 0;\n\n for (const candidate of candidates.rows) {\n const key = { [f.moduleId]: candidate[f.moduleId], [f.flowId]: candidate[f.flowId] };\n const current = yield* owner.read(f.table, equal(f.table, key), { limit: 1 });\n\n if (current.rows.length !== 1) continue;\n\n const row = current.rows[0]!,\n transitionNow = yield* owner.now(mapping.clock);\n\n const state = row[f.state];\n\n if (state === \"Pending\" || state === \"Claimed\") {\n const deadline = instant(\n mapping,\n row[state === \"Pending\" ? f.expiresAt : f.claimExpiresAt],\n );\n\n if (transitionNow < deadline) continue;\n yield* owner.update(f.table, key, {\n [f.state]: state === \"Pending\" ? \"Rejected\" : \"Ambiguous\",\n [f.snapshot]: null,\n [f.version]: owner.marker,\n });\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} >= ${deadline}`);\n terminalized++;\n } else {\n const retainUntil = Math.max(\n instant(mapping, row[f.retentionUntil]),\n row[f.claimExpiresAt] === null ? 0 : instant(mapping, row[f.claimExpiresAt]),\n );\n\n if (transitionNow <= retainUntil) continue;\n yield* owner.remove(f.table, key);\n owner.postconditions.push(sql`${mapping.clock.engineNowMillis} > ${retainUntil}`);\n removed++;\n }\n }\n\n return { terminalized, removed, hasMore: candidates.rows.length === input.limit };\n }),\n );\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { PersistenceMappingError, SubjectIdCodec } from "./model.mjs";
2
2
  import { InferInsertModel, InferSelectModel, SQL, Table } from "drizzle-orm";
3
- import { Effect } from "effect";
3
+ import { Crypto, Effect, PlatformError } from "effect";
4
4
  import { AuthenticationRequirement, SecurityRevision } from "@yielded/auth/Sessions";
5
5
  import { OAuthAccountRevision, OAuthActionAuthorization, OAuthCredentialSnapshot, OAuthExternalIdentity, OAuthRegistrationIntent } from "@yielded/auth/OAuth";
6
6
  import { AuthenticationFactor } from "@yielded/auth/Operations";
@@ -392,8 +392,8 @@ export interface OAuthCleanupDescriptor<N> {
392
392
  }
393
393
  export declare const oauthCleanupTable: <T extends Table, N>(input: OAuthCleanupTable<T, N>) => OAuthCleanupDescriptor<N>;
394
394
  /** A stable application/reference lock acquired before an ownership target.
395
- * Missing rows retain ownership. Conditions are synchronous and use detached
396
- * native IDs; every writer of the guarded reference follows the same order. */
395
+ * Missing rows retain ownership. Conditions use detached native IDs; every
396
+ * writer of the guarded reference follows the same order. */
397
397
  export interface OAuthReferenceGuardTable<T extends Table, N> {
398
398
  readonly table: T;
399
399
  readonly orderBy: Column<T>;
@@ -401,7 +401,7 @@ export interface OAuthReferenceGuardTable<T extends Table, N> {
401
401
  readonly identity: typeof OAuthExternalIdentity.Type;
402
402
  readonly identityKey: string;
403
403
  readonly subjectId: N;
404
- }) => SQL;
404
+ }) => SQL | Effect.Effect<SQL, PlatformError.PlatformError, Crypto.Crypto>;
405
405
  }
406
406
  export interface OAuthReferenceGuardDescriptor<N> {
407
407
  readonly table: Table;
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-model.mjs","names":[],"sources":["../../src/drizzle/oauth-model.ts"],"sourcesContent":["import type {\n OAuthActionAuthorization,\n OAuthAccountRevision,\n OAuthRegistrationIntent,\n OAuthCredentialSnapshot,\n OAuthExternalIdentity,\n} from \"@yielded/auth/OAuth\";\nimport type { AuthenticationFactor } from \"@yielded/auth/Operations\";\nimport type { AuthenticationRequirement, SecurityRevision } from \"@yielded/auth/Sessions\";\nimport type { InferInsertModel, InferSelectModel, SQL, Table } from \"drizzle-orm\";\nimport type { Effect } from \"effect\";\n\nimport type { PersistenceMappingError, SubjectIdCodec } from \"./model\";\n\ntype Column<T extends Table> = Extract<keyof T[\"_\"][\"columns\"], string>;\n\nexport type OAuthFlowState =\n | \"Pending\"\n | \"Claimed\"\n | \"Verified\"\n | \"RegistrationIssued\"\n | \"Linked\"\n | \"Cancelled\"\n | \"Rejected\"\n | \"Ambiguous\"\n | \"Conflict\";\n\nexport type OAuthTupleState = \"Unowned\" | \"Reserved\" | \"Owned\";\nexport type OAuthRegistrationState = \"Unbound\" | \"Registered\" | \"ProvisioningPending\" | \"Rejected\";\nexport type OAuthAction = OAuthActionAuthorization[\"challenge\"][\"action\"];\n\n/** The engine writes every critical column explicitly after applying the pure\n * consumer encoder. Native instant values must roundtrip without precision loss. */\nexport interface OAuthClock {\n readonly encodeInstant: (millis: number) => unknown;\n readonly decodeInstant: (value: unknown) => number;\n /** Actual engine wall clock sampled after locks, not transaction-start time.\n * PostgreSQL uses clock_timestamp(), never now()/CURRENT_TIMESTAMP. D1 repeats\n * its primary-engine sample bounds in final guards. Return integer milliseconds. */\n readonly engineNowMillis: SQL;\n}\n\nexport interface OAuthSubjectReadTable<S extends Table> {\n readonly table: S;\n readonly id: Column<S>;\n readonly status: Column<S>;\n readonly securityRevision: Column<S>;\n readonly isActiveStatus: (value: unknown) => boolean;\n readonly activeCondition: SQL;\n}\n\nexport interface OAuthSubjectTable<S extends Table> extends OAuthSubjectReadTable<S> {\n readonly decodeActionRequirement: (\n row: InferSelectModel<S>,\n action: OAuthAction,\n ) => AuthenticationRequirement;\n readonly decodeAuthenticationRequirement: (row: InferSelectModel<S>) => AuthenticationRequirement;\n readonly nextSecurityRevision: (current: SecurityRevision) => SecurityRevision;\n}\n\nexport interface OAuthOwnershipReadTable<O extends Table, N> {\n readonly table: O;\n readonly identityKey: Column<O>;\n readonly provider: Column<O>;\n readonly issuer: Column<O>;\n readonly externalSubject: Column<O>;\n readonly subjectId: Column<O>;\n /** Includes Owned state when authority and ownership share a physical table. */\n readonly ownedCondition: SQL;\n readonly decodeSubjectId: (row: InferSelectModel<O>) => N;\n}\n\nexport interface OAuthOwnershipTable<O extends Table, N> extends OAuthOwnershipReadTable<O, N> {\n readonly encodeInsert: (input: {\n readonly identity: typeof OAuthExternalIdentity.Type;\n readonly identityKey: string;\n readonly subjectId: N;\n }) => InferInsertModel<O>;\n}\n\nexport interface OAuthCredentialReadTable<C extends Table> {\n readonly table: C;\n readonly moduleId: Column<C>;\n readonly credentialId: Column<C>;\n readonly subjectId: Column<C>;\n readonly identityKey: Column<C>;\n readonly credentialRevision: Column<C>;\n readonly status: Column<C>;\n readonly isActiveStatus: (value: unknown) => boolean;\n readonly activeCondition: SQL;\n}\n\nexport interface OAuthCredentialTable<C extends Table, N> extends OAuthCredentialReadTable<C> {\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly subjectId: N;\n readonly identityKey: string;\n readonly credentialId: string;\n readonly credentialRevision: SecurityRevision;\n }) => InferInsertModel<C>;\n /** This slice removes login rows. Historical records belong in separate audit storage. */\n readonly removal: \"delete\";\n}\n\nexport interface OAuthAuthorityReadTable<C extends Table> {\n readonly table: C;\n readonly subjectId: Column<C>;\n readonly credentialId: Column<C>;\n readonly revision: Column<C>;\n readonly status: Column<C>;\n readonly isActiveStatus: (value: unknown) => boolean;\n readonly activeCondition: SQL;\n}\n\nexport interface OAuthAuthorityTable<C extends Table, N> extends OAuthAuthorityReadTable<C> {\n readonly encodeInsert: (input: {\n readonly subjectId: N;\n readonly credentialId: string;\n readonly revision: SecurityRevision;\n }) => InferInsertModel<C>;\n}\n\n/** Both purposes may use the same physical table. Shared tables share module/flow\n * and module/command uniqueness. The snapshot has the exact purpose-specific core\n * codec; terminal writes erase it, while identity, claim and retention columns remain. */\nexport interface OAuthFlowTable<F extends Table> {\n readonly table: F;\n readonly moduleId: Column<F>;\n readonly flowId: Column<F>;\n readonly commandId: Column<F>;\n readonly purpose: Column<F>;\n readonly generation: Column<F>;\n readonly state: Column<F>;\n readonly version: Column<F>;\n readonly stateDigest: Column<F>;\n readonly binderVerifier: Column<F>;\n readonly binderExpiresAt: Column<F>;\n readonly snapshot: Column<F>;\n readonly issuedAt: Column<F>;\n readonly expiresAt: Column<F>;\n readonly claimId: Column<F>;\n readonly claimedAt: Column<F>;\n readonly claimExpiresAt: Column<F>;\n readonly retentionUntil: Column<F>;\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly flowId: string;\n readonly purpose: \"sign-in\" | \"link\";\n }) => InferInsertModel<F>;\n}\n\nexport interface OAuthTupleAuthorityTable<T extends Table, N> {\n readonly table: T;\n readonly identityKey: Column<T>;\n readonly provider: Column<T>;\n readonly issuer: Column<T>;\n readonly externalSubject: Column<T>;\n readonly state: Column<T>;\n readonly version: Column<T>;\n readonly subjectId: Column<T>;\n /** Exact reservation identity; no application payload or bearer. */\n readonly reservation: Column<T>;\n readonly encodeInsert: (input: {\n readonly identityKey: string;\n readonly identity: typeof OAuthExternalIdentity.Type;\n readonly subjectId?: N;\n }) => InferInsertModel<T>;\n}\n\nexport interface OAuthRegistrationIntentTable<I extends Table> {\n readonly table: I;\n readonly moduleId: Column<I>;\n readonly reference: Column<I>;\n readonly flowId: Column<I>;\n readonly claimId: Column<I>;\n readonly identityKey: Column<I>;\n readonly version: Column<I>;\n readonly state: Column<I>;\n readonly snapshot: Column<I>;\n readonly commandId: Column<I>;\n readonly fingerprint: Column<I>;\n readonly pendingReference: Column<I>;\n readonly expiresAt: Column<I>;\n readonly retentionUntil: Column<I>;\n readonly encodeInsert: (intent: OAuthRegistrationIntent) => InferInsertModel<I>;\n}\n\nexport interface OAuthRegistrationCommandTable<R extends Table, Registration> {\n readonly table: R;\n readonly moduleId: Column<R>;\n readonly commandId: Column<R>;\n readonly reference: Column<R>;\n readonly identityKey: Column<R>;\n readonly fingerprint: Column<R>;\n readonly intentSnapshot: Column<R>;\n readonly applicationSnapshot: Column<R>;\n readonly provisioningIdentity: Column<R>;\n readonly decision: Column<R>;\n readonly retentionUntil: Column<R>;\n /** Persists exact detached Type before protected pending work can start. */\n readonly encodeInsert: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly commandId: string;\n readonly fingerprint: string;\n readonly registration: Registration;\n readonly provisioningIdentity: string;\n }) => InferInsertModel<R>;\n}\n\nexport interface OAuthUnlinkCommandTable<U extends Table> {\n readonly table: U;\n readonly moduleId: Column<U>;\n readonly commandId: Column<U>;\n readonly subjectId: Column<U>;\n readonly credentialId: Column<U>;\n readonly intentSnapshot: Column<U>;\n readonly decision: Column<U>;\n readonly retentionUntil: Column<U>;\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly commandId: string;\n readonly credential: OAuthCredentialSnapshot;\n }) => InferInsertModel<U>;\n}\n\nexport interface OAuthEligibilityFact {\n readonly credentialId: string;\n readonly revision: SecurityRevision;\n readonly usablePrimary: boolean;\n readonly factors: ReadonlyArray<AuthenticationFactor>;\n readonly userVerified: boolean;\n readonly phishingResistant: boolean;\n}\n\n/** Each descriptor reads only its own subject-scoped method rows. The native row\n * projector and SQL condition must express the same installed method eligibility.\n * All source/identifier/policy mutations advance subject securityRevision. D1 also\n * guards exact selected IDs/versions and absence/count assumptions, never just a\n * stale boolean. An over-limit graph fails closed rather than truncating. */\nexport interface OAuthEligibilityTable<T extends Table, N> {\n readonly table: T;\n readonly subjectId: Column<T>;\n readonly credentialId: Column<T>;\n readonly revision: Column<T>;\n readonly scope: string;\n readonly condition: (subjectId: N) => SQL;\n readonly decode: (row: InferSelectModel<T>) => OAuthEligibilityFact | undefined;\n}\n\n/** Authenticated command replay uses current subject status and this additional\n * nonconsuming SQL policy. It never consumes a fresh action factor. */\nexport interface OAuthMetadataPolicy<N> {\n readonly condition: (subjectId: N) => SQL;\n}\n\nexport interface OAuthCleanupTable<T extends Table, N> {\n readonly table: T;\n readonly subjectId: Column<T>;\n /** Bound to this subject's old revision; no opaque independently committing service. */\n readonly condition: (input: {\n readonly subjectId: N;\n readonly revision: OAuthAccountRevision;\n readonly removedCredentialId?: string;\n }) => SQL;\n readonly disposition: \"delete\";\n}\n\nexport interface OAuthRegistrationEligibility<N> {\n /** Pure SQL guards for mutable app policy; evaluated again after app writes. */\n readonly condition: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly nativeSubjectId?: N;\n }) => SQL;\n}\n\nexport interface OAuthD1Mapping {\n readonly d1: { readonly primary: true };\n}\n\nexport const requiredOAuthSignInConstraints = {\n flow: \"unique(flow.moduleId,flow.flowId)\",\n command: \"unique(flow.moduleId,flow.commandId)\",\n stateDigest: \"unique(flow.stateDigest)\",\n ownership: \"unique(ownership.identityKey)\",\n credentialId: \"unique(credential.credentialId)\",\n credentialIdentity: \"unique(credential.identityKey)\",\n authorityCredential: \"unique(authority.subjectId,authority.credentialId)\",\n} as const;\n\nexport const requiredOAuthTupleConstraints = { identityKey: \"unique(tuple.identityKey)\" } as const;\n\nexport const requiredOAuthRegistrationConstraints = {\n intentReference: \"unique(intent.moduleId,intent.reference)\",\n intentFlow: \"unique(intent.moduleId,intent.flowId)\",\n command: \"unique(registrationCommand.moduleId,registrationCommand.commandId)\",\n} as const;\n\nexport const requiredOAuthAccountsConstraints = {\n unlinkCommand: \"unique(unlinkCommand.moduleId,unlinkCommand.commandId)\",\n} as const;\n\nexport interface OAuthSignInMapping<\n S extends Table,\n O extends Table,\n C extends Table,\n AC extends Table,\n F extends Table,\n N,\n> {\n readonly subject: OAuthSubjectReadTable<S>;\n readonly ownership: OAuthOwnershipReadTable<O, N>;\n readonly credential: OAuthCredentialReadTable<C>;\n readonly authority: OAuthAuthorityReadTable<AC>;\n readonly flow: OAuthFlowTable<F>;\n readonly subjectId: SubjectIdCodec<N>;\n readonly clock: OAuthClock;\n readonly constraints: typeof requiredOAuthSignInConstraints;\n}\n\nexport type OAuthOwnershipMutation<T extends Table, O extends Table, N> =\n | { readonly mode: \"integrated\"; readonly tuple: OAuthTupleAuthorityTable<T, N> }\n | {\n readonly mode: \"separate\";\n readonly tuple: OAuthTupleAuthorityTable<T, N>;\n readonly external: OAuthOwnershipTable<O, N>;\n };\n\nexport interface OAuthRegistrationIntentMapping<\n S extends Table,\n O extends Table,\n C extends Table,\n AC extends Table,\n F extends Table,\n T extends Table,\n I extends Table,\n N,\n> {\n readonly signIn: OAuthSignInMapping<S, O, C, AC, F, N>;\n readonly ownership: OAuthOwnershipMutation<T, O, N>;\n readonly intent: OAuthRegistrationIntentTable<I>;\n readonly tupleConstraints: typeof requiredOAuthTupleConstraints;\n readonly registrationConstraints: Pick<\n typeof requiredOAuthRegistrationConstraints,\n \"intentReference\" | \"intentFlow\"\n >;\n readonly eligibility: OAuthRegistrationEligibility<N>;\n}\n\nexport interface OAuthRegistrationBase<\n Registration,\n T extends Table,\n O extends Table,\n I extends Table,\n R extends Table,\n N,\n> {\n readonly ownership: OAuthOwnershipMutation<T, O, N>;\n readonly intent: OAuthRegistrationIntentTable<I>;\n readonly command: OAuthRegistrationCommandTable<R, Registration>;\n readonly clock: OAuthClock;\n readonly tupleConstraints: typeof requiredOAuthTupleConstraints;\n readonly constraints: typeof requiredOAuthRegistrationConstraints;\n readonly inspect: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n }) => Effect.Effect<\n { readonly fingerprint: string; readonly eligible: boolean },\n PersistenceMappingError\n >;\n /** Required for an explicitly bound native/DO command: no asynchronous callback\n * is evaluated inside the physical owner. Standalone inspection is pre-owner. */\n readonly inspectSync?: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n }) => { readonly fingerprint: string; readonly eligible: boolean };\n /** Type projection, never the original wire transformation. */\n readonly snapshot: (\n registration: Registration,\n ) => Effect.Effect<Registration, PersistenceMappingError>;\n readonly snapshotSync?: (registration: Registration) => Registration;\n /** Canonical bounded storage of Registration.Type. These are Type codecs, not\n * the original wire decoder/encoder; decode(encode(value)) must encode identically.\n * The engine writes and roundtrip-checks this exact string (maximum 1 MiB). */\n readonly application: {\n readonly encode: (registration: Registration) => string;\n readonly decode: (stored: string) => Registration;\n };\n readonly eligibility: {\n /** Stable application authority anchors, in one configured global order.\n * Omit only for immutable/tuple-local policy or an equivalent explicit outer\n * owner lock. Each scope must match 1..64 rows, never an absent quota row.\n * Locks precede tuple/intent/command locks; postcondition owns changed state. */\n readonly guards?: ReadonlyArray<OAuthRegistrationGuardDescriptor<Registration, N>>;\n readonly admission: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n readonly nativeSubjectId?: N;\n }) => SQL;\n /** Evaluated after subject/application writes, including appended coordinator\n * writes. May assert consumption of the admission invitation/quota. */\n readonly postcondition: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n readonly nativeSubjectId?: N;\n }) => SQL;\n };\n readonly allocateProvisioningIdentity: Effect.Effect<string, PersistenceMappingError>;\n readonly retentionMillis: number;\n}\n\nexport interface OAuthRegistrationGuardTable<T extends Table, Registration, N> {\n readonly table: T;\n readonly orderBy: Column<T>;\n readonly condition: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n readonly nativeSubjectId?: N;\n }) => SQL;\n}\n\nexport interface OAuthRegistrationGuardDescriptor<Registration, N> {\n readonly table: Table;\n readonly orderBy: string;\n readonly condition: OAuthRegistrationGuardTable<Table, Registration, N>[\"condition\"];\n}\n\nexport const oauthRegistrationGuardTable = <T extends Table, Registration, N>(\n input: OAuthRegistrationGuardTable<T, Registration, N>,\n): OAuthRegistrationGuardDescriptor<Registration, N> =>\n Object.freeze({\n table: input.table,\n orderBy: input.orderBy,\n condition: input.condition,\n });\n\nexport type OAuthRegistrationMapping<\n Registration,\n S extends Table,\n O extends Table,\n C extends Table,\n AC extends Table,\n T extends Table,\n I extends Table,\n R extends Table,\n N,\n> = OAuthRegistrationBase<Registration, T, O, I, R, N> &\n (\n | {\n readonly mode: \"pending\";\n readonly allocatePendingReference: Effect.Effect<string, PersistenceMappingError>;\n }\n | {\n readonly mode: \"atomic\";\n readonly subjectId: SubjectIdCodec<N>;\n readonly subject: OAuthSubjectReadTable<S>;\n readonly credential: OAuthCredentialTable<C, N>;\n readonly authority: OAuthAuthorityTable<AC, N>;\n readonly allocateSubjectId: Effect.Effect<N, PersistenceMappingError>;\n readonly allocateCredentialId: Effect.Effect<string, PersistenceMappingError>;\n readonly allocateRevision: Effect.Effect<SecurityRevision, PersistenceMappingError>;\n readonly encodeSubjectInsert: (\n input: { readonly intent: OAuthRegistrationIntent; readonly registration: Registration },\n ids: { readonly subjectId: N; readonly securityRevision: SecurityRevision },\n ) => InferInsertModel<S>;\n }\n );\n\n/** Heterogeneous descriptors are made by typed factories and projected privately. */\nexport interface OAuthEligibilityDescriptor<N> {\n readonly _tag: \"OAuthEligibilityDescriptor\";\n readonly scope: string;\n readonly table: Table;\n readonly subjectId: string;\n readonly credentialId: string;\n readonly revision: string;\n readonly condition: (subjectId: N) => SQL;\n readonly decode: (row: unknown) => OAuthEligibilityFact | undefined;\n}\n\nexport const oauthEligibilityTable = <T extends Table, N>(\n input: OAuthEligibilityTable<T, N>,\n): OAuthEligibilityDescriptor<N> => {\n const { table, subjectId, credentialId, revision, scope, condition, decode } = input;\n\n return Object.freeze({\n _tag: \"OAuthEligibilityDescriptor\",\n table,\n subjectId,\n credentialId,\n revision,\n scope,\n condition,\n decode: (row: unknown) => decode(row as InferSelectModel<T>),\n });\n};\n\nexport interface OAuthCleanupDescriptor<N> {\n readonly table: Table;\n readonly subjectId: string;\n readonly condition: OAuthCleanupTable<Table, N>[\"condition\"];\n}\n\nexport const oauthCleanupTable = <T extends Table, N>(\n input: OAuthCleanupTable<T, N>,\n): OAuthCleanupDescriptor<N> =>\n Object.freeze({ table: input.table, subjectId: input.subjectId, condition: input.condition });\n\n/** A stable application/reference lock acquired before an ownership target.\n * Missing rows retain ownership. Conditions are synchronous and use detached\n * native IDs; every writer of the guarded reference follows the same order. */\nexport interface OAuthReferenceGuardTable<T extends Table, N> {\n readonly table: T;\n readonly orderBy: Column<T>;\n readonly condition: (input: {\n readonly identity: typeof OAuthExternalIdentity.Type;\n readonly identityKey: string;\n readonly subjectId: N;\n }) => SQL;\n}\n\nexport interface OAuthReferenceGuardDescriptor<N> {\n readonly table: Table;\n readonly orderBy: string;\n readonly condition: OAuthReferenceGuardTable<Table, N>[\"condition\"];\n}\n\nexport const oauthReferenceGuardTable = <T extends Table, N>(\n input: OAuthReferenceGuardTable<T, N>,\n): OAuthReferenceGuardDescriptor<N> =>\n Object.freeze({\n table: input.table,\n orderBy: input.orderBy,\n condition: input.condition,\n });\n\nexport interface OAuthAccountsMapping<\n S extends Table,\n O extends Table,\n C extends Table,\n AC extends Table,\n F extends Table,\n T extends Table,\n U extends Table,\n N,\n> {\n readonly subject: OAuthSubjectTable<S>;\n readonly ownership: OAuthOwnershipMutation<T, O, N>;\n readonly credential: OAuthCredentialTable<C, N>;\n readonly authority: OAuthAuthorityTable<AC, N>;\n readonly flow: OAuthFlowTable<F>;\n readonly command: OAuthUnlinkCommandTable<U>;\n readonly subjectId: SubjectIdCodec<N>;\n readonly clock: OAuthClock;\n readonly constraints: typeof requiredOAuthSignInConstraints &\n typeof requiredOAuthAccountsConstraints;\n readonly tupleConstraints: typeof requiredOAuthTupleConstraints;\n readonly eligibility: ReadonlyArray<OAuthEligibilityDescriptor<N>>;\n readonly cleanup: ReadonlyArray<OAuthCleanupDescriptor<N>>;\n readonly metadata: OAuthMetadataPolicy<N>;\n readonly sessionInvalidation: \"same-authority-immediate\" | \"original-absolute-expiry\";\n /** Omit only when connected access is absent. A predicate alone conservatively\n * retains ownership; release also needs all configured guard rows below. */\n readonly connectedReference?: (input: {\n readonly identityKey: string;\n readonly subjectId: N;\n }) => SQL;\n /** At most 32 descriptors, each locking 1..64 stable rows in supplied order.\n * Missing/empty guards retain Owned, even when the reference predicate is false. */\n readonly connectedReferenceGuards?: ReadonlyArray<OAuthReferenceGuardDescriptor<N>>;\n readonly allocateCredentialId: Effect.Effect<string, PersistenceMappingError>;\n readonly allocateRevision: Effect.Effect<SecurityRevision, PersistenceMappingError>;\n}\n\nexport interface OAuthRegistrationAuthority<Registration> {\n readonly read: (\n access: import(\"@yielded/auth/OAuth\").OAuthRegistrationAccess,\n ) => Effect.Effect<\n import(\"@yielded/auth/OAuth\").OAuthRegistrationInspection | undefined,\n import(\"@yielded/auth/OAuth\").OAuthUnavailable\n >;\n readonly inspect: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n }) => Effect.Effect<\n {\n readonly fingerprint: import(\"@yielded/auth/Schema\").TokenDigest;\n readonly eligible: boolean;\n },\n import(\"@yielded/auth/OAuth\").OAuthUnavailable\n >;\n readonly register: <A>(\n input: {\n readonly access: import(\"@yielded/auth/OAuth\").OAuthRegistrationAccess;\n readonly intent: OAuthRegistrationIntent;\n readonly commandId: typeof import(\"@yielded/auth/OAuth\").OAuthCommandId.Type;\n readonly registration: Registration;\n readonly fingerprint: import(\"@yielded/auth/Schema\").TokenDigest;\n },\n prepare: import(\"@yielded/auth/OAuth\").PrepareOAuthCommit<\n import(\"@yielded/auth/OAuth\").OAuthRegistrationDecision,\n A\n >,\n ) => Effect.Effect<\n import(\"@yielded/auth/Hooks\").PreparedCommit<A>,\n import(\"@yielded/auth/OAuth\").OAuthUnavailable\n >;\n readonly cleanup: <A>(\n input: import(\"@yielded/auth/OAuth\").OAuthCleanupInput,\n prepare: import(\"@yielded/auth/OAuth\").PrepareOAuthCommit<\n { readonly removed: number; readonly hasMore: boolean },\n A\n >,\n ) => Effect.Effect<\n import(\"@yielded/auth/Hooks\").PreparedCommit<A>,\n import(\"@yielded/auth/OAuth\").OAuthUnavailable\n >;\n}\n"],"mappings":";AAuRA,MAAa,iCAAiC;CAC5C,MAAM;CACN,SAAS;CACT,aAAa;CACb,WAAW;CACX,cAAc;CACd,oBAAoB;CACpB,qBAAqB;AACvB;AAEA,MAAa,gCAAgC,EAAE,aAAa,4BAA4B;AAExF,MAAa,uCAAuC;CAClD,iBAAiB;CACjB,YAAY;CACZ,SAAS;AACX;AAEA,MAAa,mCAAmC,EAC9C,eAAe,yDACjB;AA+HA,MAAa,+BACX,UAEA,OAAO,OAAO;CACZ,OAAO,MAAM;CACb,SAAS,MAAM;CACf,WAAW,MAAM;AACnB,CAAC;AA8CH,MAAa,yBACX,UACkC;CAClC,MAAM,EAAE,OAAO,WAAW,cAAc,UAAU,OAAO,WAAW,WAAW;CAE/E,OAAO,OAAO,OAAO;EACnB,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;EACA,SAAS,QAAiB,OAAO,GAA0B;CAC7D,CAAC;AACH;AAQA,MAAa,qBACX,UAEA,OAAO,OAAO;CAAE,OAAO,MAAM;CAAO,WAAW,MAAM;CAAW,WAAW,MAAM;AAAU,CAAC;AAqB9F,MAAa,4BACX,UAEA,OAAO,OAAO;CACZ,OAAO,MAAM;CACb,SAAS,MAAM;CACf,WAAW,MAAM;AACnB,CAAC"}
1
+ {"version":3,"file":"oauth-model.mjs","names":[],"sources":["../../src/drizzle/oauth-model.ts"],"sourcesContent":["import type {\n OAuthActionAuthorization,\n OAuthAccountRevision,\n OAuthRegistrationIntent,\n OAuthCredentialSnapshot,\n OAuthExternalIdentity,\n} from \"@yielded/auth/OAuth\";\nimport type { AuthenticationFactor } from \"@yielded/auth/Operations\";\nimport type { AuthenticationRequirement, SecurityRevision } from \"@yielded/auth/Sessions\";\nimport type { InferInsertModel, InferSelectModel, SQL, Table } from \"drizzle-orm\";\nimport type { Crypto, Effect, PlatformError } from \"effect\";\n\nimport type { PersistenceMappingError, SubjectIdCodec } from \"./model\";\n\ntype Column<T extends Table> = Extract<keyof T[\"_\"][\"columns\"], string>;\n\nexport type OAuthFlowState =\n | \"Pending\"\n | \"Claimed\"\n | \"Verified\"\n | \"RegistrationIssued\"\n | \"Linked\"\n | \"Cancelled\"\n | \"Rejected\"\n | \"Ambiguous\"\n | \"Conflict\";\n\nexport type OAuthTupleState = \"Unowned\" | \"Reserved\" | \"Owned\";\nexport type OAuthRegistrationState = \"Unbound\" | \"Registered\" | \"ProvisioningPending\" | \"Rejected\";\nexport type OAuthAction = OAuthActionAuthorization[\"challenge\"][\"action\"];\n\n/** The engine writes every critical column explicitly after applying the pure\n * consumer encoder. Native instant values must roundtrip without precision loss. */\nexport interface OAuthClock {\n readonly encodeInstant: (millis: number) => unknown;\n readonly decodeInstant: (value: unknown) => number;\n /** Actual engine wall clock sampled after locks, not transaction-start time.\n * PostgreSQL uses clock_timestamp(), never now()/CURRENT_TIMESTAMP. D1 repeats\n * its primary-engine sample bounds in final guards. Return integer milliseconds. */\n readonly engineNowMillis: SQL;\n}\n\nexport interface OAuthSubjectReadTable<S extends Table> {\n readonly table: S;\n readonly id: Column<S>;\n readonly status: Column<S>;\n readonly securityRevision: Column<S>;\n readonly isActiveStatus: (value: unknown) => boolean;\n readonly activeCondition: SQL;\n}\n\nexport interface OAuthSubjectTable<S extends Table> extends OAuthSubjectReadTable<S> {\n readonly decodeActionRequirement: (\n row: InferSelectModel<S>,\n action: OAuthAction,\n ) => AuthenticationRequirement;\n readonly decodeAuthenticationRequirement: (row: InferSelectModel<S>) => AuthenticationRequirement;\n readonly nextSecurityRevision: (current: SecurityRevision) => SecurityRevision;\n}\n\nexport interface OAuthOwnershipReadTable<O extends Table, N> {\n readonly table: O;\n readonly identityKey: Column<O>;\n readonly provider: Column<O>;\n readonly issuer: Column<O>;\n readonly externalSubject: Column<O>;\n readonly subjectId: Column<O>;\n /** Includes Owned state when authority and ownership share a physical table. */\n readonly ownedCondition: SQL;\n readonly decodeSubjectId: (row: InferSelectModel<O>) => N;\n}\n\nexport interface OAuthOwnershipTable<O extends Table, N> extends OAuthOwnershipReadTable<O, N> {\n readonly encodeInsert: (input: {\n readonly identity: typeof OAuthExternalIdentity.Type;\n readonly identityKey: string;\n readonly subjectId: N;\n }) => InferInsertModel<O>;\n}\n\nexport interface OAuthCredentialReadTable<C extends Table> {\n readonly table: C;\n readonly moduleId: Column<C>;\n readonly credentialId: Column<C>;\n readonly subjectId: Column<C>;\n readonly identityKey: Column<C>;\n readonly credentialRevision: Column<C>;\n readonly status: Column<C>;\n readonly isActiveStatus: (value: unknown) => boolean;\n readonly activeCondition: SQL;\n}\n\nexport interface OAuthCredentialTable<C extends Table, N> extends OAuthCredentialReadTable<C> {\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly subjectId: N;\n readonly identityKey: string;\n readonly credentialId: string;\n readonly credentialRevision: SecurityRevision;\n }) => InferInsertModel<C>;\n /** This slice removes login rows. Historical records belong in separate audit storage. */\n readonly removal: \"delete\";\n}\n\nexport interface OAuthAuthorityReadTable<C extends Table> {\n readonly table: C;\n readonly subjectId: Column<C>;\n readonly credentialId: Column<C>;\n readonly revision: Column<C>;\n readonly status: Column<C>;\n readonly isActiveStatus: (value: unknown) => boolean;\n readonly activeCondition: SQL;\n}\n\nexport interface OAuthAuthorityTable<C extends Table, N> extends OAuthAuthorityReadTable<C> {\n readonly encodeInsert: (input: {\n readonly subjectId: N;\n readonly credentialId: string;\n readonly revision: SecurityRevision;\n }) => InferInsertModel<C>;\n}\n\n/** Both purposes may use the same physical table. Shared tables share module/flow\n * and module/command uniqueness. The snapshot has the exact purpose-specific core\n * codec; terminal writes erase it, while identity, claim and retention columns remain. */\nexport interface OAuthFlowTable<F extends Table> {\n readonly table: F;\n readonly moduleId: Column<F>;\n readonly flowId: Column<F>;\n readonly commandId: Column<F>;\n readonly purpose: Column<F>;\n readonly generation: Column<F>;\n readonly state: Column<F>;\n readonly version: Column<F>;\n readonly stateDigest: Column<F>;\n readonly binderVerifier: Column<F>;\n readonly binderExpiresAt: Column<F>;\n readonly snapshot: Column<F>;\n readonly issuedAt: Column<F>;\n readonly expiresAt: Column<F>;\n readonly claimId: Column<F>;\n readonly claimedAt: Column<F>;\n readonly claimExpiresAt: Column<F>;\n readonly retentionUntil: Column<F>;\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly flowId: string;\n readonly purpose: \"sign-in\" | \"link\";\n }) => InferInsertModel<F>;\n}\n\nexport interface OAuthTupleAuthorityTable<T extends Table, N> {\n readonly table: T;\n readonly identityKey: Column<T>;\n readonly provider: Column<T>;\n readonly issuer: Column<T>;\n readonly externalSubject: Column<T>;\n readonly state: Column<T>;\n readonly version: Column<T>;\n readonly subjectId: Column<T>;\n /** Exact reservation identity; no application payload or bearer. */\n readonly reservation: Column<T>;\n readonly encodeInsert: (input: {\n readonly identityKey: string;\n readonly identity: typeof OAuthExternalIdentity.Type;\n readonly subjectId?: N;\n }) => InferInsertModel<T>;\n}\n\nexport interface OAuthRegistrationIntentTable<I extends Table> {\n readonly table: I;\n readonly moduleId: Column<I>;\n readonly reference: Column<I>;\n readonly flowId: Column<I>;\n readonly claimId: Column<I>;\n readonly identityKey: Column<I>;\n readonly version: Column<I>;\n readonly state: Column<I>;\n readonly snapshot: Column<I>;\n readonly commandId: Column<I>;\n readonly fingerprint: Column<I>;\n readonly pendingReference: Column<I>;\n readonly expiresAt: Column<I>;\n readonly retentionUntil: Column<I>;\n readonly encodeInsert: (intent: OAuthRegistrationIntent) => InferInsertModel<I>;\n}\n\nexport interface OAuthRegistrationCommandTable<R extends Table, Registration> {\n readonly table: R;\n readonly moduleId: Column<R>;\n readonly commandId: Column<R>;\n readonly reference: Column<R>;\n readonly identityKey: Column<R>;\n readonly fingerprint: Column<R>;\n readonly intentSnapshot: Column<R>;\n readonly applicationSnapshot: Column<R>;\n readonly provisioningIdentity: Column<R>;\n readonly decision: Column<R>;\n readonly retentionUntil: Column<R>;\n /** Persists exact detached Type before protected pending work can start. */\n readonly encodeInsert: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly commandId: string;\n readonly fingerprint: string;\n readonly registration: Registration;\n readonly provisioningIdentity: string;\n }) => InferInsertModel<R>;\n}\n\nexport interface OAuthUnlinkCommandTable<U extends Table> {\n readonly table: U;\n readonly moduleId: Column<U>;\n readonly commandId: Column<U>;\n readonly subjectId: Column<U>;\n readonly credentialId: Column<U>;\n readonly intentSnapshot: Column<U>;\n readonly decision: Column<U>;\n readonly retentionUntil: Column<U>;\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly commandId: string;\n readonly credential: OAuthCredentialSnapshot;\n }) => InferInsertModel<U>;\n}\n\nexport interface OAuthEligibilityFact {\n readonly credentialId: string;\n readonly revision: SecurityRevision;\n readonly usablePrimary: boolean;\n readonly factors: ReadonlyArray<AuthenticationFactor>;\n readonly userVerified: boolean;\n readonly phishingResistant: boolean;\n}\n\n/** Each descriptor reads only its own subject-scoped method rows. The native row\n * projector and SQL condition must express the same installed method eligibility.\n * All source/identifier/policy mutations advance subject securityRevision. D1 also\n * guards exact selected IDs/versions and absence/count assumptions, never just a\n * stale boolean. An over-limit graph fails closed rather than truncating. */\nexport interface OAuthEligibilityTable<T extends Table, N> {\n readonly table: T;\n readonly subjectId: Column<T>;\n readonly credentialId: Column<T>;\n readonly revision: Column<T>;\n readonly scope: string;\n readonly condition: (subjectId: N) => SQL;\n readonly decode: (row: InferSelectModel<T>) => OAuthEligibilityFact | undefined;\n}\n\n/** Authenticated command replay uses current subject status and this additional\n * nonconsuming SQL policy. It never consumes a fresh action factor. */\nexport interface OAuthMetadataPolicy<N> {\n readonly condition: (subjectId: N) => SQL;\n}\n\nexport interface OAuthCleanupTable<T extends Table, N> {\n readonly table: T;\n readonly subjectId: Column<T>;\n /** Bound to this subject's old revision; no opaque independently committing service. */\n readonly condition: (input: {\n readonly subjectId: N;\n readonly revision: OAuthAccountRevision;\n readonly removedCredentialId?: string;\n }) => SQL;\n readonly disposition: \"delete\";\n}\n\nexport interface OAuthRegistrationEligibility<N> {\n /** Pure SQL guards for mutable app policy; evaluated again after app writes. */\n readonly condition: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly nativeSubjectId?: N;\n }) => SQL;\n}\n\nexport interface OAuthD1Mapping {\n readonly d1: { readonly primary: true };\n}\n\nexport const requiredOAuthSignInConstraints = {\n flow: \"unique(flow.moduleId,flow.flowId)\",\n command: \"unique(flow.moduleId,flow.commandId)\",\n stateDigest: \"unique(flow.stateDigest)\",\n ownership: \"unique(ownership.identityKey)\",\n credentialId: \"unique(credential.credentialId)\",\n credentialIdentity: \"unique(credential.identityKey)\",\n authorityCredential: \"unique(authority.subjectId,authority.credentialId)\",\n} as const;\n\nexport const requiredOAuthTupleConstraints = { identityKey: \"unique(tuple.identityKey)\" } as const;\n\nexport const requiredOAuthRegistrationConstraints = {\n intentReference: \"unique(intent.moduleId,intent.reference)\",\n intentFlow: \"unique(intent.moduleId,intent.flowId)\",\n command: \"unique(registrationCommand.moduleId,registrationCommand.commandId)\",\n} as const;\n\nexport const requiredOAuthAccountsConstraints = {\n unlinkCommand: \"unique(unlinkCommand.moduleId,unlinkCommand.commandId)\",\n} as const;\n\nexport interface OAuthSignInMapping<\n S extends Table,\n O extends Table,\n C extends Table,\n AC extends Table,\n F extends Table,\n N,\n> {\n readonly subject: OAuthSubjectReadTable<S>;\n readonly ownership: OAuthOwnershipReadTable<O, N>;\n readonly credential: OAuthCredentialReadTable<C>;\n readonly authority: OAuthAuthorityReadTable<AC>;\n readonly flow: OAuthFlowTable<F>;\n readonly subjectId: SubjectIdCodec<N>;\n readonly clock: OAuthClock;\n readonly constraints: typeof requiredOAuthSignInConstraints;\n}\n\nexport type OAuthOwnershipMutation<T extends Table, O extends Table, N> =\n | { readonly mode: \"integrated\"; readonly tuple: OAuthTupleAuthorityTable<T, N> }\n | {\n readonly mode: \"separate\";\n readonly tuple: OAuthTupleAuthorityTable<T, N>;\n readonly external: OAuthOwnershipTable<O, N>;\n };\n\nexport interface OAuthRegistrationIntentMapping<\n S extends Table,\n O extends Table,\n C extends Table,\n AC extends Table,\n F extends Table,\n T extends Table,\n I extends Table,\n N,\n> {\n readonly signIn: OAuthSignInMapping<S, O, C, AC, F, N>;\n readonly ownership: OAuthOwnershipMutation<T, O, N>;\n readonly intent: OAuthRegistrationIntentTable<I>;\n readonly tupleConstraints: typeof requiredOAuthTupleConstraints;\n readonly registrationConstraints: Pick<\n typeof requiredOAuthRegistrationConstraints,\n \"intentReference\" | \"intentFlow\"\n >;\n readonly eligibility: OAuthRegistrationEligibility<N>;\n}\n\nexport interface OAuthRegistrationBase<\n Registration,\n T extends Table,\n O extends Table,\n I extends Table,\n R extends Table,\n N,\n> {\n readonly ownership: OAuthOwnershipMutation<T, O, N>;\n readonly intent: OAuthRegistrationIntentTable<I>;\n readonly command: OAuthRegistrationCommandTable<R, Registration>;\n readonly clock: OAuthClock;\n readonly tupleConstraints: typeof requiredOAuthTupleConstraints;\n readonly constraints: typeof requiredOAuthRegistrationConstraints;\n readonly inspect: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n }) => Effect.Effect<\n { readonly fingerprint: string; readonly eligible: boolean },\n PersistenceMappingError\n >;\n /** Required for an explicitly bound native/DO command: no asynchronous callback\n * is evaluated inside the physical owner. Standalone inspection is pre-owner. */\n readonly inspectSync?: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n }) => { readonly fingerprint: string; readonly eligible: boolean };\n /** Type projection, never the original wire transformation. */\n readonly snapshot: (\n registration: Registration,\n ) => Effect.Effect<Registration, PersistenceMappingError>;\n readonly snapshotSync?: (registration: Registration) => Registration;\n /** Canonical bounded storage of Registration.Type. These are Type codecs, not\n * the original wire decoder/encoder; decode(encode(value)) must encode identically.\n * The engine writes and roundtrip-checks this exact string (maximum 1 MiB). */\n readonly application: {\n readonly encode: (registration: Registration) => string;\n readonly decode: (stored: string) => Registration;\n };\n readonly eligibility: {\n /** Stable application authority anchors, in one configured global order.\n * Omit only for immutable/tuple-local policy or an equivalent explicit outer\n * owner lock. Each scope must match 1..64 rows, never an absent quota row.\n * Locks precede tuple/intent/command locks; postcondition owns changed state. */\n readonly guards?: ReadonlyArray<OAuthRegistrationGuardDescriptor<Registration, N>>;\n readonly admission: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n readonly nativeSubjectId?: N;\n }) => SQL;\n /** Evaluated after subject/application writes, including appended coordinator\n * writes. May assert consumption of the admission invitation/quota. */\n readonly postcondition: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n readonly nativeSubjectId?: N;\n }) => SQL;\n };\n readonly allocateProvisioningIdentity: Effect.Effect<string, PersistenceMappingError>;\n readonly retentionMillis: number;\n}\n\nexport interface OAuthRegistrationGuardTable<T extends Table, Registration, N> {\n readonly table: T;\n readonly orderBy: Column<T>;\n readonly condition: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n readonly nativeSubjectId?: N;\n }) => SQL;\n}\n\nexport interface OAuthRegistrationGuardDescriptor<Registration, N> {\n readonly table: Table;\n readonly orderBy: string;\n readonly condition: OAuthRegistrationGuardTable<Table, Registration, N>[\"condition\"];\n}\n\nexport const oauthRegistrationGuardTable = <T extends Table, Registration, N>(\n input: OAuthRegistrationGuardTable<T, Registration, N>,\n): OAuthRegistrationGuardDescriptor<Registration, N> =>\n Object.freeze({\n table: input.table,\n orderBy: input.orderBy,\n condition: input.condition,\n });\n\nexport type OAuthRegistrationMapping<\n Registration,\n S extends Table,\n O extends Table,\n C extends Table,\n AC extends Table,\n T extends Table,\n I extends Table,\n R extends Table,\n N,\n> = OAuthRegistrationBase<Registration, T, O, I, R, N> &\n (\n | {\n readonly mode: \"pending\";\n readonly allocatePendingReference: Effect.Effect<string, PersistenceMappingError>;\n }\n | {\n readonly mode: \"atomic\";\n readonly subjectId: SubjectIdCodec<N>;\n readonly subject: OAuthSubjectReadTable<S>;\n readonly credential: OAuthCredentialTable<C, N>;\n readonly authority: OAuthAuthorityTable<AC, N>;\n readonly allocateSubjectId: Effect.Effect<N, PersistenceMappingError>;\n readonly allocateCredentialId: Effect.Effect<string, PersistenceMappingError>;\n readonly allocateRevision: Effect.Effect<SecurityRevision, PersistenceMappingError>;\n readonly encodeSubjectInsert: (\n input: { readonly intent: OAuthRegistrationIntent; readonly registration: Registration },\n ids: { readonly subjectId: N; readonly securityRevision: SecurityRevision },\n ) => InferInsertModel<S>;\n }\n );\n\n/** Heterogeneous descriptors are made by typed factories and projected privately. */\nexport interface OAuthEligibilityDescriptor<N> {\n readonly _tag: \"OAuthEligibilityDescriptor\";\n readonly scope: string;\n readonly table: Table;\n readonly subjectId: string;\n readonly credentialId: string;\n readonly revision: string;\n readonly condition: (subjectId: N) => SQL;\n readonly decode: (row: unknown) => OAuthEligibilityFact | undefined;\n}\n\nexport const oauthEligibilityTable = <T extends Table, N>(\n input: OAuthEligibilityTable<T, N>,\n): OAuthEligibilityDescriptor<N> => {\n const { table, subjectId, credentialId, revision, scope, condition, decode } = input;\n\n return Object.freeze({\n _tag: \"OAuthEligibilityDescriptor\",\n table,\n subjectId,\n credentialId,\n revision,\n scope,\n condition,\n decode: (row: unknown) => decode(row as InferSelectModel<T>),\n });\n};\n\nexport interface OAuthCleanupDescriptor<N> {\n readonly table: Table;\n readonly subjectId: string;\n readonly condition: OAuthCleanupTable<Table, N>[\"condition\"];\n}\n\nexport const oauthCleanupTable = <T extends Table, N>(\n input: OAuthCleanupTable<T, N>,\n): OAuthCleanupDescriptor<N> =>\n Object.freeze({ table: input.table, subjectId: input.subjectId, condition: input.condition });\n\n/** A stable application/reference lock acquired before an ownership target.\n * Missing rows retain ownership. Conditions use detached native IDs; every\n * writer of the guarded reference follows the same order. */\nexport interface OAuthReferenceGuardTable<T extends Table, N> {\n readonly table: T;\n readonly orderBy: Column<T>;\n readonly condition: (input: {\n readonly identity: typeof OAuthExternalIdentity.Type;\n readonly identityKey: string;\n readonly subjectId: N;\n }) => SQL | Effect.Effect<SQL, PlatformError.PlatformError, Crypto.Crypto>;\n}\n\nexport interface OAuthReferenceGuardDescriptor<N> {\n readonly table: Table;\n readonly orderBy: string;\n readonly condition: OAuthReferenceGuardTable<Table, N>[\"condition\"];\n}\n\nexport const oauthReferenceGuardTable = <T extends Table, N>(\n input: OAuthReferenceGuardTable<T, N>,\n): OAuthReferenceGuardDescriptor<N> =>\n Object.freeze({\n table: input.table,\n orderBy: input.orderBy,\n condition: input.condition,\n });\n\nexport interface OAuthAccountsMapping<\n S extends Table,\n O extends Table,\n C extends Table,\n AC extends Table,\n F extends Table,\n T extends Table,\n U extends Table,\n N,\n> {\n readonly subject: OAuthSubjectTable<S>;\n readonly ownership: OAuthOwnershipMutation<T, O, N>;\n readonly credential: OAuthCredentialTable<C, N>;\n readonly authority: OAuthAuthorityTable<AC, N>;\n readonly flow: OAuthFlowTable<F>;\n readonly command: OAuthUnlinkCommandTable<U>;\n readonly subjectId: SubjectIdCodec<N>;\n readonly clock: OAuthClock;\n readonly constraints: typeof requiredOAuthSignInConstraints &\n typeof requiredOAuthAccountsConstraints;\n readonly tupleConstraints: typeof requiredOAuthTupleConstraints;\n readonly eligibility: ReadonlyArray<OAuthEligibilityDescriptor<N>>;\n readonly cleanup: ReadonlyArray<OAuthCleanupDescriptor<N>>;\n readonly metadata: OAuthMetadataPolicy<N>;\n readonly sessionInvalidation: \"same-authority-immediate\" | \"original-absolute-expiry\";\n /** Omit only when connected access is absent. A predicate alone conservatively\n * retains ownership; release also needs all configured guard rows below. */\n readonly connectedReference?: (input: {\n readonly identityKey: string;\n readonly subjectId: N;\n }) => SQL;\n /** At most 32 descriptors, each locking 1..64 stable rows in supplied order.\n * Missing/empty guards retain Owned, even when the reference predicate is false. */\n readonly connectedReferenceGuards?: ReadonlyArray<OAuthReferenceGuardDescriptor<N>>;\n readonly allocateCredentialId: Effect.Effect<string, PersistenceMappingError>;\n readonly allocateRevision: Effect.Effect<SecurityRevision, PersistenceMappingError>;\n}\n\nexport interface OAuthRegistrationAuthority<Registration> {\n readonly read: (\n access: import(\"@yielded/auth/OAuth\").OAuthRegistrationAccess,\n ) => Effect.Effect<\n import(\"@yielded/auth/OAuth\").OAuthRegistrationInspection | undefined,\n import(\"@yielded/auth/OAuth\").OAuthUnavailable\n >;\n readonly inspect: (input: {\n readonly intent: OAuthRegistrationIntent;\n readonly registration: Registration;\n }) => Effect.Effect<\n {\n readonly fingerprint: import(\"@yielded/auth/Schema\").TokenDigest;\n readonly eligible: boolean;\n },\n import(\"@yielded/auth/OAuth\").OAuthUnavailable\n >;\n readonly register: <A>(\n input: {\n readonly access: import(\"@yielded/auth/OAuth\").OAuthRegistrationAccess;\n readonly intent: OAuthRegistrationIntent;\n readonly commandId: typeof import(\"@yielded/auth/OAuth\").OAuthCommandId.Type;\n readonly registration: Registration;\n readonly fingerprint: import(\"@yielded/auth/Schema\").TokenDigest;\n },\n prepare: import(\"@yielded/auth/OAuth\").PrepareOAuthCommit<\n import(\"@yielded/auth/OAuth\").OAuthRegistrationDecision,\n A\n >,\n ) => Effect.Effect<\n import(\"@yielded/auth/Hooks\").PreparedCommit<A>,\n import(\"@yielded/auth/OAuth\").OAuthUnavailable\n >;\n readonly cleanup: <A>(\n input: import(\"@yielded/auth/OAuth\").OAuthCleanupInput,\n prepare: import(\"@yielded/auth/OAuth\").PrepareOAuthCommit<\n { readonly removed: number; readonly hasMore: boolean },\n A\n >,\n ) => Effect.Effect<\n import(\"@yielded/auth/Hooks\").PreparedCommit<A>,\n import(\"@yielded/auth/OAuth\").OAuthUnavailable\n >;\n}\n"],"mappings":";AAuRA,MAAa,iCAAiC;CAC5C,MAAM;CACN,SAAS;CACT,aAAa;CACb,WAAW;CACX,cAAc;CACd,oBAAoB;CACpB,qBAAqB;AACvB;AAEA,MAAa,gCAAgC,EAAE,aAAa,4BAA4B;AAExF,MAAa,uCAAuC;CAClD,iBAAiB;CACjB,YAAY;CACZ,SAAS;AACX;AAEA,MAAa,mCAAmC,EAC9C,eAAe,yDACjB;AA+HA,MAAa,+BACX,UAEA,OAAO,OAAO;CACZ,OAAO,MAAM;CACb,SAAS,MAAM;CACf,WAAW,MAAM;AACnB,CAAC;AA8CH,MAAa,yBACX,UACkC;CAClC,MAAM,EAAE,OAAO,WAAW,cAAc,UAAU,OAAO,WAAW,WAAW;CAE/E,OAAO,OAAO,OAAO;EACnB,MAAM;EACN;EACA;EACA;EACA;EACA;EACA;EACA,SAAS,QAAiB,OAAO,GAA0B;CAC7D,CAAC;AACH;AAQA,MAAa,qBACX,UAEA,OAAO,OAAO;CAAE,OAAO,MAAM;CAAO,WAAW,MAAM;CAAW,WAAW,MAAM;AAAU,CAAC;AAqB9F,MAAa,4BACX,UAEA,OAAO,OAAO;CACZ,OAAO,MAAM;CACb,SAAS,MAAM;CACf,WAAW,MAAM;AACnB,CAAC"}
@@ -18,7 +18,7 @@ const reservationStorage = storage(Schema.Struct({
18
18
  provisioningIdentity: Schema.String
19
19
  }));
20
20
  const readTuple = (ownership, identity) => Effect.flatMap(CurrentOAuthTransaction, (owner) => Effect.gen(function* () {
21
- const t = ownership.tuple, key = oauthIdentityKey(identity);
21
+ const t = ownership.tuple, key = yield* oauthIdentityKey(identity);
22
22
  const where = { [t.identityKey]: key };
23
23
  const observed = yield* owner.read(t.table, equal(t.table, where), { limit: 1 });
24
24
  if (observed.rows.length === 0) {
@@ -155,7 +155,7 @@ const inspectIntent = (mapping, original, discovery = false) => Effect.flatMap(C
155
155
  const row = observed.rows[0];
156
156
  if (row === void 0) return void 0;
157
157
  const intent = intentStorage.decode(row[i.snapshot]), c = intent.context, now = yield* owner.now(mapping.clock);
158
- invariant(row[i.moduleId] === c.moduleId && row[i.reference] === intent.reference && row[i.flowId] === c.flowId && row[i.claimId] === intent.claimId && row[i.identityKey] === oauthIdentityKey(intent.identity) && mapping.clock.decodeInstant(row[i.expiresAt]) === intent.expiresAtMillis && mapping.clock.decodeInstant(row[i.retentionUntil]) === intent.retentionUntilMillis);
158
+ invariant(row[i.moduleId] === c.moduleId && row[i.reference] === intent.reference && row[i.flowId] === c.flowId && row[i.claimId] === intent.claimId && row[i.identityKey] === (yield* oauthIdentityKey(intent.identity)) && mapping.clock.decodeInstant(row[i.expiresAt]) === intent.expiresAtMillis && mapping.clock.decodeInstant(row[i.retentionUntil]) === intent.retentionUntilMillis);
159
159
  if (access.moduleId !== c.moduleId || access.reference !== intent.reference || access.flowId !== c.flowId || access.requestBindingVerifier !== c.requestBindingVerifier || access.requestBindingExpiresAtMillis !== c.requestBindingExpiresAtMillis || access.credentialDigest !== intent.credentialDigest || now < intent.issuedAtMillis || now >= intent.expiresAtMillis) return void 0;
160
160
  let application;
161
161
  if (row[i.state] === "Unbound") {