@yielded/auth-persistence 0.1.0-beta.7
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 +21 -0
- package/dist/Drizzle.d.mts +28 -0
- package/dist/Drizzle.mjs +28 -0
- package/dist/DrizzleD1.d.mts +963 -0
- package/dist/DrizzleD1.mjs +29 -0
- package/dist/DrizzleD1.mjs.map +1 -0
- package/dist/DrizzleLibsql.d.mts +2284 -0
- package/dist/DrizzleLibsql.mjs +92 -0
- package/dist/DrizzleLibsql.mjs.map +1 -0
- package/dist/DrizzleMysql2.d.mts +1820 -0
- package/dist/DrizzleMysql2.mjs +55 -0
- package/dist/DrizzleMysql2.mjs.map +1 -0
- package/dist/DrizzlePglite.d.mts +1826 -0
- package/dist/DrizzlePglite.mjs +53 -0
- package/dist/DrizzlePglite.mjs.map +1 -0
- package/dist/DrizzlePostgres.d.mts +1826 -0
- package/dist/DrizzlePostgres.mjs +53 -0
- package/dist/DrizzlePostgres.mjs.map +1 -0
- package/dist/DrizzleSqliteBun.d.mts +2279 -0
- package/dist/DrizzleSqliteBun.mjs +70 -0
- package/dist/DrizzleSqliteBun.mjs.map +1 -0
- package/dist/DrizzleSqliteDo.d.mts +2329 -0
- package/dist/DrizzleSqliteDo.mjs +105 -0
- package/dist/DrizzleSqliteDo.mjs.map +1 -0
- package/dist/DrizzleSqliteNode.d.mts +2279 -0
- package/dist/DrizzleSqliteNode.mjs +70 -0
- package/dist/DrizzleSqliteNode.mjs.map +1 -0
- package/dist/DrizzleSqliteWasm.d.mts +2282 -0
- package/dist/DrizzleSqliteWasm.mjs +70 -0
- package/dist/DrizzleSqliteWasm.mjs.map +1 -0
- package/dist/drizzle/D1BatchStatements.d.mts +11 -0
- package/dist/drizzle/D1BatchStatements.mjs +8 -0
- package/dist/drizzle/D1BatchStatements.mjs.map +1 -0
- package/dist/drizzle/PasswordPreparedPostconditions.mjs +12 -0
- package/dist/drizzle/PasswordPreparedPostconditions.mjs.map +1 -0
- package/dist/drizzle/SuppliedService.d.mts +10 -0
- package/dist/drizzle/d1-emails.d.mts +62 -0
- package/dist/drizzle/d1-emails.mjs +580 -0
- package/dist/drizzle/d1-emails.mjs.map +1 -0
- package/dist/drizzle/d1-generated-statement.d.mts +2 -0
- package/dist/drizzle/d1-generated-statement.mjs +79 -0
- package/dist/drizzle/d1-generated-statement.mjs.map +1 -0
- package/dist/drizzle/d1-identity.d.mts +31 -0
- package/dist/drizzle/d1-identity.mjs +119 -0
- package/dist/drizzle/d1-identity.mjs.map +1 -0
- package/dist/drizzle/d1-oauth.d.mts +301 -0
- package/dist/drizzle/d1-oauth.mjs +76 -0
- package/dist/drizzle/d1-oauth.mjs.map +1 -0
- package/dist/drizzle/d1-passkey.d.mts +51 -0
- package/dist/drizzle/d1-passkey.mjs +95 -0
- package/dist/drizzle/d1-passkey.mjs.map +1 -0
- package/dist/drizzle/d1-password-prepared.d.mts +25 -0
- package/dist/drizzle/d1-password-prepared.mjs +461 -0
- package/dist/drizzle/d1-password-prepared.mjs.map +1 -0
- package/dist/drizzle/d1-passwords.d.mts +87 -0
- package/dist/drizzle/d1-passwords.mjs +1004 -0
- package/dist/drizzle/d1-passwords.mjs.map +1 -0
- package/dist/drizzle/d1-phone.d.mts +26 -0
- package/dist/drizzle/d1-phone.mjs +30 -0
- package/dist/drizzle/d1-phone.mjs.map +1 -0
- package/dist/drizzle/d1-planning.d.mts +12 -0
- package/dist/drizzle/d1-planning.mjs +43 -0
- package/dist/drizzle/d1-planning.mjs.map +1 -0
- package/dist/drizzle/d1-proofs.d.mts +80 -0
- package/dist/drizzle/d1-proofs.mjs +830 -0
- package/dist/drizzle/d1-proofs.mjs.map +1 -0
- package/dist/drizzle/d1-sessions.d.mts +67 -0
- package/dist/drizzle/d1-sessions.mjs +966 -0
- package/dist/drizzle/d1-sessions.mjs.map +1 -0
- package/dist/drizzle/d1-totp.d.mts +26 -0
- package/dist/drizzle/d1-totp.mjs +27 -0
- package/dist/drizzle/d1-totp.mjs.map +1 -0
- package/dist/drizzle/email-model.d.mts +354 -0
- package/dist/drizzle/email-model.mjs +21 -0
- package/dist/drizzle/email-model.mjs.map +1 -0
- package/dist/drizzle/email-registration.d.mts +30 -0
- package/dist/drizzle/email-registration.mjs +238 -0
- package/dist/drizzle/email-registration.mjs.map +1 -0
- package/dist/drizzle/email-sql.d.mts +4 -0
- package/dist/drizzle/email-sql.mjs +9 -0
- package/dist/drizzle/email-sql.mjs.map +1 -0
- package/dist/drizzle/email-target.d.mts +20 -0
- package/dist/drizzle/email-target.mjs +72 -0
- package/dist/drizzle/email-target.mjs.map +1 -0
- package/dist/drizzle/model.d.mts +250 -0
- package/dist/drizzle/model.mjs +58 -0
- package/dist/drizzle/model.mjs.map +1 -0
- package/dist/drizzle/mysql-emails.d.mts +71 -0
- package/dist/drizzle/mysql-emails.mjs +38 -0
- package/dist/drizzle/mysql-emails.mjs.map +1 -0
- package/dist/drizzle/mysql-identity.d.mts +22 -0
- package/dist/drizzle/mysql-identity.mjs +94 -0
- package/dist/drizzle/mysql-identity.mjs.map +1 -0
- package/dist/drizzle/mysql-password-prepared.d.mts +30 -0
- package/dist/drizzle/mysql-password-prepared.mjs +16 -0
- package/dist/drizzle/mysql-password-prepared.mjs.map +1 -0
- package/dist/drizzle/mysql-passwords.d.mts +86 -0
- package/dist/drizzle/mysql-passwords.mjs +38 -0
- package/dist/drizzle/mysql-passwords.mjs.map +1 -0
- package/dist/drizzle/mysql-proofs.d.mts +75 -0
- package/dist/drizzle/mysql-proofs.mjs +23 -0
- package/dist/drizzle/mysql-proofs.mjs.map +1 -0
- package/dist/drizzle/mysql-sessions.d.mts +237 -0
- package/dist/drizzle/mysql-sessions.mjs +53 -0
- package/dist/drizzle/mysql-sessions.mjs.map +1 -0
- package/dist/drizzle/mysql.d.mts +70 -0
- package/dist/drizzle/mysql.mjs +218 -0
- package/dist/drizzle/mysql.mjs.map +1 -0
- package/dist/drizzle/oauth-accounts.mjs +358 -0
- package/dist/drizzle/oauth-accounts.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-access.mjs +210 -0
- package/dist/drizzle/oauth-connected-access.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-collection.mjs +202 -0
- package/dist/drizzle/oauth-connected-collection.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-custody.mjs +146 -0
- package/dist/drizzle/oauth-connected-custody.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-drivers.mjs +76 -0
- package/dist/drizzle/oauth-connected-drivers.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-flow.mjs +247 -0
- package/dist/drizzle/oauth-connected-flow.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-input.mjs +103 -0
- package/dist/drizzle/oauth-connected-input.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-maintenance.mjs +214 -0
- package/dist/drizzle/oauth-connected-maintenance.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-management.mjs +228 -0
- package/dist/drizzle/oauth-connected-management.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-model.d.mts +278 -0
- package/dist/drizzle/oauth-connected-model.mjs +22 -0
- package/dist/drizzle/oauth-connected-model.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-reference.d.mts +17 -0
- package/dist/drizzle/oauth-connected-reference.mjs +53 -0
- package/dist/drizzle/oauth-connected-reference.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-settlement.mjs +117 -0
- package/dist/drizzle/oauth-connected-settlement.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-state.d.mts +14 -0
- package/dist/drizzle/oauth-connected-state.mjs +422 -0
- package/dist/drizzle/oauth-connected-state.mjs.map +1 -0
- package/dist/drizzle/oauth-connected-target.d.mts +753 -0
- package/dist/drizzle/oauth-connected-target.mjs +91 -0
- package/dist/drizzle/oauth-connected-target.mjs.map +1 -0
- package/dist/drizzle/oauth-drivers.mjs +51 -0
- package/dist/drizzle/oauth-drivers.mjs.map +1 -0
- package/dist/drizzle/oauth-flow.d.mts +5 -0
- package/dist/drizzle/oauth-flow.mjs +253 -0
- package/dist/drizzle/oauth-flow.mjs.map +1 -0
- package/dist/drizzle/oauth-input.mjs +127 -0
- package/dist/drizzle/oauth-input.mjs.map +1 -0
- package/dist/drizzle/oauth-model.d.mts +463 -0
- package/dist/drizzle/oauth-model.mjs +49 -0
- package/dist/drizzle/oauth-model.mjs.map +1 -0
- package/dist/drizzle/oauth-mysql.mjs +8 -0
- package/dist/drizzle/oauth-mysql.mjs.map +1 -0
- package/dist/drizzle/oauth-owner.d.mts +4 -0
- package/dist/drizzle/oauth-owner.mjs +10 -0
- package/dist/drizzle/oauth-owner.mjs.map +1 -0
- package/dist/drizzle/oauth-registration.d.mts +6 -0
- package/dist/drizzle/oauth-registration.mjs +374 -0
- package/dist/drizzle/oauth-registration.mjs.map +1 -0
- package/dist/drizzle/oauth-state.mjs +107 -0
- package/dist/drizzle/oauth-state.mjs.map +1 -0
- package/dist/drizzle/oauth-target.d.mts +111 -0
- package/dist/drizzle/oauth-target.mjs +246 -0
- package/dist/drizzle/oauth-target.mjs.map +1 -0
- package/dist/drizzle/passkey-drivers.mjs +34 -0
- package/dist/drizzle/passkey-drivers.mjs.map +1 -0
- package/dist/drizzle/passkey-kernel.mjs +8 -0
- package/dist/drizzle/passkey-kernel.mjs.map +1 -0
- package/dist/drizzle/passkey-model.d.mts +272 -0
- package/dist/drizzle/passkey-model.mjs +34 -0
- package/dist/drizzle/passkey-model.mjs.map +1 -0
- package/dist/drizzle/passkey-registration-ceremony-model.d.mts +50 -0
- package/dist/drizzle/passkey-registration-ceremony-model.mjs +18 -0
- package/dist/drizzle/passkey-registration-ceremony-model.mjs.map +1 -0
- package/dist/drizzle/passkey-state.mjs +7 -0
- package/dist/drizzle/passkey-state.mjs.map +1 -0
- package/dist/drizzle/passkey-target.d.mts +9 -0
- package/dist/drizzle/passkey-target.mjs +7 -0
- package/dist/drizzle/passkey-target.mjs.map +1 -0
- package/dist/drizzle/passkey-write-drivers.mjs +32 -0
- package/dist/drizzle/passkey-write-drivers.mjs.map +1 -0
- package/dist/drizzle/passkey-write-model.d.mts +190 -0
- package/dist/drizzle/passkey-write-model.mjs +13 -0
- package/dist/drizzle/passkey-write-model.mjs.map +1 -0
- package/dist/drizzle/passkey-write-target.d.mts +11 -0
- package/dist/drizzle/passkey-write-target.mjs +7 -0
- package/dist/drizzle/passkey-write-target.mjs.map +1 -0
- package/dist/drizzle/password-model.d.mts +329 -0
- package/dist/drizzle/password-model.mjs +23 -0
- package/dist/drizzle/password-model.mjs.map +1 -0
- package/dist/drizzle/password-prepared-model.d.mts +94 -0
- package/dist/drizzle/password-prepared-model.mjs +11 -0
- package/dist/drizzle/password-prepared-model.mjs.map +1 -0
- package/dist/drizzle/password-prepared-sql.mjs +390 -0
- package/dist/drizzle/password-prepared-sql.mjs.map +1 -0
- package/dist/drizzle/password-prepared-state.mjs +104 -0
- package/dist/drizzle/password-prepared-state.mjs.map +1 -0
- package/dist/drizzle/password-prepared-target.d.mts +12 -0
- package/dist/drizzle/password-prepared-target.mjs +56 -0
- package/dist/drizzle/password-prepared-target.mjs.map +1 -0
- package/dist/drizzle/password-registration.d.mts +19 -0
- package/dist/drizzle/password-registration.mjs +135 -0
- package/dist/drizzle/password-registration.mjs.map +1 -0
- package/dist/drizzle/password-sql.d.mts +5 -0
- package/dist/drizzle/password-sql.mjs +9 -0
- package/dist/drizzle/password-sql.mjs.map +1 -0
- package/dist/drizzle/password-target.d.mts +17 -0
- package/dist/drizzle/password-target.mjs +61 -0
- package/dist/drizzle/password-target.mjs.map +1 -0
- package/dist/drizzle/pg-emails.d.mts +72 -0
- package/dist/drizzle/pg-emails.mjs +38 -0
- package/dist/drizzle/pg-emails.mjs.map +1 -0
- package/dist/drizzle/pg-password-prepared.d.mts +31 -0
- package/dist/drizzle/pg-password-prepared.mjs +16 -0
- package/dist/drizzle/pg-password-prepared.mjs.map +1 -0
- package/dist/drizzle/pg-passwords.d.mts +87 -0
- package/dist/drizzle/pg-passwords.mjs +38 -0
- package/dist/drizzle/pg-passwords.mjs.map +1 -0
- package/dist/drizzle/pg-proofs.d.mts +76 -0
- package/dist/drizzle/pg-proofs.mjs +22 -0
- package/dist/drizzle/pg-proofs.mjs.map +1 -0
- package/dist/drizzle/pg-sessions.d.mts +238 -0
- package/dist/drizzle/pg-sessions.mjs +53 -0
- package/dist/drizzle/pg-sessions.mjs.map +1 -0
- package/dist/drizzle/pg.d.mts +81 -0
- package/dist/drizzle/pg.mjs +290 -0
- package/dist/drizzle/pg.mjs.map +1 -0
- package/dist/drizzle/phone-model.d.mts +115 -0
- package/dist/drizzle/phone-model.mjs +39 -0
- package/dist/drizzle/phone-model.mjs.map +1 -0
- package/dist/drizzle/phone-state.mjs +16 -0
- package/dist/drizzle/phone-state.mjs.map +1 -0
- package/dist/drizzle/phone-target.d.mts +17 -0
- package/dist/drizzle/phone-target.mjs +170 -0
- package/dist/drizzle/phone-target.mjs.map +1 -0
- package/dist/drizzle/proof-model.d.mts +286 -0
- package/dist/drizzle/proof-model.mjs +17 -0
- package/dist/drizzle/proof-model.mjs.map +1 -0
- package/dist/drizzle/proof-sql.d.mts +4 -0
- package/dist/drizzle/proof-sql.mjs +8 -0
- package/dist/drizzle/proof-sql.mjs.map +1 -0
- package/dist/drizzle/proof-target.d.mts +12 -0
- package/dist/drizzle/proof-target.mjs +36 -0
- package/dist/drizzle/proof-target.mjs.map +1 -0
- package/dist/drizzle/query-operations.mjs +26 -0
- package/dist/drizzle/query-operations.mjs.map +1 -0
- package/dist/drizzle/session-model.d.mts +200 -0
- package/dist/drizzle/session-model.mjs +20 -0
- package/dist/drizzle/session-model.mjs.map +1 -0
- package/dist/drizzle/session-sql.mjs +8 -0
- package/dist/drizzle/session-sql.mjs.map +1 -0
- package/dist/drizzle/session-target.d.mts +28 -0
- package/dist/drizzle/session-target.mjs +47 -0
- package/dist/drizzle/session-target.mjs.map +1 -0
- package/dist/drizzle/sqlite-emails.mjs +45 -0
- package/dist/drizzle/sqlite-emails.mjs.map +1 -0
- package/dist/drizzle/sqlite-identity.mjs +91 -0
- package/dist/drizzle/sqlite-identity.mjs.map +1 -0
- package/dist/drizzle/sqlite-password-prepared.mjs +21 -0
- package/dist/drizzle/sqlite-password-prepared.mjs.map +1 -0
- package/dist/drizzle/sqlite-passwords.mjs +49 -0
- package/dist/drizzle/sqlite-passwords.mjs.map +1 -0
- package/dist/drizzle/sqlite-proofs.mjs +29 -0
- package/dist/drizzle/sqlite-proofs.mjs.map +1 -0
- package/dist/drizzle/sqlite-sessions.mjs +74 -0
- package/dist/drizzle/sqlite-sessions.mjs.map +1 -0
- package/dist/drizzle/sqlite.d.mts +78 -0
- package/dist/drizzle/sqlite.mjs +217 -0
- package/dist/drizzle/sqlite.mjs.map +1 -0
- package/dist/drizzle/standalone-guard.mjs +19 -0
- package/dist/drizzle/standalone-guard.mjs.map +1 -0
- package/dist/drizzle/step-up-model.d.mts +65 -0
- package/dist/drizzle/step-up-model.mjs +9 -0
- package/dist/drizzle/step-up-model.mjs.map +1 -0
- package/dist/drizzle/step-up-state.mjs +32 -0
- package/dist/drizzle/step-up-state.mjs.map +1 -0
- package/dist/drizzle/totp-model.d.mts +84 -0
- package/dist/drizzle/totp-model.mjs +13 -0
- package/dist/drizzle/totp-model.mjs.map +1 -0
- package/dist/drizzle/totp-state.d.mts +38 -0
- package/dist/drizzle/totp-state.mjs +287 -0
- package/dist/drizzle/totp-state.mjs.map +1 -0
- package/dist/drizzle/totp-target.d.mts +17 -0
- package/dist/drizzle/totp-target.mjs +81 -0
- package/dist/drizzle/totp-target.mjs.map +1 -0
- package/dist/drizzle/transaction-execution.d.mts +4 -0
- package/dist/drizzle/transaction-execution.mjs +11 -0
- package/dist/drizzle/transaction-execution.mjs.map +1 -0
- package/dist/drizzle/transaction-mysql.mjs +46 -0
- package/dist/drizzle/transaction-mysql.mjs.map +1 -0
- package/dist/drizzle/transaction-owner.d.mts +2 -0
- package/dist/drizzle/transaction-owner.mjs +8 -0
- package/dist/drizzle/transaction-owner.mjs.map +1 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +5 -0
- package/dist/internal/configuration.d.mts +174 -0
- package/dist/internal/configuration.mjs +7 -0
- package/dist/internal/configuration.mjs.map +1 -0
- package/dist/internal/drizzle-migrations.mjs +19 -0
- package/dist/internal/drizzle-migrations.mjs.map +1 -0
- package/dist/internal/drizzle-postgres.mjs +39 -0
- package/dist/internal/drizzle-postgres.mjs.map +1 -0
- package/dist/internal/drizzle-sqlite.mjs +37 -0
- package/dist/internal/drizzle-sqlite.mjs.map +1 -0
- package/dist/internal/email-kernel.d.mts +13 -0
- package/dist/internal/email-kernel.mjs +487 -0
- package/dist/internal/email-kernel.mjs.map +1 -0
- package/dist/internal/mapping-error.d.mts +11 -0
- package/dist/internal/mapping-error.mjs +30 -0
- package/dist/internal/mapping-error.mjs.map +1 -0
- package/dist/internal/passkey/admission.d.mts +7 -0
- package/dist/internal/passkey/admission.mjs +216 -0
- package/dist/internal/passkey/admission.mjs.map +1 -0
- package/dist/internal/passkey/credentials.d.mts +6 -0
- package/dist/internal/passkey/credentials.mjs +249 -0
- package/dist/internal/passkey/credentials.mjs.map +1 -0
- package/dist/internal/passkey/enrollment.mjs +138 -0
- package/dist/internal/passkey/enrollment.mjs.map +1 -0
- package/dist/internal/passkey/flow.d.mts +10 -0
- package/dist/internal/passkey/flow.mjs +452 -0
- package/dist/internal/passkey/flow.mjs.map +1 -0
- package/dist/internal/passkey/management.mjs +231 -0
- package/dist/internal/passkey/management.mjs.map +1 -0
- package/dist/internal/passkey/registration-ceremony.d.mts +9 -0
- package/dist/internal/passkey/registration-ceremony.mjs +129 -0
- package/dist/internal/passkey/registration-ceremony.mjs.map +1 -0
- package/dist/internal/passkey/registration-custody.d.mts +2 -0
- package/dist/internal/passkey/registration-custody.mjs +52 -0
- package/dist/internal/passkey/registration-custody.mjs.map +1 -0
- package/dist/internal/passkey/registration-write.mjs +211 -0
- package/dist/internal/passkey/registration-write.mjs.map +1 -0
- package/dist/internal/passkey/state.d.mts +5 -0
- package/dist/internal/passkey/state.mjs +234 -0
- package/dist/internal/passkey/state.mjs.map +1 -0
- package/dist/internal/passkey/target.d.mts +19 -0
- package/dist/internal/passkey/target.mjs +190 -0
- package/dist/internal/passkey/target.mjs.map +1 -0
- package/dist/internal/passkey/write-state.mjs +345 -0
- package/dist/internal/passkey/write-state.mjs.map +1 -0
- package/dist/internal/passkey/write-target.mjs +192 -0
- package/dist/internal/passkey/write-target.mjs.map +1 -0
- package/dist/internal/passkey-kernel.mjs +49 -0
- package/dist/internal/passkey-kernel.mjs.map +1 -0
- package/dist/internal/passkeys.mjs +367 -0
- package/dist/internal/passkeys.mjs.map +1 -0
- package/dist/internal/password-kernel.d.mts +13 -0
- package/dist/internal/password-kernel.mjs +704 -0
- package/dist/internal/password-kernel.mjs.map +1 -0
- package/dist/internal/persistence.mjs +289 -0
- package/dist/internal/persistence.mjs.map +1 -0
- package/dist/internal/phone-kernel.mjs +434 -0
- package/dist/internal/phone-kernel.mjs.map +1 -0
- package/dist/internal/proof-kernel.d.mts +9 -0
- package/dist/internal/proof-kernel.mjs +619 -0
- package/dist/internal/proof-kernel.mjs.map +1 -0
- package/dist/internal/query-operations.d.mts +3 -0
- package/dist/internal/registration.mjs +65 -0
- package/dist/internal/registration.mjs.map +1 -0
- package/dist/internal/session-kernel.mjs +737 -0
- package/dist/internal/session-kernel.mjs.map +1 -0
- package/dist/internal/sql-persistence.d.mts +11 -0
- package/dist/internal/sql-persistence.mjs +37 -0
- package/dist/internal/sql-persistence.mjs.map +1 -0
- package/dist/internal/sql-query.mjs +207 -0
- package/dist/internal/sql-query.mjs.map +1 -0
- package/dist/internal/sql-table.d.mts +37 -0
- package/dist/internal/sql-table.mjs +71 -0
- package/dist/internal/sql-table.mjs.map +1 -0
- package/dist/internal/storage-mapping.mjs +687 -0
- package/dist/internal/storage-mapping.mjs.map +1 -0
- package/dist/internal/storage-tables.d.mts +914 -0
- package/dist/internal/storage-tables.mjs +387 -0
- package/dist/internal/storage-tables.mjs.map +1 -0
- package/dist/internal/storage-validation.mjs +58 -0
- package/dist/internal/storage-validation.mjs.map +1 -0
- package/dist/internal/transaction-execution-kernel.d.mts +18 -0
- package/dist/internal/transaction-execution-kernel.mjs +118 -0
- package/dist/internal/transaction-execution-kernel.mjs.map +1 -0
- package/dist/internal/transaction-kernel.d.mts +7 -0
- package/dist/internal/transaction-kernel.mjs +260 -0
- package/dist/internal/transaction-kernel.mjs.map +1 -0
- package/package.json +1 -0
- package/src/Drizzle.ts +378 -0
- package/src/DrizzleD1.ts +136 -0
- package/src/DrizzleLibsql.ts +301 -0
- package/src/DrizzleMysql2.ts +184 -0
- package/src/DrizzlePglite.ts +174 -0
- package/src/DrizzlePostgres.ts +174 -0
- package/src/DrizzleSqliteBun.ts +258 -0
- package/src/DrizzleSqliteDo.ts +473 -0
- package/src/DrizzleSqliteNode.ts +259 -0
- package/src/DrizzleSqliteWasm.ts +263 -0
- package/src/drizzle/D1BatchStatements.ts +10 -0
- package/src/drizzle/PasswordPreparedPostconditions.ts +30 -0
- package/src/drizzle/SuppliedService.ts +10 -0
- package/src/drizzle/d1-emails.ts +1829 -0
- package/src/drizzle/d1-generated-statement.ts +129 -0
- package/src/drizzle/d1-identity.ts +375 -0
- package/src/drizzle/d1-oauth.ts +340 -0
- package/src/drizzle/d1-passkey.ts +373 -0
- package/src/drizzle/d1-password-prepared.ts +1270 -0
- package/src/drizzle/d1-passwords.ts +2656 -0
- package/src/drizzle/d1-phone.ts +96 -0
- package/src/drizzle/d1-planning.ts +104 -0
- package/src/drizzle/d1-proofs.ts +2305 -0
- package/src/drizzle/d1-sessions.ts +2857 -0
- package/src/drizzle/d1-totp.ts +78 -0
- package/src/drizzle/email-model.ts +516 -0
- package/src/drizzle/email-registration.ts +698 -0
- package/src/drizzle/email-sql.ts +24 -0
- package/src/drizzle/email-target.ts +243 -0
- package/src/drizzle/model.ts +463 -0
- package/src/drizzle/mysql-emails.ts +321 -0
- package/src/drizzle/mysql-identity.ts +324 -0
- package/src/drizzle/mysql-password-prepared.ts +204 -0
- package/src/drizzle/mysql-passwords.ts +339 -0
- package/src/drizzle/mysql-proofs.ts +181 -0
- package/src/drizzle/mysql-sessions.ts +741 -0
- package/src/drizzle/mysql.ts +687 -0
- package/src/drizzle/oauth-accounts.ts +804 -0
- package/src/drizzle/oauth-connected-access.ts +354 -0
- package/src/drizzle/oauth-connected-collection.ts +324 -0
- package/src/drizzle/oauth-connected-custody.ts +277 -0
- package/src/drizzle/oauth-connected-drivers.ts +465 -0
- package/src/drizzle/oauth-connected-flow.ts +441 -0
- package/src/drizzle/oauth-connected-input.ts +127 -0
- package/src/drizzle/oauth-connected-maintenance.ts +345 -0
- package/src/drizzle/oauth-connected-management.ts +365 -0
- package/src/drizzle/oauth-connected-model.ts +347 -0
- package/src/drizzle/oauth-connected-reference.ts +112 -0
- package/src/drizzle/oauth-connected-settlement.ts +226 -0
- package/src/drizzle/oauth-connected-state.ts +845 -0
- package/src/drizzle/oauth-connected-target.ts +264 -0
- package/src/drizzle/oauth-drivers.ts +569 -0
- package/src/drizzle/oauth-flow.ts +462 -0
- package/src/drizzle/oauth-input.ts +201 -0
- package/src/drizzle/oauth-model.ts +617 -0
- package/src/drizzle/oauth-mysql.ts +10 -0
- package/src/drizzle/oauth-owner.ts +29 -0
- package/src/drizzle/oauth-registration.ts +640 -0
- package/src/drizzle/oauth-state.ts +215 -0
- package/src/drizzle/oauth-target.ts +750 -0
- package/src/drizzle/passkey-drivers.ts +385 -0
- package/src/drizzle/passkey-kernel.ts +3 -0
- package/src/drizzle/passkey-model.ts +353 -0
- package/src/drizzle/passkey-registration-ceremony-model.ts +69 -0
- package/src/drizzle/passkey-state.ts +3 -0
- package/src/drizzle/passkey-target.ts +23 -0
- package/src/drizzle/passkey-write-drivers.ts +395 -0
- package/src/drizzle/passkey-write-model.ts +271 -0
- package/src/drizzle/passkey-write-target.ts +9 -0
- package/src/drizzle/password-model.ts +491 -0
- package/src/drizzle/password-prepared-model.ts +259 -0
- package/src/drizzle/password-prepared-sql.ts +1191 -0
- package/src/drizzle/password-prepared-state.ts +231 -0
- package/src/drizzle/password-prepared-target.ts +160 -0
- package/src/drizzle/password-registration.ts +374 -0
- package/src/drizzle/password-sql.ts +12 -0
- package/src/drizzle/password-target.ts +224 -0
- package/src/drizzle/pg-emails.ts +321 -0
- package/src/drizzle/pg-password-prepared.ts +205 -0
- package/src/drizzle/pg-passwords.ts +338 -0
- package/src/drizzle/pg-proofs.ts +191 -0
- package/src/drizzle/pg-sessions.ts +750 -0
- package/src/drizzle/pg.ts +984 -0
- package/src/drizzle/phone-model.ts +190 -0
- package/src/drizzle/phone-state.ts +21 -0
- package/src/drizzle/phone-target.ts +472 -0
- package/src/drizzle/proof-model.ts +398 -0
- package/src/drizzle/proof-sql.ts +9 -0
- package/src/drizzle/proof-target.ts +122 -0
- package/src/drizzle/query-operations.ts +37 -0
- package/src/drizzle/session-model.ts +370 -0
- package/src/drizzle/session-sql.ts +13 -0
- package/src/drizzle/session-target.ts +338 -0
- package/src/drizzle/sqlite-emails.ts +366 -0
- package/src/drizzle/sqlite-identity.ts +344 -0
- package/src/drizzle/sqlite-password-prepared.ts +260 -0
- package/src/drizzle/sqlite-passwords.ts +497 -0
- package/src/drizzle/sqlite-proofs.ts +202 -0
- package/src/drizzle/sqlite-sessions.ts +971 -0
- package/src/drizzle/sqlite.ts +705 -0
- package/src/drizzle/standalone-guard.ts +38 -0
- package/src/drizzle/step-up-model.ts +128 -0
- package/src/drizzle/step-up-state.ts +139 -0
- package/src/drizzle/totp-model.ts +92 -0
- package/src/drizzle/totp-state.ts +525 -0
- package/src/drizzle/totp-target.ts +308 -0
- package/src/drizzle/transaction-execution.ts +12 -0
- package/src/drizzle/transaction-mysql.ts +104 -0
- package/src/drizzle/transaction-owner.ts +10 -0
- package/src/index.ts +4 -0
- package/src/internal/configuration.ts +282 -0
- package/src/internal/drizzle-migrations.ts +30 -0
- package/src/internal/drizzle-postgres.ts +81 -0
- package/src/internal/drizzle-sqlite.ts +79 -0
- package/src/internal/email-kernel.ts +1532 -0
- package/src/internal/mapping-error.ts +36 -0
- package/src/internal/passkey/admission.ts +362 -0
- package/src/internal/passkey/credentials.ts +511 -0
- package/src/internal/passkey/enrollment.ts +326 -0
- package/src/internal/passkey/flow.ts +1062 -0
- package/src/internal/passkey/management.ts +422 -0
- package/src/internal/passkey/registration-ceremony.ts +283 -0
- package/src/internal/passkey/registration-custody.ts +91 -0
- package/src/internal/passkey/registration-write.ts +426 -0
- package/src/internal/passkey/state.ts +354 -0
- package/src/internal/passkey/target.ts +586 -0
- package/src/internal/passkey/write-state.ts +681 -0
- package/src/internal/passkey/write-target.ts +452 -0
- package/src/internal/passkey-kernel.ts +102 -0
- package/src/internal/passkeys.ts +597 -0
- package/src/internal/password-kernel.ts +2122 -0
- package/src/internal/persistence.ts +590 -0
- package/src/internal/phone-kernel.ts +843 -0
- package/src/internal/proof-kernel.ts +1949 -0
- package/src/internal/query-operations.ts +26 -0
- package/src/internal/registration.ts +160 -0
- package/src/internal/session-kernel.ts +2210 -0
- package/src/internal/sql-persistence.ts +45 -0
- package/src/internal/sql-query.ts +298 -0
- package/src/internal/sql-table.ts +89 -0
- package/src/internal/storage-mapping.ts +706 -0
- package/src/internal/storage-tables.ts +408 -0
- package/src/internal/storage-validation.ts +117 -0
- package/src/internal/transaction-execution-kernel.ts +317 -0
- package/src/internal/transaction-kernel.ts +582 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-model.mjs","names":[],"sources":["../../src/drizzle/password-model.ts"],"sourcesContent":["import { type RecoveryReference, type LoginIdentifier } from \"@yielded/auth/Identity\";\nimport type {\n PasswordAction,\n PasswordAttemptId,\n PasswordCredentialSnapshot,\n PasswordReplacement,\n PasswordRegistrationDecision,\n EncodedPasswordHash,\n} from \"@yielded/auth/Password\";\nimport type { AuthenticationRequirement, SecurityRevision } from \"@yielded/auth/Sessions\";\nimport type { InferInsertModel, InferSelectModel, SQL, Table } from \"drizzle-orm\";\nimport type { Effect, Redacted } from \"effect\";\n\nimport type { PersistenceMappingError, SubjectIdCodec } from \"./model\";\n\ntype ColumnKey<T extends Table> = Extract<keyof T[\"_\"][\"columns\"], string>;\n\nexport type PasswordAttemptAction = \"sign-in\" | \"change\";\nexport type PasswordAttemptState = \"pending\" | \"verified\" | \"rejected\";\nexport type PasswordRateScopeKind = \"action\" | \"identifier\" | \"subject\";\n\nexport interface PasswordScopeKeys {\n readonly action: string;\n readonly identifier: string;\n readonly subject?: string;\n}\n\nexport interface PasswordSubjectTable<Subject extends Table, _NativeSubjectId> {\n readonly table: Subject;\n readonly id: ColumnKey<Subject>;\n readonly status: ColumnKey<Subject>;\n readonly securityRevision: ColumnKey<Subject>;\n readonly isActiveStatus: (value: unknown) => boolean;\n readonly decodeRequirement: (\n row: InferSelectModel<Subject>,\n ) => Effect.Effect<AuthenticationRequirement, PersistenceMappingError>;\n /** Current policy for this exact credential mutation, decoded under the subject lock. */\n readonly decodeActionRequirement: (\n row: InferSelectModel<Subject>,\n action: PasswordAction,\n ) => Effect.Effect<AuthenticationRequirement, PersistenceMappingError>;\n readonly nextSecurityRevision?: (\n current: SecurityRevision,\n ) => Effect.Effect<SecurityRevision, PersistenceMappingError>;\n readonly nextSecurityRevisionSync?: (current: SecurityRevision) => SecurityRevision;\n /** Required only by D1 conditional statements. */\n readonly d1ActiveStatusValue?: unknown;\n}\n\nexport interface PasswordIdentifierTable<Identifier extends Table, NativeSubjectId> {\n readonly table: Identifier;\n readonly namespace: ColumnKey<Identifier>;\n readonly value: ColumnKey<Identifier>;\n readonly subjectId: ColumnKey<Identifier>;\n readonly verifiedAt: ColumnKey<Identifier>;\n readonly bindingRevision: ColumnKey<Identifier>;\n /** Consumer-owned current login/recovery eligibility, including row status. */\n readonly isCurrent: (row: InferSelectModel<Identifier>) => boolean;\n /** Required by D1 so current ownership/eligibility is rechecked in the batch. */\n readonly d1CurrentCondition?: (input: {\n readonly identifier: LoginIdentifier;\n readonly nativeSubjectId: NativeSubjectId;\n }) => SQL;\n readonly encodeInitialInsert: (\n identifier: LoginIdentifier,\n subjectId: NativeSubjectId,\n bindingRevision: SecurityRevision,\n ) => InferInsertModel<Identifier>;\n}\n\nexport interface PasswordAuthorityCredentialTable<Credential extends Table, NativeSubjectId> {\n readonly table: Credential;\n readonly subjectId: ColumnKey<Credential>;\n readonly credentialId: ColumnKey<Credential>;\n readonly revision: ColumnKey<Credential>;\n readonly status?: ColumnKey<Credential>;\n readonly isActiveStatus?: (value: unknown) => boolean;\n readonly d1ActiveStatusValue?: unknown;\n readonly encodeInsert: (input: {\n readonly subjectId: NativeSubjectId;\n readonly credentialId: string;\n readonly revision: SecurityRevision;\n }) => InferInsertModel<Credential>;\n readonly encodeRevision: (revision: SecurityRevision) => Partial<InferInsertModel<Credential>>;\n}\n\nexport interface PasswordCredentialTable<\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n NativeSubjectId,\n> {\n readonly table: Credential;\n readonly moduleId: ColumnKey<Credential>;\n readonly subjectId: ColumnKey<Credential>;\n readonly credentialId: ColumnKey<Credential>;\n readonly credentialRevision: ColumnKey<Credential>;\n readonly verifierVersion: ColumnKey<Credential>;\n readonly verifier: ColumnKey<Credential>;\n readonly normalization: ColumnKey<Credential>;\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly subjectId: NativeSubjectId;\n readonly credentialId: string;\n readonly credentialRevision: SecurityRevision;\n readonly verifierVersion: SecurityRevision;\n readonly replacement: PasswordReplacement;\n }) => InferInsertModel<Credential>;\n readonly encodeVerifier: (\n verifier: Redacted.Redacted<EncodedPasswordHash>,\n verifierVersion: SecurityRevision,\n ) => Partial<InferInsertModel<Credential>>;\n readonly encodeReplacement: (input: {\n readonly replacement: PasswordReplacement;\n readonly credentialRevision: SecurityRevision;\n readonly verifierVersion: SecurityRevision;\n }) => Partial<InferInsertModel<Credential>>;\n readonly decode: (input: {\n readonly moduleId: string;\n readonly subject: InferSelectModel<Subject>;\n readonly identifier: InferSelectModel<Identifier>;\n readonly credential: InferSelectModel<Credential>;\n }) => Effect.Effect<PasswordCredentialSnapshot, PersistenceMappingError>;\n}\n\nexport interface PasswordAttemptRecord {\n readonly moduleId: string;\n readonly action: PasswordAttemptAction;\n readonly attemptId: PasswordAttemptId;\n readonly identifier: LoginIdentifier;\n readonly subjectId?: string;\n readonly credentialId?: string;\n readonly securityRevision?: SecurityRevision;\n readonly credentialRevision?: SecurityRevision;\n readonly verifierVersion?: SecurityRevision;\n readonly identifierBindingRevision?: SecurityRevision;\n readonly admittedAtMillis: number;\n readonly deadlineMillis: number;\n readonly retentionUntilMillis: number;\n}\n\nexport interface PasswordAttemptTable<Attempt extends Table, NativeSubjectId> {\n readonly table: Attempt;\n readonly moduleId: ColumnKey<Attempt>;\n readonly action: ColumnKey<Attempt>;\n readonly attemptId: ColumnKey<Attempt>;\n readonly identifierNamespace: ColumnKey<Attempt>;\n readonly identifierValue: ColumnKey<Attempt>;\n readonly subjectId: ColumnKey<Attempt>;\n readonly credentialId: ColumnKey<Attempt>;\n readonly securityRevision: ColumnKey<Attempt>;\n readonly credentialRevision: ColumnKey<Attempt>;\n readonly verifierVersion: ColumnKey<Attempt>;\n readonly identifierBindingRevision: ColumnKey<Attempt>;\n readonly admittedAt: ColumnKey<Attempt>;\n readonly deadline: ColumnKey<Attempt>;\n readonly retentionUntil: ColumnKey<Attempt>;\n readonly state: ColumnKey<Attempt>;\n readonly encodeInsert: (\n record: PasswordAttemptRecord,\n input: { readonly nativeSubjectId?: NativeSubjectId; readonly state: \"pending\" },\n ) => InferInsertModel<Attempt>;\n}\n\nexport interface PasswordRateScopeTable<RateScope extends Table> {\n readonly table: RateScope;\n readonly moduleId: ColumnKey<RateScope>;\n readonly action: ColumnKey<RateScope>;\n readonly scopeKind: ColumnKey<RateScope>;\n readonly scopeKey: ColumnKey<RateScope>;\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly action: PasswordAttemptAction;\n readonly scopeKind: PasswordRateScopeKind;\n readonly scopeKey: string;\n }) => InferInsertModel<RateScope>;\n}\n\nexport interface PasswordChargeTable<Charge extends Table> {\n readonly table: Charge;\n readonly moduleId: ColumnKey<Charge>;\n readonly action: ColumnKey<Charge>;\n readonly scopeKind: ColumnKey<Charge>;\n readonly scopeKey: ColumnKey<Charge>;\n readonly attemptId: ColumnKey<Charge>;\n readonly occurredAt: ColumnKey<Charge>;\n readonly retentionUntil: ColumnKey<Charge>;\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly action: PasswordAttemptAction;\n readonly scopeKind: PasswordRateScopeKind;\n readonly scopeKey: string;\n readonly attemptId: PasswordAttemptId;\n readonly occurredAtMillis: number;\n readonly retentionUntilMillis: number;\n }) => InferInsertModel<Charge>;\n}\n\nexport interface PasswordCommandTable<Command extends Table> {\n readonly table: Command;\n readonly moduleId: ColumnKey<Command>;\n readonly commandId: ColumnKey<Command>;\n readonly action: ColumnKey<Command>;\n readonly bindingDigest: ColumnKey<Command>;\n readonly decision: ColumnKey<Command>;\n readonly retentionUntil: ColumnKey<Command>;\n readonly encodeInsert: (input: {\n readonly moduleId: string;\n readonly commandId: string;\n readonly action: string;\n readonly bindingDigest: string;\n readonly decision: \"changed\";\n readonly retentionUntilMillis: number;\n }) => InferInsertModel<Command>;\n}\n\nexport interface RequiredPasswordConstraints {\n readonly identifier: \"unique(identifier.namespace,identifier.value)\";\n readonly authorityCredential: \"unique(authorityCredential.subjectId,authorityCredential.credentialId)\";\n readonly credentialSubject: \"unique(credential.moduleId,credential.subjectId)\";\n readonly credentialId: \"unique(credential.moduleId,credential.credentialId)\";\n readonly attempt: \"unique(attempt.moduleId,attempt.attemptId)\";\n readonly rateScope: \"unique(rateScope.moduleId,rateScope.action,rateScope.scopeKind,rateScope.scopeKey)\";\n readonly charge: \"unique(charge.moduleId,charge.action,charge.scopeKind,charge.scopeKey,charge.attemptId)\";\n readonly command: \"unique(command.moduleId,command.commandId)\";\n}\n\nexport const requiredPasswordConstraints: RequiredPasswordConstraints = {\n identifier: \"unique(identifier.namespace,identifier.value)\",\n authorityCredential: \"unique(authorityCredential.subjectId,authorityCredential.credentialId)\",\n credentialSubject: \"unique(credential.moduleId,credential.subjectId)\",\n credentialId: \"unique(credential.moduleId,credential.credentialId)\",\n attempt: \"unique(attempt.moduleId,attempt.attemptId)\",\n rateScope: \"unique(rateScope.moduleId,rateScope.action,rateScope.scopeKind,rateScope.scopeKey)\",\n charge: \"unique(charge.moduleId,charge.action,charge.scopeKind,charge.scopeKey,charge.attemptId)\",\n command: \"unique(command.moduleId,command.commandId)\",\n};\n\nexport interface PasswordConstraintClassifier {\n /** Match only the mapped command uniqueness constraint. */\n readonly isCommandConflict: (cause: unknown) => boolean;\n /** Match only the mapped rate-scope uniqueness constraint. */\n readonly isRateScopeConflict: (cause: unknown) => boolean;\n}\n\nexport interface PasswordD1Clock {\n readonly engineNow: SQL;\n readonly engineNowMillis: SQL;\n readonly engineInstantMinus: (millis: number) => SQL;\n readonly engineInstantPlus: (millis: number) => SQL;\n}\n\nexport interface PasswordPersistenceMapping<\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n AuthorityCredential extends Table,\n Attempt extends Table,\n RateScope extends Table,\n Charge extends Table,\n Command extends Table,\n NativeSubjectId,\n> extends PasswordConstraintClassifier {\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId>;\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId>;\n readonly credential: PasswordCredentialTable<Subject, Identifier, Credential, NativeSubjectId>;\n /** Every factor revision named by action evidence, including non-password factors. */\n readonly authorityCredential: PasswordAuthorityCredentialTable<\n AuthorityCredential,\n NativeSubjectId\n >;\n readonly attempt: PasswordAttemptTable<Attempt, NativeSubjectId>;\n readonly rateScope: PasswordRateScopeTable<RateScope>;\n readonly charge: PasswordChargeTable<Charge>;\n readonly command: PasswordCommandTable<Command>;\n readonly subjectId: SubjectIdCodec<NativeSubjectId>;\n readonly constraints: RequiredPasswordConstraints;\n readonly scopeKeys: (input: {\n readonly moduleId: string;\n readonly action: PasswordAttemptAction;\n readonly identifier: LoginIdentifier;\n readonly subjectId?: string;\n }) => PasswordScopeKeys;\n readonly encodeInstant: (epochMillis: number) => unknown;\n readonly decodeInstant: (native: unknown) => Effect.Effect<number, PersistenceMappingError>;\n readonly allocateAttemptId?: Effect.Effect<PasswordAttemptId, PersistenceMappingError>;\n readonly allocateAttemptIdSync?: () => PasswordAttemptId;\n readonly allocateCredentialId?: Effect.Effect<string, PersistenceMappingError>;\n readonly allocateCredentialIdSync?: () => string;\n readonly allocateRevision?: Effect.Effect<SecurityRevision, PersistenceMappingError>;\n readonly allocateRevisionSync?: () => SecurityRevision;\n readonly commandRetentionMillis: number;\n /** All semantic replacements still bump subject revision. This flag only declares bearer invalidation latency. */\n readonly sessionInvalidation: \"same-authority-immediate\" | \"original-absolute-expiry\";\n readonly d1?: PasswordD1Clock;\n}\n\nexport type D1PasswordPersistenceMapping<\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n AuthorityCredential extends Table,\n Attempt extends Table,\n RateScope extends Table,\n Charge extends Table,\n Command extends Table,\n NativeSubjectId,\n> = PasswordPersistenceMapping<\n Subject,\n Identifier,\n Credential,\n AuthorityCredential,\n Attempt,\n RateScope,\n Charge,\n Command,\n NativeSubjectId\n> & {\n readonly d1: PasswordD1Clock;\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId> & {\n readonly d1ActiveStatusValue: unknown;\n };\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId> & {\n readonly d1CurrentCondition: (input: {\n readonly identifier: LoginIdentifier;\n readonly nativeSubjectId: NativeSubjectId;\n }) => SQL;\n };\n readonly authorityCredential: PasswordAuthorityCredentialTable<\n AuthorityCredential,\n NativeSubjectId\n > & {\n readonly d1ActiveStatusValue: unknown;\n };\n};\n\nexport type PasswordRegistrationState = \"pending\" | \"created\";\n\nexport interface PasswordRegistrationIntent<Registration> {\n readonly moduleId: string;\n readonly requestId: string;\n readonly identifier: LoginIdentifier;\n readonly registration: Registration;\n readonly replacement: PasswordReplacement;\n}\n\nexport interface PasswordRegistrationTable<Registration, Request extends Table, NativeSubjectId> {\n readonly table: Request;\n readonly moduleId: ColumnKey<Request>;\n readonly requestId: ColumnKey<Request>;\n readonly state: ColumnKey<Request>;\n readonly subjectId: ColumnKey<Request>;\n readonly recoveryReference: ColumnKey<Request>;\n readonly encodeInsert: (\n input: PasswordRegistrationIntent<Registration>,\n state: {\n readonly state: PasswordRegistrationState;\n readonly nativeSubjectId?: NativeSubjectId;\n readonly recoveryReference?: typeof RecoveryReference.Type;\n },\n ) => InferInsertModel<Request>;\n /** Replay projection must never expose a stored subject or decode protected intent. */\n readonly decodeReplay: (\n row: InferSelectModel<Request>,\n ) => Effect.Effect<\n Exclude<PasswordRegistrationDecision, { readonly _tag: \"Created\" }>,\n PersistenceMappingError\n >;\n}\n\nexport interface PasswordRegistrationProvisioning<\n Registration,\n Subject extends Table,\n NativeSubjectId,\n> {\n readonly encodeSubjectInsert: (\n input: PasswordRegistrationIntent<Registration>,\n values: {\n readonly nativeSubjectId: NativeSubjectId | undefined;\n readonly securityRevision: SecurityRevision;\n },\n ) => InferInsertModel<Subject>;\n readonly allocateSubjectId?: Effect.Effect<NativeSubjectId, PersistenceMappingError>;\n readonly allocateSubjectIdSync?: () => NativeSubjectId;\n /** Interactive targets use this for database-generated/autoincrement keys. */\n readonly decodeGeneratedId?: (\n rows: ReadonlyArray<unknown>,\n ) => Effect.Effect<NativeSubjectId, PersistenceMappingError>;\n}\n\nexport interface RequiredPasswordRegistrationConstraints {\n readonly request: \"unique(registration.moduleId,registration.requestId)\";\n readonly recoveryReference: \"unique(registration.recoveryReference)\";\n readonly identifier: \"unique(identifier.namespace,identifier.value)\";\n readonly credentialSubject: \"unique(credential.moduleId,credential.subjectId)\";\n readonly authorityCredential: \"unique(authorityCredential.subjectId,authorityCredential.credentialId)\";\n}\n\nexport const requiredPasswordRegistrationConstraints: RequiredPasswordRegistrationConstraints = {\n request: \"unique(registration.moduleId,registration.requestId)\",\n recoveryReference: \"unique(registration.recoveryReference)\",\n identifier: \"unique(identifier.namespace,identifier.value)\",\n credentialSubject: \"unique(credential.moduleId,credential.subjectId)\",\n authorityCredential: \"unique(authorityCredential.subjectId,authorityCredential.credentialId)\",\n};\n\nexport interface PasswordRegistrationConstraintClassifier {\n readonly isRequestConflict: (cause: unknown) => boolean;\n readonly isIdentifierConflict: (cause: unknown) => boolean;\n readonly isCredentialConflict: (cause: unknown) => boolean;\n}\n\nexport type PasswordRegistrationMapping<\n Registration,\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n AuthorityCredential extends Table,\n Request extends Table,\n NativeSubjectId,\n> = PasswordRegistrationConstraintClassifier & {\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId>;\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId>;\n readonly credential: PasswordCredentialTable<Subject, Identifier, Credential, NativeSubjectId>;\n readonly authorityCredential: PasswordAuthorityCredentialTable<\n AuthorityCredential,\n NativeSubjectId\n >;\n readonly registration: PasswordRegistrationTable<Registration, Request, NativeSubjectId>;\n readonly subjectId: SubjectIdCodec<NativeSubjectId>;\n readonly constraints: RequiredPasswordRegistrationConstraints;\n readonly allocateCredentialId?: Effect.Effect<string, PersistenceMappingError>;\n readonly allocateCredentialIdSync?: () => string;\n readonly allocateRevision?: Effect.Effect<SecurityRevision, PersistenceMappingError>;\n readonly allocateRevisionSync?: () => SecurityRevision;\n} & (\n | {\n readonly mode: \"atomic\";\n readonly provisioning: PasswordRegistrationProvisioning<\n Registration,\n Subject,\n NativeSubjectId\n > &\n (\n | {\n readonly idMode: \"allocated\";\n readonly allocateSubjectId: Effect.Effect<NativeSubjectId, PersistenceMappingError>;\n }\n | {\n readonly idMode: \"synchronous\";\n readonly allocateSubjectIdSync: () => NativeSubjectId;\n }\n | {\n readonly idMode: \"generated\";\n readonly decodeGeneratedId: (\n rows: ReadonlyArray<unknown>,\n ) => Effect.Effect<NativeSubjectId, PersistenceMappingError>;\n }\n );\n }\n | {\n readonly mode: \"pending\";\n readonly allocateRecoveryReference?: Effect.Effect<\n typeof RecoveryReference.Type,\n PersistenceMappingError\n >;\n readonly allocateRecoveryReferenceSync?: () => typeof RecoveryReference.Type;\n }\n );\n\nexport type AnyPasswordPersistenceMapping = PasswordPersistenceMapping<\n Table,\n Table,\n Table,\n Table,\n Table,\n Table,\n Table,\n Table,\n unknown\n>;\n\nexport type AnyPasswordRegistrationMapping<Registration = unknown> = PasswordRegistrationMapping<\n Registration,\n Table,\n Table,\n Table,\n Table,\n Table,\n unknown\n>;\n"],"mappings":";;AAmOA,MAAa,8BAA2D;CACtE,YAAY;CACZ,qBAAqB;CACrB,mBAAmB;CACnB,cAAc;CACd,SAAS;CACT,WAAW;CACX,QAAQ;CACR,SAAS;AACX;AAkKA,MAAa,0CAAmF;CAC9F,SAAS;CACT,mBAAmB;CACnB,YAAY;CACZ,mBAAmB;CACnB,qBAAqB;AACvB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { PersistenceMappingError } from "../internal/mapping-error.mjs";
|
|
2
|
+
import "./model.mjs";
|
|
3
|
+
import { D1PasswordPersistenceMapping, PasswordPersistenceMapping } from "./password-model.mjs";
|
|
4
|
+
import { D1ProofPersistenceMapping, ProofPersistenceMapping, RequiredProofConstraints } from "./proof-model.mjs";
|
|
5
|
+
import { Effect } from "effect";
|
|
6
|
+
import { PasswordPreparedReady, PasswordPreparedReservation, PasswordPreparedVersion } from "@yielded/auth/Password";
|
|
7
|
+
import { InferInsertModel, InferSelectModel, SQL, Table } from "drizzle-orm";
|
|
8
|
+
//#region src/drizzle/password-prepared-model.d.ts
|
|
9
|
+
type ColumnKey<T extends Table> = Extract<keyof T["_"]["columns"], string>;
|
|
10
|
+
type PasswordPreparedState = "Preparing" | "Ready" | "Consumed" | "Cancelled" | "Expired";
|
|
11
|
+
/** The retained intent is also its nonrefundable admission charge. Scalar identity,
|
|
12
|
+
* scope and timing columns survive sensitive snapshot/digest erasure. */
|
|
13
|
+
interface PasswordPreparedIntentTable<Intent extends Table, NativeSubjectId> {
|
|
14
|
+
readonly table: Intent;
|
|
15
|
+
readonly moduleId: ColumnKey<Intent>;
|
|
16
|
+
readonly intentId: ColumnKey<Intent>;
|
|
17
|
+
readonly commandId: ColumnKey<Intent>;
|
|
18
|
+
readonly subjectId: ColumnKey<Intent>;
|
|
19
|
+
readonly action: ColumnKey<Intent>;
|
|
20
|
+
readonly generation: ColumnKey<Intent>;
|
|
21
|
+
readonly version: ColumnKey<Intent>;
|
|
22
|
+
readonly state: ColumnKey<Intent>;
|
|
23
|
+
readonly digest: ColumnKey<Intent>;
|
|
24
|
+
readonly snapshot: ColumnKey<Intent>;
|
|
25
|
+
readonly identifierScope: ColumnKey<Intent>;
|
|
26
|
+
readonly createdAt: ColumnKey<Intent>;
|
|
27
|
+
readonly admittedAt: ColumnKey<Intent>;
|
|
28
|
+
readonly admissionRetainUntil: ColumnKey<Intent>;
|
|
29
|
+
readonly preparationExpiresAt: ColumnKey<Intent>;
|
|
30
|
+
readonly expiresAt: ColumnKey<Intent>;
|
|
31
|
+
readonly retainUntil: ColumnKey<Intent>;
|
|
32
|
+
readonly states: Readonly<Record<PasswordPreparedState, InferSelectModel<Intent>[ColumnKey<Intent>]>>;
|
|
33
|
+
readonly encodeInsert: (input: {
|
|
34
|
+
readonly reservation: PasswordPreparedReservation;
|
|
35
|
+
readonly nativeSubjectId: NativeSubjectId;
|
|
36
|
+
readonly identifierScope: string;
|
|
37
|
+
readonly admittedAtMillis: number;
|
|
38
|
+
readonly admissionRetainUntilMillis: number;
|
|
39
|
+
/** Bounded private core codec output; contains a salted verifier for Change/Reset. */
|
|
40
|
+
readonly snapshot: string;
|
|
41
|
+
}) => InferInsertModel<Intent>;
|
|
42
|
+
readonly encodeReady: (input: {
|
|
43
|
+
readonly ready: PasswordPreparedReady;
|
|
44
|
+
readonly snapshot: string;
|
|
45
|
+
}) => Partial<InferInsertModel<Intent>>;
|
|
46
|
+
/** Erase snapshot and digest, preserving every identity/scope/time column. */
|
|
47
|
+
readonly encodeTerminal: (state: Exclude<PasswordPreparedState, "Preparing" | "Ready">) => Partial<InferInsertModel<Intent>>;
|
|
48
|
+
}
|
|
49
|
+
/** One permanent row per configured module; never one row per attacker input.
|
|
50
|
+
* Native owners lock this before subject → identifier → sorted credentials → intent.
|
|
51
|
+
* It serializes admission and maintenance without process-local locks. */
|
|
52
|
+
interface PasswordPreparedAdmissionTable<Admission extends Table> {
|
|
53
|
+
readonly table: Admission;
|
|
54
|
+
readonly moduleId: ColumnKey<Admission>;
|
|
55
|
+
readonly intentId: ColumnKey<Admission>;
|
|
56
|
+
readonly admittedAt: ColumnKey<Admission>;
|
|
57
|
+
readonly admissionRetainUntil: ColumnKey<Admission>;
|
|
58
|
+
readonly encodeInsert: (moduleId: string) => InferInsertModel<Admission>;
|
|
59
|
+
}
|
|
60
|
+
declare const requiredPasswordPreparedConstraints: {
|
|
61
|
+
readonly admission: "unique(admission.moduleId)";
|
|
62
|
+
readonly intent: "unique(intent.moduleId,intent.intentId)";
|
|
63
|
+
readonly command: "unique(intent.moduleId,intent.commandId)";
|
|
64
|
+
readonly digest: "unique(intent.digest)";
|
|
65
|
+
};
|
|
66
|
+
type RequiredPasswordPreparedConstraints = typeof requiredPasswordPreparedConstraints;
|
|
67
|
+
interface PasswordPreparedPersistenceMapping<Subject extends Table, Identifier extends Table, Credential extends Table, AuthorityCredential extends Table, Attempt extends Table, RateScope extends Table, Charge extends Table, Command extends Table, Intent extends Table, Admission extends Table, NativeSubjectId> {
|
|
68
|
+
readonly password: PasswordPersistenceMapping<Subject, Identifier, Credential, AuthorityCredential, Attempt, RateScope, Charge, Command, NativeSubjectId>;
|
|
69
|
+
readonly intent: PasswordPreparedIntentTable<Intent, NativeSubjectId>;
|
|
70
|
+
readonly admission: PasswordPreparedAdmissionTable<Admission>;
|
|
71
|
+
readonly constraints: RequiredPasswordPreparedConstraints;
|
|
72
|
+
readonly allocateVersion?: Effect.Effect<PasswordPreparedVersion, PersistenceMappingError>;
|
|
73
|
+
/** Required by synchronous owners, invoked inside their actual transactionSync. */
|
|
74
|
+
readonly allocateVersionSync?: () => PasswordPreparedVersion;
|
|
75
|
+
}
|
|
76
|
+
type D1PasswordPreparedPersistenceMapping<Subject extends Table, Identifier extends Table, Credential extends Table, AuthorityCredential extends Table, Attempt extends Table, RateScope extends Table, Charge extends Table, Command extends Table, Intent extends Table, Admission extends Table, NativeSubjectId> = PasswordPreparedPersistenceMapping<Subject, Identifier, Credential, AuthorityCredential, Attempt, RateScope, Charge, Command, Intent, Admission, NativeSubjectId> & {
|
|
77
|
+
/** Convert a stored native instant to epoch milliseconds in the same SQL engine. */
|
|
78
|
+
readonly admissionClock: {
|
|
79
|
+
readonly toMillis: (instant: SQL) => SQL;
|
|
80
|
+
};
|
|
81
|
+
readonly password: D1PasswordPersistenceMapping<Subject, Identifier, Credential, AuthorityCredential, Attempt, RateScope, Charge, Command, NativeSubjectId>;
|
|
82
|
+
};
|
|
83
|
+
/** Optional real proof completion authority. Request/delivery/abuse capabilities
|
|
84
|
+
* are not required to complete the original continuation. */
|
|
85
|
+
type PasswordPreparedProofMapping<Series extends Table, Continuation extends Table, Command extends Table, Subject extends Table, Identifier extends Table, Credential extends Table, NativeSubjectId> = Pick<ProofPersistenceMapping<Table, Series, Table, Continuation, Table, Table, Table, Command, Subject, Identifier, Credential, NativeSubjectId>, "series" | "continuation" | "command" | "authority" | "scopeKeys" | "encodeInstant" | "decodeInstant" | "allocateVersion" | "allocateVersionSync" | "isSeriesConflict" | "isCommandConflict" | "d1"> & {
|
|
86
|
+
readonly constraints: Pick<RequiredProofConstraints, "series" | "continuationId" | "continuationDigest" | "command">;
|
|
87
|
+
};
|
|
88
|
+
type D1PasswordPreparedProofMapping<Series extends Table, Continuation extends Table, Command extends Table, Subject extends Table, Identifier extends Table, Credential extends Table, NativeSubjectId> = Pick<D1ProofPersistenceMapping<Table, Series, Table, Continuation, Table, Table, Table, Command, Subject, Identifier, Credential, NativeSubjectId>, Exclude<keyof PasswordPreparedProofMapping<Series, Continuation, Command, Subject, Identifier, Credential, NativeSubjectId>, "constraints">> & {
|
|
89
|
+
readonly constraints: PasswordPreparedProofMapping<Series, Continuation, Command, Subject, Identifier, Credential, NativeSubjectId>["constraints"];
|
|
90
|
+
};
|
|
91
|
+
type AnyPasswordPreparedPersistenceMapping = PasswordPreparedPersistenceMapping<Table, Table, Table, Table, Table, Table, Table, Table, Table, Table, unknown>;
|
|
92
|
+
//#endregion
|
|
93
|
+
export { AnyPasswordPreparedPersistenceMapping, D1PasswordPreparedPersistenceMapping, D1PasswordPreparedProofMapping, PasswordPreparedAdmissionTable, PasswordPreparedIntentTable, PasswordPreparedPersistenceMapping, PasswordPreparedProofMapping, PasswordPreparedState, RequiredPasswordPreparedConstraints, requiredPasswordPreparedConstraints };
|
|
94
|
+
//# sourceMappingURL=password-prepared-model.d.mts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/drizzle/password-prepared-model.ts
|
|
2
|
+
const requiredPasswordPreparedConstraints = {
|
|
3
|
+
admission: "unique(admission.moduleId)",
|
|
4
|
+
intent: "unique(intent.moduleId,intent.intentId)",
|
|
5
|
+
command: "unique(intent.moduleId,intent.commandId)",
|
|
6
|
+
digest: "unique(intent.digest)"
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { requiredPasswordPreparedConstraints };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=password-prepared-model.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-prepared-model.mjs","names":[],"sources":["../../src/drizzle/password-prepared-model.ts"],"sourcesContent":["import type {\n PasswordPreparedReady,\n PasswordPreparedReservation,\n PasswordPreparedVersion,\n} from \"@yielded/auth/Password\";\nimport type { InferInsertModel, InferSelectModel, SQL, Table } from \"drizzle-orm\";\nimport type { Effect } from \"effect\";\n\nimport type { PersistenceMappingError } from \"./model\";\nimport type { D1PasswordPersistenceMapping, PasswordPersistenceMapping } from \"./password-model\";\nimport type {\n D1ProofPersistenceMapping,\n ProofPersistenceMapping,\n RequiredProofConstraints,\n} from \"./proof-model\";\n\ntype ColumnKey<T extends Table> = Extract<keyof T[\"_\"][\"columns\"], string>;\nexport type PasswordPreparedState = \"Preparing\" | \"Ready\" | \"Consumed\" | \"Cancelled\" | \"Expired\";\n\n/** The retained intent is also its nonrefundable admission charge. Scalar identity,\n * scope and timing columns survive sensitive snapshot/digest erasure. */\nexport interface PasswordPreparedIntentTable<Intent extends Table, NativeSubjectId> {\n readonly table: Intent;\n readonly moduleId: ColumnKey<Intent>;\n readonly intentId: ColumnKey<Intent>;\n readonly commandId: ColumnKey<Intent>;\n readonly subjectId: ColumnKey<Intent>;\n readonly action: ColumnKey<Intent>;\n readonly generation: ColumnKey<Intent>;\n readonly version: ColumnKey<Intent>;\n readonly state: ColumnKey<Intent>;\n readonly digest: ColumnKey<Intent>;\n readonly snapshot: ColumnKey<Intent>;\n readonly identifierScope: ColumnKey<Intent>;\n readonly createdAt: ColumnKey<Intent>;\n readonly admittedAt: ColumnKey<Intent>;\n readonly admissionRetainUntil: ColumnKey<Intent>;\n readonly preparationExpiresAt: ColumnKey<Intent>;\n readonly expiresAt: ColumnKey<Intent>;\n readonly retainUntil: ColumnKey<Intent>;\n readonly states: Readonly<\n Record<PasswordPreparedState, InferSelectModel<Intent>[ColumnKey<Intent>]>\n >;\n readonly encodeInsert: (input: {\n readonly reservation: PasswordPreparedReservation;\n readonly nativeSubjectId: NativeSubjectId;\n readonly identifierScope: string;\n readonly admittedAtMillis: number;\n readonly admissionRetainUntilMillis: number;\n /** Bounded private core codec output; contains a salted verifier for Change/Reset. */\n readonly snapshot: string;\n }) => InferInsertModel<Intent>;\n readonly encodeReady: (input: {\n readonly ready: PasswordPreparedReady;\n readonly snapshot: string;\n }) => Partial<InferInsertModel<Intent>>;\n /** Erase snapshot and digest, preserving every identity/scope/time column. */\n readonly encodeTerminal: (\n state: Exclude<PasswordPreparedState, \"Preparing\" | \"Ready\">,\n ) => Partial<InferInsertModel<Intent>>;\n}\n\n/** One permanent row per configured module; never one row per attacker input.\n * Native owners lock this before subject → identifier → sorted credentials → intent.\n * It serializes admission and maintenance without process-local locks. */\nexport interface PasswordPreparedAdmissionTable<Admission extends Table> {\n readonly table: Admission;\n readonly moduleId: ColumnKey<Admission>;\n readonly intentId: ColumnKey<Admission>;\n readonly admittedAt: ColumnKey<Admission>;\n readonly admissionRetainUntil: ColumnKey<Admission>;\n readonly encodeInsert: (moduleId: string) => InferInsertModel<Admission>;\n}\n\nexport const requiredPasswordPreparedConstraints = {\n admission: \"unique(admission.moduleId)\",\n intent: \"unique(intent.moduleId,intent.intentId)\",\n command: \"unique(intent.moduleId,intent.commandId)\",\n digest: \"unique(intent.digest)\",\n} as const;\n\nexport type RequiredPasswordPreparedConstraints = typeof requiredPasswordPreparedConstraints;\n\nexport interface PasswordPreparedPersistenceMapping<\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n AuthorityCredential extends Table,\n Attempt extends Table,\n RateScope extends Table,\n Charge extends Table,\n Command extends Table,\n Intent extends Table,\n Admission extends Table,\n NativeSubjectId,\n> {\n readonly password: PasswordPersistenceMapping<\n Subject,\n Identifier,\n Credential,\n AuthorityCredential,\n Attempt,\n RateScope,\n Charge,\n Command,\n NativeSubjectId\n >;\n readonly intent: PasswordPreparedIntentTable<Intent, NativeSubjectId>;\n readonly admission: PasswordPreparedAdmissionTable<Admission>;\n readonly constraints: RequiredPasswordPreparedConstraints;\n readonly allocateVersion?: Effect.Effect<PasswordPreparedVersion, PersistenceMappingError>;\n /** Required by synchronous owners, invoked inside their actual transactionSync. */\n readonly allocateVersionSync?: () => PasswordPreparedVersion;\n}\n\nexport type D1PasswordPreparedPersistenceMapping<\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n AuthorityCredential extends Table,\n Attempt extends Table,\n RateScope extends Table,\n Charge extends Table,\n Command extends Table,\n Intent extends Table,\n Admission extends Table,\n NativeSubjectId,\n> = PasswordPreparedPersistenceMapping<\n Subject,\n Identifier,\n Credential,\n AuthorityCredential,\n Attempt,\n RateScope,\n Charge,\n Command,\n Intent,\n Admission,\n NativeSubjectId\n> & {\n /** Convert a stored native instant to epoch milliseconds in the same SQL engine. */\n readonly admissionClock: { readonly toMillis: (instant: SQL) => SQL };\n readonly password: D1PasswordPersistenceMapping<\n Subject,\n Identifier,\n Credential,\n AuthorityCredential,\n Attempt,\n RateScope,\n Charge,\n Command,\n NativeSubjectId\n >;\n};\n\n/** Optional real proof completion authority. Request/delivery/abuse capabilities\n * are not required to complete the original continuation. */\nexport type PasswordPreparedProofMapping<\n Series extends Table,\n Continuation extends Table,\n Command extends Table,\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n NativeSubjectId,\n> = Pick<\n ProofPersistenceMapping<\n Table,\n Series,\n Table,\n Continuation,\n Table,\n Table,\n Table,\n Command,\n Subject,\n Identifier,\n Credential,\n NativeSubjectId\n >,\n | \"series\"\n | \"continuation\"\n | \"command\"\n | \"authority\"\n | \"scopeKeys\"\n | \"encodeInstant\"\n | \"decodeInstant\"\n | \"allocateVersion\"\n | \"allocateVersionSync\"\n | \"isSeriesConflict\"\n | \"isCommandConflict\"\n | \"d1\"\n> & {\n readonly constraints: Pick<\n RequiredProofConstraints,\n \"series\" | \"continuationId\" | \"continuationDigest\" | \"command\"\n >;\n};\n\nexport type D1PasswordPreparedProofMapping<\n Series extends Table,\n Continuation extends Table,\n Command extends Table,\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n NativeSubjectId,\n> = Pick<\n D1ProofPersistenceMapping<\n Table,\n Series,\n Table,\n Continuation,\n Table,\n Table,\n Table,\n Command,\n Subject,\n Identifier,\n Credential,\n NativeSubjectId\n >,\n Exclude<\n keyof PasswordPreparedProofMapping<\n Series,\n Continuation,\n Command,\n Subject,\n Identifier,\n Credential,\n NativeSubjectId\n >,\n \"constraints\"\n >\n> & {\n readonly constraints: PasswordPreparedProofMapping<\n Series,\n Continuation,\n Command,\n Subject,\n Identifier,\n Credential,\n NativeSubjectId\n >[\"constraints\"];\n};\n\nexport type AnyPasswordPreparedPersistenceMapping = PasswordPreparedPersistenceMapping<\n Table,\n Table,\n Table,\n Table,\n Table,\n Table,\n Table,\n Table,\n Table,\n Table,\n unknown\n>;\n"],"mappings":";AA0EA,MAAa,sCAAsC;CACjD,WAAW;CACX,QAAQ;CACR,SAAS;CACT,QAAQ;AACV"}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { CurrentPasswordPreparedTransaction, PasswordPreparedJournalGuards, PasswordPreparedPostconditions } from "./PasswordPreparedPostconditions.mjs";
|
|
2
|
+
import { CurrentPasswordSql } from "../internal/password-kernel.mjs";
|
|
3
|
+
import { requiredPasswordPreparedConstraints } from "./password-prepared-model.mjs";
|
|
4
|
+
import { column } from "./model.mjs";
|
|
5
|
+
import { checkProofCompletionIn, completeProofPlanIn } from "./proof-sql.mjs";
|
|
6
|
+
import { passwordSqlKernel } from "./password-sql.mjs";
|
|
7
|
+
import { CompletionInput, ContextInput, encodeReservation, evidenceCurrent, identifierScope, reservationOf, sameRevision, snapshotMutation, snapshotReserve, unavailable } from "./password-prepared-state.mjs";
|
|
8
|
+
import { Cause, DateTime, Effect, Option, Predicate, Redacted, Schema } from "effect";
|
|
9
|
+
import { reportPersistenceFailure } from "@yielded/auth/Persistence";
|
|
10
|
+
import { CurrentCommitJournal, HookConfigurationError, LifecycleHooks } from "@yielded/auth/Hooks";
|
|
11
|
+
import { AuthenticationRevision } from "@yielded/auth/Sessions";
|
|
12
|
+
import { PasswordPreparedVersion, PasswordRejected, PasswordUnavailable, decodePasswordPreparedReady, encodePasswordPreparedReady, snapshotPasswordCredential, snapshotPasswordPreparedReady, snapshotPasswordPreparedReservation, snapshotPasswordRequirement } from "@yielded/auth/Password";
|
|
13
|
+
import { ProofBinding, ProofUnavailable } from "@yielded/auth/Proofs";
|
|
14
|
+
import { and, count, eq, gt, isNotNull, isNull, lte, or } from "drizzle-orm";
|
|
15
|
+
//#region src/drizzle/password-prepared-sql.ts
|
|
16
|
+
const translateFailure = (effect) => reportPersistenceFailure(effect, (error) => Schema.is(PasswordUnavailable)(error) || Schema.is(ProofUnavailable)(error) || Schema.is(HookConfigurationError)(error)).pipe(Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, () => unavailable()))));
|
|
17
|
+
const translateContextFailure = (effect) => reportPersistenceFailure(effect, (error) => Schema.is(PasswordUnavailable)(error) || Schema.is(PasswordRejected)(error) || Schema.is(ProofUnavailable)(error) || Schema.is(HookConfigurationError)(error)).pipe(Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, (error) => Schema.is(PasswordRejected)(error) ? error : unavailable()))));
|
|
18
|
+
const nowMillis = DateTime.now.pipe(Effect.map(DateTime.toEpochMillis));
|
|
19
|
+
const read = (query, locking) => locking && typeof query.for === "function" ? query.for("update") : query;
|
|
20
|
+
const columns = (mapping) => {
|
|
21
|
+
const table = mapping.intent;
|
|
22
|
+
return {
|
|
23
|
+
moduleId: column(table.table, table.moduleId),
|
|
24
|
+
intentId: column(table.table, table.intentId),
|
|
25
|
+
commandId: column(table.table, table.commandId),
|
|
26
|
+
subjectId: column(table.table, table.subjectId),
|
|
27
|
+
action: column(table.table, table.action),
|
|
28
|
+
generation: column(table.table, table.generation),
|
|
29
|
+
version: column(table.table, table.version),
|
|
30
|
+
state: column(table.table, table.state),
|
|
31
|
+
digest: column(table.table, table.digest),
|
|
32
|
+
snapshot: column(table.table, table.snapshot),
|
|
33
|
+
identifierScope: column(table.table, table.identifierScope),
|
|
34
|
+
createdAt: column(table.table, table.createdAt),
|
|
35
|
+
admittedAt: column(table.table, table.admittedAt),
|
|
36
|
+
admissionRetainUntil: column(table.table, table.admissionRetainUntil),
|
|
37
|
+
preparationExpiresAt: column(table.table, table.preparationExpiresAt),
|
|
38
|
+
expiresAt: column(table.table, table.expiresAt),
|
|
39
|
+
retainUntil: column(table.table, table.retainUntil)
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
const valid = (mapping) => Object.entries(requiredPasswordPreparedConstraints).every(([key, value]) => mapping.constraints[key] === value);
|
|
43
|
+
const lockAnchor = Effect.fn("DrizzlePasswordPrepared.lockAnchor")(function* (mapping, configuration, moduleId, create = true) {
|
|
44
|
+
const database = yield* CurrentPasswordSql;
|
|
45
|
+
const a = mapping.admission, key = column(a.table, a.moduleId);
|
|
46
|
+
if (create) yield* configuration.insertIfAbsent(database.insert(a.table).values(a.encodeInsert(moduleId)), a.moduleId, moduleId);
|
|
47
|
+
const rows = yield* read(database.select().from(a.table).where(eq(key, moduleId)).limit(2), configuration.locking);
|
|
48
|
+
if (rows.length > 1 || create && rows.length !== 1) return yield* unavailable();
|
|
49
|
+
return rows.length === 1;
|
|
50
|
+
});
|
|
51
|
+
const bindingJson = Schema.encodeSync(Schema.fromJsonString(ProofBinding));
|
|
52
|
+
const captureAuthority = Effect.fn("DrizzlePasswordPrepared.captureAuthority")(function* (mapping, configuration, input) {
|
|
53
|
+
const database = yield* CurrentPasswordSql;
|
|
54
|
+
const p = mapping.password;
|
|
55
|
+
const locked = yield* passwordSqlKernel.lockSubject(p, input.subjectId, configuration.locking);
|
|
56
|
+
if (locked.row === void 0 || !p.subject.isActiveStatus(locked.row[p.subject.status])) return void 0;
|
|
57
|
+
const ic = passwordSqlKernel.identifierColumns(p), ac = passwordSqlKernel.authorityCredentialColumns(p);
|
|
58
|
+
let identifier;
|
|
59
|
+
if (input.action !== "add-password") {
|
|
60
|
+
if (input.reset !== void 0) identifier = (yield* passwordSqlKernel.lockIdentifier(p, input.reset.binding.identifier, configuration.locking))[0];
|
|
61
|
+
else {
|
|
62
|
+
const discovered = (yield* read(database.select().from(p.identifier.table).where(eq(ic.subjectId, locked.nativeSubjectId)).orderBy(ic.namespace, ic.value), false)).find((row) => p.identifier.isCurrent(row));
|
|
63
|
+
if (discovered !== void 0) identifier = (yield* passwordSqlKernel.lockIdentifier(p, {
|
|
64
|
+
namespace: discovered[p.identifier.namespace],
|
|
65
|
+
value: discovered[p.identifier.value]
|
|
66
|
+
}, configuration.locking))[0];
|
|
67
|
+
}
|
|
68
|
+
if (identifier === void 0 || !p.identifier.isCurrent(identifier) || !p.subjectId.equals(identifier[p.identifier.subjectId], locked.nativeSubjectId)) return void 0;
|
|
69
|
+
}
|
|
70
|
+
const credential = (yield* passwordSqlKernel.readPasswordCredential(p, input.moduleId, locked.nativeSubjectId, configuration.locking))[0];
|
|
71
|
+
if (input.action === "add-password" !== (credential === void 0)) return void 0;
|
|
72
|
+
const snapshot = credential === void 0 ? void 0 : yield* p.credential.decode({
|
|
73
|
+
moduleId: input.moduleId,
|
|
74
|
+
subject: locked.row,
|
|
75
|
+
identifier,
|
|
76
|
+
credential
|
|
77
|
+
}).pipe(Effect.flatMap(snapshotPasswordCredential));
|
|
78
|
+
if (snapshot !== void 0 && (snapshot.moduleId !== input.moduleId || snapshot.revision.subjectId !== input.subjectId || snapshot.revision.securityRevision !== locked.row[p.subject.securityRevision] || snapshot.credentialId !== credential[p.credential.credentialId] || snapshot.credentialRevision !== credential[p.credential.credentialRevision] || snapshot.verifierVersion !== credential[p.credential.verifierVersion] || Redacted.value(snapshot.verifier) !== credential[p.credential.verifier] || snapshot.normalization !== credential[p.credential.normalization] || snapshot.identifier.namespace !== identifier[p.identifier.namespace] || snapshot.identifier.value !== identifier[p.identifier.value] || snapshot.identifierBindingRevision !== identifier[p.identifier.bindingRevision])) return void 0;
|
|
79
|
+
const active = (yield* read(database.select().from(p.authorityCredential.table).where(eq(ac.subjectId, locked.nativeSubjectId)).orderBy(ac.credentialId), configuration.locking)).filter((row) => p.authorityCredential.status === void 0 || p.authorityCredential.isActiveStatus?.(row[p.authorityCredential.status]) === true);
|
|
80
|
+
if (active.length > 64) return yield* unavailable();
|
|
81
|
+
const revision = snapshot?.revision ?? AuthenticationRevision.make({
|
|
82
|
+
subjectId: input.subjectId,
|
|
83
|
+
securityRevision: locked.row[p.subject.securityRevision],
|
|
84
|
+
credentials: active.map((row) => ({
|
|
85
|
+
credentialId: row[p.authorityCredential.credentialId],
|
|
86
|
+
revision: row[p.authorityCredential.revision]
|
|
87
|
+
}))
|
|
88
|
+
});
|
|
89
|
+
if (revision.credentials.some((expected) => !active.some((row) => row[p.authorityCredential.credentialId] === expected.credentialId && row[p.authorityCredential.revision] === expected.revision))) return void 0;
|
|
90
|
+
const requirement = yield* p.subject.decodeActionRequirement(locked.row, input.action).pipe(Effect.flatMap(snapshotPasswordRequirement));
|
|
91
|
+
return {
|
|
92
|
+
...locked,
|
|
93
|
+
identifier,
|
|
94
|
+
snapshot,
|
|
95
|
+
revision,
|
|
96
|
+
requirement
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
const currentAuthority = Effect.fn("DrizzlePasswordPrepared.currentAuthority")(function* (mapping, configuration, record) {
|
|
100
|
+
const current = yield* captureAuthority(mapping, configuration, {
|
|
101
|
+
moduleId: record.moduleId,
|
|
102
|
+
action: record.action,
|
|
103
|
+
subjectId: record.revision.subjectId,
|
|
104
|
+
...record.reset === void 0 ? {} : { reset: record.reset }
|
|
105
|
+
});
|
|
106
|
+
if (current === void 0 || !sameRevision(current.revision, record.revision) || (current.snapshot === void 0 ? record.credential !== void 0 : record.credential === void 0 || !passwordSqlKernel.sameCredentialSnapshot(current.snapshot, record.credential))) return void 0;
|
|
107
|
+
return current;
|
|
108
|
+
});
|
|
109
|
+
const rowCondition = (mapping, row) => {
|
|
110
|
+
const c = columns(mapping);
|
|
111
|
+
return and(...Object.entries(c).map(([key, value]) => {
|
|
112
|
+
const item = row[mapping.intent[key]];
|
|
113
|
+
return Predicate.isNullish(item) ? isNull(value) : eq(value, item);
|
|
114
|
+
}));
|
|
115
|
+
};
|
|
116
|
+
const readIntent = Effect.fn("Drizzle.readIntent")(function* (mapping, condition, locking) {
|
|
117
|
+
const database = yield* CurrentPasswordSql;
|
|
118
|
+
return yield* read(database.select().from(mapping.intent.table).where(condition).limit(2), locking);
|
|
119
|
+
});
|
|
120
|
+
const recordMatches = Effect.fn("DrizzlePasswordPrepared.recordMatches")(function* (mapping, row, record, nativeSubjectId, snapshot) {
|
|
121
|
+
const t = mapping.intent, p = mapping.password;
|
|
122
|
+
if (row === void 0 || row[t.moduleId] !== record.moduleId || row[t.intentId] !== record.intentId || row[t.commandId] !== record.commandId || !p.subjectId.equals(row[t.subjectId], nativeSubjectId) || row[t.action] !== record.action || row[t.generation] !== record.generation || row[t.version] !== record.version || row[t.state] !== t.states[record._tag] || row[t.snapshot] !== snapshot || row[t.identifierScope] !== identifierScope(record) || (record._tag === "Ready" ? row[t.digest] !== record.digest : !Predicate.isNullish(row[t.digest]))) return false;
|
|
123
|
+
for (const [key, instant] of [
|
|
124
|
+
[t.createdAt, record.createdAtMillis],
|
|
125
|
+
[t.preparationExpiresAt, record.preparationExpiresAtMillis],
|
|
126
|
+
[t.retainUntil, record.retainUntilMillis]
|
|
127
|
+
]) if ((yield* p.decodeInstant(row[key])) !== instant) return false;
|
|
128
|
+
return record._tag === "Ready" ? (yield* p.decodeInstant(row[t.expiresAt])) === record.expiresAtMillis : Predicate.isNullish(row[t.expiresAt]);
|
|
129
|
+
});
|
|
130
|
+
const terminal = Effect.fn("DrizzlePasswordPrepared.terminal")(function* (mapping, row, state) {
|
|
131
|
+
yield* (yield* CurrentPasswordSql).update(mapping.intent.table).set(mapping.intent.encodeTerminal(state)).where(rowCondition(mapping, row));
|
|
132
|
+
const c = columns(mapping), t = mapping.intent;
|
|
133
|
+
const rows = yield* readIntent(mapping, and(eq(c.moduleId, row[t.moduleId]), eq(c.intentId, row[t.intentId])), false);
|
|
134
|
+
const expected = {
|
|
135
|
+
...row,
|
|
136
|
+
[t.state]: t.states[state],
|
|
137
|
+
[t.snapshot]: null,
|
|
138
|
+
[t.digest]: null
|
|
139
|
+
};
|
|
140
|
+
if (rows.length !== 1 || (yield* readIntent(mapping, rowCondition(mapping, expected), false)).length !== 1) return yield* unavailable();
|
|
141
|
+
});
|
|
142
|
+
const makeSqlPasswordPreparedPersistence = Effect.fn("makeSqlPasswordPreparedPersistence")(function* (database, mapping, configuration) {
|
|
143
|
+
const hooks = yield* LifecycleHooks;
|
|
144
|
+
const p = mapping.password, c = columns(mapping), t = mapping.intent;
|
|
145
|
+
const owned = (body) => valid(mapping) ? passwordSqlKernel.owned(database, p, configuration, Effect.gen(function* () {
|
|
146
|
+
const journal = yield* CurrentCommitJournal;
|
|
147
|
+
const guards = yield* Effect.serviceOption(PasswordPreparedJournalGuards);
|
|
148
|
+
if (Option.isSome(guards) && !guards.value.register(journal.prepare(void 0))) return yield* unavailable();
|
|
149
|
+
return yield* body;
|
|
150
|
+
})) : Effect.fail(unavailable());
|
|
151
|
+
const complete = (uncaptured, prepare) => Effect.gen(function* () {
|
|
152
|
+
const input = yield* snapshotMutation(uncaptured);
|
|
153
|
+
const completion = uncaptured.completion === void 0 ? void 0 : {
|
|
154
|
+
prepare: uncaptured.completion.prepare,
|
|
155
|
+
input: yield* Schema.encodeEffect(Schema.fromJsonString(CompletionInput))(uncaptured.completion.input).pipe(Effect.flatMap(Schema.decodeEffect(Schema.fromJsonString(CompletionInput))), Effect.mapError(unavailable))
|
|
156
|
+
};
|
|
157
|
+
if (input.intent.action === "reset-password" !== (completion !== void 0) || completion !== void 0 && configuration.proof === void 0) return yield* unavailable();
|
|
158
|
+
return yield* owned(Effect.gen(function* () {
|
|
159
|
+
const transaction = yield* CurrentPasswordSql;
|
|
160
|
+
const journal = yield* CurrentCommitJournal;
|
|
161
|
+
yield* lockAnchor(mapping, configuration, input.intent.moduleId);
|
|
162
|
+
if ((yield* passwordSqlKernel.validateMutationAuthority(p, configuration, input.mutation, input.intent.action)) === void 0) return prepare("rejected", journal);
|
|
163
|
+
const current = yield* currentAuthority(mapping, configuration, input.intent);
|
|
164
|
+
if (current === void 0) return prepare("rejected", journal);
|
|
165
|
+
const rows = yield* readIntent(mapping, and(eq(c.moduleId, input.intent.moduleId), eq(c.intentId, input.intent.intentId)), configuration.locking);
|
|
166
|
+
const row = rows[0], encoded = yield* encodePasswordPreparedReady(input.intent);
|
|
167
|
+
if (rows.length !== 1 || !(yield* recordMatches(mapping, row, input.intent, current.nativeSubjectId, encoded)) || !evidenceCurrent(input, current.requirement, yield* nowMillis) || (yield* passwordSqlKernel.commandExists(p, input.intent.moduleId, input.intent.commandId, configuration.locking)).length !== 0) return prepare("rejected", journal);
|
|
168
|
+
if (completion !== void 0 && (input.intent.reset === void 0 || completion.input.continuationId !== input.intent.reset.continuationId || bindingJson(completion.input.binding) !== bindingJson(input.intent.reset.binding) || !passwordSqlKernel.proofCompletionMatchesPassword({
|
|
169
|
+
...input.mutation,
|
|
170
|
+
completion
|
|
171
|
+
}))) return prepare("rejected", journal);
|
|
172
|
+
const credentialRevision = yield* passwordSqlKernel.allocate(configuration.mode, p.allocateRevision, p.allocateRevisionSync);
|
|
173
|
+
const verifierVersion = yield* passwordSqlKernel.allocate(configuration.mode, p.allocateRevision, p.allocateRevisionSync);
|
|
174
|
+
const nextSecurityRevision = yield* passwordSqlKernel.allocateNextSecurityRevision(p, configuration.mode, input.intent.revision.securityRevision);
|
|
175
|
+
if (nextSecurityRevision === input.intent.revision.securityRevision || credentialRevision === input.intent.credential?.credentialRevision || verifierVersion === input.intent.credential?.verifierVersion) return yield* unavailable();
|
|
176
|
+
const credentialId = input.intent.action === "add-password" ? yield* passwordSqlKernel.allocate(configuration.mode, p.allocateCredentialId, p.allocateCredentialIdSync) : void 0;
|
|
177
|
+
let appliedAt;
|
|
178
|
+
const assertApplied = Effect.fn("DrizzlePasswordPrepared.assertApplied")(() => Effect.flatMap(CurrentPasswordPreparedTransaction, (currentTransaction) => Effect.gen(function* () {
|
|
179
|
+
if (appliedAt === void 0) return;
|
|
180
|
+
if (!(yield* passwordSqlKernel.checkMutationApplied(p, input.mutation, current.nativeSubjectId, {
|
|
181
|
+
credentialId: credentialId ?? input.intent.credential.credentialId,
|
|
182
|
+
credentialRevision,
|
|
183
|
+
verifierVersion,
|
|
184
|
+
nextSecurityRevision
|
|
185
|
+
}, appliedAt)) || (yield* readIntent(mapping, rowCondition(mapping, {
|
|
186
|
+
...row,
|
|
187
|
+
[t.state]: t.states.Consumed,
|
|
188
|
+
[t.snapshot]: null,
|
|
189
|
+
[t.digest]: null
|
|
190
|
+
}), false)).length !== 1 || !evidenceCurrent(input, current.requirement, yield* nowMillis)) return yield* unavailable();
|
|
191
|
+
}).pipe(Effect.provideService(CurrentPasswordSql, currentTransaction))));
|
|
192
|
+
const validateApplied = Effect.gen(function* () {
|
|
193
|
+
yield* assertApplied().pipe(Effect.provideService(CurrentPasswordPreparedTransaction, transaction));
|
|
194
|
+
if (appliedAt === void 0) return;
|
|
195
|
+
const postconditions = yield* Effect.serviceOption(PasswordPreparedPostconditions);
|
|
196
|
+
if (Option.isSome(postconditions) && !postconditions.value.register(assertApplied().pipe(translateFailure))) return yield* unavailable();
|
|
197
|
+
});
|
|
198
|
+
const apply = Effect.fn("DrizzlePasswordPrepared.apply")(function* () {
|
|
199
|
+
const finalNow = yield* nowMillis;
|
|
200
|
+
if (!evidenceCurrent(input, current.requirement, finalNow)) return false;
|
|
201
|
+
if (!(input.intent.action === "add-password" ? yield* passwordSqlKernel.addPasswordIn(p, configuration, input.mutation, {
|
|
202
|
+
credentialId,
|
|
203
|
+
credentialRevision,
|
|
204
|
+
verifierVersion,
|
|
205
|
+
nextSecurityRevision
|
|
206
|
+
}, finalNow) : yield* passwordSqlKernel.writeReplacement(p, input.mutation, current.nativeSubjectId, {
|
|
207
|
+
credentialRevision,
|
|
208
|
+
verifierVersion,
|
|
209
|
+
nextSecurityRevision
|
|
210
|
+
}, finalNow))) return yield* unavailable();
|
|
211
|
+
appliedAt = finalNow;
|
|
212
|
+
yield* terminal(mapping, row, "Consumed");
|
|
213
|
+
if (!evidenceCurrent(input, current.requirement, yield* nowMillis)) return yield* unavailable();
|
|
214
|
+
return true;
|
|
215
|
+
});
|
|
216
|
+
if (completion !== void 0) {
|
|
217
|
+
let receipt;
|
|
218
|
+
yield* completeProofPlanIn(configuration.proof.mapping, configuration.proof.configuration, completion, Effect.gen(function* () {
|
|
219
|
+
return yield* apply();
|
|
220
|
+
}), (decision) => {
|
|
221
|
+
receipt = prepare(decision === "completed" ? "changed" : "rejected", journal);
|
|
222
|
+
return decision;
|
|
223
|
+
});
|
|
224
|
+
yield* validateApplied;
|
|
225
|
+
return receipt ?? prepare("rejected", journal);
|
|
226
|
+
}
|
|
227
|
+
const changed = yield* apply();
|
|
228
|
+
yield* validateApplied;
|
|
229
|
+
return prepare(changed ? "changed" : "rejected", journal);
|
|
230
|
+
}));
|
|
231
|
+
});
|
|
232
|
+
return {
|
|
233
|
+
reserve: (uncaptured, prepare) => Effect.gen(function* () {
|
|
234
|
+
const input = yield* snapshotReserve(uncaptured);
|
|
235
|
+
if (input.action === "reset-password" !== (input.reset !== void 0 && input.completion !== void 0) || input.action === "reset-password" && configuration.proof === void 0 || input.generation !== input.policy.generation || input.policy.retentionMillis < Math.max(input.policy.preparationLifetimeMillis + input.policy.lifetimeMillis, input.policy.admission.action.windowMillis, input.policy.admission.identifier.windowMillis, input.policy.admission.subject.windowMillis) || input.invalidation.existingSessions === "immediate" && p.sessionInvalidation !== "same-authority-immediate") return yield* unavailable();
|
|
236
|
+
return yield* owned(Effect.gen(function* () {
|
|
237
|
+
const transaction = yield* CurrentPasswordSql;
|
|
238
|
+
const journal = yield* CurrentCommitJournal;
|
|
239
|
+
yield* lockAnchor(mapping, configuration, input.moduleId);
|
|
240
|
+
const version = PasswordPreparedVersion.make(yield* passwordSqlKernel.allocate(configuration.mode, mapping.allocateVersion, mapping.allocateVersionSync));
|
|
241
|
+
const authority = yield* captureAuthority(mapping, configuration, input);
|
|
242
|
+
if (authority === void 0) return yield* unavailable();
|
|
243
|
+
if (input.reset !== void 0) {
|
|
244
|
+
if (input.completion === void 0 || input.completion.moduleId !== `${input.moduleId}/reset` || input.completion.purpose !== "password-reset" || input.reset.continuationId !== input.completion.continuationId || bindingJson(input.reset.binding) !== bindingJson(input.completion.binding) || input.reset.binding._tag !== "Subject" || !sameRevision(input.reset.binding.revision, authority.revision) || authority.snapshot?.identifierVerifiedAtMillis === void 0 || !(yield* checkProofCompletionIn(configuration.proof.mapping, configuration.proof.configuration, input.completion))) return yield* unavailable();
|
|
245
|
+
}
|
|
246
|
+
if ((yield* readIntent(mapping, and(eq(c.moduleId, input.moduleId), eq(c.commandId, input.commandId)), configuration.locking)).length) return prepare({ _tag: "Existing" }, journal);
|
|
247
|
+
const now = yield* nowMillis, nativeNow = p.encodeInstant(now);
|
|
248
|
+
const scope = identifierScope({
|
|
249
|
+
credential: authority.snapshot,
|
|
250
|
+
revision: authority.revision
|
|
251
|
+
});
|
|
252
|
+
if (((yield* read(transaction.select({ total: count() }).from(t.table).where(and(eq(c.moduleId, input.moduleId), eq(c.subjectId, authority.nativeSubjectId), or(and(eq(c.state, t.states.Preparing), gt(c.preparationExpiresAt, nativeNow)), and(eq(c.state, t.states.Ready), gt(c.expiresAt, nativeNow))))), false))[0]?.total ?? 0) >= input.policy.maximumPendingPerSubject) return yield* unavailable();
|
|
253
|
+
for (const [condition, budget] of [
|
|
254
|
+
[eq(c.action, input.action), input.policy.admission.action],
|
|
255
|
+
[eq(c.identifierScope, scope), input.policy.admission.identifier],
|
|
256
|
+
[eq(c.subjectId, authority.nativeSubjectId), input.policy.admission.subject]
|
|
257
|
+
]) if (((yield* read(transaction.select({ total: count() }).from(t.table).where(and(eq(c.moduleId, input.moduleId), condition, gt(c.admittedAt, p.encodeInstant(now - budget.windowMillis)))), false))[0]?.total ?? 0) >= budget.limit) return yield* unavailable();
|
|
258
|
+
const reservation = yield* snapshotPasswordPreparedReservation({
|
|
259
|
+
_tag: "Preparing",
|
|
260
|
+
moduleId: input.moduleId,
|
|
261
|
+
generation: input.generation,
|
|
262
|
+
intentId: input.intentId,
|
|
263
|
+
version,
|
|
264
|
+
commandId: input.commandId,
|
|
265
|
+
action: input.action,
|
|
266
|
+
revision: authority.revision,
|
|
267
|
+
...authority.snapshot === void 0 ? {} : { credential: authority.snapshot },
|
|
268
|
+
capturedRequirement: authority.requirement,
|
|
269
|
+
...input.reset === void 0 ? {} : { reset: input.reset },
|
|
270
|
+
invalidation: input.invalidation,
|
|
271
|
+
createdAtMillis: now,
|
|
272
|
+
preparationExpiresAtMillis: now + input.policy.preparationLifetimeMillis,
|
|
273
|
+
retainUntilMillis: now + input.policy.retentionMillis
|
|
274
|
+
});
|
|
275
|
+
const snapshot = yield* encodeReservation(reservation);
|
|
276
|
+
yield* transaction.insert(t.table).values(t.encodeInsert({
|
|
277
|
+
reservation,
|
|
278
|
+
nativeSubjectId: authority.nativeSubjectId,
|
|
279
|
+
identifierScope: scope,
|
|
280
|
+
snapshot,
|
|
281
|
+
admittedAtMillis: now,
|
|
282
|
+
admissionRetainUntilMillis: now + Math.max(input.policy.admission.action.windowMillis, input.policy.admission.identifier.windowMillis, input.policy.admission.subject.windowMillis)
|
|
283
|
+
}));
|
|
284
|
+
const rows = yield* readIntent(mapping, and(eq(c.moduleId, input.moduleId), eq(c.intentId, input.intentId)), false);
|
|
285
|
+
if (rows.length !== 1 || !(yield* recordMatches(mapping, rows[0], reservation, authority.nativeSubjectId, snapshot))) return yield* unavailable();
|
|
286
|
+
const admittedUntil = now + Math.max(input.policy.admission.action.windowMillis, input.policy.admission.identifier.windowMillis, input.policy.admission.subject.windowMillis);
|
|
287
|
+
if ((yield* p.decodeInstant(rows[0][t.admittedAt])) !== now || (yield* p.decodeInstant(rows[0][t.admissionRetainUntil])) !== admittedUntil || (yield* nowMillis) >= reservation.preparationExpiresAtMillis || input.completion !== void 0 && !(yield* checkProofCompletionIn(configuration.proof.mapping, configuration.proof.configuration, input.completion))) return yield* unavailable();
|
|
288
|
+
return prepare({
|
|
289
|
+
_tag: "Reserved",
|
|
290
|
+
reservation
|
|
291
|
+
}, journal);
|
|
292
|
+
}));
|
|
293
|
+
}).pipe(Effect.provideService(CurrentPasswordSql, database), Effect.provideService(LifecycleHooks, hooks), translateFailure),
|
|
294
|
+
publishReady: (uncaptured, prepare) => Effect.gen(function* () {
|
|
295
|
+
const reservation = yield* snapshotPasswordPreparedReservation(uncaptured.reservation), ready = yield* snapshotPasswordPreparedReady(uncaptured.ready);
|
|
296
|
+
const snapshot = yield* encodeReservation(reservation), readySnapshot = yield* encodePasswordPreparedReady(ready);
|
|
297
|
+
if ((yield* encodeReservation(reservationOf(ready))) !== snapshot) return yield* unavailable();
|
|
298
|
+
return yield* owned(Effect.gen(function* () {
|
|
299
|
+
const transaction = yield* CurrentPasswordSql;
|
|
300
|
+
const journal = yield* CurrentCommitJournal;
|
|
301
|
+
yield* lockAnchor(mapping, configuration, reservation.moduleId);
|
|
302
|
+
const authority = yield* currentAuthority(mapping, configuration, reservation);
|
|
303
|
+
if (authority === void 0) return prepare("rejected", journal);
|
|
304
|
+
const rows = yield* readIntent(mapping, and(eq(c.moduleId, reservation.moduleId), eq(c.intentId, reservation.intentId)), configuration.locking), row = rows[0];
|
|
305
|
+
const now = yield* nowMillis;
|
|
306
|
+
if (rows.length !== 1 || !(yield* recordMatches(mapping, row, reservation, authority.nativeSubjectId, snapshot)) || now < ready.issuedAtMillis || now >= reservation.preparationExpiresAtMillis || now >= ready.expiresAtMillis) return prepare("rejected", journal);
|
|
307
|
+
yield* transaction.update(t.table).set(t.encodeReady({
|
|
308
|
+
ready,
|
|
309
|
+
snapshot: readySnapshot
|
|
310
|
+
})).where(rowCondition(mapping, row));
|
|
311
|
+
const saved = yield* readIntent(mapping, and(eq(c.moduleId, ready.moduleId), eq(c.intentId, ready.intentId)), false);
|
|
312
|
+
if (saved.length !== 1 || !(yield* recordMatches(mapping, saved[0], ready, authority.nativeSubjectId, readySnapshot)) || (yield* readIntent(mapping, and(eq(c.moduleId, ready.moduleId), eq(c.intentId, ready.intentId), eq(c.admittedAt, row[t.admittedAt]), eq(c.admissionRetainUntil, row[t.admissionRetainUntil])), false)).length !== 1) return yield* unavailable();
|
|
313
|
+
if ((yield* nowMillis) >= reservation.preparationExpiresAtMillis || (yield* nowMillis) >= ready.expiresAtMillis) return yield* unavailable();
|
|
314
|
+
return prepare("published", journal);
|
|
315
|
+
}));
|
|
316
|
+
}).pipe(Effect.provideService(CurrentPasswordSql, database), Effect.provideService(LifecycleHooks, hooks), translateFailure),
|
|
317
|
+
context: (uncaptured) => Effect.gen(function* () {
|
|
318
|
+
const input = yield* Schema.decodeEffect(ContextInput)({ ...uncaptured }).pipe(Effect.mapError(unavailable));
|
|
319
|
+
return (yield* passwordSqlKernel.safeRead(database, configuration, Effect.gen(function* () {
|
|
320
|
+
if (!valid(mapping) || !(yield* lockAnchor(mapping, configuration, input.moduleId, false))) return void 0;
|
|
321
|
+
const rows = yield* readIntent(mapping, and(eq(c.moduleId, input.moduleId), eq(c.generation, input.generation), eq(c.digest, input.digest), eq(c.state, t.states.Ready)), false);
|
|
322
|
+
if (rows.length !== 1) return void 0;
|
|
323
|
+
const selected = yield* decodePasswordPreparedReady(rows[0][t.snapshot]);
|
|
324
|
+
const authority = yield* currentAuthority(mapping, configuration, selected);
|
|
325
|
+
if (authority === void 0) return void 0;
|
|
326
|
+
const locked = yield* readIntent(mapping, rowCondition(mapping, rows[0]), configuration.locking);
|
|
327
|
+
const now = yield* nowMillis;
|
|
328
|
+
if (locked.length !== 1 || now < selected.issuedAtMillis || now >= selected.expiresAtMillis || selected.moduleId !== input.moduleId || selected.generation !== input.generation || selected.digest !== input.digest || !(yield* recordMatches(mapping, locked[0], selected, authority.nativeSubjectId, yield* encodePasswordPreparedReady(selected)))) return void 0;
|
|
329
|
+
return {
|
|
330
|
+
record: selected,
|
|
331
|
+
currentRequirement: authority.requirement
|
|
332
|
+
};
|
|
333
|
+
}))) ?? (yield* PasswordRejected.make({}));
|
|
334
|
+
}).pipe(Effect.provideService(CurrentPasswordSql, database), Effect.provideService(LifecycleHooks, hooks), translateContextFailure),
|
|
335
|
+
complete: (input, prepare) => complete(input, prepare).pipe(Effect.provideService(CurrentPasswordSql, database), Effect.provideService(LifecycleHooks, hooks), translateFailure),
|
|
336
|
+
resetWithProof: (input, prepare) => complete(input, prepare).pipe(Effect.provideService(CurrentPasswordSql, database), Effect.provideService(LifecycleHooks, hooks), translateFailure),
|
|
337
|
+
cancel: (uncaptured, prepare) => Effect.gen(function* () {
|
|
338
|
+
const record = yield* snapshotPasswordPreparedReady(uncaptured.record), snapshot = yield* encodePasswordPreparedReady(record);
|
|
339
|
+
return yield* owned(Effect.gen(function* () {
|
|
340
|
+
const journal = yield* CurrentCommitJournal;
|
|
341
|
+
yield* lockAnchor(mapping, configuration, record.moduleId);
|
|
342
|
+
const authority = yield* currentAuthority(mapping, configuration, record);
|
|
343
|
+
if (authority === void 0) return prepare(false, journal);
|
|
344
|
+
const rows = yield* readIntent(mapping, and(eq(c.moduleId, record.moduleId), eq(c.intentId, record.intentId)), configuration.locking);
|
|
345
|
+
const now = yield* nowMillis;
|
|
346
|
+
if (rows.length !== 1 || now < record.issuedAtMillis || now >= record.expiresAtMillis || !(yield* recordMatches(mapping, rows[0], record, authority.nativeSubjectId, snapshot))) return prepare(false, journal);
|
|
347
|
+
yield* terminal(mapping, rows[0], "Cancelled");
|
|
348
|
+
return prepare(true, journal);
|
|
349
|
+
}));
|
|
350
|
+
}).pipe(Effect.provideService(CurrentPasswordSql, database), Effect.provideService(LifecycleHooks, hooks), translateFailure),
|
|
351
|
+
cleanup: (uncaptured, prepare) => Effect.gen(function* () {
|
|
352
|
+
const input = { ...uncaptured };
|
|
353
|
+
if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 1e3) return yield* unavailable();
|
|
354
|
+
return yield* owned(Effect.gen(function* () {
|
|
355
|
+
const transaction = yield* CurrentPasswordSql;
|
|
356
|
+
const journal = yield* CurrentCommitJournal;
|
|
357
|
+
if (!(yield* lockAnchor(mapping, configuration, input.moduleId, false))) return prepare({
|
|
358
|
+
removed: 0,
|
|
359
|
+
hasMore: false
|
|
360
|
+
}, journal);
|
|
361
|
+
const now = p.encodeInstant(yield* nowMillis);
|
|
362
|
+
const due = and(eq(c.moduleId, input.moduleId), or(and(lte(c.retainUntil, now), lte(c.admissionRetainUntil, now)), and(isNotNull(c.snapshot), or(and(eq(c.state, t.states.Preparing), lte(c.preparationExpiresAt, now)), and(eq(c.state, t.states.Ready), lte(c.expiresAt, now))))));
|
|
363
|
+
const rows = yield* read(transaction.select().from(t.table).where(due).orderBy(c.createdAt, c.intentId).limit(input.limit + 1), configuration.locking);
|
|
364
|
+
let removed = 0;
|
|
365
|
+
for (const row of rows.slice(0, input.limit)) if ((yield* readIntent(mapping, and(rowCondition(mapping, row), lte(c.retainUntil, now), lte(c.admissionRetainUntil, now)), false)).length === 1) {
|
|
366
|
+
yield* transaction.delete(t.table).where(rowCondition(mapping, row));
|
|
367
|
+
if ((yield* readIntent(mapping, and(eq(c.moduleId, input.moduleId), eq(c.intentId, row[t.intentId])), false)).length) return yield* unavailable();
|
|
368
|
+
removed++;
|
|
369
|
+
} else yield* terminal(mapping, row, "Expired");
|
|
370
|
+
return prepare({
|
|
371
|
+
removed,
|
|
372
|
+
hasMore: (yield* read(transaction.select().from(t.table).where(due).limit(1), false)).length > 0
|
|
373
|
+
}, journal);
|
|
374
|
+
}));
|
|
375
|
+
}).pipe(Effect.provideService(CurrentPasswordSql, database), Effect.provideService(LifecycleHooks, hooks), translateFailure)
|
|
376
|
+
};
|
|
377
|
+
});
|
|
378
|
+
const passwordPreparedSqlKernel = {
|
|
379
|
+
columns,
|
|
380
|
+
recordMatches,
|
|
381
|
+
captureAuthority,
|
|
382
|
+
currentAuthority,
|
|
383
|
+
rowCondition,
|
|
384
|
+
valid,
|
|
385
|
+
identifierScope
|
|
386
|
+
};
|
|
387
|
+
//#endregion
|
|
388
|
+
export { makeSqlPasswordPreparedPersistence, passwordPreparedSqlKernel };
|
|
389
|
+
|
|
390
|
+
//# sourceMappingURL=password-prepared-sql.mjs.map
|