@yielded/auth-persistence 0.1.0-beta.21 → 0.1.0-beta.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/Adapter.d.mts +4 -2
  2. package/dist/Adapter.mjs +3 -1
  3. package/dist/internal/authority-snapshot.mjs +53 -0
  4. package/dist/internal/authority-snapshot.mjs.map +1 -0
  5. package/dist/internal/configuration.d.mts +1 -1
  6. package/dist/internal/configuration.mjs.map +1 -1
  7. package/dist/internal/models/password-model.d.mts +3 -53
  8. package/dist/internal/models/password-model.mjs +0 -2
  9. package/dist/internal/models/password-model.mjs.map +1 -1
  10. package/dist/internal/native-sql-table.d.mts +30 -0
  11. package/dist/internal/native-sql-table.mjs +104 -0
  12. package/dist/internal/native-sql-table.mjs.map +1 -0
  13. package/dist/internal/passkey/target.d.mts +1 -1
  14. package/dist/internal/passkeys.mjs +1 -1
  15. package/dist/internal/password-attempts.d.mts +12 -0
  16. package/dist/internal/password-attempts.mjs +197 -0
  17. package/dist/internal/password-attempts.mjs.map +1 -0
  18. package/dist/internal/password-kernel.d.mts +15 -12
  19. package/dist/internal/password-kernel.mjs +39 -202
  20. package/dist/internal/password-kernel.mjs.map +1 -1
  21. package/dist/internal/persistence.d.mts +2 -0
  22. package/dist/internal/persistence.mjs +4 -4
  23. package/dist/internal/persistence.mjs.map +1 -1
  24. package/dist/internal/session-kernel.d.mts +3 -1
  25. package/dist/internal/session-kernel.mjs +22 -12
  26. package/dist/internal/session-kernel.mjs.map +1 -1
  27. package/dist/internal/sql-persistence.mjs +3 -1
  28. package/dist/internal/sql-persistence.mjs.map +1 -1
  29. package/dist/internal/storage-mapping.mjs +1 -30
  30. package/dist/internal/storage-mapping.mjs.map +1 -1
  31. package/dist/internal/storage-tables.d.mts +0 -43
  32. package/dist/internal/storage-tables.mjs +0 -26
  33. package/dist/internal/storage-tables.mjs.map +1 -1
  34. package/dist/internal/transaction-execution-kernel.d.mts +1 -1
  35. package/dist/internal/transaction-kernel.d.mts +1 -1
  36. package/package.json +1 -1
  37. package/src/Adapter.ts +9 -4
  38. package/src/internal/authority-snapshot.ts +91 -0
  39. package/src/internal/configuration.ts +1 -6
  40. package/src/internal/models/password-model.ts +0 -64
  41. package/src/internal/native-sql-table.ts +164 -0
  42. package/src/internal/password-attempts.ts +466 -0
  43. package/src/internal/password-kernel.ts +102 -623
  44. package/src/internal/persistence.ts +5 -10
  45. package/src/internal/session-kernel.ts +89 -27
  46. package/src/internal/sql-persistence.ts +2 -0
  47. package/src/internal/storage-mapping.ts +0 -29
  48. package/src/internal/storage-tables.ts +0 -15
@@ -6,7 +6,7 @@ import { AnyEmailAddressMapping, AnyEmailRegistrationMapping, AnyEmailSignInMapp
6
6
  import { D1PasskeyMapping, PasskeyAdmissionTable, PasskeyCeremonyMapping, PasskeyChargeInsert, PasskeyChargeKind, PasskeyChargeTable, PasskeyClock, PasskeyColumn, PasskeyCredentialMapping, PasskeyCredentialOwnershipTable, PasskeyCredentialReadTable, PasskeyCredentialServices, PasskeyEnrollmentContextMapping, PasskeyEnrollmentContextServices, PasskeyFactorReadTable, PasskeyFlowInsert, PasskeyFlowState, PasskeyFlowTable, PasskeyHandleOwnershipTable, PasskeyHandleReadTable, PasskeyHandleReservationTable, PasskeyMappingSource, PasskeyModuleTable, PasskeyPersistenceMapping, PasskeyPersistenceServices, PasskeyPolicyGuard, PasskeySubjectIdCodec, PasskeySubjectReadTable, passkeyCredentialsLayer, passkeyEnrollmentContextLayer, passkeyPersistenceLayer, passkeyPolicyGuard, requiredPasskeyCredentialConstraints, requiredPasskeyPersistenceConstraints } from "./internal/models/passkey-model.mjs";
7
7
  import { PasskeyRegistrationCeremonyCapabilities, PasskeyRegistrationCeremonyMapping, PasskeyRegistrationCeremonyServices, PasskeyRegistrationIntentReadTable, requiredPasskeyRegistrationCeremonyConstraints } from "./internal/models/passkey-registration-ceremony-model.mjs";
8
8
  import { PasskeyCommandTable, PasskeyCredentialInsert, PasskeyInvalidationInput, PasskeyInvalidationMutation, PasskeyManagementMapping, PasskeyManagementServices, PasskeyRegistrationMapping, PasskeyRegistrationServices, PasskeyRegistrationWriter, PasskeyWriteTables, passkeyInvalidationMutation, requiredPasskeyManagementConstraints, requiredPasskeyRegistrationWriteConstraints } from "./internal/models/passkey-write-model.mjs";
9
- import { AnyPasswordPersistenceMapping, AnyPasswordRegistrationMapping, D1PasswordPersistenceMapping, PasswordAttemptAction, PasswordAttemptRecord, PasswordAttemptState, PasswordAttemptTable, PasswordAuthorityCredentialTable, PasswordChargeTable, PasswordCommandTable, PasswordConstraintClassifier, PasswordCredentialTable, PasswordD1Clock, PasswordIdentifierTable, PasswordPersistenceMapping, PasswordRateScopeKind, PasswordRateScopeTable, PasswordRegistrationConstraintClassifier, PasswordRegistrationIntent, PasswordRegistrationMapping, PasswordRegistrationProvisioning, PasswordRegistrationState, PasswordRegistrationTable, PasswordScopeKeys, PasswordSubjectTable, RequiredPasswordConstraints, RequiredPasswordRegistrationConstraints, requiredPasswordConstraints, requiredPasswordRegistrationConstraints } from "./internal/models/password-model.mjs";
9
+ import { AnyPasswordPersistenceMapping, AnyPasswordRegistrationMapping, D1PasswordPersistenceMapping, PasswordAttemptAction, PasswordAttemptRecord, PasswordAttemptState, PasswordAttemptTable, PasswordAuthorityCredentialTable, PasswordCommandTable, PasswordConstraintClassifier, PasswordCredentialTable, PasswordD1Clock, PasswordIdentifierTable, PasswordPersistenceMapping, PasswordRegistrationConstraintClassifier, PasswordRegistrationIntent, PasswordRegistrationMapping, PasswordRegistrationProvisioning, PasswordRegistrationState, PasswordRegistrationTable, PasswordSubjectTable, RequiredPasswordConstraints, RequiredPasswordRegistrationConstraints, requiredPasswordConstraints, requiredPasswordRegistrationConstraints } from "./internal/models/password-model.mjs";
10
10
  import { AnyProofPersistenceMapping, D1ProofPersistenceMapping, ProofAbuseEventTable, ProofAction, ProofAuthorityInput, ProofAuthorityTables, ProofCommandDecision, ProofCommandKind, ProofCommandTable, ProofConstraintClassifier, ProofContinuationRecord, ProofContinuationTable, ProofD1Clock, ProofDeliveryState, ProofFailureEventTable, ProofGenerationState, ProofGenerationTable, ProofPersistenceMapping, ProofRateScopeTable, ProofRequestTable, ProofScopeKeys, ProofScopeKind, ProofSeriesTable, RequiredProofConstraints, requiredProofConstraints } from "./internal/models/proof-model.mjs";
11
11
  import { AuthenticationAuthorityMapping, D1AuthenticationAuthorityMapping, D1PendingAuthenticationMapping, D1SessionClockMapping, D1SignedSessionValidityMapping, D1StatefulSessionMapping, PendingAuthenticationMapping, PendingAuthenticationTables, RequiredPendingAuthenticationConstraints, RequiredSessionConstraints, RequiredSignedValidityConstraints, RequiredStatefulPendingConstraints, SessionAuthorityTables, SessionConstraintClassifier, SessionFlowTables, SessionIdCodec, SessionSubjectTables, SignedSessionValidityMapping, SignedSessionValidityTables, StatefulSessionMapping, StatefulSessionTables, requiredPendingAuthenticationConstraints, requiredSessionConstraints, requiredSignedValidityConstraints, requiredStatefulPendingConstraints } from "./internal/models/session-model.mjs";
12
12
  import { D1SessionStepUpMapping, RequiredSessionStepUpConstraints, SessionStepUpIntentTables, SessionStepUpMapping, SessionStepUpSourceTables, requiredSessionStepUpConstraints } from "./internal/models/step-up-model.mjs";
@@ -18,6 +18,8 @@ import { CurrentPasskeyTransaction, PasskeyOwner } from "./internal/passkey/stat
18
18
  import { TransactionBound, TransactionCoordinatorError, TransactionExecution, TransactionTargetConfiguration, makeTransactionExecutionKernel } from "./internal/transaction-execution-kernel.mjs";
19
19
  import { PasskeyCoordinatorError, PasskeyExecution, PasskeyTargetConfiguration } from "./internal/passkey/target.mjs";
20
20
  import { PasskeyKernel, makePasskeyKernel } from "./internal/passkey-kernel.mjs";
21
+ import { NativeSqlTables, SqlTable, makeNativeSqlTables, nativeSqlAlias } from "./internal/native-sql-table.mjs";
22
+ import { samePasswordCredentialSnapshot } from "./internal/password-attempts.mjs";
21
23
  import { CurrentPasswordSql, PasswordSqlConfiguration, PasswordSqlDatabase, PasswordSqlQuery, makePasswordKernel } from "./internal/password-kernel.mjs";
22
24
  import { CurrentPasswordPreparedTransaction, PasswordPreparedJournalGuards, PasswordPreparedPostcondition, PasswordPreparedPostconditions } from "./internal/PasswordPreparedPostconditions.mjs";
23
25
  import { CurrentPhoneTransaction, makePhoneKernel } from "./internal/phone-kernel.mjs";
@@ -29,4 +31,4 @@ import { makeComposedPasskeys } from "./internal/passkeys.mjs";
29
31
  import { makeMappings } from "./internal/storage-mapping.mjs";
30
32
  import { PasswordRegistrationAuthority } from "./internal/registration-contract.mjs";
31
33
  import { PhysicalStorageTable, StorageValidation, validateStorage, validateStorageBatch, withStorageValidation } from "./internal/storage-validation.mjs";
32
- export { type AnyEmailAddressMapping, type AnyEmailRegistrationMapping, type AnyEmailSignInMapping, type AnyPasswordPersistenceMapping, type AnyPasswordRegistrationMapping, type AnyProofPersistenceMapping, type AuthenticationAuthorityMapping, type BoundPersistence, type ClaimsCodec, type CurrentAddress, CurrentEmailSql, CurrentPasskeyTransaction, CurrentPasswordPreparedTransaction, CurrentPasswordSql, CurrentPhoneTransaction, CurrentProofSql, CurrentSessionSql, type D1AuthenticationAuthorityMapping, type D1EmailAddressMapping, type D1EmailRegistrationMapping, type D1PasskeyMapping, type D1PasswordPersistenceMapping, type D1PendingAuthenticationMapping, type D1ProofPersistenceMapping, type D1SessionClockMapping, type D1SessionStepUpMapping, type D1SignedSessionValidityMapping, type D1StatefulSessionMapping, type Definition, type EmailAddressMapping, type EmailAuthorityCredentialTable, type EmailCommandTable, type EmailCredentialReadTable, type EmailCredentialTable, type EmailD1Clock, type EmailIdentifierReadTable, type EmailIdentifierTable, type EmailRegistrationAuthorityCredentialTable, type EmailRegistrationCredentialTable, type EmailRegistrationIdentifierTable, type EmailRegistrationIntent, type EmailRegistrationMapping, type EmailRegistrationProvisioning, type EmailRegistrationState, type EmailRegistrationTable, type EmailSignInMapping, type EmailSqlConfiguration, type EmailSqlDatabase, type EmailSqlQuery, type EmailSubjectReadTable, type EmailSubjectTable, type GuardedUpdate, NativeDatabase, type Observation, type PasskeyAdmissionTable, type PasskeyCeremonyMapping, type PasskeyChargeInsert, type PasskeyChargeKind, type PasskeyChargeTable, type PasskeyClock, type PasskeyColumn, type PasskeyCommandTable, type PasskeyCoordinatorError, type PasskeyCredentialInsert, type PasskeyCredentialMapping, type PasskeyCredentialOwnershipTable, type PasskeyCredentialReadTable, type PasskeyCredentialServices, type PasskeyEnrollmentContextMapping, type PasskeyEnrollmentContextServices, type PasskeyExecution, type PasskeyFactorReadTable, type PasskeyFlowInsert, type PasskeyFlowState, type PasskeyFlowTable, type PasskeyHandleOwnershipTable, type PasskeyHandleReadTable, type PasskeyHandleReservationTable, type PasskeyInvalidationInput, type PasskeyInvalidationMutation, type PasskeyKernel, type PasskeyManagementMapping, type PasskeyManagementServices, type PasskeyMappingSource, type PasskeyModuleTable, type PasskeyOwner, type PasskeyPersistenceMapping, type PasskeyPersistenceServices, type PasskeyPolicyGuard, type PasskeyRegistrationCeremonyCapabilities, type PasskeyRegistrationCeremonyMapping, type PasskeyRegistrationCeremonyServices, type PasskeyRegistrationIntentReadTable, type PasskeyRegistrationMapping, type PasskeyRegistrationServices, type PasskeyRegistrationWriter, type PasskeySubjectIdCodec, type PasskeySubjectReadTable, type PasskeyTargetConfiguration, type PasskeyWriteTables, type PasswordAttemptAction, type PasswordAttemptRecord, type PasswordAttemptState, type PasswordAttemptTable, type PasswordAuthorityCredentialTable, type PasswordChargeTable, type PasswordCommandTable, type PasswordConstraintClassifier, type PasswordCredentialTable, type PasswordD1Clock, type PasswordIdentifierTable, type PasswordPersistenceMapping, PasswordPreparedJournalGuards, type PasswordPreparedPostcondition, PasswordPreparedPostconditions, type PasswordRateScopeKind, type PasswordRateScopeTable, type PasswordRegistrationAuthority, type PasswordRegistrationConstraintClassifier, type PasswordRegistrationIntent, type PasswordRegistrationMapping, type PasswordRegistrationProvisioning, type PasswordRegistrationState, type PasswordRegistrationTable, type PasswordScopeKeys, type PasswordSqlConfiguration, type PasswordSqlDatabase, type PasswordSqlQuery, type PasswordSubjectTable, type PendingAuthenticationMapping, type PendingAuthenticationTables, type PersistenceApi, PersistenceConfigurationError, PersistenceMappingError, type PhysicalStorageTable, type ProofAbuseEventTable, type ProofAction, type ProofAuthorityInput, type ProofAuthorityTables, type ProofCommandDecision, type ProofCommandKind, type ProofCommandTable, type ProofConstraintClassifier, type ProofContinuationRecord, type ProofContinuationTable, type ProofD1Clock, type ProofDeliveryState, type ProofFailureEventTable, type ProofGenerationState, type ProofGenerationTable, type ProofPersistenceMapping, type ProofRateScopeTable, type ProofRequestTable, type ProofScopeKeys, type ProofScopeKind, type ProofSeriesTable, type ProofSqlConfiguration, type ProofSqlDatabase, type ProofSqlQuery, type QueryFailure, type QueryOperations, type RequiredEmailAddressConstraints, type RequiredEmailRegistrationConstraints, type RequiredEmailSignInConstraints, type RequiredPasswordConstraints, type RequiredPasswordRegistrationConstraints, type RequiredPendingAuthenticationConstraints, type RequiredProofConstraints, type RequiredSessionConstraints, type RequiredSessionStepUpConstraints, type RequiredSignedValidityConstraints, type RequiredStatefulPendingConstraints, type Row, type SessionAuthorityTables, type SessionConstraintClassifier, type SessionFlowTables, type SessionIdCodec, type SessionSqlDatabase, type SessionSqlOptions, type SessionStepUpIntentTables, type SessionStepUpMapping, type SessionStepUpSourceTables, type SessionSubjectTables, type SignedSessionValidityMapping, type SignedSessionValidityTables, type SqlColumn, type SqlExpression, type SqlFragment, type StatefulSessionMapping, type StatefulSessionTables, type StorageTable, type StorageValidation, type SubjectIdCodec, type TableModel, type TransactionBound, type TransactionCoordinatorError, type TransactionExecution, type TransactionNativeDatabase, type TransactionOwner, type TransactionTargetConfiguration, createPersistence, decodeStepUpIntent, encodeStepUpIntent, isMappedConstraintConflict, makeComposedPasskeys, makeEmailKernel, makePasskeyKernel, makePasswordKernel, makePhoneKernel, makeProofKernel, makeSessionKernel, makeMappings as makeStorageMappings, makeTransactionExecutionKernel, makeTransactionKernel, passkeyCredentialsLayer, passkeyEnrollmentContextLayer, passkeyInvalidationMutation, passkeyPersistenceLayer, passkeyPolicyGuard, requireStandalone, requiredEmailAddressConstraints, requiredEmailRegistrationConstraints, requiredEmailSignInConstraints, requiredPasskeyCredentialConstraints, requiredPasskeyManagementConstraints, requiredPasskeyPersistenceConstraints, requiredPasskeyRegistrationCeremonyConstraints, requiredPasskeyRegistrationWriteConstraints, requiredPasswordConstraints, requiredPasswordRegistrationConstraints, requiredPendingAuthenticationConstraints, requiredProofConstraints, requiredSessionConstraints, requiredSessionStepUpConstraints, requiredSignedValidityConstraints, requiredStatefulPendingConstraints, stepUpIntentLive, validateStepUpPlan, validateStorage, validateStorageBatch, withStorageValidation };
34
+ export { type AnyEmailAddressMapping, type AnyEmailRegistrationMapping, type AnyEmailSignInMapping, type AnyPasswordPersistenceMapping, type AnyPasswordRegistrationMapping, type AnyProofPersistenceMapping, type AuthenticationAuthorityMapping, type BoundPersistence, type ClaimsCodec, type CurrentAddress, CurrentEmailSql, CurrentPasskeyTransaction, CurrentPasswordPreparedTransaction, CurrentPasswordSql, CurrentPhoneTransaction, CurrentProofSql, CurrentSessionSql, type D1AuthenticationAuthorityMapping, type D1EmailAddressMapping, type D1EmailRegistrationMapping, type D1PasskeyMapping, type D1PasswordPersistenceMapping, type D1PendingAuthenticationMapping, type D1ProofPersistenceMapping, type D1SessionClockMapping, type D1SessionStepUpMapping, type D1SignedSessionValidityMapping, type D1StatefulSessionMapping, type Definition, type EmailAddressMapping, type EmailAuthorityCredentialTable, type EmailCommandTable, type EmailCredentialReadTable, type EmailCredentialTable, type EmailD1Clock, type EmailIdentifierReadTable, type EmailIdentifierTable, type EmailRegistrationAuthorityCredentialTable, type EmailRegistrationCredentialTable, type EmailRegistrationIdentifierTable, type EmailRegistrationIntent, type EmailRegistrationMapping, type EmailRegistrationProvisioning, type EmailRegistrationState, type EmailRegistrationTable, type EmailSignInMapping, type EmailSqlConfiguration, type EmailSqlDatabase, type EmailSqlQuery, type EmailSubjectReadTable, type EmailSubjectTable, type GuardedUpdate, NativeDatabase, type NativeSqlTables, type Observation, type PasskeyAdmissionTable, type PasskeyCeremonyMapping, type PasskeyChargeInsert, type PasskeyChargeKind, type PasskeyChargeTable, type PasskeyClock, type PasskeyColumn, type PasskeyCommandTable, type PasskeyCoordinatorError, type PasskeyCredentialInsert, type PasskeyCredentialMapping, type PasskeyCredentialOwnershipTable, type PasskeyCredentialReadTable, type PasskeyCredentialServices, type PasskeyEnrollmentContextMapping, type PasskeyEnrollmentContextServices, type PasskeyExecution, type PasskeyFactorReadTable, type PasskeyFlowInsert, type PasskeyFlowState, type PasskeyFlowTable, type PasskeyHandleOwnershipTable, type PasskeyHandleReadTable, type PasskeyHandleReservationTable, type PasskeyInvalidationInput, type PasskeyInvalidationMutation, type PasskeyKernel, type PasskeyManagementMapping, type PasskeyManagementServices, type PasskeyMappingSource, type PasskeyModuleTable, type PasskeyOwner, type PasskeyPersistenceMapping, type PasskeyPersistenceServices, type PasskeyPolicyGuard, type PasskeyRegistrationCeremonyCapabilities, type PasskeyRegistrationCeremonyMapping, type PasskeyRegistrationCeremonyServices, type PasskeyRegistrationIntentReadTable, type PasskeyRegistrationMapping, type PasskeyRegistrationServices, type PasskeyRegistrationWriter, type PasskeySubjectIdCodec, type PasskeySubjectReadTable, type PasskeyTargetConfiguration, type PasskeyWriteTables, type PasswordAttemptAction, type PasswordAttemptRecord, type PasswordAttemptState, type PasswordAttemptTable, type PasswordAuthorityCredentialTable, type PasswordCommandTable, type PasswordConstraintClassifier, type PasswordCredentialTable, type PasswordD1Clock, type PasswordIdentifierTable, type PasswordPersistenceMapping, PasswordPreparedJournalGuards, type PasswordPreparedPostcondition, PasswordPreparedPostconditions, type PasswordRegistrationAuthority, type PasswordRegistrationConstraintClassifier, type PasswordRegistrationIntent, type PasswordRegistrationMapping, type PasswordRegistrationProvisioning, type PasswordRegistrationState, type PasswordRegistrationTable, type PasswordSqlConfiguration, type PasswordSqlDatabase, type PasswordSqlQuery, type PasswordSubjectTable, type PendingAuthenticationMapping, type PendingAuthenticationTables, type PersistenceApi, PersistenceConfigurationError, PersistenceMappingError, type PhysicalStorageTable, type ProofAbuseEventTable, type ProofAction, type ProofAuthorityInput, type ProofAuthorityTables, type ProofCommandDecision, type ProofCommandKind, type ProofCommandTable, type ProofConstraintClassifier, type ProofContinuationRecord, type ProofContinuationTable, type ProofD1Clock, type ProofDeliveryState, type ProofFailureEventTable, type ProofGenerationState, type ProofGenerationTable, type ProofPersistenceMapping, type ProofRateScopeTable, type ProofRequestTable, type ProofScopeKeys, type ProofScopeKind, type ProofSeriesTable, type ProofSqlConfiguration, type ProofSqlDatabase, type ProofSqlQuery, type QueryFailure, type QueryOperations, type RequiredEmailAddressConstraints, type RequiredEmailRegistrationConstraints, type RequiredEmailSignInConstraints, type RequiredPasswordConstraints, type RequiredPasswordRegistrationConstraints, type RequiredPendingAuthenticationConstraints, type RequiredProofConstraints, type RequiredSessionConstraints, type RequiredSessionStepUpConstraints, type RequiredSignedValidityConstraints, type RequiredStatefulPendingConstraints, type Row, type SessionAuthorityTables, type SessionConstraintClassifier, type SessionFlowTables, type SessionIdCodec, type SessionSqlDatabase, type SessionSqlOptions, type SessionStepUpIntentTables, type SessionStepUpMapping, type SessionStepUpSourceTables, type SessionSubjectTables, type SignedSessionValidityMapping, type SignedSessionValidityTables, type SqlColumn, type SqlExpression, type SqlFragment, type SqlTable, type StatefulSessionMapping, type StatefulSessionTables, type StorageTable, type StorageValidation, type SubjectIdCodec, type TableModel, type TransactionBound, type TransactionCoordinatorError, type TransactionExecution, type TransactionNativeDatabase, type TransactionOwner, type TransactionTargetConfiguration, createPersistence, decodeStepUpIntent, encodeStepUpIntent, isMappedConstraintConflict, makeComposedPasskeys, makeEmailKernel, makeNativeSqlTables, makePasskeyKernel, makePasswordKernel, makePhoneKernel, makeProofKernel, makeSessionKernel, makeMappings as makeStorageMappings, makeTransactionExecutionKernel, makeTransactionKernel, nativeSqlAlias, passkeyCredentialsLayer, passkeyEnrollmentContextLayer, passkeyInvalidationMutation, passkeyPersistenceLayer, passkeyPolicyGuard, requireStandalone, requiredEmailAddressConstraints, requiredEmailRegistrationConstraints, requiredEmailSignInConstraints, requiredPasskeyCredentialConstraints, requiredPasskeyManagementConstraints, requiredPasskeyPersistenceConstraints, requiredPasskeyRegistrationCeremonyConstraints, requiredPasskeyRegistrationWriteConstraints, requiredPasswordConstraints, requiredPasswordRegistrationConstraints, requiredPendingAuthenticationConstraints, requiredProofConstraints, requiredSessionConstraints, requiredSessionStepUpConstraints, requiredSignedValidityConstraints, requiredStatefulPendingConstraints, samePasswordCredentialSnapshot, stepUpIntentLive, validateStepUpPlan, validateStorage, validateStorageBatch, withStorageValidation };
package/dist/Adapter.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { PersistenceConfigurationError } from "./internal/configuration.mjs";
2
2
  import { PersistenceMappingError, isMappedConstraintConflict } from "./internal/mapping-error.mjs";
3
+ import { makeNativeSqlTables, nativeSqlAlias } from "./internal/native-sql-table.mjs";
3
4
  import { passkeyCredentialsLayer, passkeyEnrollmentContextLayer, passkeyPersistenceLayer, passkeyPolicyGuard, requiredPasskeyCredentialConstraints, requiredPasskeyPersistenceConstraints } from "./internal/models/passkey-model.mjs";
4
5
  import { passkeyInvalidationMutation, requiredPasskeyManagementConstraints, requiredPasskeyRegistrationWriteConstraints } from "./internal/models/passkey-write-model.mjs";
5
6
  import { requiredPasskeyRegistrationCeremonyConstraints } from "./internal/models/passkey-registration-ceremony-model.mjs";
@@ -15,6 +16,7 @@ import { makeComposedPasskeys } from "./internal/passkeys.mjs";
15
16
  import { requiredEmailAddressConstraints, requiredEmailRegistrationConstraints, requiredEmailSignInConstraints } from "./internal/models/email-model.mjs";
16
17
  import { CurrentEmailSql, makeEmailKernel } from "./internal/email-kernel.mjs";
17
18
  import { requiredPasswordConstraints, requiredPasswordRegistrationConstraints } from "./internal/models/password-model.mjs";
19
+ import { samePasswordCredentialSnapshot } from "./internal/password-attempts.mjs";
18
20
  import { CurrentPasswordSql, makePasswordKernel } from "./internal/password-kernel.mjs";
19
21
  import { CurrentPhoneTransaction, makePhoneKernel } from "./internal/phone-kernel.mjs";
20
22
  import { decodeStepUpIntent, encodeStepUpIntent, stepUpIntentLive, validateStepUpPlan } from "./internal/step-up-state.mjs";
@@ -24,4 +26,4 @@ import { validateStorage, validateStorageBatch, withStorageValidation } from "./
24
26
  import { createPersistence } from "./internal/persistence.mjs";
25
27
  import { requiredPendingAuthenticationConstraints, requiredSessionConstraints, requiredSignedValidityConstraints, requiredStatefulPendingConstraints } from "./internal/models/session-model.mjs";
26
28
  import { requiredSessionStepUpConstraints } from "./internal/models/step-up-model.mjs";
27
- export { CurrentEmailSql, CurrentPasskeyTransaction, CurrentPasswordPreparedTransaction, CurrentPasswordSql, CurrentPhoneTransaction, CurrentProofSql, CurrentSessionSql, NativeDatabase, PasswordPreparedJournalGuards, PasswordPreparedPostconditions, PersistenceConfigurationError, PersistenceMappingError, createPersistence, decodeStepUpIntent, encodeStepUpIntent, isMappedConstraintConflict, makeComposedPasskeys, makeEmailKernel, makePasskeyKernel, makePasswordKernel, makePhoneKernel, makeProofKernel, makeSessionKernel, makeMappings as makeStorageMappings, makeTransactionExecutionKernel, makeTransactionKernel, passkeyCredentialsLayer, passkeyEnrollmentContextLayer, passkeyInvalidationMutation, passkeyPersistenceLayer, passkeyPolicyGuard, requireStandalone, requiredEmailAddressConstraints, requiredEmailRegistrationConstraints, requiredEmailSignInConstraints, requiredPasskeyCredentialConstraints, requiredPasskeyManagementConstraints, requiredPasskeyPersistenceConstraints, requiredPasskeyRegistrationCeremonyConstraints, requiredPasskeyRegistrationWriteConstraints, requiredPasswordConstraints, requiredPasswordRegistrationConstraints, requiredPendingAuthenticationConstraints, requiredProofConstraints, requiredSessionConstraints, requiredSessionStepUpConstraints, requiredSignedValidityConstraints, requiredStatefulPendingConstraints, stepUpIntentLive, validateStepUpPlan, validateStorage, validateStorageBatch, withStorageValidation };
29
+ export { CurrentEmailSql, CurrentPasskeyTransaction, CurrentPasswordPreparedTransaction, CurrentPasswordSql, CurrentPhoneTransaction, CurrentProofSql, CurrentSessionSql, NativeDatabase, PasswordPreparedJournalGuards, PasswordPreparedPostconditions, PersistenceConfigurationError, PersistenceMappingError, createPersistence, decodeStepUpIntent, encodeStepUpIntent, isMappedConstraintConflict, makeComposedPasskeys, makeEmailKernel, makeNativeSqlTables, makePasskeyKernel, makePasswordKernel, makePhoneKernel, makeProofKernel, makeSessionKernel, makeMappings as makeStorageMappings, makeTransactionExecutionKernel, makeTransactionKernel, nativeSqlAlias, passkeyCredentialsLayer, passkeyEnrollmentContextLayer, passkeyInvalidationMutation, passkeyPersistenceLayer, passkeyPolicyGuard, requireStandalone, requiredEmailAddressConstraints, requiredEmailRegistrationConstraints, requiredEmailSignInConstraints, requiredPasskeyCredentialConstraints, requiredPasskeyManagementConstraints, requiredPasskeyPersistenceConstraints, requiredPasskeyRegistrationCeremonyConstraints, requiredPasskeyRegistrationWriteConstraints, requiredPasswordConstraints, requiredPasswordRegistrationConstraints, requiredPendingAuthenticationConstraints, requiredProofConstraints, requiredSessionConstraints, requiredSessionStepUpConstraints, requiredSignedValidityConstraints, requiredStatefulPendingConstraints, samePasswordCredentialSnapshot, stepUpIntentLive, validateStepUpPlan, validateStorage, validateStorageBatch, withStorageValidation };
@@ -0,0 +1,53 @@
1
+ import { sqlMapping } from "./native-sql-table.mjs";
2
+ import { NativeDatabase } from "./transaction-kernel.mjs";
3
+ import { Effect, Schema } from "effect";
4
+ import { AuthenticationRevision, StaleAuthentication } from "@yielded/auth/Sessions";
5
+ //#region src/internal/authority-snapshot.ts
6
+ /** One unlocked statement reads the subject and requested credentials: a coherent
7
+ * preflight view, or a commit owner's view where writers are already serialized.
8
+ * Row-locking commit owners lock and revalidate through their ordered reads.
9
+ */
10
+ const makeAuthoritySnapshot = (tables, mapping) => Effect.fnUntraced(function* (subjectId, credentialIds) {
11
+ const sql = (yield* NativeDatabase).$client.withoutTransforms();
12
+ if (new Set(credentialIds).size !== credentialIds.length) return yield* StaleAuthentication.make({});
13
+ const { s, c } = yield* sqlMapping(() => ({
14
+ s: tables(mapping.subject.table).as("auth_subject"),
15
+ c: tables(mapping.credential.table).as("auth_credential")
16
+ }));
17
+ const nativeId = yield* sqlMapping(() => mapping.subjectId.toNative(subjectId)).pipe(Effect.flatten);
18
+ const requested = [...credentialIds].sort((a, b) => a.localeCompare(b));
19
+ const rows = yield* sqlMapping(() => sql`select ${s.fields("s_")}
20
+ ${requested.length === 0 ? sql.literal("") : sql`, ${c.fields("c_")}`}
21
+ from ${s.name}
22
+ ${requested.length === 0 ? sql.literal("") : sql`inner join ${c.name} on
23
+ ${c.column(mapping.credential.subjectId)} = ${c.value(mapping.credential.subjectId, nativeId)}
24
+ and ${sql.or(requested.map((id) => sql`${c.column(mapping.credential.credentialId)} = ${c.value(mapping.credential.credentialId, id)}`))}`}
25
+ where ${s.column(mapping.subject.id)} = ${s.value(mapping.subject.id, nativeId)}`).pipe(Effect.flatten);
26
+ const first = rows[0];
27
+ if (first === void 0 || rows.length !== Math.max(1, requested.length)) return yield* StaleAuthentication.make({});
28
+ const subject = yield* sqlMapping(() => s.decode(first, "s_"));
29
+ if (!(yield* sqlMapping(() => mapping.subject.isActiveStatus(subject[mapping.subject.status])))) return yield* StaleAuthentication.make({});
30
+ const credentials = yield* sqlMapping(() => requested.length === 0 ? [] : rows.map((row) => c.decode(row, "c_")));
31
+ if (yield* sqlMapping(() => credentials.some((row) => mapping.credential.status !== void 0 && mapping.credential.isActiveStatus?.(row[mapping.credential.status]) !== true))) return yield* StaleAuthentication.make({});
32
+ const revision = yield* Schema.decodeUnknownEffect(AuthenticationRevision)({
33
+ subjectId,
34
+ securityRevision: subject[mapping.subject.securityRevision],
35
+ credentials: credentials.map((row) => ({
36
+ credentialId: row[mapping.credential.credentialId],
37
+ revision: row[mapping.credential.revision]
38
+ }))
39
+ });
40
+ const sorted = [...revision.credentials].sort((a, b) => a.credentialId.localeCompare(b.credentialId));
41
+ if (sorted.some((item, index) => item.credentialId !== requested[index])) return yield* StaleAuthentication.make({});
42
+ return {
43
+ subject,
44
+ revision: {
45
+ ...revision,
46
+ credentials: sorted
47
+ }
48
+ };
49
+ });
50
+ //#endregion
51
+ export { makeAuthoritySnapshot };
52
+
53
+ //# sourceMappingURL=authority-snapshot.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authority-snapshot.mjs","names":[],"sources":["../../src/internal/authority-snapshot.ts"],"sourcesContent":["import type { SubjectId } from \"@yielded/auth/Schema\";\nimport { AuthenticationRevision, StaleAuthentication } from \"@yielded/auth/Sessions\";\nimport { Effect, Schema } from \"effect\";\n\nimport type { SessionAuthorityTables } from \"./models/session-model\";\nimport { sqlMapping, type NativeSqlTables } from \"./native-sql-table\";\nimport type { AnyTableModel } from \"./query-operations\";\nimport { NativeDatabase } from \"./transaction-kernel\";\n\n/** One unlocked statement reads the subject and requested credentials: a coherent\n * preflight view, or a commit owner's view where writers are already serialized.\n * Row-locking commit owners lock and revalidate through their ordered reads.\n */\nexport const makeAuthoritySnapshot = (\n tables: NativeSqlTables,\n mapping: SessionAuthorityTables<AnyTableModel, AnyTableModel, unknown>,\n) =>\n Effect.fnUntraced(function* (subjectId: SubjectId, credentialIds: ReadonlyArray<string>) {\n const sql = (yield* NativeDatabase).$client.withoutTransforms();\n\n if (new Set(credentialIds).size !== credentialIds.length)\n return yield* StaleAuthentication.make({});\n\n const { s, c } = yield* sqlMapping(() => ({\n s: tables(mapping.subject.table).as(\"auth_subject\"),\n c: tables(mapping.credential.table).as(\"auth_credential\"),\n }));\n\n const nativeId = yield* sqlMapping(() => mapping.subjectId.toNative(subjectId)).pipe(\n Effect.flatten,\n );\n\n const requested = [...credentialIds].sort((a, b) => a.localeCompare(b));\n\n const rows = yield* sqlMapping(\n () => sql<Record<string, unknown>>`select ${s.fields(\"s_\")}\n ${requested.length === 0 ? sql.literal(\"\") : sql`, ${c.fields(\"c_\")}`}\n from ${s.name}\n ${\n requested.length === 0\n ? sql.literal(\"\")\n : sql`inner join ${c.name} on\n ${c.column(mapping.credential.subjectId)} = ${c.value(mapping.credential.subjectId, nativeId)}\n and ${sql.or(requested.map((id) => sql`${c.column(mapping.credential.credentialId)} = ${c.value(mapping.credential.credentialId, id)}`))}`\n }\n where ${s.column(mapping.subject.id)} = ${s.value(mapping.subject.id, nativeId)}`,\n ).pipe(Effect.flatten);\n\n const first = rows[0];\n\n if (first === undefined || rows.length !== Math.max(1, requested.length))\n return yield* StaleAuthentication.make({});\n\n const subject = yield* sqlMapping(() => s.decode(first, \"s_\"));\n\n if (!(yield* sqlMapping(() => mapping.subject.isActiveStatus(subject[mapping.subject.status]))))\n return yield* StaleAuthentication.make({});\n\n const credentials = yield* sqlMapping(() =>\n requested.length === 0 ? [] : rows.map((row) => c.decode(row, \"c_\")),\n );\n\n if (\n yield* sqlMapping(() =>\n credentials.some(\n (row) =>\n mapping.credential.status !== undefined &&\n mapping.credential.isActiveStatus?.(row[mapping.credential.status]) !== true,\n ),\n )\n )\n return yield* StaleAuthentication.make({});\n\n const revision = yield* Schema.decodeUnknownEffect(AuthenticationRevision)({\n subjectId,\n securityRevision: subject[mapping.subject.securityRevision],\n credentials: credentials.map((row) => ({\n credentialId: row[mapping.credential.credentialId],\n revision: row[mapping.credential.revision],\n })),\n });\n\n const sorted = [...revision.credentials].sort((a, b) =>\n a.credentialId.localeCompare(b.credentialId),\n );\n\n if (sorted.some((item, index) => item.credentialId !== requested[index]))\n return yield* StaleAuthentication.make({});\n\n return { subject, revision: { ...revision, credentials: sorted } };\n });\n"],"mappings":";;;;;;;;;AAaA,MAAa,yBACX,QACA,YAEA,OAAO,WAAW,WAAW,WAAsB,eAAsC;CACvF,MAAM,OAAO,OAAO,eAAA,CAAgB,QAAQ,kBAAkB;CAE9D,IAAI,IAAI,IAAI,aAAa,CAAC,CAAC,SAAS,cAAc,QAChD,OAAO,OAAO,oBAAoB,KAAK,CAAC,CAAC;CAE3C,MAAM,EAAE,GAAG,MAAM,OAAO,kBAAkB;EACxC,GAAG,OAAO,QAAQ,QAAQ,KAAK,CAAC,CAAC,GAAG,cAAc;EAClD,GAAG,OAAO,QAAQ,WAAW,KAAK,CAAC,CAAC,GAAG,iBAAiB;CAC1D,EAAE;CAEF,MAAM,WAAW,OAAO,iBAAiB,QAAQ,UAAU,SAAS,SAAS,CAAC,CAAC,CAAC,KAC9E,OAAO,OACT;CAEA,MAAM,YAAY,CAAC,GAAG,aAAa,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;CAEtE,MAAM,OAAO,OAAO,iBACZ,GAA4B,UAAU,EAAE,OAAO,IAAI,EAAE;QACzD,UAAU,WAAW,IAAI,IAAI,QAAQ,EAAE,IAAI,GAAG,KAAK,EAAE,OAAO,IAAI,IAAI;aAC/D,EAAE,KAAK;QAEZ,UAAU,WAAW,IACjB,IAAI,QAAQ,EAAE,IACd,GAAG,cAAc,EAAE,KAAK;UAC1B,EAAE,OAAO,QAAQ,WAAW,SAAS,EAAE,KAAK,EAAE,MAAM,QAAQ,WAAW,WAAW,QAAQ,EAAE;cACxF,IAAI,GAAG,UAAU,KAAK,OAAO,GAAG,GAAG,EAAE,OAAO,QAAQ,WAAW,YAAY,EAAE,KAAK,EAAE,MAAM,QAAQ,WAAW,cAAc,EAAE,GAAG,CAAC,IACxI;cACO,EAAE,OAAO,QAAQ,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,QAAQ,QAAQ,IAAI,QAAQ,GAChF,CAAC,CAAC,KAAK,OAAO,OAAO;CAErB,MAAM,QAAQ,KAAK;CAEnB,IAAI,UAAU,KAAA,KAAa,KAAK,WAAW,KAAK,IAAI,GAAG,UAAU,MAAM,GACrE,OAAO,OAAO,oBAAoB,KAAK,CAAC,CAAC;CAE3C,MAAM,UAAU,OAAO,iBAAiB,EAAE,OAAO,OAAO,IAAI,CAAC;CAE7D,IAAI,EAAE,OAAO,iBAAiB,QAAQ,QAAQ,eAAe,QAAQ,QAAQ,QAAQ,OAAO,CAAC,IAC3F,OAAO,OAAO,oBAAoB,KAAK,CAAC,CAAC;CAE3C,MAAM,cAAc,OAAO,iBACzB,UAAU,WAAW,IAAI,CAAC,IAAI,KAAK,KAAK,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC,CACrE;CAEA,IACE,OAAO,iBACL,YAAY,MACT,QACC,QAAQ,WAAW,WAAW,KAAA,KAC9B,QAAQ,WAAW,iBAAiB,IAAI,QAAQ,WAAW,OAAO,MAAM,IAC5E,CACF,GAEA,OAAO,OAAO,oBAAoB,KAAK,CAAC,CAAC;CAE3C,MAAM,WAAW,OAAO,OAAO,oBAAoB,sBAAsB,CAAC,CAAC;EACzE;EACA,kBAAkB,QAAQ,QAAQ,QAAQ;EAC1C,aAAa,YAAY,KAAK,SAAS;GACrC,cAAc,IAAI,QAAQ,WAAW;GACrC,UAAU,IAAI,QAAQ,WAAW;EACnC,EAAE;CACJ,CAAC;CAED,MAAM,SAAS,CAAC,GAAG,SAAS,WAAW,CAAC,CAAC,MAAM,GAAG,MAChD,EAAE,aAAa,cAAc,EAAE,YAAY,CAC7C;CAEA,IAAI,OAAO,MAAM,MAAM,UAAU,KAAK,iBAAiB,UAAU,MAAM,GACrE,OAAO,OAAO,oBAAoB,KAAK,CAAC,CAAC;CAE3C,OAAO;EAAE;EAAS,UAAU;GAAE,GAAG;GAAU,aAAa;EAAO;CAAE;AACnE,CAAC"}
@@ -98,7 +98,7 @@ type UsesProofs<A extends {
98
98
  readonly strategies: Readonly<Record<string, Strategy>>;
99
99
  }> = Enabled<A, "phone"> | Enabled<A, "email"> | ManagedPassword<A>;
100
100
  export type Ports<C extends ClaimsCodec, Id extends string, A extends Definition<C, Id>> = AuthenticationAuthority | KeyId<A["sessions"]["StatefulSessionPersistence"]> | KeyId<A["sessions"]["SessionRepository"]> | (Enabled<A, "password"> extends never ? never : PasswordPersistence) | KeyId<RegistrationKey<ManagedPassword<A>>> | (Enabled<A, "passkey"> extends never ? never : PasskeyPersistence | PasskeyCredentials) | (ManagedPasskey<A> extends never ? never : PasskeyManagementPersistence | PasskeyEnrollmentContext) | (Enabled<A, "email"> extends never ? never : EmailAddressPersistence) | (UsesProofs<A> extends never ? never : ProofPersistence) | (Enabled<A, "phone"> extends never ? never : PhoneAdmission | PhoneSignInTargets);
101
- export type Roles<C extends ClaimsCodec, Id extends string, A extends Definition<C, Id>> = "identifiers" | "credentials" | "sessions" | "sessionFlows" | (Enabled<A, "password"> extends never ? never : "passwords" | "passwordAttempts" | "passwordScopes" | "passwordCharges" | "passwordCommands") | (ManagedPassword<A> extends never ? never : "passwordRegistrations") | (Enabled<A, "phone"> extends never ? never : "phoneState") | (Enabled<A, "email"> extends never ? never : "emailCredentials" | "emailCommands") | (Enabled<A, "passkey"> extends never ? never : "passkeyCredentials" | "passkeyOwnership" | "passkeyHandles" | "passkeyModules" | "passkeyFlows" | "passkeyAdmissions" | "passkeyCharges") | (ManagedPasskey<A> extends never ? never : "passkeyCommands") | (UsesProofs<A> extends never ? never : ProofRoles);
101
+ export type Roles<C extends ClaimsCodec, Id extends string, A extends Definition<C, Id>> = "identifiers" | "credentials" | "sessions" | "sessionFlows" | (Enabled<A, "password"> extends never ? never : "passwords" | "passwordAttempts" | "passwordCommands") | (ManagedPassword<A> extends never ? never : "passwordRegistrations") | (Enabled<A, "phone"> extends never ? never : "phoneState") | (Enabled<A, "email"> extends never ? never : "emailCredentials" | "emailCommands") | (Enabled<A, "passkey"> extends never ? never : "passkeyCredentials" | "passkeyOwnership" | "passkeyHandles" | "passkeyModules" | "passkeyFlows" | "passkeyAdmissions" | "passkeyCharges") | (ManagedPasskey<A> extends never ? never : "passkeyCommands") | (UsesProofs<A> extends never ? never : ProofRoles);
102
102
  export interface SubjectOptions<T extends object, NativeId> {
103
103
  readonly table: T;
104
104
  readonly id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"configuration.mjs","names":[],"sources":["../../src/internal/configuration.ts"],"sourcesContent":["import type { EmailAction, EmailAddressPersistence } from \"@yielded/auth/Email\";\nimport type { LoginIdentifier } from \"@yielded/auth/Identity\";\nimport type {\n PasskeyActionChallenge,\n PasskeyConfig,\n PasskeyCredentials,\n PasskeyEnrollmentContext,\n PasskeyManagementPersistence,\n PasskeyManagementPolicy,\n PasskeyMethodPolicy,\n PasskeyPersistence,\n PasskeyConfigurationError,\n} from \"@yielded/auth/Passkey\";\nimport type {\n PasswordAction,\n PasswordPersistence,\n PasswordUnavailable,\n} from \"@yielded/auth/Password\";\nimport type { PhoneAdmission, PhoneSignInTargets } from \"@yielded/auth/PhoneOtp\";\nimport type { ProofPersistence } from \"@yielded/auth/Proofs\";\nimport type { SubjectId } from \"@yielded/auth/Schema\";\nimport type {\n AuthenticationAuthority,\n AuthenticationRequirement,\n make as makeSessions,\n} from \"@yielded/auth/Sessions\";\nimport { type Context, type Crypto, type Effect, type Layer, Schema } from \"effect\";\nimport type { SqlClient } from \"effect/sql\";\n\nimport type { PersistenceMappingError } from \"./mapping-error\";\nimport type { StorageRole } from \"./storage-tables\";\n\nexport class PersistenceConfigurationError extends Schema.TaggedError<PersistenceConfigurationError>()(\n \"PersistenceConfigurationError\",\n { reason: Schema.String },\n) {}\n\nexport type ClaimsCodec = Schema.Codec<unknown, unknown, never, never>;\n\nexport interface PasskeyFeature {\n readonly kind: \"passkey\";\n readonly moduleId: string;\n readonly policy: Effect.Effect<PasskeyMethodPolicy, PasskeyConfigurationError, PasskeyConfig>;\n readonly management?: boolean;\n readonly managementPolicy?: PasskeyManagementPolicy;\n}\n\nexport interface Strategy {\n readonly strategy: object;\n readonly persistence?:\n | PasskeyFeature\n | {\n readonly kind: \"password\" | \"phone\" | \"email\";\n readonly moduleId: string;\n readonly lifecycle?: boolean;\n readonly management?: boolean;\n readonly addresses?: boolean;\n };\n readonly RegistrationAuthority?: Context.Key<unknown, unknown>;\n}\n\nexport interface Definition<C extends ClaimsCodec, Id extends string> {\n readonly namespace: string;\n readonly claims: C;\n readonly sessionMode?: string | undefined;\n readonly sessions: ReturnType<typeof makeSessions<C, Id>>;\n readonly strategies: Readonly<Record<string, Strategy>>;\n}\n\ntype KeyId<T> = T extends Context.Key<infer Id, infer _Service> ? Id : never;\ntype Enabled<\n A extends { readonly strategies: Readonly<Record<string, Strategy>> },\n Kind extends \"password\" | \"phone\" | \"email\" | \"passkey\",\n> = Extract<A[\"strategies\"][keyof A[\"strategies\"]], { persistence: { kind: Kind } }>;\n\ntype ManagedPassword<A extends { readonly strategies: Readonly<Record<string, Strategy>> }> =\n Extract<Enabled<A, \"password\">, { persistence: { management: true } }>;\n\ntype ManagedPasskey<A extends { readonly strategies: Readonly<Record<string, Strategy>> }> =\n Extract<Enabled<A, \"passkey\">, { persistence: { management: true } }>;\n\nexport type PasskeyRequirement<\n A extends { readonly strategies: Readonly<Record<string, Strategy>> },\n> = Enabled<A, \"passkey\"> extends never ? never : PasskeyConfig;\n\ntype RegistrationKey<S> = S extends { readonly RegistrationAuthority: infer K } ? K : never;\ntype Registration<S> =\n RegistrationKey<S> extends Context.Key<infer _Id, infer Service>\n ? Service extends { readonly register: (input: infer Input, ...args: never[]) => unknown }\n ? Input extends { readonly registration: infer Value }\n ? Value\n : never\n : never\n : never;\n\nexport interface ProvisioningId<Id extends string> {\n readonly authNamespace: Id;\n readonly service: \"PersistenceProvisioning\";\n}\n\nexport type Provisioning<A extends { readonly strategies: Readonly<Record<string, Strategy>> }> = {\n readonly [\n K in keyof A[\"strategies\"] as A[\"strategies\"][K] extends {\n persistence: { kind: \"password\"; management: true };\n }\n ? K\n : never\n ]: (input: {\n readonly identifier: LoginIdentifier;\n readonly registration: Registration<A[\"strategies\"][K]>;\n }) => Effect.Effect<SubjectId, PasswordUnavailable>;\n};\n\nexport type ProvisioningRequirement<\n A extends { readonly namespace: string; readonly strategies: Readonly<Record<string, Strategy>> },\n> = ManagedPassword<A> extends never ? never : ProvisioningId<A[\"namespace\"]>;\n\ntype ProofRoles =\n | \"proofRequests\"\n | \"proofSeries\"\n | \"proofGenerations\"\n | \"proofContinuations\"\n | \"proofScopes\"\n | \"proofAbuse\"\n | \"proofFailures\"\n | \"proofCommands\";\n\ntype UsesProofs<A extends { readonly strategies: Readonly<Record<string, Strategy>> }> =\n | Enabled<A, \"phone\">\n | Enabled<A, \"email\">\n | ManagedPassword<A>;\n\nexport type Ports<C extends ClaimsCodec, Id extends string, A extends Definition<C, Id>> =\n | AuthenticationAuthority\n | KeyId<A[\"sessions\"][\"StatefulSessionPersistence\"]>\n | KeyId<A[\"sessions\"][\"SessionRepository\"]>\n | (Enabled<A, \"password\"> extends never ? never : PasswordPersistence)\n | KeyId<RegistrationKey<ManagedPassword<A>>>\n | (Enabled<A, \"passkey\"> extends never ? never : PasskeyPersistence | PasskeyCredentials)\n | (ManagedPasskey<A> extends never\n ? never\n : PasskeyManagementPersistence | PasskeyEnrollmentContext)\n | (Enabled<A, \"email\"> extends never ? never : EmailAddressPersistence)\n | (UsesProofs<A> extends never ? never : ProofPersistence)\n | (Enabled<A, \"phone\"> extends never ? never : PhoneAdmission | PhoneSignInTargets);\n\nexport type Roles<C extends ClaimsCodec, Id extends string, A extends Definition<C, Id>> =\n | \"identifiers\"\n | \"credentials\"\n | \"sessions\"\n | \"sessionFlows\"\n | (Enabled<A, \"password\"> extends never\n ? never\n :\n | \"passwords\"\n | \"passwordAttempts\"\n | \"passwordScopes\"\n | \"passwordCharges\"\n | \"passwordCommands\")\n | (ManagedPassword<A> extends never ? never : \"passwordRegistrations\")\n | (Enabled<A, \"phone\"> extends never ? never : \"phoneState\")\n | (Enabled<A, \"email\"> extends never ? never : \"emailCredentials\" | \"emailCommands\")\n | (Enabled<A, \"passkey\"> extends never\n ? never\n :\n | \"passkeyCredentials\"\n | \"passkeyOwnership\"\n | \"passkeyHandles\"\n | \"passkeyModules\"\n | \"passkeyFlows\"\n | \"passkeyAdmissions\"\n | \"passkeyCharges\")\n | (ManagedPasskey<A> extends never ? never : \"passkeyCommands\")\n | (UsesProofs<A> extends never ? never : ProofRoles);\n\nexport interface SubjectOptions<T extends object, NativeId> {\n readonly table: T;\n readonly id: string;\n readonly status: string;\n readonly activeValue: unknown;\n readonly securityRevision: string;\n readonly idCodec: Schema.Codec<SubjectId, NativeId>;\n readonly requirements: (\n row: Readonly<Record<string, unknown>>,\n ) => Effect.Effect<AuthenticationRequirement, PersistenceMappingError>;\n /** Defaults to sign-in requirements. Recovery can have a distinct application policy. */\n readonly actionRequirements?: (\n row: Readonly<Record<string, unknown>>,\n action: PasswordAction | EmailAction | PasskeyActionChallenge[\"action\"],\n ) => Effect.Effect<AuthenticationRequirement, PersistenceMappingError>;\n}\n\n/** Codecs at the application-owned subject and timestamp boundary. */\nexport interface SubjectMapping {\n readonly table: object;\n readonly id: string;\n readonly status: string;\n readonly securityRevision: string;\n readonly activeValue: unknown;\n readonly requirements: SubjectOptions<object, unknown>[\"requirements\"];\n readonly actionRequirements: NonNullable<SubjectOptions<object, unknown>[\"actionRequirements\"]>;\n readonly toSubject: (value: unknown) => Effect.Effect<SubjectId, PersistenceMappingError>;\n readonly toNative: (value: SubjectId) => Effect.Effect<unknown, PersistenceMappingError>;\n readonly toSubjectSync: (value: unknown) => SubjectId;\n readonly toNativeSync: (value: SubjectId) => unknown;\n}\n\nexport interface MappingInput {\n readonly tables: Partial<Record<StorageRole, object>>;\n readonly subjects: SubjectMapping;\n readonly encodeInstant: (millis: number) => unknown;\n readonly decodeInstant: (value: unknown) => Effect.Effect<number, PersistenceMappingError>;\n readonly decodeInstantSync: (value: unknown) => number;\n}\n\nexport interface StorageLayout<\n T extends object,\n Role extends StorageRole = StorageRole,\n> extends MappingInput {\n readonly namespace: string;\n readonly schema: Readonly<Record<Role, T>>;\n}\n\nexport interface ConfigId<Id extends string> {\n readonly authNamespace: Id;\n readonly service: \"PersistenceConfig\";\n}\n\nexport interface TimestampOptions<Instant> {\n readonly type: \"text\" | \"integer\";\n readonly codec: Schema.Codec<number, Instant>;\n}\n\nexport interface BoundPersistence<\n T extends object,\n R,\n C extends ClaimsCodec,\n Id extends string,\n A extends Definition<C, Id>,\n> {\n readonly Config: Context.Service<ConfigId<A[\"namespace\"]>, StorageLayout<T, Roles<C, Id, A>>> & {\n readonly layer: (\n value: StorageLayout<T, Roles<C, Id, A>>,\n ) => Layer.Layer<ConfigId<A[\"namespace\"]>>;\n };\n /** Create only the application subject. Runs inside the owning auth SQL transaction;\n * use that SqlClient (including Drizzle over it), and return the new subject ID.\n * Do not perform external side effects or open an independent transaction here.\n */\n readonly Provisioning: Context.Service<ProvisioningRequirement<A>, Provisioning<A>>;\n readonly layer: Layer.Layer<\n Ports<C, Id, A>,\n PersistenceConfigurationError,\n | Crypto.Crypto\n | ConfigId<A[\"namespace\"]>\n | ProvisioningRequirement<A>\n | PasskeyRequirement<A>\n | SqlClient.SqlClient\n | R\n >;\n readonly managed: <N, Instant = number>(options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables?: Partial<Record<Roles<C, Id, A>, T>>;\n /** Stable SQL identifier prefix; reuse the deployed prefix for existing tables. */\n readonly prefix: string;\n readonly timestamps?: TimestampOptions<Instant>;\n }) => StorageLayout<T, Roles<C, Id, A>>;\n readonly map: <N, Instant = number>(options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables: Readonly<Record<Roles<C, Id, A>, T>>;\n readonly timestamps?: TimestampOptions<Instant>;\n }) => StorageLayout<T, Roles<C, Id, A>>;\n}\n\n/** Shared configuration shape. The backend chooses table types and service requirements. */\nexport interface PersistenceApi<T extends object, R = never> {\n readonly make: <\n C extends ClaimsCodec,\n const Id extends string,\n const A extends Definition<C, Id>,\n >(\n auth: A & Definition<C, Id>,\n ) => BoundPersistence<T, R, C, Id, A>;\n}\n"],"mappings":";;AAgCA,IAAa,gCAAb,cAAmD,OAAO,YAA2C,CAAC,CACpG,iCACA,EAAE,QAAQ,OAAO,OAAO,CAC1B,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"configuration.mjs","names":[],"sources":["../../src/internal/configuration.ts"],"sourcesContent":["import type { EmailAction, EmailAddressPersistence } from \"@yielded/auth/Email\";\nimport type { LoginIdentifier } from \"@yielded/auth/Identity\";\nimport type {\n PasskeyActionChallenge,\n PasskeyConfig,\n PasskeyCredentials,\n PasskeyEnrollmentContext,\n PasskeyManagementPersistence,\n PasskeyManagementPolicy,\n PasskeyMethodPolicy,\n PasskeyPersistence,\n PasskeyConfigurationError,\n} from \"@yielded/auth/Passkey\";\nimport type {\n PasswordAction,\n PasswordPersistence,\n PasswordUnavailable,\n} from \"@yielded/auth/Password\";\nimport type { PhoneAdmission, PhoneSignInTargets } from \"@yielded/auth/PhoneOtp\";\nimport type { ProofPersistence } from \"@yielded/auth/Proofs\";\nimport type { SubjectId } from \"@yielded/auth/Schema\";\nimport type {\n AuthenticationAuthority,\n AuthenticationRequirement,\n make as makeSessions,\n} from \"@yielded/auth/Sessions\";\nimport { type Context, type Crypto, type Effect, type Layer, Schema } from \"effect\";\nimport type { SqlClient } from \"effect/sql\";\n\nimport type { PersistenceMappingError } from \"./mapping-error\";\nimport type { StorageRole } from \"./storage-tables\";\n\nexport class PersistenceConfigurationError extends Schema.TaggedError<PersistenceConfigurationError>()(\n \"PersistenceConfigurationError\",\n { reason: Schema.String },\n) {}\n\nexport type ClaimsCodec = Schema.Codec<unknown, unknown, never, never>;\n\nexport interface PasskeyFeature {\n readonly kind: \"passkey\";\n readonly moduleId: string;\n readonly policy: Effect.Effect<PasskeyMethodPolicy, PasskeyConfigurationError, PasskeyConfig>;\n readonly management?: boolean;\n readonly managementPolicy?: PasskeyManagementPolicy;\n}\n\nexport interface Strategy {\n readonly strategy: object;\n readonly persistence?:\n | PasskeyFeature\n | {\n readonly kind: \"password\" | \"phone\" | \"email\";\n readonly moduleId: string;\n readonly lifecycle?: boolean;\n readonly management?: boolean;\n readonly addresses?: boolean;\n };\n readonly RegistrationAuthority?: Context.Key<unknown, unknown>;\n}\n\nexport interface Definition<C extends ClaimsCodec, Id extends string> {\n readonly namespace: string;\n readonly claims: C;\n readonly sessionMode?: string | undefined;\n readonly sessions: ReturnType<typeof makeSessions<C, Id>>;\n readonly strategies: Readonly<Record<string, Strategy>>;\n}\n\ntype KeyId<T> = T extends Context.Key<infer Id, infer _Service> ? Id : never;\ntype Enabled<\n A extends { readonly strategies: Readonly<Record<string, Strategy>> },\n Kind extends \"password\" | \"phone\" | \"email\" | \"passkey\",\n> = Extract<A[\"strategies\"][keyof A[\"strategies\"]], { persistence: { kind: Kind } }>;\n\ntype ManagedPassword<A extends { readonly strategies: Readonly<Record<string, Strategy>> }> =\n Extract<Enabled<A, \"password\">, { persistence: { management: true } }>;\n\ntype ManagedPasskey<A extends { readonly strategies: Readonly<Record<string, Strategy>> }> =\n Extract<Enabled<A, \"passkey\">, { persistence: { management: true } }>;\n\nexport type PasskeyRequirement<\n A extends { readonly strategies: Readonly<Record<string, Strategy>> },\n> = Enabled<A, \"passkey\"> extends never ? never : PasskeyConfig;\n\ntype RegistrationKey<S> = S extends { readonly RegistrationAuthority: infer K } ? K : never;\ntype Registration<S> =\n RegistrationKey<S> extends Context.Key<infer _Id, infer Service>\n ? Service extends { readonly register: (input: infer Input, ...args: never[]) => unknown }\n ? Input extends { readonly registration: infer Value }\n ? Value\n : never\n : never\n : never;\n\nexport interface ProvisioningId<Id extends string> {\n readonly authNamespace: Id;\n readonly service: \"PersistenceProvisioning\";\n}\n\nexport type Provisioning<A extends { readonly strategies: Readonly<Record<string, Strategy>> }> = {\n readonly [\n K in keyof A[\"strategies\"] as A[\"strategies\"][K] extends {\n persistence: { kind: \"password\"; management: true };\n }\n ? K\n : never\n ]: (input: {\n readonly identifier: LoginIdentifier;\n readonly registration: Registration<A[\"strategies\"][K]>;\n }) => Effect.Effect<SubjectId, PasswordUnavailable>;\n};\n\nexport type ProvisioningRequirement<\n A extends { readonly namespace: string; readonly strategies: Readonly<Record<string, Strategy>> },\n> = ManagedPassword<A> extends never ? never : ProvisioningId<A[\"namespace\"]>;\n\ntype ProofRoles =\n | \"proofRequests\"\n | \"proofSeries\"\n | \"proofGenerations\"\n | \"proofContinuations\"\n | \"proofScopes\"\n | \"proofAbuse\"\n | \"proofFailures\"\n | \"proofCommands\";\n\ntype UsesProofs<A extends { readonly strategies: Readonly<Record<string, Strategy>> }> =\n | Enabled<A, \"phone\">\n | Enabled<A, \"email\">\n | ManagedPassword<A>;\n\nexport type Ports<C extends ClaimsCodec, Id extends string, A extends Definition<C, Id>> =\n | AuthenticationAuthority\n | KeyId<A[\"sessions\"][\"StatefulSessionPersistence\"]>\n | KeyId<A[\"sessions\"][\"SessionRepository\"]>\n | (Enabled<A, \"password\"> extends never ? never : PasswordPersistence)\n | KeyId<RegistrationKey<ManagedPassword<A>>>\n | (Enabled<A, \"passkey\"> extends never ? never : PasskeyPersistence | PasskeyCredentials)\n | (ManagedPasskey<A> extends never\n ? never\n : PasskeyManagementPersistence | PasskeyEnrollmentContext)\n | (Enabled<A, \"email\"> extends never ? never : EmailAddressPersistence)\n | (UsesProofs<A> extends never ? never : ProofPersistence)\n | (Enabled<A, \"phone\"> extends never ? never : PhoneAdmission | PhoneSignInTargets);\n\nexport type Roles<C extends ClaimsCodec, Id extends string, A extends Definition<C, Id>> =\n | \"identifiers\"\n | \"credentials\"\n | \"sessions\"\n | \"sessionFlows\"\n | (Enabled<A, \"password\"> extends never\n ? never\n : \"passwords\" | \"passwordAttempts\" | \"passwordCommands\")\n | (ManagedPassword<A> extends never ? never : \"passwordRegistrations\")\n | (Enabled<A, \"phone\"> extends never ? never : \"phoneState\")\n | (Enabled<A, \"email\"> extends never ? never : \"emailCredentials\" | \"emailCommands\")\n | (Enabled<A, \"passkey\"> extends never\n ? never\n :\n | \"passkeyCredentials\"\n | \"passkeyOwnership\"\n | \"passkeyHandles\"\n | \"passkeyModules\"\n | \"passkeyFlows\"\n | \"passkeyAdmissions\"\n | \"passkeyCharges\")\n | (ManagedPasskey<A> extends never ? never : \"passkeyCommands\")\n | (UsesProofs<A> extends never ? never : ProofRoles);\n\nexport interface SubjectOptions<T extends object, NativeId> {\n readonly table: T;\n readonly id: string;\n readonly status: string;\n readonly activeValue: unknown;\n readonly securityRevision: string;\n readonly idCodec: Schema.Codec<SubjectId, NativeId>;\n readonly requirements: (\n row: Readonly<Record<string, unknown>>,\n ) => Effect.Effect<AuthenticationRequirement, PersistenceMappingError>;\n /** Defaults to sign-in requirements. Recovery can have a distinct application policy. */\n readonly actionRequirements?: (\n row: Readonly<Record<string, unknown>>,\n action: PasswordAction | EmailAction | PasskeyActionChallenge[\"action\"],\n ) => Effect.Effect<AuthenticationRequirement, PersistenceMappingError>;\n}\n\n/** Codecs at the application-owned subject and timestamp boundary. */\nexport interface SubjectMapping {\n readonly table: object;\n readonly id: string;\n readonly status: string;\n readonly securityRevision: string;\n readonly activeValue: unknown;\n readonly requirements: SubjectOptions<object, unknown>[\"requirements\"];\n readonly actionRequirements: NonNullable<SubjectOptions<object, unknown>[\"actionRequirements\"]>;\n readonly toSubject: (value: unknown) => Effect.Effect<SubjectId, PersistenceMappingError>;\n readonly toNative: (value: SubjectId) => Effect.Effect<unknown, PersistenceMappingError>;\n readonly toSubjectSync: (value: unknown) => SubjectId;\n readonly toNativeSync: (value: SubjectId) => unknown;\n}\n\nexport interface MappingInput {\n readonly tables: Partial<Record<StorageRole, object>>;\n readonly subjects: SubjectMapping;\n readonly encodeInstant: (millis: number) => unknown;\n readonly decodeInstant: (value: unknown) => Effect.Effect<number, PersistenceMappingError>;\n readonly decodeInstantSync: (value: unknown) => number;\n}\n\nexport interface StorageLayout<\n T extends object,\n Role extends StorageRole = StorageRole,\n> extends MappingInput {\n readonly namespace: string;\n readonly schema: Readonly<Record<Role, T>>;\n}\n\nexport interface ConfigId<Id extends string> {\n readonly authNamespace: Id;\n readonly service: \"PersistenceConfig\";\n}\n\nexport interface TimestampOptions<Instant> {\n readonly type: \"text\" | \"integer\";\n readonly codec: Schema.Codec<number, Instant>;\n}\n\nexport interface BoundPersistence<\n T extends object,\n R,\n C extends ClaimsCodec,\n Id extends string,\n A extends Definition<C, Id>,\n> {\n readonly Config: Context.Service<ConfigId<A[\"namespace\"]>, StorageLayout<T, Roles<C, Id, A>>> & {\n readonly layer: (\n value: StorageLayout<T, Roles<C, Id, A>>,\n ) => Layer.Layer<ConfigId<A[\"namespace\"]>>;\n };\n /** Create only the application subject. Runs inside the owning auth SQL transaction;\n * use that SqlClient (including Drizzle over it), and return the new subject ID.\n * Do not perform external side effects or open an independent transaction here.\n */\n readonly Provisioning: Context.Service<ProvisioningRequirement<A>, Provisioning<A>>;\n readonly layer: Layer.Layer<\n Ports<C, Id, A>,\n PersistenceConfigurationError,\n | Crypto.Crypto\n | ConfigId<A[\"namespace\"]>\n | ProvisioningRequirement<A>\n | PasskeyRequirement<A>\n | SqlClient.SqlClient\n | R\n >;\n readonly managed: <N, Instant = number>(options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables?: Partial<Record<Roles<C, Id, A>, T>>;\n /** Stable SQL identifier prefix; reuse the deployed prefix for existing tables. */\n readonly prefix: string;\n readonly timestamps?: TimestampOptions<Instant>;\n }) => StorageLayout<T, Roles<C, Id, A>>;\n readonly map: <N, Instant = number>(options: {\n readonly subjects: SubjectOptions<T, N>;\n readonly tables: Readonly<Record<Roles<C, Id, A>, T>>;\n readonly timestamps?: TimestampOptions<Instant>;\n }) => StorageLayout<T, Roles<C, Id, A>>;\n}\n\n/** Shared configuration shape. The backend chooses table types and service requirements. */\nexport interface PersistenceApi<T extends object, R = never> {\n readonly make: <\n C extends ClaimsCodec,\n const Id extends string,\n const A extends Definition<C, Id>,\n >(\n auth: A & Definition<C, Id>,\n ) => BoundPersistence<T, R, C, Id, A>;\n}\n"],"mappings":";;AAgCA,IAAa,gCAAb,cAAmD,OAAO,YAA2C,CAAC,CACpG,iCACA,EAAE,QAAQ,OAAO,OAAO,CAC1B,CAAC,CAAC,CAAC"}
@@ -9,12 +9,6 @@ import { LoginIdentifier, RecoveryReference } from "@yielded/auth/Identity";
9
9
  type ColumnKey<T extends TableModel> = T["column"];
10
10
  export type PasswordAttemptAction = "sign-in" | "change";
11
11
  export type PasswordAttemptState = "pending" | "verified" | "rejected";
12
- export type PasswordRateScopeKind = "action" | "identifier" | "subject";
13
- export interface PasswordScopeKeys {
14
- readonly action: string;
15
- readonly identifier: string;
16
- readonly subject?: string;
17
- }
18
12
  export interface PasswordSubjectTable<Subject extends TableModel, _NativeSubjectId> {
19
13
  readonly table: Subject["table"];
20
14
  readonly id: ColumnKey<Subject>;
@@ -127,38 +121,6 @@ export interface PasswordAttemptTable<Attempt extends TableModel, NativeSubjectI
127
121
  readonly state: "pending";
128
122
  }) => Attempt["insert"];
129
123
  }
130
- export interface PasswordRateScopeTable<RateScope extends TableModel> {
131
- readonly table: RateScope["table"];
132
- readonly moduleId: ColumnKey<RateScope>;
133
- readonly action: ColumnKey<RateScope>;
134
- readonly scopeKind: ColumnKey<RateScope>;
135
- readonly scopeKey: ColumnKey<RateScope>;
136
- readonly encodeInsert: (input: {
137
- readonly moduleId: string;
138
- readonly action: PasswordAttemptAction;
139
- readonly scopeKind: PasswordRateScopeKind;
140
- readonly scopeKey: string;
141
- }) => RateScope["insert"];
142
- }
143
- export interface PasswordChargeTable<Charge extends TableModel> {
144
- readonly table: Charge["table"];
145
- readonly moduleId: ColumnKey<Charge>;
146
- readonly action: ColumnKey<Charge>;
147
- readonly scopeKind: ColumnKey<Charge>;
148
- readonly scopeKey: ColumnKey<Charge>;
149
- readonly attemptId: ColumnKey<Charge>;
150
- readonly occurredAt: ColumnKey<Charge>;
151
- readonly retentionUntil: ColumnKey<Charge>;
152
- readonly encodeInsert: (input: {
153
- readonly moduleId: string;
154
- readonly action: PasswordAttemptAction;
155
- readonly scopeKind: PasswordRateScopeKind;
156
- readonly scopeKey: string;
157
- readonly attemptId: PasswordAttemptId;
158
- readonly occurredAtMillis: number;
159
- readonly retentionUntilMillis: number;
160
- }) => Charge["insert"];
161
- }
162
124
  export interface PasswordCommandTable<Command extends TableModel> {
163
125
  readonly table: Command["table"];
164
126
  readonly moduleId: ColumnKey<Command>;
@@ -182,16 +144,12 @@ export interface RequiredPasswordConstraints {
182
144
  readonly credentialSubject: "unique(credential.moduleId,credential.subjectId)";
183
145
  readonly credentialId: "unique(credential.moduleId,credential.credentialId)";
184
146
  readonly attempt: "unique(attempt.moduleId,attempt.attemptId)";
185
- readonly rateScope: "unique(rateScope.moduleId,rateScope.action,rateScope.scopeKind,rateScope.scopeKey)";
186
- readonly charge: "unique(charge.moduleId,charge.action,charge.scopeKind,charge.scopeKey,charge.attemptId)";
187
147
  readonly command: "unique(command.moduleId,command.commandId)";
188
148
  }
189
149
  export declare const requiredPasswordConstraints: RequiredPasswordConstraints;
190
150
  export interface PasswordConstraintClassifier {
191
151
  /** Match only the mapped command uniqueness constraint. */
192
152
  readonly isCommandConflict: (cause: unknown) => boolean;
193
- /** Match only the mapped rate-scope uniqueness constraint. */
194
- readonly isRateScopeConflict: (cause: unknown) => boolean;
195
153
  }
196
154
  export interface PasswordD1Clock<Expression extends SqlExpression = SqlExpression> {
197
155
  readonly engineNow: Expression;
@@ -199,24 +157,16 @@ export interface PasswordD1Clock<Expression extends SqlExpression = SqlExpressio
199
157
  readonly engineInstantMinus: (millis: number) => Expression;
200
158
  readonly engineInstantPlus: (millis: number) => Expression;
201
159
  }
202
- export interface PasswordPersistenceMapping<Subject extends TableModel, Identifier extends TableModel, Credential extends TableModel, AuthorityCredential extends TableModel, Attempt extends TableModel, RateScope extends TableModel, Charge extends TableModel, Command extends TableModel, NativeSubjectId, Expression extends SqlExpression = SqlExpression> extends PasswordConstraintClassifier {
160
+ export interface PasswordPersistenceMapping<Subject extends TableModel, Identifier extends TableModel, Credential extends TableModel, AuthorityCredential extends TableModel, Attempt extends TableModel, Command extends TableModel, NativeSubjectId, Expression extends SqlExpression = SqlExpression> extends PasswordConstraintClassifier {
203
161
  readonly subject: PasswordSubjectTable<Subject, NativeSubjectId>;
204
162
  readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId, Expression>;
205
163
  readonly credential: PasswordCredentialTable<Subject, Identifier, Credential, NativeSubjectId>;
206
164
  /** Every factor revision named by action evidence, including non-password factors. */
207
165
  readonly authorityCredential: PasswordAuthorityCredentialTable<AuthorityCredential, NativeSubjectId>;
208
166
  readonly attempt: PasswordAttemptTable<Attempt, NativeSubjectId>;
209
- readonly rateScope: PasswordRateScopeTable<RateScope>;
210
- readonly charge: PasswordChargeTable<Charge>;
211
167
  readonly command: PasswordCommandTable<Command>;
212
168
  readonly subjectId: SubjectIdCodec<NativeSubjectId>;
213
169
  readonly constraints: RequiredPasswordConstraints;
214
- readonly scopeKeys: (input: {
215
- readonly moduleId: string;
216
- readonly action: PasswordAttemptAction;
217
- readonly identifier: LoginIdentifier;
218
- readonly subjectId?: string;
219
- }) => PasswordScopeKeys;
220
170
  readonly encodeInstant: (epochMillis: number) => unknown;
221
171
  readonly decodeInstant: (native: unknown) => Effect.Effect<number, PersistenceMappingError>;
222
172
  readonly allocateAttemptId?: Effect.Effect<PasswordAttemptId, PersistenceMappingError>;
@@ -230,7 +180,7 @@ export interface PasswordPersistenceMapping<Subject extends TableModel, Identifi
230
180
  readonly sessionInvalidation: "same-authority-immediate" | "original-absolute-expiry";
231
181
  readonly d1?: PasswordD1Clock<Expression>;
232
182
  }
233
- export type D1PasswordPersistenceMapping<Subject extends TableModel, Identifier extends TableModel, Credential extends TableModel, AuthorityCredential extends TableModel, Attempt extends TableModel, RateScope extends TableModel, Charge extends TableModel, Command extends TableModel, NativeSubjectId, Expression extends SqlExpression = SqlExpression> = PasswordPersistenceMapping<Subject, Identifier, Credential, AuthorityCredential, Attempt, RateScope, Charge, Command, NativeSubjectId, Expression> & {
183
+ export type D1PasswordPersistenceMapping<Subject extends TableModel, Identifier extends TableModel, Credential extends TableModel, AuthorityCredential extends TableModel, Attempt extends TableModel, Command extends TableModel, NativeSubjectId, Expression extends SqlExpression = SqlExpression> = PasswordPersistenceMapping<Subject, Identifier, Credential, AuthorityCredential, Attempt, Command, NativeSubjectId, Expression> & {
234
184
  readonly d1: PasswordD1Clock<Expression>;
235
185
  readonly subject: PasswordSubjectTable<Subject, NativeSubjectId> & {
236
186
  readonly d1ActiveStatusValue: unknown;
@@ -322,7 +272,7 @@ export type PasswordRegistrationMapping<Registration, Subject extends TableModel
322
272
  readonly allocateRecoveryReference?: Effect.Effect<typeof RecoveryReference.Type, PersistenceMappingError>;
323
273
  readonly allocateRecoveryReferenceSync?: () => typeof RecoveryReference.Type;
324
274
  });
325
- export type AnyPasswordPersistenceMapping<Expression extends SqlExpression = SqlExpression> = PasswordPersistenceMapping<AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, unknown, Expression>;
275
+ export type AnyPasswordPersistenceMapping<Expression extends SqlExpression = SqlExpression> = PasswordPersistenceMapping<AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, unknown, Expression>;
326
276
  export type AnyPasswordRegistrationMapping<Registration = unknown, Expression extends SqlExpression = SqlExpression> = PasswordRegistrationMapping<Registration, AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, AnyTableModel, unknown, Expression>;
327
277
  //#endregion
328
278
  //# sourceMappingURL=password-model.d.mts.map
@@ -6,8 +6,6 @@ const requiredPasswordConstraints = {
6
6
  credentialSubject: "unique(credential.moduleId,credential.subjectId)",
7
7
  credentialId: "unique(credential.moduleId,credential.credentialId)",
8
8
  attempt: "unique(attempt.moduleId,attempt.attemptId)",
9
- rateScope: "unique(rateScope.moduleId,rateScope.action,rateScope.scopeKind,rateScope.scopeKey)",
10
- charge: "unique(charge.moduleId,charge.action,charge.scopeKind,charge.scopeKey,charge.attemptId)",
11
9
  command: "unique(command.moduleId,command.commandId)"
12
10
  };
13
11
  const requiredPasswordRegistrationConstraints = {
@@ -1 +1 @@
1
- {"version":3,"file":"password-model.mjs","names":[],"sources":["../../../src/internal/models/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 { Effect, Redacted } from \"effect\";\n\nimport type { AnyTableModel, TableModel as Table, SqlExpression } from \"../query-operations\";\nimport type { PersistenceMappingError, SubjectIdCodec } from \"./common\";\n\ntype ColumnKey<T extends Table> = T[\"column\"];\n\nexport type PasswordAttemptAction = \"sign-in\" | \"change\";\n\nexport type PasswordAttemptState = \"pending\" | \"verified\" | \"rejected\";\n\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[\"table\"];\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: Subject[\"select\"],\n ) => Effect.Effect<AuthenticationRequirement, PersistenceMappingError>;\n /** Current policy for this exact credential mutation, decoded under the subject lock. */\n readonly decodeActionRequirement: (\n row: Subject[\"select\"],\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<\n Identifier extends Table,\n NativeSubjectId,\n Expression extends SqlExpression = SqlExpression,\n> {\n readonly table: Identifier[\"table\"];\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: Identifier[\"select\"]) => 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 }) => Expression;\n readonly encodeInitialInsert: (\n identifier: LoginIdentifier,\n subjectId: NativeSubjectId,\n bindingRevision: SecurityRevision,\n ) => Identifier[\"insert\"];\n}\n\nexport interface PasswordAuthorityCredentialTable<Credential extends Table, NativeSubjectId> {\n readonly table: Credential[\"table\"];\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 }) => Credential[\"insert\"];\n readonly encodeRevision: (revision: SecurityRevision) => Partial<Credential[\"insert\"]>;\n}\n\nexport interface PasswordCredentialTable<\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n NativeSubjectId,\n> {\n readonly table: Credential[\"table\"];\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 }) => Credential[\"insert\"];\n readonly encodeVerifier: (\n verifier: Redacted.Redacted<EncodedPasswordHash>,\n verifierVersion: SecurityRevision,\n ) => Partial<Credential[\"insert\"]>;\n readonly encodeReplacement: (input: {\n readonly replacement: PasswordReplacement;\n readonly credentialRevision: SecurityRevision;\n readonly verifierVersion: SecurityRevision;\n }) => Partial<Credential[\"insert\"]>;\n readonly decode: (input: {\n readonly moduleId: string;\n readonly subject: Subject[\"select\"];\n readonly identifier: Identifier[\"select\"];\n readonly credential: Credential[\"select\"];\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[\"table\"];\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: {\n readonly nativeSubjectId?: NativeSubjectId;\n readonly state: \"pending\";\n },\n ) => Attempt[\"insert\"];\n}\n\nexport interface PasswordRateScopeTable<RateScope extends Table> {\n readonly table: RateScope[\"table\"];\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 }) => RateScope[\"insert\"];\n}\n\nexport interface PasswordChargeTable<Charge extends Table> {\n readonly table: Charge[\"table\"];\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 }) => Charge[\"insert\"];\n}\n\nexport interface PasswordCommandTable<Command extends Table> {\n readonly table: Command[\"table\"];\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 }) => Command[\"insert\"];\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<Expression extends SqlExpression = SqlExpression> {\n readonly engineNow: Expression;\n readonly engineNowMillis: Expression;\n readonly engineInstantMinus: (millis: number) => Expression;\n readonly engineInstantPlus: (millis: number) => Expression;\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 Expression extends SqlExpression = SqlExpression,\n> extends PasswordConstraintClassifier {\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId>;\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId, Expression>;\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<Expression>;\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 Expression extends SqlExpression = SqlExpression,\n> = PasswordPersistenceMapping<\n Subject,\n Identifier,\n Credential,\n AuthorityCredential,\n Attempt,\n RateScope,\n Charge,\n Command,\n NativeSubjectId,\n Expression\n> & {\n readonly d1: PasswordD1Clock<Expression>;\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId> & {\n readonly d1ActiveStatusValue: unknown;\n };\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId, Expression> & {\n readonly d1CurrentCondition: (input: {\n readonly identifier: LoginIdentifier;\n readonly nativeSubjectId: NativeSubjectId;\n }) => Expression;\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[\"table\"];\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 ) => Request[\"insert\"];\n /** Replay projection must never expose a stored subject or decode protected intent. */\n readonly decodeReplay: (row: Request[\"select\"]) => Effect.Effect<\n Exclude<\n PasswordRegistrationDecision,\n {\n readonly _tag: \"Created\";\n }\n >,\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 ) => Subject[\"insert\"];\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 Expression extends SqlExpression = SqlExpression,\n> = PasswordRegistrationConstraintClassifier & {\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId>;\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId, Expression>;\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<Expression extends SqlExpression = SqlExpression> =\n PasswordPersistenceMapping<\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n unknown,\n Expression\n >;\n\nexport type AnyPasswordRegistrationMapping<\n Registration = unknown,\n Expression extends SqlExpression = SqlExpression,\n> = PasswordRegistrationMapping<\n Registration,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n unknown,\n Expression\n>;\n"],"mappings":";;AA4OA,MAAa,8BAA2D;CACtE,YAAY;CACZ,qBAAqB;CACrB,mBAAmB;CACnB,cAAc;CACd,SAAS;CACT,WAAW;CACX,QAAQ;CACR,SAAS;AACX;AAwKA,MAAa,0CAAmF;CAC9F,SAAS;CACT,mBAAmB;CACnB,YAAY;CACZ,mBAAmB;CACnB,qBAAqB;AACvB"}
1
+ {"version":3,"file":"password-model.mjs","names":[],"sources":["../../../src/internal/models/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 { Effect, Redacted } from \"effect\";\n\nimport type { AnyTableModel, TableModel as Table, SqlExpression } from \"../query-operations\";\nimport type { PersistenceMappingError, SubjectIdCodec } from \"./common\";\n\ntype ColumnKey<T extends Table> = T[\"column\"];\n\nexport type PasswordAttemptAction = \"sign-in\" | \"change\";\n\nexport type PasswordAttemptState = \"pending\" | \"verified\" | \"rejected\";\n\nexport interface PasswordSubjectTable<Subject extends Table, _NativeSubjectId> {\n readonly table: Subject[\"table\"];\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: Subject[\"select\"],\n ) => Effect.Effect<AuthenticationRequirement, PersistenceMappingError>;\n /** Current policy for this exact credential mutation, decoded under the subject lock. */\n readonly decodeActionRequirement: (\n row: Subject[\"select\"],\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<\n Identifier extends Table,\n NativeSubjectId,\n Expression extends SqlExpression = SqlExpression,\n> {\n readonly table: Identifier[\"table\"];\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: Identifier[\"select\"]) => 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 }) => Expression;\n readonly encodeInitialInsert: (\n identifier: LoginIdentifier,\n subjectId: NativeSubjectId,\n bindingRevision: SecurityRevision,\n ) => Identifier[\"insert\"];\n}\n\nexport interface PasswordAuthorityCredentialTable<Credential extends Table, NativeSubjectId> {\n readonly table: Credential[\"table\"];\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 }) => Credential[\"insert\"];\n readonly encodeRevision: (revision: SecurityRevision) => Partial<Credential[\"insert\"]>;\n}\n\nexport interface PasswordCredentialTable<\n Subject extends Table,\n Identifier extends Table,\n Credential extends Table,\n NativeSubjectId,\n> {\n readonly table: Credential[\"table\"];\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 }) => Credential[\"insert\"];\n readonly encodeVerifier: (\n verifier: Redacted.Redacted<EncodedPasswordHash>,\n verifierVersion: SecurityRevision,\n ) => Partial<Credential[\"insert\"]>;\n readonly encodeReplacement: (input: {\n readonly replacement: PasswordReplacement;\n readonly credentialRevision: SecurityRevision;\n readonly verifierVersion: SecurityRevision;\n }) => Partial<Credential[\"insert\"]>;\n readonly decode: (input: {\n readonly moduleId: string;\n readonly subject: Subject[\"select\"];\n readonly identifier: Identifier[\"select\"];\n readonly credential: Credential[\"select\"];\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[\"table\"];\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: {\n readonly nativeSubjectId?: NativeSubjectId;\n readonly state: \"pending\";\n },\n ) => Attempt[\"insert\"];\n}\n\nexport interface PasswordCommandTable<Command extends Table> {\n readonly table: Command[\"table\"];\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 }) => Command[\"insert\"];\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 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 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}\n\nexport interface PasswordD1Clock<Expression extends SqlExpression = SqlExpression> {\n readonly engineNow: Expression;\n readonly engineNowMillis: Expression;\n readonly engineInstantMinus: (millis: number) => Expression;\n readonly engineInstantPlus: (millis: number) => Expression;\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 Command extends Table,\n NativeSubjectId,\n Expression extends SqlExpression = SqlExpression,\n> extends PasswordConstraintClassifier {\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId>;\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId, Expression>;\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 command: PasswordCommandTable<Command>;\n readonly subjectId: SubjectIdCodec<NativeSubjectId>;\n readonly constraints: RequiredPasswordConstraints;\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<Expression>;\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 Command extends Table,\n NativeSubjectId,\n Expression extends SqlExpression = SqlExpression,\n> = PasswordPersistenceMapping<\n Subject,\n Identifier,\n Credential,\n AuthorityCredential,\n Attempt,\n Command,\n NativeSubjectId,\n Expression\n> & {\n readonly d1: PasswordD1Clock<Expression>;\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId> & {\n readonly d1ActiveStatusValue: unknown;\n };\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId, Expression> & {\n readonly d1CurrentCondition: (input: {\n readonly identifier: LoginIdentifier;\n readonly nativeSubjectId: NativeSubjectId;\n }) => Expression;\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[\"table\"];\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 ) => Request[\"insert\"];\n /** Replay projection must never expose a stored subject or decode protected intent. */\n readonly decodeReplay: (row: Request[\"select\"]) => Effect.Effect<\n Exclude<\n PasswordRegistrationDecision,\n {\n readonly _tag: \"Created\";\n }\n >,\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 ) => Subject[\"insert\"];\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 Expression extends SqlExpression = SqlExpression,\n> = PasswordRegistrationConstraintClassifier & {\n readonly subject: PasswordSubjectTable<Subject, NativeSubjectId>;\n readonly identifier: PasswordIdentifierTable<Identifier, NativeSubjectId, Expression>;\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<Expression extends SqlExpression = SqlExpression> =\n PasswordPersistenceMapping<\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n unknown,\n Expression\n >;\n\nexport type AnyPasswordRegistrationMapping<\n Registration = unknown,\n Expression extends SqlExpression = SqlExpression,\n> = PasswordRegistrationMapping<\n Registration,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n AnyTableModel,\n unknown,\n Expression\n>;\n"],"mappings":";;AAgMA,MAAa,8BAA2D;CACtE,YAAY;CACZ,qBAAqB;CACrB,mBAAmB;CACnB,cAAc;CACd,SAAS;CACT,SAAS;AACX;AAwJA,MAAa,0CAAmF;CAC9F,SAAS;CACT,mBAAmB;CACnB,YAAY;CACZ,mBAAmB;CACnB,qBAAqB;AACvB"}
@@ -0,0 +1,30 @@
1
+ import "./mapping-error.mjs";
2
+ import { Effect } from "effect";
3
+ import * as Statement$1 from "effect/sql/Statement";
4
+ import { SqlClient } from "effect/sql/SqlClient";
5
+ //#region src/internal/native-sql-table.d.ts
6
+ /** Physical SQL representation only. Semantic row codecs and policy remain in
7
+ * the owning mapping. Execute assembled statements without name/result transforms. */
8
+ export interface SqlTable {
9
+ readonly name: Statement$1.Fragment;
10
+ /** Alias reads only; writes continue to target the original physical table. */
11
+ readonly as: (alias: string) => SqlTable;
12
+ readonly column: (key: string) => Statement$1.Fragment;
13
+ /** Project every column under an ordinal alias, using a distinct prefix per table. */
14
+ readonly fields: (prefix: string) => Statement$1.Fragment;
15
+ readonly decode: (row: Readonly<Record<string, unknown>>, prefix: string) => Record<string, unknown>;
16
+ readonly value: (key: string, value: unknown) => Statement$1.Fragment;
17
+ /** Complete INSERT prefix; append conflict/returning clauses in the owning operation. */
18
+ readonly insert: (values: Readonly<Record<string, unknown>>) => Statement$1.Fragment;
19
+ /** Complete UPDATE ... SET prefix; the owning operation supplies its predicate. */
20
+ readonly update: (values: Readonly<Record<string, unknown>>) => Statement$1.Fragment;
21
+ }
22
+ export type NativeSqlTables = (table: object) => SqlTable;
23
+ /** Prefixes are short ASCII identifiers so ordinal aliases cannot be truncated
24
+ * by PostgreSQL. Callers distinguish tables by prefix, never by physical names. */
25
+ export declare const nativeSqlAlias: (prefix: string, index: number) => string;
26
+ /** Cache physical metadata only; insert/update materialize values and hooks at
27
+ * each call. Construction acquires no client and owns no transaction. */
28
+ export declare const makeNativeSqlTables: (client: SqlClient, convert?: (client: SqlClient, table: object) => SqlTable) => NativeSqlTables;
29
+ //#endregion
30
+ //# sourceMappingURL=native-sql-table.d.mts.map
@@ -0,0 +1,104 @@
1
+ import { PersistenceMappingError } from "./mapping-error.mjs";
2
+ import { Table, identifier } from "./sql-table.mjs";
3
+ import { Effect } from "effect";
4
+ import * as Statement$1 from "effect/sql/Statement";
5
+ //#region src/internal/native-sql-table.ts
6
+ /** Capture synchronous mapping callbacks without changing SQL execution errors. */
7
+ const sqlMapping = (thunk) => Effect.try({
8
+ try: thunk,
9
+ catch: (cause) => PersistenceMappingError.make({
10
+ operation: "mapping",
11
+ cause
12
+ })
13
+ });
14
+ /** Prefixes are short ASCII identifiers so ordinal aliases cannot be truncated
15
+ * by PostgreSQL. Callers distinguish tables by prefix, never by physical names. */
16
+ const nativeSqlAlias = (prefix, index) => {
17
+ if (!/^[A-Za-z_][A-Za-z0-9_]{0,39}$/.test(prefix)) throw PersistenceMappingError.make({
18
+ operation: "mapping",
19
+ cause: "Invalid SQL alias prefix"
20
+ });
21
+ return `${prefix}${index}`;
22
+ };
23
+ const directTable = (client, physical) => {
24
+ if (!(physical instanceof Table)) throw PersistenceMappingError.make({
25
+ operation: "mapping",
26
+ cause: "Expected a SQL table"
27
+ });
28
+ const quote = (name) => {
29
+ if (name.includes("\0")) throw PersistenceMappingError.make({
30
+ operation: "mapping",
31
+ cause: "NUL in SQL identifier"
32
+ });
33
+ return client.literal(identifier(name));
34
+ };
35
+ const name = physical.schema === void 0 ? quote(physical.name) : client`${quote(physical.schema)}.${quote(physical.name)}`;
36
+ const columns = Object.entries(physical.columns);
37
+ const getColumn = (key) => {
38
+ const column = Object.hasOwn(physical.columns, key) ? physical.columns[key] : void 0;
39
+ if (column === void 0) throw PersistenceMappingError.make({
40
+ operation: "column",
41
+ cause: "Missing SQL column"
42
+ });
43
+ return column;
44
+ };
45
+ const value = (key, input) => {
46
+ const mapped = getColumn(key);
47
+ if (Statement$1.isFragment(input)) return input;
48
+ const encoded = input === null ? null : mapped.mapToDriverValue(input);
49
+ return Statement$1.fragment([Statement$1.parameter(typeof encoded === "boolean" ? client.onDialectOrElse({
50
+ sqlite: () => Number(encoded),
51
+ orElse: () => encoded
52
+ }) : encoded)]);
53
+ };
54
+ const entries = (values) => Object.entries(values).filter(([key, input]) => Object.hasOwn(physical.columns, key) && input !== void 0);
55
+ const bind = (alias) => {
56
+ const reference = alias === void 0 ? name : quote(alias);
57
+ const column = (key) => client`${reference}.${quote(getColumn(key).options.name)}`;
58
+ return {
59
+ name: alias === void 0 ? name : client`${name} AS ${reference}`,
60
+ as: bind,
61
+ column,
62
+ value,
63
+ fields: (prefix) => client.join(", ", false)(columns.map(([key], index) => client`${column(key)} AS ${quote(nativeSqlAlias(prefix, index))}`)),
64
+ decode: (row, prefix) => Object.fromEntries(columns.map(([key, field], index) => {
65
+ const alias = nativeSqlAlias(prefix, index);
66
+ if (!Object.hasOwn(row, alias)) throw PersistenceMappingError.make({
67
+ operation: "decode",
68
+ cause: "Missing SQL projection field"
69
+ });
70
+ return [key, field.decode(row[alias])];
71
+ })),
72
+ insert: (values) => {
73
+ const fields = entries(values);
74
+ if (fields.length === 0) return client`INSERT INTO ${name} DEFAULT VALUES`;
75
+ return client`INSERT INTO ${name} (${client.join(", ", false)(fields.map(([key]) => quote(getColumn(key).options.name)))}) VALUES (${client.join(", ", false)(fields.map(([key, input]) => value(key, input)))})`;
76
+ },
77
+ update: (values) => {
78
+ const fields = entries(values);
79
+ if (fields.length === 0) throw PersistenceMappingError.make({
80
+ operation: "mapping",
81
+ cause: "Empty SQL update"
82
+ });
83
+ return client`UPDATE ${name} SET ${client.join(", ", false)(fields.map(([key, input]) => client`${quote(getColumn(key).options.name)} = ${value(key, input)}`))}`;
84
+ }
85
+ };
86
+ };
87
+ return bind();
88
+ };
89
+ /** Cache physical metadata only; insert/update materialize values and hooks at
90
+ * each call. Construction acquires no client and owns no transaction. */
91
+ const makeNativeSqlTables = (client, convert = directTable) => {
92
+ const tables = /* @__PURE__ */ new WeakMap();
93
+ return (table) => {
94
+ const existing = tables.get(table);
95
+ if (existing !== void 0) return existing;
96
+ const mapped = convert(client, table);
97
+ tables.set(table, mapped);
98
+ return mapped;
99
+ };
100
+ };
101
+ //#endregion
102
+ export { makeNativeSqlTables, nativeSqlAlias, sqlMapping };
103
+
104
+ //# sourceMappingURL=native-sql-table.mjs.map