@yielded/auth-persistence-drizzle 0.1.0-beta.17 → 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.
- package/README.md +8 -1
- package/dist/D1.d.mts +120 -120
- package/dist/Libsql.d.mts +154 -154
- package/dist/Mysql2.d.mts +166 -166
- package/dist/Pglite.d.mts +166 -166
- package/dist/Postgres.d.mts +152 -152
- package/dist/SqliteBun.d.mts +168 -168
- package/dist/SqliteDo.d.mts +237 -259
- package/dist/SqliteDo.mjs +30 -45
- package/dist/SqliteDo.mjs.map +1 -1
- package/dist/SqliteNode.d.mts +154 -154
- package/dist/SqliteWasm.d.mts +163 -163
- package/dist/drizzle/crypto.mjs +11 -0
- package/dist/drizzle/crypto.mjs.map +1 -0
- package/dist/drizzle/d1-identity.mjs +2 -2
- package/dist/drizzle/d1-identity.mjs.map +1 -1
- package/dist/drizzle/d1-oauth.d.mts +16 -16
- package/dist/drizzle/d1-oauth.mjs.map +1 -1
- package/dist/drizzle/d1-passkey.d.mts +6 -6
- package/dist/drizzle/d1-passkey.mjs.map +1 -1
- package/dist/drizzle/d1-password-prepared.mjs +3 -3
- package/dist/drizzle/d1-password-prepared.mjs.map +1 -1
- package/dist/drizzle/d1-passwords.d.mts +1 -1
- package/dist/drizzle/d1-passwords.mjs +1 -1
- package/dist/drizzle/d1-passwords.mjs.map +1 -1
- package/dist/drizzle/d1-phone.d.mts +3 -3
- package/dist/drizzle/d1-phone.mjs.map +1 -1
- package/dist/drizzle/d1-proofs.d.mts +1 -1
- package/dist/drizzle/d1-sessions.d.mts +1 -1
- package/dist/drizzle/d1-sessions.mjs +4 -3
- package/dist/drizzle/d1-sessions.mjs.map +1 -1
- package/dist/drizzle/d1-totp.d.mts +3 -3
- package/dist/drizzle/d1-totp.mjs.map +1 -1
- package/dist/drizzle/mysql-identity.mjs +2 -2
- package/dist/drizzle/mysql-identity.mjs.map +1 -1
- package/dist/drizzle/oauth-accounts.mjs +9 -8
- package/dist/drizzle/oauth-accounts.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-collection.mjs +1 -1
- package/dist/drizzle/oauth-connected-collection.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-custody.mjs +5 -4
- package/dist/drizzle/oauth-connected-custody.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-drivers.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-flow.mjs +8 -7
- package/dist/drizzle/oauth-connected-flow.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-management.mjs +3 -2
- package/dist/drizzle/oauth-connected-management.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-reference.mjs +8 -4
- package/dist/drizzle/oauth-connected-reference.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-settlement.mjs +4 -4
- package/dist/drizzle/oauth-connected-settlement.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-sign-in.mjs +11 -10
- package/dist/drizzle/oauth-connected-sign-in.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-state.d.mts +265 -265
- package/dist/drizzle/oauth-connected-state.mjs +23 -20
- package/dist/drizzle/oauth-connected-state.mjs.map +1 -1
- package/dist/drizzle/oauth-connected-target.d.mts +105 -105
- package/dist/drizzle/oauth-connected-target.mjs.map +1 -1
- package/dist/drizzle/oauth-drivers.mjs.map +1 -1
- package/dist/drizzle/oauth-flow.mjs +1 -1
- package/dist/drizzle/oauth-flow.mjs.map +1 -1
- package/dist/drizzle/oauth-model.d.mts +4 -4
- package/dist/drizzle/oauth-model.mjs.map +1 -1
- package/dist/drizzle/oauth-registration.mjs +2 -2
- package/dist/drizzle/oauth-registration.mjs.map +1 -1
- package/dist/drizzle/oauth-state.mjs +11 -12
- package/dist/drizzle/oauth-state.mjs.map +1 -1
- package/dist/drizzle/oauth-target.d.mts +4 -4
- package/dist/drizzle/oauth-target.mjs.map +1 -1
- package/dist/drizzle/passkey-drivers.mjs.map +1 -1
- package/dist/drizzle/passkey-write-drivers.mjs.map +1 -1
- package/dist/drizzle/passkey-write-target.d.mts +1 -1
- package/dist/drizzle/password-prepared-sql.mjs +1 -1
- package/dist/drizzle/password-prepared-sql.mjs.map +1 -1
- package/dist/drizzle/password-prepared-state.mjs +1 -1
- package/dist/drizzle/pg-identity.mjs +2 -2
- package/dist/drizzle/pg-identity.mjs.map +1 -1
- package/dist/drizzle/phone-model.d.mts +2 -2
- package/dist/drizzle/phone-model.mjs +3 -3
- package/dist/drizzle/phone-model.mjs.map +1 -1
- package/dist/drizzle/phone-target.d.mts +1 -1
- package/dist/drizzle/phone-target.mjs +2 -2
- package/dist/drizzle/phone-target.mjs.map +1 -1
- package/dist/drizzle/sqlite-do-database.d.mts +29 -0
- package/dist/drizzle/sqlite-do-database.mjs +45 -0
- package/dist/drizzle/sqlite-do-database.mjs.map +1 -0
- package/dist/drizzle/sqlite-emails.mjs.map +1 -1
- package/dist/drizzle/sqlite-identity.mjs +2 -2
- package/dist/drizzle/sqlite-identity.mjs.map +1 -1
- package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
- package/dist/drizzle/sqlite-proofs.mjs.map +1 -1
- package/dist/drizzle/sqlite-sessions.mjs.map +1 -1
- package/dist/drizzle/storage-validation.mjs +17 -9
- package/dist/drizzle/storage-validation.mjs.map +1 -1
- package/dist/drizzle/totp-state.mjs +8 -8
- package/dist/drizzle/totp-state.mjs.map +1 -1
- package/dist/drizzle/totp-target.d.mts +1 -1
- package/dist/drizzle/totp-target.mjs +2 -2
- package/dist/drizzle/totp-target.mjs.map +1 -1
- package/package.json +1 -1
- package/src/SqliteDo.ts +63 -70
- package/src/drizzle/crypto.ts +14 -0
- package/src/drizzle/d1-identity.ts +2 -2
- package/src/drizzle/d1-oauth.ts +14 -5
- package/src/drizzle/d1-passkey.ts +5 -1
- package/src/drizzle/d1-password-prepared.ts +11 -5
- package/src/drizzle/d1-passwords.ts +1 -1
- package/src/drizzle/d1-phone.ts +2 -1
- package/src/drizzle/d1-sessions.ts +8 -2
- package/src/drizzle/d1-totp.ts +6 -2
- package/src/drizzle/mysql-identity.ts +2 -2
- package/src/drizzle/oauth-accounts.ts +14 -13
- package/src/drizzle/oauth-connected-collection.ts +1 -1
- package/src/drizzle/oauth-connected-custody.ts +8 -6
- package/src/drizzle/oauth-connected-drivers.ts +9 -3
- package/src/drizzle/oauth-connected-flow.ts +6 -6
- package/src/drizzle/oauth-connected-management.ts +1 -1
- package/src/drizzle/oauth-connected-reference.ts +14 -9
- package/src/drizzle/oauth-connected-settlement.ts +4 -4
- package/src/drizzle/oauth-connected-sign-in.ts +11 -10
- package/src/drizzle/oauth-connected-state.ts +40 -25
- package/src/drizzle/oauth-connected-target.ts +9 -5
- package/src/drizzle/oauth-drivers.ts +13 -5
- package/src/drizzle/oauth-flow.ts +1 -1
- package/src/drizzle/oauth-model.ts +4 -4
- package/src/drizzle/oauth-registration.ts +2 -2
- package/src/drizzle/oauth-state.ts +17 -15
- package/src/drizzle/oauth-target.ts +11 -3
- package/src/drizzle/passkey-drivers.ts +7 -3
- package/src/drizzle/passkey-write-drivers.ts +11 -2
- package/src/drizzle/password-prepared-sql.ts +1 -1
- package/src/drizzle/pg-identity.ts +2 -2
- package/src/drizzle/phone-model.ts +3 -3
- package/src/drizzle/phone-target.ts +11 -4
- package/src/drizzle/sqlite-do-database.ts +87 -0
- package/src/drizzle/sqlite-emails.ts +1 -1
- package/src/drizzle/sqlite-identity.ts +2 -2
- package/src/drizzle/sqlite-passwords.ts +1 -1
- package/src/drizzle/sqlite-proofs.ts +2 -2
- package/src/drizzle/sqlite-sessions.ts +2 -2
- package/src/drizzle/storage-validation.ts +15 -6
- package/src/drizzle/totp-state.ts +8 -8
- package/src/drizzle/totp-target.ts +11 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-sessions.mjs","names":[],"sources":["../../src/drizzle/sqlite-sessions.ts"],"sourcesContent":["import { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport type { LifecycleHooks, HookConfigurationError } from \"@yielded/auth/Hooks\";\nimport {\n AuthenticationAuthority,\n type SessionUnavailable,\n type PendingAuthentication,\n type SessionRepository,\n type SignedSessionValidity,\n type StatefulSessionPersistence,\n type SessionStepUpPersistence,\n} from \"@yielded/auth/Sessions\";\nimport type { AnyRelations } from \"drizzle-orm\";\nimport type { EffectLibsqlDatabase } from \"drizzle-orm/effect-libsql\";\nimport type { EffectSQLiteBunDatabase } from \"drizzle-orm/effect-sqlite-bun\";\nimport type { EffectSQLiteDoDatabase } from \"drizzle-orm/effect-sqlite-do\";\nimport type { EffectSQLiteNodeDatabase } from \"drizzle-orm/effect-sqlite-node\";\nimport type { EffectSQLiteWasmDatabase } from \"drizzle-orm/effect-sqlite-wasm\";\nimport type { AnySQLiteTable } from \"drizzle-orm/sqlite-core\";\nimport { Context, Effect } from \"effect\";\nimport type { SqlError } from \"effect/sql/SqlError\";\n\nimport { nativeDatabase } from \"./native-database\";\nimport type {\n AuthenticationAuthorityMapping,\n PendingAuthenticationMapping,\n SignedSessionValidityMapping,\n StatefulSessionMapping,\n} from \"./session-model\";\nimport { CurrentSessionSql } from \"./session-sql\";\nimport {\n coordinateTargetAuthenticationAuthority,\n coordinateTargetPendingAuthentication,\n coordinateTargetSignedSessionValidity,\n coordinateTargetStatefulSessions,\n makeTargetAuthenticationAuthorityServices,\n makeTargetPendingAuthenticationServices,\n makeTargetSignedSessionValidityServices,\n makeTargetStatefulSessionServices,\n type SessionTargetConfiguration,\n makeTargetSessionStepUpServices,\n coordinateTargetSessionStepUp,\n} from \"./session-target\";\nimport {\n type TransactionService,\n acquireTransactionService,\n transactionService,\n} from \"./standalone-guard\";\nimport type { SuppliedService } from \"./SuppliedService\";\n\ntype Database =\n | EffectLibsqlDatabase<AnyRelations>\n | EffectSQLiteBunDatabase<AnyRelations>\n | EffectSQLiteDoDatabase<AnyRelations>\n | EffectSQLiteNodeDatabase<AnyRelations>\n | EffectSQLiteWasmDatabase<AnyRelations>;\ntype TransactionOf<D extends Database> = Parameters<Parameters<D[\"transaction\"]>[0]>[0];\n\nexport const sqliteSessionConfiguration = (\n mode: \"interactive\" | \"synchronous\",\n standaloneGuard: Effect.Effect<void, SessionUnavailable>,\n coordinatorGuard?: Effect.Effect<void, SessionUnavailable>,\n): SessionTargetConfiguration => ({\n mode,\n locking: false,\n standaloneGuard,\n ...(coordinatorGuard === undefined ? {} : { coordinatorGuard }),\n});\n\nexport const makeSqliteAuthenticationAuthorityServices = <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n>(\n mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>,\n configuration: SessionTargetConfiguration,\n) => makeTargetAuthenticationAuthorityServices<Claims>(mapping, configuration);\n\nexport const makeSqlitePendingAuthenticationServices = <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\n>(\n mapping: PendingAuthenticationMapping<Claims, S, C, P, F, NativeId>,\n configuration: SessionTargetConfiguration,\n) => makeTargetPendingAuthenticationServices<Claims>(mapping, configuration);\n\nexport const makeSqliteStatefulSessionServices = <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n>(\n mapping: StatefulSessionMapping<Claims, S, C, Session, F, P, NativeId, NativeSessionId>,\n configuration: SessionTargetConfiguration,\n) => makeTargetStatefulSessionServices<Claims>(mapping, configuration);\n\nexport const makeSqliteSignedSessionValidityServices = <\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n>(\n mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>,\n configuration: SessionTargetConfiguration,\n) => makeTargetSignedSessionValidityServices(mapping, configuration);\n\nexport const coordinateSqliteAuthenticationAuthority = <\n Claims,\n D extends Database,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n A,\n E,\n R,\n>(\n database: D,\n mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: { readonly authenticationAuthority: AuthenticationAuthority[\"Service\"] },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetAuthenticationAuthority<Claims, TransactionOf<D>, A, E, R>(\n database,\n mapping,\n configuration,\n owner,\n );\n\nexport const coordinateSqlitePendingAuthentication = <\n Claims,\n D extends Database,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\n A,\n E,\n R,\n>(\n database: D,\n mapping: PendingAuthenticationMapping<Claims, S, C, P, F, NativeId>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: { readonly pendingAuthentication: PendingAuthentication<Claims> },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetPendingAuthentication<Claims, TransactionOf<D>, A, E, R>(\n database,\n mapping,\n configuration,\n owner,\n );\n\nexport const coordinateSqliteStatefulSessions = <\n Claims,\n D extends Database,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n>(\n database: D,\n mapping: StatefulSessionMapping<Claims, S, C, Session, F, P, NativeId, NativeSessionId>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: {\n readonly statefulSessionPersistence: StatefulSessionPersistence<Claims>;\n readonly sessionRepository: SessionRepository;\n },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetStatefulSessions<Claims, TransactionOf<D>, A, E, R>(\n database,\n mapping,\n configuration,\n owner,\n );\n\nexport const coordinateSqliteSignedSessionValidity = <\n D extends Database,\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n>(\n database: D,\n mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: { readonly signedSessionValidity: SignedSessionValidity },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetSignedSessionValidity<TransactionOf<D>, A, E, R>(\n database,\n mapping,\n configuration,\n owner,\n );\n\nexport const makeSqliteSessionTarget = <\n DatabaseId,\n D extends Database,\n Synchronous extends boolean = false,\n>(\n databaseService: Context.Service<DatabaseId, D>,\n configuration:\n | SessionTargetConfiguration\n | ((service: TransactionService | undefined) => SessionTargetConfiguration),\n) => {\n const configurationFor = (database: D) =>\n typeof configuration === \"function\"\n ? configuration(transactionService(database))\n : configuration;\n\n const standaloneConfiguration =\n typeof configuration === \"function\"\n ? Effect.map(acquireTransactionService(databaseService), configuration)\n : Effect.succeed(configuration);\n\n function coordinateSessionStepUp<\n Database extends D,\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: SessionStepUpMapping<\n NoInfer<Claims>,\n S,\n C,\n I,\n Session,\n T,\n NativeId,\n NativeSessionId\n >;\n readonly target: SuppliedService<Id, SessionStepUpPersistence<Claims>>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<Id> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n (Synchronous extends true ? never : Exclude<R, Id>) | LifecycleHooks | DatabaseRequirements\n >;\n function coordinateSessionStepUp<\n Database extends D,\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: SessionStepUpMapping<\n NoInfer<Claims>,\n S,\n C,\n I,\n Session,\n T,\n NativeId,\n NativeSessionId\n >;\n readonly target: SuppliedService<Id, SessionStepUpPersistence<Claims>>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<Id | TxId> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, Id | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateSessionStepUp<\n Database extends D,\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: SessionStepUpMapping<\n NoInfer<Claims>,\n S,\n C,\n I,\n Session,\n T,\n NativeId,\n NativeSessionId\n >;\n readonly target: SuppliedService<Id, SessionStepUpPersistence<Claims>>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, Id> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqliteSessionStepUp(\n database,\n options.mapping,\n options.target,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: { readonly sessionStepUpPersistence: SessionStepUpPersistence<Claims> },\n ) => {\n const provided = Context.make(options.target, services.sessionStepUpPersistence);\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 coordinateAuthenticationAuthority<\n Database extends D,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<AuthenticationAuthority> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, AuthenticationAuthority>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateAuthenticationAuthority<\n Database extends D,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\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: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<AuthenticationAuthority | TxId> : R\n >,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, AuthenticationAuthority | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateAuthenticationAuthority<\n Database extends D,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\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: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, AuthenticationAuthority> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqliteAuthenticationAuthority(\n database,\n options.mapping,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: { readonly authenticationAuthority: AuthenticationAuthority[\"Service\"] },\n ) => {\n const provided = Context.make(AuthenticationAuthority, services.authenticationAuthority);\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 coordinatePendingAuthentication<\n Database extends D,\n TargetId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: PendingAuthenticationMapping<NoInfer<Claims>, S, C, P, F, NativeId>;\n readonly target: SuppliedService<TargetId, PendingAuthentication<Claims>>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TargetId> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinatePendingAuthentication<\n Database extends D,\n TargetId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\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: PendingAuthenticationMapping<NoInfer<Claims>, S, C, P, F, NativeId>;\n readonly target: SuppliedService<TargetId, PendingAuthentication<Claims>>;\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 E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinatePendingAuthentication<\n Database extends D,\n TargetId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\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: PendingAuthenticationMapping<NoInfer<Claims>, S, C, P, F, NativeId>;\n readonly target: SuppliedService<TargetId, PendingAuthentication<Claims>>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, TargetId> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqlitePendingAuthentication(\n database,\n options.mapping,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: { readonly pendingAuthentication: PendingAuthentication<Claims> },\n ) => {\n const provided = Context.make(options.target, services.pendingAuthentication);\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 coordinateStatefulSessions<\n Database extends D,\n PersistenceId,\n RepositoryId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: StatefulSessionMapping<\n NoInfer<Claims>,\n S,\n C,\n Session,\n F,\n P,\n NativeId,\n NativeSessionId\n >;\n readonly persistence: SuppliedService<PersistenceId, StatefulSessionPersistence<Claims>>;\n readonly repository: SuppliedService<RepositoryId, SessionRepository>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<PersistenceId | RepositoryId> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, PersistenceId | RepositoryId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateStatefulSessions<\n Database extends D,\n PersistenceId,\n RepositoryId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: StatefulSessionMapping<\n NoInfer<Claims>,\n S,\n C,\n Session,\n F,\n P,\n NativeId,\n NativeSessionId\n >;\n readonly persistence: SuppliedService<PersistenceId, StatefulSessionPersistence<Claims>>;\n readonly repository: SuppliedService<RepositoryId, SessionRepository>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<PersistenceId | RepositoryId | TxId> : R\n >,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, PersistenceId | RepositoryId | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateStatefulSessions<\n Database extends D,\n PersistenceId,\n RepositoryId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: StatefulSessionMapping<\n NoInfer<Claims>,\n S,\n C,\n Session,\n F,\n P,\n NativeId,\n NativeSessionId\n >;\n readonly persistence: SuppliedService<PersistenceId, StatefulSessionPersistence<Claims>>;\n readonly repository: SuppliedService<RepositoryId, SessionRepository>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, PersistenceId | RepositoryId> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqliteStatefulSessions(\n database,\n options.mapping,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: {\n readonly statefulSessionPersistence: StatefulSessionPersistence<Claims>;\n readonly sessionRepository: SessionRepository;\n },\n ) => {\n const provided = Context.make(\n options.persistence,\n services.statefulSessionPersistence,\n ).pipe(Context.add(options.repository, services.sessionRepository));\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 coordinateSignedSessionValidity<\n Database extends D,\n TargetId,\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>;\n readonly target: SuppliedService<TargetId, SignedSessionValidity>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TargetId> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateSignedSessionValidity<\n Database extends D,\n TargetId,\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>;\n readonly target: SuppliedService<TargetId, SignedSessionValidity>;\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 E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateSignedSessionValidity<\n Database extends D,\n TargetId,\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>;\n readonly target: SuppliedService<TargetId, SignedSessionValidity>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, TargetId> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqliteSignedSessionValidity(\n database,\n options.mapping,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: { readonly signedSessionValidity: SignedSessionValidity },\n ) => {\n const provided = Context.make(options.target, services.signedSessionValidity);\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 makeSessionStepUpServices: <\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n >(\n mapping: SessionStepUpMapping<\n NoInfer<Claims>,\n S,\n C,\n I,\n Session,\n T,\n NativeId,\n NativeSessionId\n >,\n target: Context.Service<Id, SessionStepUpPersistence<Claims>>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqliteSessionStepUpServices(mapping, target, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateSessionStepUp,\n makeAuthenticationAuthorityServices: <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n >(\n mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqliteAuthenticationAuthorityServices(mapping, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makePendingAuthenticationServices: <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\n >(\n mapping: PendingAuthenticationMapping<Claims, S, C, P, F, NativeId>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqlitePendingAuthenticationServices(mapping, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeStatefulSessionServices: <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n >(\n mapping: StatefulSessionMapping<Claims, S, C, Session, F, P, NativeId, NativeSessionId>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqliteStatefulSessionServices(mapping, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeSignedSessionValidityServices: <\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n >(\n mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqliteSignedSessionValidityServices(mapping, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateAuthenticationAuthority,\n coordinatePendingAuthentication,\n coordinateStatefulSessions,\n coordinateSignedSessionValidity,\n };\n};\n\nimport type { SessionStepUpMapping } from \"./step-up-model\";\n\nexport const makeSqliteSessionStepUpServices = <\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n>(\n mapping: SessionStepUpMapping<NoInfer<Claims>, S, C, I, Session, T, NativeId, NativeSessionId>,\n target: Context.Service<Id, SessionStepUpPersistence<Claims>>,\n configuration: SessionTargetConfiguration,\n) => makeTargetSessionStepUpServices(mapping, target, configuration);\n\nexport const coordinateSqliteSessionStepUp = <\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n D extends Database,\n A,\n E,\n R,\n>(\n database: D,\n mapping: SessionStepUpMapping<NoInfer<Claims>, S, C, I, Session, T, NativeId, NativeSessionId>,\n target: Context.Service<Id, SessionStepUpPersistence<Claims>>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: { readonly sessionStepUpPersistence: SessionStepUpPersistence<Claims> },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetSessionStepUp<Claims, Id, TransactionOf<D>, A, E, R>(\n database,\n mapping,\n target,\n configuration,\n owner,\n );\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sqlite-sessions.mjs","names":[],"sources":["../../src/drizzle/sqlite-sessions.ts"],"sourcesContent":["import { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport type { LifecycleHooks, HookConfigurationError } from \"@yielded/auth/Hooks\";\nimport {\n AuthenticationAuthority,\n type SessionUnavailable,\n type PendingAuthentication,\n type SessionRepository,\n type SignedSessionValidity,\n type StatefulSessionPersistence,\n type SessionStepUpPersistence,\n} from \"@yielded/auth/Sessions\";\nimport type { AnyRelations } from \"drizzle-orm\";\nimport type { EffectLibsqlDatabase } from \"drizzle-orm/effect-libsql\";\nimport type { EffectSQLiteBunDatabase } from \"drizzle-orm/effect-sqlite-bun\";\nimport type { EffectSQLiteNodeDatabase } from \"drizzle-orm/effect-sqlite-node\";\nimport type { EffectSQLiteWasmDatabase } from \"drizzle-orm/effect-sqlite-wasm\";\nimport type { AnySQLiteTable } from \"drizzle-orm/sqlite-core\";\nimport { Context, Effect } from \"effect\";\nimport type { SqlError } from \"effect/sql/SqlError\";\n\nimport { nativeDatabase } from \"./native-database\";\nimport type {\n AuthenticationAuthorityMapping,\n PendingAuthenticationMapping,\n SignedSessionValidityMapping,\n StatefulSessionMapping,\n} from \"./session-model\";\nimport { CurrentSessionSql } from \"./session-sql\";\nimport {\n coordinateTargetAuthenticationAuthority,\n coordinateTargetPendingAuthentication,\n coordinateTargetSignedSessionValidity,\n coordinateTargetStatefulSessions,\n makeTargetAuthenticationAuthorityServices,\n makeTargetPendingAuthenticationServices,\n makeTargetSignedSessionValidityServices,\n makeTargetStatefulSessionServices,\n type SessionTargetConfiguration,\n makeTargetSessionStepUpServices,\n coordinateTargetSessionStepUp,\n} from \"./session-target\";\nimport type { DatabaseValue } from \"./sqlite-do-database\";\nimport {\n type TransactionService,\n acquireTransactionService,\n transactionService,\n} from \"./standalone-guard\";\nimport type { SuppliedService } from \"./SuppliedService\";\n\ntype Database =\n | EffectLibsqlDatabase<AnyRelations>\n | EffectSQLiteBunDatabase<AnyRelations>\n | DatabaseValue<AnyRelations>\n | EffectSQLiteNodeDatabase<AnyRelations>\n | EffectSQLiteWasmDatabase<AnyRelations>;\ntype TransactionOf<D extends Database> = Parameters<Parameters<D[\"transaction\"]>[0]>[0];\n\nexport const sqliteSessionConfiguration = (\n mode: \"interactive\" | \"synchronous\",\n standaloneGuard: Effect.Effect<void, SessionUnavailable>,\n coordinatorGuard?: Effect.Effect<void, SessionUnavailable>,\n): SessionTargetConfiguration => ({\n mode,\n locking: false,\n standaloneGuard,\n ...(coordinatorGuard === undefined ? {} : { coordinatorGuard }),\n});\n\nexport const makeSqliteAuthenticationAuthorityServices = <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n>(\n mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>,\n configuration: SessionTargetConfiguration,\n) => makeTargetAuthenticationAuthorityServices<Claims>(mapping, configuration);\n\nexport const makeSqlitePendingAuthenticationServices = <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\n>(\n mapping: PendingAuthenticationMapping<Claims, S, C, P, F, NativeId>,\n configuration: SessionTargetConfiguration,\n) => makeTargetPendingAuthenticationServices<Claims>(mapping, configuration);\n\nexport const makeSqliteStatefulSessionServices = <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n>(\n mapping: StatefulSessionMapping<Claims, S, C, Session, F, P, NativeId, NativeSessionId>,\n configuration: SessionTargetConfiguration,\n) => makeTargetStatefulSessionServices<Claims>(mapping, configuration);\n\nexport const makeSqliteSignedSessionValidityServices = <\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n>(\n mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>,\n configuration: SessionTargetConfiguration,\n) => makeTargetSignedSessionValidityServices(mapping, configuration);\n\nexport const coordinateSqliteAuthenticationAuthority = <\n Claims,\n D extends Database,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n A,\n E,\n R,\n>(\n database: D,\n mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: { readonly authenticationAuthority: AuthenticationAuthority[\"Service\"] },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetAuthenticationAuthority<Claims, TransactionOf<D>, A, E, R>(\n database,\n mapping,\n configuration,\n owner,\n );\n\nexport const coordinateSqlitePendingAuthentication = <\n Claims,\n D extends Database,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\n A,\n E,\n R,\n>(\n database: D,\n mapping: PendingAuthenticationMapping<Claims, S, C, P, F, NativeId>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: { readonly pendingAuthentication: PendingAuthentication<Claims> },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetPendingAuthentication<Claims, TransactionOf<D>, A, E, R>(\n database,\n mapping,\n configuration,\n owner,\n );\n\nexport const coordinateSqliteStatefulSessions = <\n Claims,\n D extends Database,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n>(\n database: D,\n mapping: StatefulSessionMapping<Claims, S, C, Session, F, P, NativeId, NativeSessionId>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: {\n readonly statefulSessionPersistence: StatefulSessionPersistence<Claims>;\n readonly sessionRepository: SessionRepository;\n },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetStatefulSessions<Claims, TransactionOf<D>, A, E, R>(\n database,\n mapping,\n configuration,\n owner,\n );\n\nexport const coordinateSqliteSignedSessionValidity = <\n D extends Database,\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n>(\n database: D,\n mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: { readonly signedSessionValidity: SignedSessionValidity },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetSignedSessionValidity<TransactionOf<D>, A, E, R>(\n database,\n mapping,\n configuration,\n owner,\n );\n\nexport const makeSqliteSessionTarget = <\n DatabaseId,\n D extends Database,\n Synchronous extends boolean = false,\n>(\n databaseService: Context.Service<DatabaseId, D>,\n configuration:\n | SessionTargetConfiguration\n | ((service: TransactionService | undefined) => SessionTargetConfiguration),\n) => {\n const configurationFor = (database: D) =>\n typeof configuration === \"function\"\n ? configuration(transactionService(database))\n : configuration;\n\n const standaloneConfiguration =\n typeof configuration === \"function\"\n ? Effect.map(acquireTransactionService(databaseService), configuration)\n : Effect.succeed(configuration);\n\n function coordinateSessionStepUp<\n Database extends D,\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: SessionStepUpMapping<\n NoInfer<Claims>,\n S,\n C,\n I,\n Session,\n T,\n NativeId,\n NativeSessionId\n >;\n readonly target: SuppliedService<Id, SessionStepUpPersistence<Claims>>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<Id> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n (Synchronous extends true ? never : Exclude<R, Id>) | LifecycleHooks | DatabaseRequirements\n >;\n function coordinateSessionStepUp<\n Database extends D,\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: SessionStepUpMapping<\n NoInfer<Claims>,\n S,\n C,\n I,\n Session,\n T,\n NativeId,\n NativeSessionId\n >;\n readonly target: SuppliedService<Id, SessionStepUpPersistence<Claims>>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<Id | TxId> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, Id | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateSessionStepUp<\n Database extends D,\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: SessionStepUpMapping<\n NoInfer<Claims>,\n S,\n C,\n I,\n Session,\n T,\n NativeId,\n NativeSessionId\n >;\n readonly target: SuppliedService<Id, SessionStepUpPersistence<Claims>>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, Id> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqliteSessionStepUp(\n database,\n options.mapping,\n options.target,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: { readonly sessionStepUpPersistence: SessionStepUpPersistence<Claims> },\n ) => {\n const provided = Context.make(options.target, services.sessionStepUpPersistence);\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 coordinateAuthenticationAuthority<\n Database extends D,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<AuthenticationAuthority> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, AuthenticationAuthority>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateAuthenticationAuthority<\n Database extends D,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\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: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<AuthenticationAuthority | TxId> : R\n >,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, AuthenticationAuthority | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateAuthenticationAuthority<\n Database extends D,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\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: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, AuthenticationAuthority> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqliteAuthenticationAuthority(\n database,\n options.mapping,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: { readonly authenticationAuthority: AuthenticationAuthority[\"Service\"] },\n ) => {\n const provided = Context.make(AuthenticationAuthority, services.authenticationAuthority);\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 coordinatePendingAuthentication<\n Database extends D,\n TargetId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: PendingAuthenticationMapping<NoInfer<Claims>, S, C, P, F, NativeId>;\n readonly target: SuppliedService<TargetId, PendingAuthentication<Claims>>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TargetId> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinatePendingAuthentication<\n Database extends D,\n TargetId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\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: PendingAuthenticationMapping<NoInfer<Claims>, S, C, P, F, NativeId>;\n readonly target: SuppliedService<TargetId, PendingAuthentication<Claims>>;\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 E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinatePendingAuthentication<\n Database extends D,\n TargetId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\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: PendingAuthenticationMapping<NoInfer<Claims>, S, C, P, F, NativeId>;\n readonly target: SuppliedService<TargetId, PendingAuthentication<Claims>>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, TargetId> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqlitePendingAuthentication(\n database,\n options.mapping,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: { readonly pendingAuthentication: PendingAuthentication<Claims> },\n ) => {\n const provided = Context.make(options.target, services.pendingAuthentication);\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 coordinateStatefulSessions<\n Database extends D,\n PersistenceId,\n RepositoryId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: StatefulSessionMapping<\n NoInfer<Claims>,\n S,\n C,\n Session,\n F,\n P,\n NativeId,\n NativeSessionId\n >;\n readonly persistence: SuppliedService<PersistenceId, StatefulSessionPersistence<Claims>>;\n readonly repository: SuppliedService<RepositoryId, SessionRepository>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<PersistenceId | RepositoryId> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, PersistenceId | RepositoryId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateStatefulSessions<\n Database extends D,\n PersistenceId,\n RepositoryId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: StatefulSessionMapping<\n NoInfer<Claims>,\n S,\n C,\n Session,\n F,\n P,\n NativeId,\n NativeSessionId\n >;\n readonly persistence: SuppliedService<PersistenceId, StatefulSessionPersistence<Claims>>;\n readonly repository: SuppliedService<RepositoryId, SessionRepository>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<\n A,\n E,\n Synchronous extends true ? NoInfer<PersistenceId | RepositoryId | TxId> : R\n >,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, PersistenceId | RepositoryId | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateStatefulSessions<\n Database extends D,\n PersistenceId,\n RepositoryId,\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: StatefulSessionMapping<\n NoInfer<Claims>,\n S,\n C,\n Session,\n F,\n P,\n NativeId,\n NativeSessionId\n >;\n readonly persistence: SuppliedService<PersistenceId, StatefulSessionPersistence<Claims>>;\n readonly repository: SuppliedService<RepositoryId, SessionRepository>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, PersistenceId | RepositoryId> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqliteStatefulSessions(\n database,\n options.mapping,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: {\n readonly statefulSessionPersistence: StatefulSessionPersistence<Claims>;\n readonly sessionRepository: SessionRepository;\n },\n ) => {\n const provided = Context.make(\n options.persistence,\n services.statefulSessionPersistence,\n ).pipe(Context.add(options.repository, services.sessionRepository));\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 coordinateSignedSessionValidity<\n Database extends D,\n TargetId,\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n A,\n E,\n R,\n DatabaseError,\n DatabaseRequirements,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>;\n readonly target: SuppliedService<TargetId, SignedSessionValidity>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TargetId> : R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateSignedSessionValidity<\n Database extends D,\n TargetId,\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>;\n readonly target: SuppliedService<TargetId, SignedSessionValidity>;\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 E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TargetId | TxId>)\n | LifecycleHooks\n | DatabaseRequirements\n >;\n function coordinateSignedSessionValidity<\n Database extends D,\n TargetId,\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\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: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>;\n readonly target: SuppliedService<TargetId, SignedSessionValidity>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n E | SessionUnavailable | HookConfigurationError | SqlError | DatabaseError,\n Exclude<R, TargetId> | LifecycleHooks | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateSqliteSignedSessionValidity(\n database,\n options.mapping,\n configurationFor(database),\n (\n transaction: TransactionOf<Database>,\n services: { readonly signedSessionValidity: SignedSessionValidity },\n ) => {\n const provided = Context.make(options.target, services.signedSessionValidity);\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 makeSessionStepUpServices: <\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n >(\n mapping: SessionStepUpMapping<\n NoInfer<Claims>,\n S,\n C,\n I,\n Session,\n T,\n NativeId,\n NativeSessionId\n >,\n target: Context.Service<Id, SessionStepUpPersistence<Claims>>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqliteSessionStepUpServices(mapping, target, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateSessionStepUp,\n makeAuthenticationAuthorityServices: <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n >(\n mapping: AuthenticationAuthorityMapping<Claims, S, C, F, P, NativeId>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqliteAuthenticationAuthorityServices(mapping, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makePendingAuthenticationServices: <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n P extends AnySQLiteTable,\n F extends AnySQLiteTable,\n NativeId,\n >(\n mapping: PendingAuthenticationMapping<Claims, S, C, P, F, NativeId>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqlitePendingAuthenticationServices(mapping, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeStatefulSessionServices: <\n Claims,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n F extends AnySQLiteTable,\n P extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n >(\n mapping: StatefulSessionMapping<Claims, S, C, Session, F, P, NativeId, NativeSessionId>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqliteStatefulSessionServices(mapping, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n makeSignedSessionValidityServices: <\n S extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n >(\n mapping: SignedSessionValidityMapping<S, T, NativeId, NativeSessionId>,\n ) =>\n Effect.flatMap(standaloneConfiguration, (configuration) =>\n makeSqliteSignedSessionValidityServices(mapping, configuration),\n ).pipe(\n Effect.provideServiceEffect(CurrentSessionSql, nativeDatabase(databaseService)),\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateAuthenticationAuthority,\n coordinatePendingAuthentication,\n coordinateStatefulSessions,\n coordinateSignedSessionValidity,\n };\n};\n\nimport type { SessionStepUpMapping } from \"./step-up-model\";\n\nexport const makeSqliteSessionStepUpServices = <\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n>(\n mapping: SessionStepUpMapping<NoInfer<Claims>, S, C, I, Session, T, NativeId, NativeSessionId>,\n target: Context.Service<Id, SessionStepUpPersistence<Claims>>,\n configuration: SessionTargetConfiguration,\n) => makeTargetSessionStepUpServices(mapping, target, configuration);\n\nexport const coordinateSqliteSessionStepUp = <\n Claims,\n Id,\n S extends AnySQLiteTable,\n C extends AnySQLiteTable,\n I extends AnySQLiteTable,\n Session extends AnySQLiteTable,\n T extends AnySQLiteTable,\n NativeId,\n NativeSessionId,\n D extends Database,\n A,\n E,\n R,\n>(\n database: D,\n mapping: SessionStepUpMapping<NoInfer<Claims>, S, C, I, Session, T, NativeId, NativeSessionId>,\n target: Context.Service<Id, SessionStepUpPersistence<Claims>>,\n configuration: SessionTargetConfiguration,\n owner: (\n transaction: TransactionOf<D>,\n services: { readonly sessionStepUpPersistence: SessionStepUpPersistence<Claims> },\n ) => Effect.Effect<A, E, R>,\n) =>\n coordinateTargetSessionStepUp<Claims, Id, TransactionOf<D>, A, E, R>(\n database,\n mapping,\n target,\n configuration,\n owner,\n );\n"],"mappings":";;;;;;;;AAyDA,MAAa,8BACX,MACA,iBACA,sBACgC;CAChC;CACA,SAAS;CACT;CACA,GAAI,qBAAqB,KAAA,IAAY,CAAC,IAAI,EAAE,iBAAiB;AAC/D;AAEA,MAAa,6CAQX,SACA,kBACG,0CAAkD,SAAS,aAAa;AAE7E,MAAa,2CAQX,SACA,kBACG,wCAAgD,SAAS,aAAa;AAE3E,MAAa,qCAUX,SACA,kBACG,kCAA0C,SAAS,aAAa;AAErE,MAAa,2CAMX,SACA,kBACG,wCAAwC,SAAS,aAAa;AAEnE,MAAa,2CAYX,UACA,SACA,eACA,UAKA,wCACE,UACA,SACA,eACA,KACF;AAEF,MAAa,yCAYX,UACA,SACA,eACA,UAKA,sCACE,UACA,SACA,eACA,KACF;AAEF,MAAa,oCAcX,UACA,SACA,eACA,UAQA,iCACE,UACA,SACA,eACA,KACF;AAEF,MAAa,yCAUX,UACA,SACA,eACA,UAKA,sCACE,UACA,SACA,eACA,KACF;AAEF,MAAa,2BAKX,iBACA,kBAGG;CACH,MAAM,oBAAoB,aACxB,OAAO,kBAAkB,aACrB,cAAc,mBAAmB,QAAQ,CAAC,IAC1C;CAEN,MAAM,0BACJ,OAAO,kBAAkB,aACrB,OAAO,IAAI,0BAA0B,eAAe,GAAG,aAAa,IACpE,OAAO,QAAQ,aAAa;CAkFlC,SAAS,wBAmBP,SACA,SAcA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,8BACE,UACA,QAAQ,SACR,QAAQ,QACR,iBAAiB,QAAQ,IAEvB,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KAAK,QAAQ,QAAQ,SAAS,wBAAwB;GAC/E,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;CA6DA,SAAS,kCAgBP,SACA,SAIA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,wCACE,UACA,QAAQ,SACR,iBAAiB,QAAQ,IAEvB,aACA,aACG;GACH,MAAM,WAAW,QAAQ,KAAK,yBAAyB,SAAS,uBAAuB;GACvF,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;CA6DA,SAAS,gCAiBP,SACA,SAKA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,sCACE,UACA,QAAQ,SACR,iBAAiB,QAAQ,IAEvB,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;CA2FA,SAAS,2BAoBP,SACA,SAeA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,iCACE,UACA,QAAQ,SACR,iBAAiB,QAAQ,IAEvB,aACA,aAIG;GACH,MAAM,WAAW,QAAQ,KACvB,QAAQ,aACR,SAAS,0BACX,CAAC,CAAC,KAAK,QAAQ,IAAI,QAAQ,YAAY,SAAS,iBAAiB,CAAC;GAElE,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;CAyDA,SAAS,gCAeP,SACA,SAKA,MAKA;EACA,OAAO,OAAO,QAAQ,eAAe,OAAO,IAAI,aAC9C,sCACE,UACA,QAAQ,SACR,iBAAiB,QAAQ,IAEvB,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,4BAWE,SAUA,WAEA,OAAO,QAAQ,0BAA0B,kBACvC,gCAAgC,SAAS,QAAQ,aAAa,CAChE,CAAC,CAAC,KACA,OAAO,qBAAqB,mBAAmB,eAAe,eAAe,CAAC,GAC9E,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF;EACA,sCAQE,YAEA,OAAO,QAAQ,0BAA0B,kBACvC,0CAA0C,SAAS,aAAa,CAClE,CAAC,CAAC,KACA,OAAO,qBAAqB,mBAAmB,eAAe,eAAe,CAAC,GAC9E,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,oCAQE,YAEA,OAAO,QAAQ,0BAA0B,kBACvC,wCAAwC,SAAS,aAAa,CAChE,CAAC,CAAC,KACA,OAAO,qBAAqB,mBAAmB,eAAe,eAAe,CAAC,GAC9E,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,8BAUE,YAEA,OAAO,QAAQ,0BAA0B,kBACvC,kCAAkC,SAAS,aAAa,CAC1D,CAAC,CAAC,KACA,OAAO,qBAAqB,mBAAmB,eAAe,eAAe,CAAC,GAC9E,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF,oCAME,YAEA,OAAO,QAAQ,0BAA0B,kBACvC,wCAAwC,SAAS,aAAa,CAChE,CAAC,CAAC,KACA,OAAO,qBAAqB,mBAAmB,eAAe,eAAe,CAAC,GAC9E,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;EACF;EACA;EACA;EACA;CACF;AACF;AAIA,MAAa,mCAWX,SACA,QACA,kBACG,gCAAgC,SAAS,QAAQ,aAAa;AAEnE,MAAa,iCAeX,UACA,SACA,QACA,eACA,UAKA,8BACE,UACA,SACA,QACA,eACA,KACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NativeDatabase, PersistenceMappingError,
|
|
1
|
+
import { NativeDatabase, PersistenceMappingError, validateStorageBatch } from "@yielded/auth-persistence/Adapter";
|
|
2
2
|
import { Table, getTableColumns, getTableName, is } from "drizzle-orm";
|
|
3
3
|
import { Effect, Predicate, Schema } from "effect";
|
|
4
4
|
import { MySqlTable, getTableConfig } from "drizzle-orm/mysql-core";
|
|
@@ -210,20 +210,28 @@ const validateDrizzleStorage = Effect.fnUntraced(function* (mapping) {
|
|
|
210
210
|
})
|
|
211
211
|
});
|
|
212
212
|
const { $client: client } = yield* NativeDatabase;
|
|
213
|
+
const batches = /* @__PURE__ */ new Map();
|
|
213
214
|
for (const plan of physical) {
|
|
214
215
|
const pg = is(plan.table, PgTable);
|
|
215
216
|
const mysql = is(plan.table, MySqlTable);
|
|
216
217
|
const schema = pg ? getTableConfig$1(plan.table).schema : mysql ? getTableConfig(plan.table).schema : void 0;
|
|
217
218
|
const columns = getTableColumns(plan.table);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
219
|
+
const dialect = pg ? "pg" : mysql ? "mysql" : "sqlite";
|
|
220
|
+
const batch = batches.get(dialect) ?? [];
|
|
221
|
+
batch.push({
|
|
222
|
+
table: {
|
|
223
|
+
name: getTableName(plan.table),
|
|
224
|
+
...schema === void 0 ? {} : { schema },
|
|
225
|
+
columns: Object.fromEntries(plan.keys.map((key) => [key, { name: columns[key].name }]))
|
|
226
|
+
},
|
|
227
|
+
required: [plan.keys]
|
|
228
|
+
});
|
|
229
|
+
batches.set(dialect, batch);
|
|
226
230
|
}
|
|
231
|
+
for (const [dialect, requirements] of batches) yield* validateStorageBatch(dialect, requirements).pipe(Effect.provideService(SqlClient, client), Effect.mapError(() => PersistenceMappingError.make({
|
|
232
|
+
operation: "mapping",
|
|
233
|
+
cause: "Required SQL storage key is unavailable"
|
|
234
|
+
})));
|
|
227
235
|
}, Effect.catchDefect(() => Effect.fail(PersistenceMappingError.make({
|
|
228
236
|
operation: "mapping",
|
|
229
237
|
cause: "Cannot inspect SQL storage metadata"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-validation.mjs","names":["getPgTableConfig","getMysqlTableConfig"],"sources":["../../src/drizzle/storage-validation.ts"],"sourcesContent":["import {\n NativeDatabase,\n PersistenceMappingError,\n validateStorage,\n} from \"@yielded/auth-persistence/Adapter\";\nimport { getTableColumns, getTableName, is, Table } from \"drizzle-orm\";\nimport { getTableConfig as getMysqlTableConfig, MySqlTable } from \"drizzle-orm/mysql-core\";\nimport { getTableConfig as getPgTableConfig, PgTable } from \"drizzle-orm/pg-core\";\nimport { Effect, Predicate, Schema } from \"effect\";\nimport { SqlClient } from \"effect/sql/SqlClient\";\n\n// These are mapping contracts, not a parser for arbitrary constraint declarations.\n// Role aliases are explicit because their documentation names differ from mapping fields.\nconst uniquePlans: Readonly<Record<string, readonly [string, ReadonlyArray<string>]>> = {\n \"unique(abuseEvent.moduleId,abuseEvent.action,abuseEvent.scopeKind,abuseEvent.scopeKey,abuseEvent.commandId)\":\n [\"abuseEvent\", [\"moduleId\", \"action\", \"scopeKind\", \"scopeKey\", \"commandId\"]],\n \"unique(admission.moduleId)\": [\"admission\", [\"moduleId\"]],\n \"unique(attempt.moduleId,attempt.attemptId)\": [\"attempt\", [\"moduleId\", \"attemptId\"]],\n \"unique(authority.subjectId,authority.credentialId)\": [\n \"authority\",\n [\"subjectId\", \"credentialId\"],\n ],\n \"unique(authorityCredential.subjectId,authorityCredential.credentialId)\": [\n \"authorityCredential\",\n [\"subjectId\", \"credentialId\"],\n ],\n \"unique(charge.moduleId,charge.action,charge.scopeKind,charge.scopeKey,charge.attemptId)\": [\n \"charge\",\n [\"moduleId\", \"action\", \"scopeKind\", \"scopeKey\", \"attemptId\"],\n ],\n \"unique(command.moduleId,command.commandId)\": [\"command\", [\"moduleId\", \"commandId\"]],\n \"unique(connectedAdmission.admissionId)\": [\"admission\", [\"admissionId\"]],\n \"unique(connectedClient.clientKey)\": [\"client\", [\"clientKey\"]],\n \"unique(connectedCohort.cohortKey)\": [\"cohort\", [\"cohortKey\"]],\n \"unique(connectedCommand.moduleId,connectedCommand.commandId)\": [\n \"command\",\n [\"moduleId\", \"commandId\"],\n ],\n \"unique(connectedFlow.moduleId,connectedFlow.commandId)\": [\"flow\", [\"moduleId\", \"commandId\"]],\n \"unique(connectedFlow.moduleId,connectedFlow.flowId)\": [\"flow\", [\"moduleId\", \"flowId\"]],\n \"unique(connectedFlow.stateDigest)\": [\"flow\", [\"stateDigest\"]],\n \"unique(connectedGrant.moduleId,connectedGrant.grantId)\": [\"grant\", [\"moduleId\", \"grantId\"]],\n \"unique(connectedGrant.moduleId,connectedGrant.subjectId,connectedGrant.profileKey,connectedGrant.activeIdentityKey)\":\n [\"grant\", [\"moduleId\", \"subjectId\", \"profileKey\", \"activeIdentityKey\"]],\n \"unique(connectedRevocation.jobId)\": [\"job\", [\"jobId\"]],\n \"unique(continuation.moduleId,continuation.continuationId)\": [\n \"continuation\",\n [\"moduleId\", \"continuationId\"],\n ],\n \"unique(continuation.moduleId,continuation.digest)\": [\"continuation\", [\"moduleId\", \"digest\"]],\n \"unique(credential.credentialId)\": [\"credential\", [\"credentialId\"]],\n \"unique(credential.identityKey)\": [\"credential\", [\"identityKey\"]],\n \"unique(credential.moduleId,credential.credentialId)\": [\n \"credential\",\n [\"moduleId\", \"credentialId\"],\n ],\n \"unique(credential.moduleId,credential.subjectId)\": [\"credential\", [\"moduleId\", \"subjectId\"]],\n \"unique(emailCommand.moduleId,emailCommand.commandId)\": [\"command\", [\"moduleId\", \"commandId\"]],\n \"unique(emailCredential.moduleId,emailCredential.credentialId)\": [\n \"credential\",\n [\"moduleId\", \"credentialId\"],\n ],\n \"unique(emailCredential.moduleId,emailCredential.identifierNamespace,emailCredential.identifierValue)\":\n [\"credential\", [\"moduleId\", \"identifierNamespace\", \"identifierValue\"]],\n \"unique(emailRegistration.moduleId,emailRegistration.commandId)\": [\n \"registration\",\n [\"moduleId\", \"commandId\"],\n ],\n \"unique(emailRegistration.pendingReference)\": [\"registration\", [\"pendingReference\"]],\n \"unique(failureEvent.moduleId,failureEvent.seriesKey,failureEvent.commandId)\": [\n \"failureEvent\",\n [\"moduleId\", \"seriesKey\", \"commandId\"],\n ],\n \"unique(flow.flowId)\": [\"flow\", [\"flowId\"]],\n \"unique(flow.moduleId,flow.commandId)\": [\"flow\", [\"moduleId\", \"commandId\"]],\n \"unique(flow.moduleId,flow.flowId)\": [\"flow\", [\"moduleId\", \"flowId\"]],\n \"unique(flow.stateDigest)\": [\"flow\", [\"stateDigest\"]],\n \"unique(generation.moduleId,generation.deliveryId)\": [\"generation\", [\"moduleId\", \"deliveryId\"]],\n \"unique(generation.moduleId,generation.proofId)\": [\"generation\", [\"moduleId\", \"proofId\"]],\n \"unique(identifier.namespace,identifier.value)\": [\"identifier\", [\"namespace\", \"value\"]],\n \"unique(intent.digest)\": [\"intent\", [\"digest\"]],\n \"unique(intent.flowId)\": [\"intent\", [\"flowId\"]],\n \"unique(intent.moduleId,intent.commandId)\": [\"intent\", [\"moduleId\", \"commandId\"]],\n \"unique(intent.moduleId,intent.flowId)\": [\"intent\", [\"moduleId\", \"flowId\"]],\n \"unique(intent.moduleId,intent.intentId)\": [\"intent\", [\"moduleId\", \"intentId\"]],\n \"unique(intent.moduleId,intent.reference)\": [\"intent\", [\"moduleId\", \"reference\"]],\n \"unique(ownership.identityKey)\": [\"ownership\", [\"identityKey\"]],\n \"unique(pending.digest)\": [\"pending\", [\"digest\"]],\n \"unique(pending.flowId)\": [\"pending\", [\"flowId\"]],\n \"unique(rateScope.moduleId,rateScope.action,rateScope.scopeKind,rateScope.scopeKey)\": [\n \"rateScope\",\n [\"moduleId\", \"action\", \"scopeKind\", \"scopeKey\"],\n ],\n \"unique(rateScope.moduleId,rateScope.purpose,rateScope.action,rateScope.scopeKind,rateScope.scopeKey)\":\n [\"rateScope\", [\"moduleId\", \"purpose\", \"action\", \"scopeKind\", \"scopeKey\"]],\n \"unique(registration.moduleId,registration.requestId)\": [\n \"registration\",\n [\"moduleId\", \"requestId\"],\n ],\n \"unique(registration.recoveryReference)\": [\"registration\", [\"recoveryReference\"]],\n \"unique(registrationCommand.moduleId,registrationCommand.commandId)\": [\n \"command\",\n [\"moduleId\", \"commandId\"],\n ],\n \"unique(request.moduleId,request.requestId)\": [\"request\", [\"moduleId\", \"requestId\"]],\n \"unique(series.moduleId,series.purpose,series.scopeKey)\": [\n \"series\",\n [\"moduleId\", \"purpose\", \"scopeKey\"],\n ],\n \"unique(session.digest)\": [\"session\", [\"digest\"]],\n \"unique(tombstone.subjectId,tombstone.sessionId)\": [\"tombstone\", [\"subjectId\", \"sessionId\"]],\n \"unique(tuple.identityKey)\": [\"ownership.tuple\", [\"identityKey\"]],\n \"unique(unlinkCommand.moduleId,unlinkCommand.commandId)\": [\"command\", [\"moduleId\", \"commandId\"]],\n};\n\nconst arrayRoles: Readonly<Record<string, string>> = {\n credentialId: \"credential\",\n factor: \"authority\",\n credentialOwnership: \"credentialOwnership\",\n handleOwnership: \"handleOwnership\",\n boundSubjectHandle: \"handleOwnership\",\n flow: \"flow\",\n command: \"flow\",\n admission: \"admission\",\n charge: \"charge\",\n intentFlow: \"intent\",\n intentCommand: \"intent\",\n handle: \"handle\",\n};\n\nconst nestedMappings = [\n \"read\",\n \"signIn\",\n \"password\",\n \"proof\",\n \"proofs\",\n \"revocation\",\n \"pending\",\n \"session\",\n \"source\",\n];\n\nconst constraintGroups = [\n \"constraints\",\n \"tupleConstraints\",\n \"registrationConstraints\",\n \"managementConstraints\",\n];\n\nconst MappingRecord = Schema.Record(Schema.String, Schema.Unknown);\nconst record = Schema.decodeUnknownSync(MappingRecord);\n\nconst plans = (mapping: Readonly<Record<string, unknown>>) => {\n const result: Array<{ readonly table: Table; readonly keys: ReadonlyArray<string> }> = [];\n\n for (const group of constraintGroups) {\n if (mapping[group] === undefined) continue;\n for (const [name, declaration] of Object.entries(record(mapping[group]))) {\n if (declaration === \"notNull(provisioningRequest.subjectId)\") continue;\n let role: string;\n let keys: ReadonlyArray<string>;\n\n if (typeof declaration === \"string\") {\n const plan = uniquePlans[declaration];\n\n if (plan !== undefined) [role, keys] = plan;\n else if (declaration === \"unique(id)\") {\n role = \"subject\";\n keys = [\"id\"];\n } else if (declaration === \"unique(scope)\") {\n role = name;\n keys = [\"scope\"];\n } else if (declaration === \"unique(credentialId)\") {\n role = \"credential\";\n keys = [\"id\"];\n } else if (declaration === \"unique(namespace,value)\") {\n role = \"identifier\";\n keys = [\"namespace\", \"value\"];\n } else if (declaration === \"unique(provider,issuer,subject)\") {\n role = \"externalIdentity\";\n keys = [\"provider\", \"issuer\", \"subject\"];\n } else if (declaration === \"unique(requestId)\") {\n role = \"provisioningRequest\";\n keys = [\"requestId\"];\n } else throw new Error(\"Unknown storage constraint\");\n } else if (Array.isArray(declaration) && declaration.every(Predicate.isString)) {\n const mappedRole =\n group === \"managementConstraints\" && name === \"command\" ? \"command\" : arrayRoles[name];\n\n if (mappedRole === undefined) throw new Error(\"Unknown storage constraint\");\n role = mappedRole;\n keys = declaration;\n } else throw new Error(\"Invalid storage constraint\");\n\n let target: unknown = mapping;\n\n for (const segment of role.split(\".\")) target = record(target)[segment];\n // Session authority places its pending tables in one nested mapping.\n if (target === undefined && Schema.is(MappingRecord)(mapping.pending))\n target = mapping.pending[role];\n let mapped = record(target);\n\n if (role === \"pending\" && mapped.table === undefined) mapped = record(mapped.pending);\n // OAuth ownership can be integrated into its tuple authority or separate.\n if (role === \"ownership\" && mapped.table === undefined)\n mapped = record(mapped.external ?? mapped.tuple);\n if (!is(mapped.table, Table)) throw new Error(\"Missing storage table\");\n const columns = getTableColumns(mapped.table);\n\n result.push({\n table: mapped.table,\n keys: keys.map((key) => {\n const value = mapped[key];\n\n if (typeof value !== \"string\" || columns[value] === undefined)\n throw new Error(\"Missing mapped key\");\n\n return value;\n }),\n });\n }\n }\n for (const nested of nestedMappings) {\n const value = mapping[nested];\n\n if (Schema.is(MappingRecord)(value) && value.table === undefined) result.push(...plans(value));\n }\n\n return result;\n};\n\n/** Validate at acquisition using the root database supplied by the adapter. */\nexport const validateDrizzleStorage = Effect.fnUntraced(\n function* (mapping: unknown) {\n const physical = yield* Effect.try({\n try: () => plans(record(mapping)),\n catch: () =>\n PersistenceMappingError.make({\n operation: \"mapping\",\n cause: \"Invalid storage key mapping\",\n }),\n });\n\n const { $client: client } = yield* NativeDatabase;\n\n for (const plan of physical) {\n const pg = is(plan.table, PgTable);\n const mysql = is(plan.table, MySqlTable);\n\n const schema = pg\n ? getPgTableConfig(plan.table).schema\n : mysql\n ? getMysqlTableConfig(plan.table).schema\n : undefined;\n\n const columns = getTableColumns(plan.table);\n\n yield* validateStorage(\n pg ? \"pg\" : mysql ? \"mysql\" : \"sqlite\",\n {\n name: getTableName(plan.table),\n ...(schema === undefined ? {} : { schema }),\n columns: Object.fromEntries(plan.keys.map((key) => [key, { name: columns[key]!.name }])),\n },\n [plan.keys],\n ).pipe(\n Effect.provideService(SqlClient, client),\n Effect.mapError(() =>\n PersistenceMappingError.make({\n operation: \"mapping\",\n cause: \"Required SQL storage key is unavailable\",\n }),\n ),\n );\n }\n },\n Effect.catchDefect(() =>\n Effect.fail(\n PersistenceMappingError.make({\n operation: \"mapping\",\n cause: \"Cannot inspect SQL storage metadata\",\n }),\n ),\n ),\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"storage-validation.mjs","names":["getPgTableConfig","getMysqlTableConfig"],"sources":["../../src/drizzle/storage-validation.ts"],"sourcesContent":["import {\n NativeDatabase,\n PersistenceMappingError,\n validateStorageBatch,\n type StorageValidation,\n} from \"@yielded/auth-persistence/Adapter\";\nimport { getTableColumns, getTableName, is, Table } from \"drizzle-orm\";\nimport { getTableConfig as getMysqlTableConfig, MySqlTable } from \"drizzle-orm/mysql-core\";\nimport { getTableConfig as getPgTableConfig, PgTable } from \"drizzle-orm/pg-core\";\nimport { Effect, Predicate, Schema } from \"effect\";\nimport { SqlClient } from \"effect/sql/SqlClient\";\n\n// These are mapping contracts, not a parser for arbitrary constraint declarations.\n// Role aliases are explicit because their documentation names differ from mapping fields.\nconst uniquePlans: Readonly<Record<string, readonly [string, ReadonlyArray<string>]>> = {\n \"unique(abuseEvent.moduleId,abuseEvent.action,abuseEvent.scopeKind,abuseEvent.scopeKey,abuseEvent.commandId)\":\n [\"abuseEvent\", [\"moduleId\", \"action\", \"scopeKind\", \"scopeKey\", \"commandId\"]],\n \"unique(admission.moduleId)\": [\"admission\", [\"moduleId\"]],\n \"unique(attempt.moduleId,attempt.attemptId)\": [\"attempt\", [\"moduleId\", \"attemptId\"]],\n \"unique(authority.subjectId,authority.credentialId)\": [\n \"authority\",\n [\"subjectId\", \"credentialId\"],\n ],\n \"unique(authorityCredential.subjectId,authorityCredential.credentialId)\": [\n \"authorityCredential\",\n [\"subjectId\", \"credentialId\"],\n ],\n \"unique(charge.moduleId,charge.action,charge.scopeKind,charge.scopeKey,charge.attemptId)\": [\n \"charge\",\n [\"moduleId\", \"action\", \"scopeKind\", \"scopeKey\", \"attemptId\"],\n ],\n \"unique(command.moduleId,command.commandId)\": [\"command\", [\"moduleId\", \"commandId\"]],\n \"unique(connectedAdmission.admissionId)\": [\"admission\", [\"admissionId\"]],\n \"unique(connectedClient.clientKey)\": [\"client\", [\"clientKey\"]],\n \"unique(connectedCohort.cohortKey)\": [\"cohort\", [\"cohortKey\"]],\n \"unique(connectedCommand.moduleId,connectedCommand.commandId)\": [\n \"command\",\n [\"moduleId\", \"commandId\"],\n ],\n \"unique(connectedFlow.moduleId,connectedFlow.commandId)\": [\"flow\", [\"moduleId\", \"commandId\"]],\n \"unique(connectedFlow.moduleId,connectedFlow.flowId)\": [\"flow\", [\"moduleId\", \"flowId\"]],\n \"unique(connectedFlow.stateDigest)\": [\"flow\", [\"stateDigest\"]],\n \"unique(connectedGrant.moduleId,connectedGrant.grantId)\": [\"grant\", [\"moduleId\", \"grantId\"]],\n \"unique(connectedGrant.moduleId,connectedGrant.subjectId,connectedGrant.profileKey,connectedGrant.activeIdentityKey)\":\n [\"grant\", [\"moduleId\", \"subjectId\", \"profileKey\", \"activeIdentityKey\"]],\n \"unique(connectedRevocation.jobId)\": [\"job\", [\"jobId\"]],\n \"unique(continuation.moduleId,continuation.continuationId)\": [\n \"continuation\",\n [\"moduleId\", \"continuationId\"],\n ],\n \"unique(continuation.moduleId,continuation.digest)\": [\"continuation\", [\"moduleId\", \"digest\"]],\n \"unique(credential.credentialId)\": [\"credential\", [\"credentialId\"]],\n \"unique(credential.identityKey)\": [\"credential\", [\"identityKey\"]],\n \"unique(credential.moduleId,credential.credentialId)\": [\n \"credential\",\n [\"moduleId\", \"credentialId\"],\n ],\n \"unique(credential.moduleId,credential.subjectId)\": [\"credential\", [\"moduleId\", \"subjectId\"]],\n \"unique(emailCommand.moduleId,emailCommand.commandId)\": [\"command\", [\"moduleId\", \"commandId\"]],\n \"unique(emailCredential.moduleId,emailCredential.credentialId)\": [\n \"credential\",\n [\"moduleId\", \"credentialId\"],\n ],\n \"unique(emailCredential.moduleId,emailCredential.identifierNamespace,emailCredential.identifierValue)\":\n [\"credential\", [\"moduleId\", \"identifierNamespace\", \"identifierValue\"]],\n \"unique(emailRegistration.moduleId,emailRegistration.commandId)\": [\n \"registration\",\n [\"moduleId\", \"commandId\"],\n ],\n \"unique(emailRegistration.pendingReference)\": [\"registration\", [\"pendingReference\"]],\n \"unique(failureEvent.moduleId,failureEvent.seriesKey,failureEvent.commandId)\": [\n \"failureEvent\",\n [\"moduleId\", \"seriesKey\", \"commandId\"],\n ],\n \"unique(flow.flowId)\": [\"flow\", [\"flowId\"]],\n \"unique(flow.moduleId,flow.commandId)\": [\"flow\", [\"moduleId\", \"commandId\"]],\n \"unique(flow.moduleId,flow.flowId)\": [\"flow\", [\"moduleId\", \"flowId\"]],\n \"unique(flow.stateDigest)\": [\"flow\", [\"stateDigest\"]],\n \"unique(generation.moduleId,generation.deliveryId)\": [\"generation\", [\"moduleId\", \"deliveryId\"]],\n \"unique(generation.moduleId,generation.proofId)\": [\"generation\", [\"moduleId\", \"proofId\"]],\n \"unique(identifier.namespace,identifier.value)\": [\"identifier\", [\"namespace\", \"value\"]],\n \"unique(intent.digest)\": [\"intent\", [\"digest\"]],\n \"unique(intent.flowId)\": [\"intent\", [\"flowId\"]],\n \"unique(intent.moduleId,intent.commandId)\": [\"intent\", [\"moduleId\", \"commandId\"]],\n \"unique(intent.moduleId,intent.flowId)\": [\"intent\", [\"moduleId\", \"flowId\"]],\n \"unique(intent.moduleId,intent.intentId)\": [\"intent\", [\"moduleId\", \"intentId\"]],\n \"unique(intent.moduleId,intent.reference)\": [\"intent\", [\"moduleId\", \"reference\"]],\n \"unique(ownership.identityKey)\": [\"ownership\", [\"identityKey\"]],\n \"unique(pending.digest)\": [\"pending\", [\"digest\"]],\n \"unique(pending.flowId)\": [\"pending\", [\"flowId\"]],\n \"unique(rateScope.moduleId,rateScope.action,rateScope.scopeKind,rateScope.scopeKey)\": [\n \"rateScope\",\n [\"moduleId\", \"action\", \"scopeKind\", \"scopeKey\"],\n ],\n \"unique(rateScope.moduleId,rateScope.purpose,rateScope.action,rateScope.scopeKind,rateScope.scopeKey)\":\n [\"rateScope\", [\"moduleId\", \"purpose\", \"action\", \"scopeKind\", \"scopeKey\"]],\n \"unique(registration.moduleId,registration.requestId)\": [\n \"registration\",\n [\"moduleId\", \"requestId\"],\n ],\n \"unique(registration.recoveryReference)\": [\"registration\", [\"recoveryReference\"]],\n \"unique(registrationCommand.moduleId,registrationCommand.commandId)\": [\n \"command\",\n [\"moduleId\", \"commandId\"],\n ],\n \"unique(request.moduleId,request.requestId)\": [\"request\", [\"moduleId\", \"requestId\"]],\n \"unique(series.moduleId,series.purpose,series.scopeKey)\": [\n \"series\",\n [\"moduleId\", \"purpose\", \"scopeKey\"],\n ],\n \"unique(session.digest)\": [\"session\", [\"digest\"]],\n \"unique(tombstone.subjectId,tombstone.sessionId)\": [\"tombstone\", [\"subjectId\", \"sessionId\"]],\n \"unique(tuple.identityKey)\": [\"ownership.tuple\", [\"identityKey\"]],\n \"unique(unlinkCommand.moduleId,unlinkCommand.commandId)\": [\"command\", [\"moduleId\", \"commandId\"]],\n};\n\nconst arrayRoles: Readonly<Record<string, string>> = {\n credentialId: \"credential\",\n factor: \"authority\",\n credentialOwnership: \"credentialOwnership\",\n handleOwnership: \"handleOwnership\",\n boundSubjectHandle: \"handleOwnership\",\n flow: \"flow\",\n command: \"flow\",\n admission: \"admission\",\n charge: \"charge\",\n intentFlow: \"intent\",\n intentCommand: \"intent\",\n handle: \"handle\",\n};\n\nconst nestedMappings = [\n \"read\",\n \"signIn\",\n \"password\",\n \"proof\",\n \"proofs\",\n \"revocation\",\n \"pending\",\n \"session\",\n \"source\",\n];\n\nconst constraintGroups = [\n \"constraints\",\n \"tupleConstraints\",\n \"registrationConstraints\",\n \"managementConstraints\",\n];\n\nconst MappingRecord = Schema.Record(Schema.String, Schema.Unknown);\nconst record = Schema.decodeUnknownSync(MappingRecord);\n\nconst plans = (mapping: Readonly<Record<string, unknown>>) => {\n const result: Array<{ readonly table: Table; readonly keys: ReadonlyArray<string> }> = [];\n\n for (const group of constraintGroups) {\n if (mapping[group] === undefined) continue;\n for (const [name, declaration] of Object.entries(record(mapping[group]))) {\n if (declaration === \"notNull(provisioningRequest.subjectId)\") continue;\n let role: string;\n let keys: ReadonlyArray<string>;\n\n if (typeof declaration === \"string\") {\n const plan = uniquePlans[declaration];\n\n if (plan !== undefined) [role, keys] = plan;\n else if (declaration === \"unique(id)\") {\n role = \"subject\";\n keys = [\"id\"];\n } else if (declaration === \"unique(scope)\") {\n role = name;\n keys = [\"scope\"];\n } else if (declaration === \"unique(credentialId)\") {\n role = \"credential\";\n keys = [\"id\"];\n } else if (declaration === \"unique(namespace,value)\") {\n role = \"identifier\";\n keys = [\"namespace\", \"value\"];\n } else if (declaration === \"unique(provider,issuer,subject)\") {\n role = \"externalIdentity\";\n keys = [\"provider\", \"issuer\", \"subject\"];\n } else if (declaration === \"unique(requestId)\") {\n role = \"provisioningRequest\";\n keys = [\"requestId\"];\n } else throw new Error(\"Unknown storage constraint\");\n } else if (Array.isArray(declaration) && declaration.every(Predicate.isString)) {\n const mappedRole =\n group === \"managementConstraints\" && name === \"command\" ? \"command\" : arrayRoles[name];\n\n if (mappedRole === undefined) throw new Error(\"Unknown storage constraint\");\n role = mappedRole;\n keys = declaration;\n } else throw new Error(\"Invalid storage constraint\");\n\n let target: unknown = mapping;\n\n for (const segment of role.split(\".\")) target = record(target)[segment];\n // Session authority places its pending tables in one nested mapping.\n if (target === undefined && Schema.is(MappingRecord)(mapping.pending))\n target = mapping.pending[role];\n let mapped = record(target);\n\n if (role === \"pending\" && mapped.table === undefined) mapped = record(mapped.pending);\n // OAuth ownership can be integrated into its tuple authority or separate.\n if (role === \"ownership\" && mapped.table === undefined)\n mapped = record(mapped.external ?? mapped.tuple);\n if (!is(mapped.table, Table)) throw new Error(\"Missing storage table\");\n const columns = getTableColumns(mapped.table);\n\n result.push({\n table: mapped.table,\n keys: keys.map((key) => {\n const value = mapped[key];\n\n if (typeof value !== \"string\" || columns[value] === undefined)\n throw new Error(\"Missing mapped key\");\n\n return value;\n }),\n });\n }\n }\n for (const nested of nestedMappings) {\n const value = mapping[nested];\n\n if (Schema.is(MappingRecord)(value) && value.table === undefined) result.push(...plans(value));\n }\n\n return result;\n};\n\n/** Validate at acquisition using the root database supplied by the adapter. */\nexport const validateDrizzleStorage = Effect.fnUntraced(\n function* (mapping: unknown) {\n const physical = yield* Effect.try({\n try: () => plans(record(mapping)),\n catch: () =>\n PersistenceMappingError.make({\n operation: \"mapping\",\n cause: \"Invalid storage key mapping\",\n }),\n });\n\n const { $client: client } = yield* NativeDatabase;\n\n const batches = new Map<\"pg\" | \"mysql\" | \"sqlite\", StorageValidation[]>();\n\n for (const plan of physical) {\n const pg = is(plan.table, PgTable);\n const mysql = is(plan.table, MySqlTable);\n\n const schema = pg\n ? getPgTableConfig(plan.table).schema\n : mysql\n ? getMysqlTableConfig(plan.table).schema\n : undefined;\n\n const columns = getTableColumns(plan.table);\n\n const dialect = pg ? \"pg\" : mysql ? \"mysql\" : \"sqlite\";\n const batch = batches.get(dialect) ?? [];\n\n batch.push({\n table: {\n name: getTableName(plan.table),\n ...(schema === undefined ? {} : { schema }),\n columns: Object.fromEntries(plan.keys.map((key) => [key, { name: columns[key]!.name }])),\n },\n required: [plan.keys],\n });\n batches.set(dialect, batch);\n }\n for (const [dialect, requirements] of batches) {\n yield* validateStorageBatch(dialect, requirements).pipe(\n Effect.provideService(SqlClient, client),\n Effect.mapError(() =>\n PersistenceMappingError.make({\n operation: \"mapping\",\n cause: \"Required SQL storage key is unavailable\",\n }),\n ),\n );\n }\n },\n Effect.catchDefect(() =>\n Effect.fail(\n PersistenceMappingError.make({\n operation: \"mapping\",\n cause: \"Cannot inspect SQL storage metadata\",\n }),\n ),\n ),\n);\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { digest, randomId } from "./crypto.mjs";
|
|
1
2
|
import { both, makeTransactionRows } from "./transaction-owner.mjs";
|
|
2
3
|
import { sql } from "drizzle-orm";
|
|
3
4
|
import { Context, Effect, Schema } from "effect";
|
|
4
5
|
import { AuthenticationRequirement, SecurityRevision } from "@yielded/auth/Sessions";
|
|
5
6
|
import { TotpPolicy, TotpRecord, TotpUnavailable } from "@yielded/auth/Totp";
|
|
6
|
-
import { digest, randomId } from "@yielded/auth-crypto";
|
|
7
7
|
//#region src/drizzle/totp-state.ts
|
|
8
8
|
const unavailable = () => TotpUnavailable.make({});
|
|
9
9
|
const invariant = (condition) => {
|
|
@@ -20,7 +20,7 @@ const captureTotp = Effect.fn("TotpNative.capture")(function* (mapping, subjectI
|
|
|
20
20
|
invariant(mapping.subjectIds.toSubject(nativeId) === subjectId);
|
|
21
21
|
const subjectRow = (yield* owner.read(subject.table, equal(subject.table, { [subject.id]: nativeId }), { limit: 1 })).rows[0];
|
|
22
22
|
if (subjectRow === void 0 || !(yield* owner.check(sql`exists(select 1 from ${subject.table} where ${both(owner.exact(subject.table, subjectRow), subject.activeCondition)})`))) return void 0;
|
|
23
|
-
const scope = scopeFor(mapping.moduleId, subjectId), found = yield* owner.read(factor.table, equal(factor.table, { [factor.scope]: scope }), { limit: 1 }), row = found.rows[0];
|
|
23
|
+
const scope = yield* scopeFor(mapping.moduleId, subjectId), found = yield* owner.read(factor.table, equal(factor.table, { [factor.scope]: scope }), { limit: 1 }), row = found.rows[0];
|
|
24
24
|
const record = row === void 0 ? null : decodeTotpRecord(row[factor.state]);
|
|
25
25
|
invariant(record === null || (record.secret === null || record.secret.revision === record.revision) && (record.pending === null || record.pending.secret.revision === record.pending.revision));
|
|
26
26
|
invariant(record === null || record.moduleId === mapping.moduleId && record.subjectId === subjectId && record.version === row[factor.version]);
|
|
@@ -55,7 +55,7 @@ const mutateTotp = Effect.fn("TotpNative.mutate")(function* (mapping, input) {
|
|
|
55
55
|
const now = yield* owner.now({ engineNowMillis: mapping.engineNowMillis });
|
|
56
56
|
const guards = [];
|
|
57
57
|
const credentialGuards = [];
|
|
58
|
-
const commandScope = digest(`effect-auth/totp/command/v1/${mapping.moduleId.length}:${mapping.moduleId}/${input.subjectId.length}:${input.subjectId}/${input.commandId}`);
|
|
58
|
+
const commandScope = yield* digest(`effect-auth/totp/command/v1/${mapping.moduleId.length}:${mapping.moduleId}/${input.subjectId.length}:${input.subjectId}/${input.commandId}`);
|
|
59
59
|
const commandObservation = [
|
|
60
60
|
"Enroll",
|
|
61
61
|
"Confirm",
|
|
@@ -192,7 +192,7 @@ const mutateTotp = Effect.fn("TotpNative.mutate")(function* (mapping, input) {
|
|
|
192
192
|
secret: null,
|
|
193
193
|
pending: null,
|
|
194
194
|
recoveryDigests: [],
|
|
195
|
-
revision: randomId
|
|
195
|
+
revision: yield* randomId
|
|
196
196
|
};
|
|
197
197
|
semantic = true;
|
|
198
198
|
}
|
|
@@ -205,7 +205,7 @@ const mutateTotp = Effect.fn("TotpNative.mutate")(function* (mapping, input) {
|
|
|
205
205
|
secret: null,
|
|
206
206
|
pending: null,
|
|
207
207
|
recoveryDigests: [],
|
|
208
|
-
revision: randomId
|
|
208
|
+
revision: yield* randomId
|
|
209
209
|
};
|
|
210
210
|
else {
|
|
211
211
|
if (new Set(action.recoveryDigests).size !== 10) return reject;
|
|
@@ -218,12 +218,12 @@ const mutateTotp = Effect.fn("TotpNative.mutate")(function* (mapping, input) {
|
|
|
218
218
|
}
|
|
219
219
|
next = {
|
|
220
220
|
...next,
|
|
221
|
-
version: randomId
|
|
221
|
+
version: yield* randomId
|
|
222
222
|
};
|
|
223
223
|
const subject = mapping.subject, factor = mapping.factor, auth = mapping.credential;
|
|
224
224
|
const subjectKey = { [subject.id]: nativeId };
|
|
225
225
|
if (semantic) {
|
|
226
|
-
const revision = randomId
|
|
226
|
+
const revision = yield* randomId, updates = {
|
|
227
227
|
[subject.securityRevision]: revision,
|
|
228
228
|
[subject.factorEnabled]: subject.encodeEnabled(next.secret !== null)
|
|
229
229
|
};
|
|
@@ -269,7 +269,7 @@ const mutateTotp = Effect.fn("TotpNative.mutate")(function* (mapping, input) {
|
|
|
269
269
|
const values = factor.encodeInsert({
|
|
270
270
|
scope: commandScope,
|
|
271
271
|
state: "totp-command/v1",
|
|
272
|
-
version: randomId
|
|
272
|
+
version: yield* randomId
|
|
273
273
|
});
|
|
274
274
|
invariant(values[factor.scope] === commandScope && values[factor.state] === "totp-command/v1");
|
|
275
275
|
commandObservation.rows = (yield* owner.insert(factor.table, values, { [factor.scope]: commandScope })).rows;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"totp-state.mjs","names":[],"sources":["../../src/drizzle/totp-state.ts"],"sourcesContent":["import { randomId, digest } from \"@yielded/auth-crypto\";\nimport { AuthenticationRequirement, SecurityRevision } from \"@yielded/auth/Sessions\";\nimport {\n TotpUnavailable,\n type TotpMutation,\n TotpPolicy,\n TotpRecord,\n type TotpDecision,\n} from \"@yielded/auth/Totp\";\n/* oxlint-disable no-explicit-any -- private native driver bridge; public makers preserve table and ID types. */\nimport { sql, type SQL } from \"drizzle-orm\";\nimport { Context, Effect, Schema } from \"effect\";\n\nimport { both, makeTransactionRows, type TransactionOwner } from \"./transaction-owner\";\nexport const unavailable = () => TotpUnavailable.make({});\n\nexport const invariant: (condition: unknown) => asserts condition = (condition) => {\n if (!condition) throw unavailable();\n};\n\nexport class CurrentTotpTransaction extends Context.Service<\n CurrentTotpTransaction,\n TransactionOwner<TotpUnavailable>\n>()(\"effect-auth/drizzle/CurrentTotpTransaction\") {}\n\nexport const { equal, col, copiedRow } = makeTransactionRows(unavailable);\nconst codec = Schema.fromJsonString(TotpRecord);\n\nexport const encodeTotpRecord = (record: TotpRecord) => Schema.encodeSync(codec)(record);\nexport const decodeTotpRecord = (state: string) => Schema.decodeSync(codec)(state);\n\nconst scopeFor = (moduleId: string, subjectId: string) =>\n digest(`effect-auth/totp/scope/v1/${moduleId.length}:${moduleId}/${subjectId}`);\n\nexport const captureTotp = Effect.fn(\"TotpNative.capture\")(function* (\n mapping: any,\n subjectId: typeof TotpRecord.Type.subjectId,\n) {\n const owner = yield* CurrentTotpTransaction,\n subject = mapping.subject,\n factor = mapping.factor,\n nativeId = mapping.subjectIds.toNative(subjectId);\n\n invariant(mapping.subjectIds.toSubject(nativeId) === subjectId);\n\n const selected = yield* owner.read(\n subject.table,\n equal(subject.table, { [subject.id]: nativeId }),\n { limit: 1 },\n );\n\n const subjectRow = selected.rows[0];\n\n if (\n subjectRow === undefined ||\n !(yield* owner.check(\n sql`exists(select 1 from ${subject.table} where ${both(owner.exact(subject.table, subjectRow), subject.activeCondition)})`,\n ))\n )\n return undefined;\n\n const scope = scopeFor(mapping.moduleId, subjectId),\n found = yield* owner.read(factor.table, equal(factor.table, { [factor.scope]: scope }), {\n limit: 1,\n }),\n row = found.rows[0];\n\n const record = row === undefined ? null : decodeTotpRecord(row[factor.state] as string);\n\n invariant(\n record === null ||\n ((record.secret === null || record.secret.revision === record.revision) &&\n (record.pending === null || record.pending.secret.revision === record.pending.revision)),\n );\n invariant(\n record === null ||\n (record.moduleId === mapping.moduleId &&\n record.subjectId === subjectId &&\n record.version === row![factor.version]),\n );\n\n return {\n nativeId,\n subjectRow,\n factorRow: row,\n factorObservation: found,\n scope,\n snapshot: {\n revision: {\n subjectId,\n securityRevision: SecurityRevision.make(subjectRow[subject.securityRevision] as string),\n credentials:\n record === null || record.secret === null\n ? []\n : [\n {\n credentialId: record.credentialId,\n revision: SecurityRevision.make(record.revision),\n },\n ],\n },\n record,\n },\n };\n});\n\nconst reject: TotpDecision = { _tag: \"Rejected\" };\n\nexport const mutateTotp = Effect.fn(\"TotpNative.mutate\")(function* (\n mapping: any,\n input: TotpMutation,\n) {\n const owner = yield* CurrentTotpTransaction;\n\n invariant(\n input.moduleId === mapping.moduleId &&\n Schema.encodeSync(Schema.fromJsonString(TotpPolicy))(input.policy) ===\n Schema.encodeSync(Schema.fromJsonString(TotpPolicy))(mapping.policy),\n );\n const captured = yield* captureTotp(mapping, input.subjectId);\n\n if (captured === undefined) return reject;\n\n const { snapshot, subjectRow, factorRow, factorObservation, scope, nativeId } = captured,\n current = snapshot.record,\n policy = input.policy,\n action = input.action;\n\n if (\n snapshot.revision.securityRevision !== input.snapshot.revision.securityRevision ||\n (current?.version ?? null) !== (input.snapshot.record?.version ?? null)\n )\n return reject;\n if (\n (current === null) !== (input.snapshot.record === null) ||\n (current !== null && encodeTotpRecord(current) !== encodeTotpRecord(input.snapshot.record!))\n )\n return reject;\n const now = yield* owner.now({ engineNowMillis: mapping.engineNowMillis });\n const guards: SQL[] = [];\n const credentialGuards: { credentialId: string; condition: SQL }[] = [];\n\n const commandScope = digest(\n `effect-auth/totp/command/v1/${mapping.moduleId.length}:${mapping.moduleId}/${input.subjectId.length}:${input.subjectId}/${input.commandId}`,\n );\n\n const management = [\"Enroll\", \"Confirm\", \"Disable\", \"Regenerate\"].includes(action._tag);\n\n const commandObservation = management\n ? yield* owner.read(\n mapping.factor.table,\n equal(mapping.factor.table, { [mapping.factor.scope]: commandScope }),\n { limit: 1 },\n )\n : undefined;\n\n if (commandObservation !== undefined && commandObservation.rows.length !== 0) return reject;\n const timeGuards: SQL[] = [];\n\n const timeBound = (start: number, end: number) => {\n timeGuards.push(\n sql`${mapping.engineNowMillis} >= ${start} and ${mapping.engineNowMillis} < ${end}`,\n );\n };\n\n if (\n action._tag === \"Enroll\" ||\n action._tag === \"Confirm\" ||\n action._tag === \"Disable\" ||\n action._tag === \"Regenerate\"\n ) {\n const authorization = input.authorization;\n\n if (authorization === undefined) return reject;\n const { challenge, evidence } = authorization;\n\n const expectedAction = {\n Enroll: \"enroll\",\n Confirm: \"confirm\",\n Disable: \"disable\",\n Regenerate: \"regenerate\",\n }[action._tag];\n\n if (\n challenge.action !== expectedAction ||\n challenge.moduleId !== mapping.moduleId ||\n challenge.commandId !== input.commandId ||\n challenge.revision.subjectId !== input.subjectId ||\n challenge.revision.securityRevision !== snapshot.revision.securityRevision ||\n evidence.flowId !== challenge.flowId ||\n evidence.bindingDigest !== challenge.bindingDigest ||\n evidence.revision.subjectId !== input.subjectId ||\n evidence.revision.securityRevision !== snapshot.revision.securityRevision\n )\n return reject;\n const auth = mapping.credential;\n\n for (const revision of [...evidence.revision.credentials].sort((a, b) =>\n a.credentialId.localeCompare(b.credentialId),\n )) {\n const found = yield* owner.read(\n auth.table,\n equal(auth.table, { [auth.id]: revision.credentialId, [auth.subjectId]: nativeId }),\n { limit: 1 },\n );\n\n const row = found.rows[0];\n\n if (row === undefined || row[auth.revision] !== revision.revision) return reject;\n const condition = sql`exists(select 1 from ${auth.table} where ${both(owner.exact(auth.table, row), auth.activeCondition)})`;\n\n if (!(yield* owner.check(condition))) return reject;\n credentialGuards.push({ credentialId: revision.credentialId, condition });\n }\n\n const eligible = evidence.proofs.filter((proof) =>\n evidence.revision.credentials.some(\n (revision) => revision.credentialId === proof.credentialId,\n ),\n );\n\n if (eligible.length !== evidence.proofs.length || eligible.length === 0) return reject;\n\n const requirements = [\n authorization.requirement,\n Schema.decodeSync(AuthenticationRequirement)(\n mapping.subject.decodeRequirement(copiedRow(subjectRow)),\n ),\n ];\n\n const maximumAge = Math.min(\n policy.maximumEvidenceAgeMillis,\n ...requirements.map((requirement) => requirement.maximumAgeMillis),\n );\n\n const evidenceFactors = new Set(eligible.flatMap((proof) => proof.factors));\n const evidenceCredentials = new Set(eligible.map((proof) => proof.credentialId));\n\n for (const requirement of requirements) {\n if (\n !requirement.alternatives.some(\n (alternative) =>\n alternative.factors.every((factor) => evidenceFactors.has(factor)) &&\n evidenceCredentials.size >= alternative.minimumCredentials &&\n eligible.some(\n (proof) =>\n (!alternative.userVerified || proof.userVerified) &&\n (!alternative.phishingResistant || proof.phishingResistant),\n ),\n )\n )\n return reject;\n }\n for (const proof of eligible) {\n const verifiedAt = proof.verifiedAt.epochMilliseconds;\n\n if (verifiedAt > now || now - verifiedAt >= maximumAge) return reject;\n timeBound(verifiedAt, verifiedAt + maximumAge);\n }\n if (\n (current !== null && current.secret !== null) ||\n action._tag === \"Disable\" ||\n action._tag === \"Regenerate\"\n ) {\n const factors = new Set(eligible.flatMap((proof) => proof.factors));\n\n if (\n !(\n eligible.some(\n (proof) =>\n proof.userVerified && proof.phishingResistant && proof.factors.includes(\"possession\"),\n ) ||\n (factors.has(\"knowledge\") &&\n factors.has(\"possession\") &&\n new Set(eligible.map((proof) => proof.credentialId)).size >= 2)\n )\n )\n return reject;\n }\n }\n if (action._tag === \"Recovery\" && action.reset) {\n const target = action.pending;\n\n if (\n target === undefined ||\n mapping.pendingCondition === undefined ||\n target.revision.subjectId !== input.subjectId ||\n target.revision.securityRevision !== snapshot.revision.securityRevision ||\n target.expiresAtMillis <= now\n )\n return reject;\n const condition = mapping.pendingCondition(target, nativeId);\n\n if (!(yield* owner.check(condition))) return reject;\n guards.push(condition);\n timeBound(0, target.expiresAtMillis);\n }\n\n let next: TotpRecord,\n semantic = false,\n accepted = true;\n\n if (action._tag === \"Enroll\") {\n const candidate = action.record;\n\n if (\n candidate.subjectId !== input.subjectId ||\n candidate.moduleId !== input.moduleId ||\n candidate.pending === null ||\n candidate.pending.expiresAtMillis <= now ||\n candidate.pending.expiresAtMillis > now + policy.enrollmentLifetimeMillis ||\n candidate.pending.failedAttempts !== 0 ||\n candidate.pending.secret.revision !== candidate.pending.revision\n )\n return reject;\n // Reissuing cannot erase the confirmation budget during its current enrollment lifetime.\n if (current !== null && current.pending !== null && current.pending.expiresAtMillis > now)\n return reject;\n if (\n current !== null &&\n (candidate.credentialId !== current.credentialId ||\n encodeTotpRecord({ ...candidate, pending: current.pending }) !== encodeTotpRecord(current))\n )\n return reject;\n if (\n current === null &&\n (candidate.secret !== null ||\n candidate.recoveryDigests.length !== 0 ||\n candidate.acceptedStep !== -1 ||\n candidate.failedAttempts !== 0)\n )\n return reject;\n next = candidate;\n timeBound(0, candidate.pending.expiresAtMillis);\n } else {\n if (current === null) return reject;\n next = { ...current };\n if (action._tag === \"Confirm\") {\n const pending = current.pending;\n\n if (\n pending === null ||\n pending.enrollmentId !== action.enrollmentId ||\n pending.expiresAtMillis <= now ||\n pending.failedAttempts >= policy.attemptLimit\n )\n return reject;\n timeBound(0, pending.expiresAtMillis);\n if (\n action.matchedStep === null ||\n Math.abs(Math.floor(now / 30000) - action.matchedStep) > policy.clockSkewSteps\n ) {\n next = { ...current, pending: { ...pending, failedAttempts: pending.failedAttempts + 1 } };\n accepted = false;\n } else {\n if (new Set(action.recoveryDigests).size !== 10) return reject;\n next = {\n ...current,\n secret: pending.secret,\n revision: pending.secret.revision,\n pending: null,\n recoveryDigests: action.recoveryDigests,\n acceptedStep: action.matchedStep,\n attemptWindow: now,\n failedAttempts: 0,\n };\n semantic = true;\n timeBound(\n Math.max(0, (action.matchedStep - policy.clockSkewSteps) * 30000),\n (action.matchedStep + policy.clockSkewSteps + 1) * 30000,\n );\n }\n } else if (action._tag === \"Verify\" || action._tag === \"Recovery\") {\n if (current.secret === null) return reject;\n\n const expired = now >= current.attemptWindow + policy.attemptWindowMillis,\n attempts = expired ? 0 : current.failedAttempts,\n start = expired ? now : current.attemptWindow;\n\n if (attempts >= policy.attemptLimit) return reject;\n next = { ...current, attemptWindow: start, failedAttempts: attempts + 1 };\n if (action._tag === \"Verify\") {\n if (\n action.matchedStep === null ||\n action.matchedStep <= current.acceptedStep ||\n Math.abs(Math.floor(now / 30000) - action.matchedStep) > policy.clockSkewSteps\n )\n accepted = false;\n else {\n next = { ...next, acceptedStep: action.matchedStep, failedAttempts: 0 };\n timeBound(\n Math.max(0, (action.matchedStep - policy.clockSkewSteps) * 30000),\n (action.matchedStep + policy.clockSkewSteps + 1) * 30000,\n );\n }\n } else {\n if (\n (action.reset\n ? policy.lostFactorRecovery !== \"reset-with-recovery-code\"\n : !policy.allowRecoveryCodeForPending) ||\n !current.recoveryDigests.includes(action.digest)\n )\n accepted = false;\n else {\n next = {\n ...next,\n recoveryDigests: current.recoveryDigests.filter((value) => value !== action.digest),\n failedAttempts: 0,\n };\n if (action.reset) {\n next = {\n ...next,\n secret: null,\n pending: null,\n recoveryDigests: [],\n revision: randomId(),\n };\n semantic = true;\n }\n }\n }\n } else {\n if (current.secret === null) return reject;\n semantic = true;\n if (action._tag === \"Disable\")\n next = {\n ...current,\n secret: null,\n pending: null,\n recoveryDigests: [],\n revision: randomId(),\n };\n else {\n if (new Set(action.recoveryDigests).size !== 10) return reject;\n next = { ...current, recoveryDigests: action.recoveryDigests };\n }\n }\n }\n next = { ...next, version: randomId() };\n\n const subject = mapping.subject,\n factor = mapping.factor,\n auth = mapping.credential;\n\n const subjectKey = { [subject.id]: nativeId };\n\n if (semantic) {\n const revision = randomId(),\n updates = {\n [subject.securityRevision]: revision,\n [subject.factorEnabled]: subject.encodeEnabled(next.secret !== null),\n };\n\n yield* owner.update(subject.table, subjectKey, updates);\n const idKey = { [auth.id]: next.credentialId, [auth.subjectId]: nativeId };\n const existing = yield* owner.read(auth.table, equal(auth.table, idKey), { limit: 1 });\n\n if (existing.rows.length === 0) {\n const values = {\n ...auth.encodeInsert({\n credentialId: next.credentialId,\n subjectId: nativeId,\n revision: next.revision,\n active: next.secret !== null,\n }),\n [auth.id]: next.credentialId,\n [auth.subjectId]: nativeId,\n [auth.revision]: next.revision,\n [auth.status]: auth.encodeStatus(next.secret !== null),\n };\n\n existing.rows = (yield* owner.insert(auth.table, values, {\n [auth.id]: next.credentialId,\n })).rows;\n } else\n yield* owner.update(auth.table, idKey, {\n [auth.revision]: next.revision,\n [auth.status]: auth.encodeStatus(next.secret !== null),\n });\n // Management proof observations precede its own credential/revision mutation.\n // Retain all unrelated credential authority checks at final commit.\n }\n\n const state = encodeTotpRecord(next),\n values = { [factor.state]: state, [factor.version]: next.version };\n\n if (factorRow === undefined) {\n const insert = factor.encodeInsert({ scope, state, version: next.version });\n\n invariant(\n insert[factor.scope] === scope &&\n insert[factor.state] === state &&\n insert[factor.version] === next.version,\n );\n factorObservation.rows = (yield* owner.insert(factor.table, insert, {\n [factor.scope]: scope,\n })).rows;\n } else yield* owner.update(factor.table, { [factor.scope]: scope }, values);\n if (commandObservation !== undefined) {\n const values = factor.encodeInsert({\n scope: commandScope,\n state: \"totp-command/v1\",\n version: randomId(),\n });\n\n invariant(values[factor.scope] === commandScope && values[factor.state] === \"totp-command/v1\");\n commandObservation.rows = (yield* owner.insert(factor.table, values, {\n [factor.scope]: commandScope,\n })).rows;\n }\n // Exact pre-write observations plus final readback are asserted by the common owner.\n // Include active subject and native time at finalization, including on rejection commits.\n guards.push(\n sql`exists(select 1 from ${subject.table} where ${both(equal(subject.table, subjectKey), subject.activeCondition)})`,\n );\n owner.postconditions.push(\n ...guards,\n ...timeGuards,\n ...credentialGuards\n .filter((guard) => !semantic || guard.credentialId !== next.credentialId)\n .map((guard) => guard.condition),\n );\n\n return accepted ? { _tag: \"Accepted\" as const, record: next } : reject;\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"totp-state.mjs","names":[],"sources":["../../src/drizzle/totp-state.ts"],"sourcesContent":["import { AuthenticationRequirement, SecurityRevision } from \"@yielded/auth/Sessions\";\nimport {\n TotpUnavailable,\n type TotpMutation,\n TotpPolicy,\n TotpRecord,\n type TotpDecision,\n} from \"@yielded/auth/Totp\";\n/* oxlint-disable no-explicit-any -- private native driver bridge; public makers preserve table and ID types. */\nimport { sql, type SQL } from \"drizzle-orm\";\nimport { Context, Effect, Schema } from \"effect\";\n\nimport { randomId, digest } from \"./crypto\";\nimport { both, makeTransactionRows, type TransactionOwner } from \"./transaction-owner\";\nexport const unavailable = () => TotpUnavailable.make({});\n\nexport const invariant: (condition: unknown) => asserts condition = (condition) => {\n if (!condition) throw unavailable();\n};\n\nexport class CurrentTotpTransaction extends Context.Service<\n CurrentTotpTransaction,\n TransactionOwner<TotpUnavailable>\n>()(\"effect-auth/drizzle/CurrentTotpTransaction\") {}\n\nexport const { equal, col, copiedRow } = makeTransactionRows(unavailable);\nconst codec = Schema.fromJsonString(TotpRecord);\n\nexport const encodeTotpRecord = (record: TotpRecord) => Schema.encodeSync(codec)(record);\nexport const decodeTotpRecord = (state: string) => Schema.decodeSync(codec)(state);\n\nconst scopeFor = (moduleId: string, subjectId: string) =>\n digest(`effect-auth/totp/scope/v1/${moduleId.length}:${moduleId}/${subjectId}`);\n\nexport const captureTotp = Effect.fn(\"TotpNative.capture\")(function* (\n mapping: any,\n subjectId: typeof TotpRecord.Type.subjectId,\n) {\n const owner = yield* CurrentTotpTransaction,\n subject = mapping.subject,\n factor = mapping.factor,\n nativeId = mapping.subjectIds.toNative(subjectId);\n\n invariant(mapping.subjectIds.toSubject(nativeId) === subjectId);\n\n const selected = yield* owner.read(\n subject.table,\n equal(subject.table, { [subject.id]: nativeId }),\n { limit: 1 },\n );\n\n const subjectRow = selected.rows[0];\n\n if (\n subjectRow === undefined ||\n !(yield* owner.check(\n sql`exists(select 1 from ${subject.table} where ${both(owner.exact(subject.table, subjectRow), subject.activeCondition)})`,\n ))\n )\n return undefined;\n\n const scope = yield* scopeFor(mapping.moduleId, subjectId),\n found = yield* owner.read(factor.table, equal(factor.table, { [factor.scope]: scope }), {\n limit: 1,\n }),\n row = found.rows[0];\n\n const record = row === undefined ? null : decodeTotpRecord(row[factor.state] as string);\n\n invariant(\n record === null ||\n ((record.secret === null || record.secret.revision === record.revision) &&\n (record.pending === null || record.pending.secret.revision === record.pending.revision)),\n );\n invariant(\n record === null ||\n (record.moduleId === mapping.moduleId &&\n record.subjectId === subjectId &&\n record.version === row![factor.version]),\n );\n\n return {\n nativeId,\n subjectRow,\n factorRow: row,\n factorObservation: found,\n scope,\n snapshot: {\n revision: {\n subjectId,\n securityRevision: SecurityRevision.make(subjectRow[subject.securityRevision] as string),\n credentials:\n record === null || record.secret === null\n ? []\n : [\n {\n credentialId: record.credentialId,\n revision: SecurityRevision.make(record.revision),\n },\n ],\n },\n record,\n },\n };\n});\n\nconst reject: TotpDecision = { _tag: \"Rejected\" };\n\nexport const mutateTotp = Effect.fn(\"TotpNative.mutate\")(function* (\n mapping: any,\n input: TotpMutation,\n) {\n const owner = yield* CurrentTotpTransaction;\n\n invariant(\n input.moduleId === mapping.moduleId &&\n Schema.encodeSync(Schema.fromJsonString(TotpPolicy))(input.policy) ===\n Schema.encodeSync(Schema.fromJsonString(TotpPolicy))(mapping.policy),\n );\n const captured = yield* captureTotp(mapping, input.subjectId);\n\n if (captured === undefined) return reject;\n\n const { snapshot, subjectRow, factorRow, factorObservation, scope, nativeId } = captured,\n current = snapshot.record,\n policy = input.policy,\n action = input.action;\n\n if (\n snapshot.revision.securityRevision !== input.snapshot.revision.securityRevision ||\n (current?.version ?? null) !== (input.snapshot.record?.version ?? null)\n )\n return reject;\n if (\n (current === null) !== (input.snapshot.record === null) ||\n (current !== null && encodeTotpRecord(current) !== encodeTotpRecord(input.snapshot.record!))\n )\n return reject;\n const now = yield* owner.now({ engineNowMillis: mapping.engineNowMillis });\n const guards: SQL[] = [];\n const credentialGuards: { credentialId: string; condition: SQL }[] = [];\n\n const commandScope = yield* digest(\n `effect-auth/totp/command/v1/${mapping.moduleId.length}:${mapping.moduleId}/${input.subjectId.length}:${input.subjectId}/${input.commandId}`,\n );\n\n const management = [\"Enroll\", \"Confirm\", \"Disable\", \"Regenerate\"].includes(action._tag);\n\n const commandObservation = management\n ? yield* owner.read(\n mapping.factor.table,\n equal(mapping.factor.table, { [mapping.factor.scope]: commandScope }),\n { limit: 1 },\n )\n : undefined;\n\n if (commandObservation !== undefined && commandObservation.rows.length !== 0) return reject;\n const timeGuards: SQL[] = [];\n\n const timeBound = (start: number, end: number) => {\n timeGuards.push(\n sql`${mapping.engineNowMillis} >= ${start} and ${mapping.engineNowMillis} < ${end}`,\n );\n };\n\n if (\n action._tag === \"Enroll\" ||\n action._tag === \"Confirm\" ||\n action._tag === \"Disable\" ||\n action._tag === \"Regenerate\"\n ) {\n const authorization = input.authorization;\n\n if (authorization === undefined) return reject;\n const { challenge, evidence } = authorization;\n\n const expectedAction = {\n Enroll: \"enroll\",\n Confirm: \"confirm\",\n Disable: \"disable\",\n Regenerate: \"regenerate\",\n }[action._tag];\n\n if (\n challenge.action !== expectedAction ||\n challenge.moduleId !== mapping.moduleId ||\n challenge.commandId !== input.commandId ||\n challenge.revision.subjectId !== input.subjectId ||\n challenge.revision.securityRevision !== snapshot.revision.securityRevision ||\n evidence.flowId !== challenge.flowId ||\n evidence.bindingDigest !== challenge.bindingDigest ||\n evidence.revision.subjectId !== input.subjectId ||\n evidence.revision.securityRevision !== snapshot.revision.securityRevision\n )\n return reject;\n const auth = mapping.credential;\n\n for (const revision of [...evidence.revision.credentials].sort((a, b) =>\n a.credentialId.localeCompare(b.credentialId),\n )) {\n const found = yield* owner.read(\n auth.table,\n equal(auth.table, { [auth.id]: revision.credentialId, [auth.subjectId]: nativeId }),\n { limit: 1 },\n );\n\n const row = found.rows[0];\n\n if (row === undefined || row[auth.revision] !== revision.revision) return reject;\n const condition = sql`exists(select 1 from ${auth.table} where ${both(owner.exact(auth.table, row), auth.activeCondition)})`;\n\n if (!(yield* owner.check(condition))) return reject;\n credentialGuards.push({ credentialId: revision.credentialId, condition });\n }\n\n const eligible = evidence.proofs.filter((proof) =>\n evidence.revision.credentials.some(\n (revision) => revision.credentialId === proof.credentialId,\n ),\n );\n\n if (eligible.length !== evidence.proofs.length || eligible.length === 0) return reject;\n\n const requirements = [\n authorization.requirement,\n Schema.decodeSync(AuthenticationRequirement)(\n mapping.subject.decodeRequirement(copiedRow(subjectRow)),\n ),\n ];\n\n const maximumAge = Math.min(\n policy.maximumEvidenceAgeMillis,\n ...requirements.map((requirement) => requirement.maximumAgeMillis),\n );\n\n const evidenceFactors = new Set(eligible.flatMap((proof) => proof.factors));\n const evidenceCredentials = new Set(eligible.map((proof) => proof.credentialId));\n\n for (const requirement of requirements) {\n if (\n !requirement.alternatives.some(\n (alternative) =>\n alternative.factors.every((factor) => evidenceFactors.has(factor)) &&\n evidenceCredentials.size >= alternative.minimumCredentials &&\n eligible.some(\n (proof) =>\n (!alternative.userVerified || proof.userVerified) &&\n (!alternative.phishingResistant || proof.phishingResistant),\n ),\n )\n )\n return reject;\n }\n for (const proof of eligible) {\n const verifiedAt = proof.verifiedAt.epochMilliseconds;\n\n if (verifiedAt > now || now - verifiedAt >= maximumAge) return reject;\n timeBound(verifiedAt, verifiedAt + maximumAge);\n }\n if (\n (current !== null && current.secret !== null) ||\n action._tag === \"Disable\" ||\n action._tag === \"Regenerate\"\n ) {\n const factors = new Set(eligible.flatMap((proof) => proof.factors));\n\n if (\n !(\n eligible.some(\n (proof) =>\n proof.userVerified && proof.phishingResistant && proof.factors.includes(\"possession\"),\n ) ||\n (factors.has(\"knowledge\") &&\n factors.has(\"possession\") &&\n new Set(eligible.map((proof) => proof.credentialId)).size >= 2)\n )\n )\n return reject;\n }\n }\n if (action._tag === \"Recovery\" && action.reset) {\n const target = action.pending;\n\n if (\n target === undefined ||\n mapping.pendingCondition === undefined ||\n target.revision.subjectId !== input.subjectId ||\n target.revision.securityRevision !== snapshot.revision.securityRevision ||\n target.expiresAtMillis <= now\n )\n return reject;\n const condition = mapping.pendingCondition(target, nativeId);\n\n if (!(yield* owner.check(condition))) return reject;\n guards.push(condition);\n timeBound(0, target.expiresAtMillis);\n }\n\n let next: TotpRecord,\n semantic = false,\n accepted = true;\n\n if (action._tag === \"Enroll\") {\n const candidate = action.record;\n\n if (\n candidate.subjectId !== input.subjectId ||\n candidate.moduleId !== input.moduleId ||\n candidate.pending === null ||\n candidate.pending.expiresAtMillis <= now ||\n candidate.pending.expiresAtMillis > now + policy.enrollmentLifetimeMillis ||\n candidate.pending.failedAttempts !== 0 ||\n candidate.pending.secret.revision !== candidate.pending.revision\n )\n return reject;\n // Reissuing cannot erase the confirmation budget during its current enrollment lifetime.\n if (current !== null && current.pending !== null && current.pending.expiresAtMillis > now)\n return reject;\n if (\n current !== null &&\n (candidate.credentialId !== current.credentialId ||\n encodeTotpRecord({ ...candidate, pending: current.pending }) !== encodeTotpRecord(current))\n )\n return reject;\n if (\n current === null &&\n (candidate.secret !== null ||\n candidate.recoveryDigests.length !== 0 ||\n candidate.acceptedStep !== -1 ||\n candidate.failedAttempts !== 0)\n )\n return reject;\n next = candidate;\n timeBound(0, candidate.pending.expiresAtMillis);\n } else {\n if (current === null) return reject;\n next = { ...current };\n if (action._tag === \"Confirm\") {\n const pending = current.pending;\n\n if (\n pending === null ||\n pending.enrollmentId !== action.enrollmentId ||\n pending.expiresAtMillis <= now ||\n pending.failedAttempts >= policy.attemptLimit\n )\n return reject;\n timeBound(0, pending.expiresAtMillis);\n if (\n action.matchedStep === null ||\n Math.abs(Math.floor(now / 30000) - action.matchedStep) > policy.clockSkewSteps\n ) {\n next = { ...current, pending: { ...pending, failedAttempts: pending.failedAttempts + 1 } };\n accepted = false;\n } else {\n if (new Set(action.recoveryDigests).size !== 10) return reject;\n next = {\n ...current,\n secret: pending.secret,\n revision: pending.secret.revision,\n pending: null,\n recoveryDigests: action.recoveryDigests,\n acceptedStep: action.matchedStep,\n attemptWindow: now,\n failedAttempts: 0,\n };\n semantic = true;\n timeBound(\n Math.max(0, (action.matchedStep - policy.clockSkewSteps) * 30000),\n (action.matchedStep + policy.clockSkewSteps + 1) * 30000,\n );\n }\n } else if (action._tag === \"Verify\" || action._tag === \"Recovery\") {\n if (current.secret === null) return reject;\n\n const expired = now >= current.attemptWindow + policy.attemptWindowMillis,\n attempts = expired ? 0 : current.failedAttempts,\n start = expired ? now : current.attemptWindow;\n\n if (attempts >= policy.attemptLimit) return reject;\n next = { ...current, attemptWindow: start, failedAttempts: attempts + 1 };\n if (action._tag === \"Verify\") {\n if (\n action.matchedStep === null ||\n action.matchedStep <= current.acceptedStep ||\n Math.abs(Math.floor(now / 30000) - action.matchedStep) > policy.clockSkewSteps\n )\n accepted = false;\n else {\n next = { ...next, acceptedStep: action.matchedStep, failedAttempts: 0 };\n timeBound(\n Math.max(0, (action.matchedStep - policy.clockSkewSteps) * 30000),\n (action.matchedStep + policy.clockSkewSteps + 1) * 30000,\n );\n }\n } else {\n if (\n (action.reset\n ? policy.lostFactorRecovery !== \"reset-with-recovery-code\"\n : !policy.allowRecoveryCodeForPending) ||\n !current.recoveryDigests.includes(action.digest)\n )\n accepted = false;\n else {\n next = {\n ...next,\n recoveryDigests: current.recoveryDigests.filter((value) => value !== action.digest),\n failedAttempts: 0,\n };\n if (action.reset) {\n next = {\n ...next,\n secret: null,\n pending: null,\n recoveryDigests: [],\n revision: yield* randomId,\n };\n semantic = true;\n }\n }\n }\n } else {\n if (current.secret === null) return reject;\n semantic = true;\n if (action._tag === \"Disable\")\n next = {\n ...current,\n secret: null,\n pending: null,\n recoveryDigests: [],\n revision: yield* randomId,\n };\n else {\n if (new Set(action.recoveryDigests).size !== 10) return reject;\n next = { ...current, recoveryDigests: action.recoveryDigests };\n }\n }\n }\n next = { ...next, version: yield* randomId };\n\n const subject = mapping.subject,\n factor = mapping.factor,\n auth = mapping.credential;\n\n const subjectKey = { [subject.id]: nativeId };\n\n if (semantic) {\n const revision = yield* randomId,\n updates = {\n [subject.securityRevision]: revision,\n [subject.factorEnabled]: subject.encodeEnabled(next.secret !== null),\n };\n\n yield* owner.update(subject.table, subjectKey, updates);\n const idKey = { [auth.id]: next.credentialId, [auth.subjectId]: nativeId };\n const existing = yield* owner.read(auth.table, equal(auth.table, idKey), { limit: 1 });\n\n if (existing.rows.length === 0) {\n const values = {\n ...auth.encodeInsert({\n credentialId: next.credentialId,\n subjectId: nativeId,\n revision: next.revision,\n active: next.secret !== null,\n }),\n [auth.id]: next.credentialId,\n [auth.subjectId]: nativeId,\n [auth.revision]: next.revision,\n [auth.status]: auth.encodeStatus(next.secret !== null),\n };\n\n existing.rows = (yield* owner.insert(auth.table, values, {\n [auth.id]: next.credentialId,\n })).rows;\n } else\n yield* owner.update(auth.table, idKey, {\n [auth.revision]: next.revision,\n [auth.status]: auth.encodeStatus(next.secret !== null),\n });\n // Management proof observations precede its own credential/revision mutation.\n // Retain all unrelated credential authority checks at final commit.\n }\n\n const state = encodeTotpRecord(next),\n values = { [factor.state]: state, [factor.version]: next.version };\n\n if (factorRow === undefined) {\n const insert = factor.encodeInsert({ scope, state, version: next.version });\n\n invariant(\n insert[factor.scope] === scope &&\n insert[factor.state] === state &&\n insert[factor.version] === next.version,\n );\n factorObservation.rows = (yield* owner.insert(factor.table, insert, {\n [factor.scope]: scope,\n })).rows;\n } else yield* owner.update(factor.table, { [factor.scope]: scope }, values);\n if (commandObservation !== undefined) {\n const values = factor.encodeInsert({\n scope: commandScope,\n state: \"totp-command/v1\",\n version: yield* randomId,\n });\n\n invariant(values[factor.scope] === commandScope && values[factor.state] === \"totp-command/v1\");\n commandObservation.rows = (yield* owner.insert(factor.table, values, {\n [factor.scope]: commandScope,\n })).rows;\n }\n // Exact pre-write observations plus final readback are asserted by the common owner.\n // Include active subject and native time at finalization, including on rejection commits.\n guards.push(\n sql`exists(select 1 from ${subject.table} where ${both(equal(subject.table, subjectKey), subject.activeCondition)})`,\n );\n owner.postconditions.push(\n ...guards,\n ...timeGuards,\n ...credentialGuards\n .filter((guard) => !semantic || guard.credentialId !== next.credentialId)\n .map((guard) => guard.condition),\n );\n\n return accepted ? { _tag: \"Accepted\" as const, record: next } : reject;\n});\n"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import "./totp-model.mjs";
|
|
|
5
5
|
import "./SuppliedService.mjs";
|
|
6
6
|
import { NativeDatabase } from "@yielded/auth-persistence/Adapter";
|
|
7
7
|
import { Table } from "drizzle-orm";
|
|
8
|
-
import { Context, Effect } from "effect";
|
|
8
|
+
import { Context, Crypto, Effect } from "effect";
|
|
9
9
|
import { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
10
10
|
import { TotpConfigurationError, TotpPersistence, TotpUnavailable } from "@yielded/auth/Totp";
|
|
11
11
|
import { Statement } from "effect/sql/Statement";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { validateDrizzleStorage } from "./storage-validation.mjs";
|
|
2
|
+
import { randomId } from "./crypto.mjs";
|
|
2
3
|
import { coordinateTransactionOwner, makeTransactionExecution, sqlClientTransactionStandaloneGuard } from "./transaction-execution.mjs";
|
|
3
4
|
import { requiredTotpConstraints } from "./totp-model.mjs";
|
|
4
5
|
import { CurrentTotpTransaction, captureTotp, invariant, mutateTotp, unavailable } from "./totp-state.mjs";
|
|
@@ -7,7 +8,6 @@ import { NativeDatabase } from "@yielded/auth-persistence/Adapter";
|
|
|
7
8
|
import { Context, Effect, Schema } from "effect";
|
|
8
9
|
import { LifecycleHooks } from "@yielded/auth/Hooks";
|
|
9
10
|
import { TotpConfigurationError, TotpMutation, TotpPersistence, TotpPolicy } from "@yielded/auth/Totp";
|
|
10
|
-
import { randomId } from "@yielded/auth-crypto";
|
|
11
11
|
//#region src/drizzle/totp-target.ts
|
|
12
12
|
const sqlClientTotpStandaloneGuard = (service) => sqlClientTransactionStandaloneGuard(unavailable, service);
|
|
13
13
|
const validateMapping = (original, configuration) => {
|
|
@@ -67,7 +67,7 @@ const coordinateTargetTotp = (database, source, configuration, body) => Effect.g
|
|
|
67
67
|
yield* validateDrizzleStorage(mapping).pipe(Effect.mapError(() => TotpConfigurationError.make({})));
|
|
68
68
|
return yield* coordinateTransactionOwner(database, CurrentTotpTransaction, configuration, Effect.void, unavailable, randomId, (execution) => services(mapping, execution), (transaction, acquireServices, append) => Effect.flatMap(acquireServices, (boundServices) => body(transaction, boundServices, append)));
|
|
69
69
|
});
|
|
70
|
-
/** Concrete driver wrappers select transaction mode
|
|
70
|
+
/** Concrete driver wrappers select transaction mode. */
|
|
71
71
|
const makeTotpTarget = (databaseService, configuration) => {
|
|
72
72
|
function coordinateTotpPersistence(acquire, options, body) {
|
|
73
73
|
return Effect.flatMap(nativeDatabase(acquire), (database) => coordinateTargetTotp(database, options.mapping, configuration, (transaction, services) => {
|