@effect-auth/core 0.1.0-alpha.16 → 0.1.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +308 -133
- package/dist/AbuseProtection.d.ts +100 -0
- package/dist/AbuseProtection.d.ts.map +1 -0
- package/dist/AbuseProtection.js +71 -0
- package/dist/AbuseProtection.js.map +1 -0
- package/dist/AccessGrant.d.ts +344 -0
- package/dist/AccessGrant.d.ts.map +1 -0
- package/dist/AccessGrant.js +687 -0
- package/dist/AccessGrant.js.map +1 -0
- package/dist/ApiKey.d.ts +0 -12
- package/dist/ApiKey.d.ts.map +1 -1
- package/dist/ApiKey.js +36 -27
- package/dist/ApiKey.js.map +1 -1
- package/dist/Assurance.d.ts +415 -0
- package/dist/Assurance.d.ts.map +1 -0
- package/dist/Assurance.js +764 -0
- package/dist/Assurance.js.map +1 -0
- package/dist/AtomicPlanExecutor.d.ts +28 -0
- package/dist/AtomicPlanExecutor.d.ts.map +1 -0
- package/dist/AtomicPlanExecutor.js +5 -0
- package/dist/AtomicPlanExecutor.js.map +1 -0
- package/dist/AuditLog.d.ts +2314 -52
- package/dist/AuditLog.d.ts.map +1 -1
- package/dist/AuditLog.js +511 -33
- package/dist/AuditLog.js.map +1 -1
- package/dist/AuthFlow.d.ts +128 -38
- package/dist/AuthFlow.d.ts.map +1 -1
- package/dist/AuthFlow.js +611 -263
- package/dist/AuthFlow.js.map +1 -1
- package/dist/AuthRateLimit.d.ts +96 -0
- package/dist/AuthRateLimit.d.ts.map +1 -0
- package/dist/AuthRateLimit.js +212 -0
- package/dist/AuthRateLimit.js.map +1 -0
- package/dist/Challenge.d.ts +0 -3
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +1 -4
- package/dist/Challenge.js.map +1 -1
- package/dist/Client.d.ts +205 -10
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +397 -16
- package/dist/Client.js.map +1 -1
- package/dist/CloudflareTurnstile.d.ts +28 -0
- package/dist/CloudflareTurnstile.d.ts.map +1 -0
- package/dist/CloudflareTurnstile.js +205 -0
- package/dist/CloudflareTurnstile.js.map +1 -0
- package/dist/Crypto.d.ts +0 -3
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +1 -4
- package/dist/Crypto.js.map +1 -1
- package/dist/DelegatedAccessStorageMigrations.d.ts +7 -0
- package/dist/DelegatedAccessStorageMigrations.d.ts.map +1 -0
- package/dist/DelegatedAccessStorageMigrations.js +159 -0
- package/dist/DelegatedAccessStorageMigrations.js.map +1 -0
- package/dist/DisposableEmailDomains.d.ts +19 -0
- package/dist/DisposableEmailDomains.d.ts.map +1 -0
- package/dist/DisposableEmailDomains.js +85 -0
- package/dist/DisposableEmailDomains.js.map +1 -0
- package/dist/DomainVerification.d.ts +0 -9
- package/dist/DomainVerification.d.ts.map +1 -1
- package/dist/DomainVerification.js +36 -22
- package/dist/DomainVerification.js.map +1 -1
- package/dist/DrizzleBunSqliteStorage.d.ts +18 -0
- package/dist/DrizzleBunSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleBunSqliteStorage.js +11 -0
- package/dist/DrizzleBunSqliteStorage.js.map +1 -0
- package/dist/DrizzleD1SqliteStorage.d.ts +4 -4
- package/dist/DrizzleD1SqliteStorage.d.ts.map +1 -1
- package/dist/DrizzleD1SqliteStorage.js +5 -5
- package/dist/DrizzleD1SqliteStorage.js.map +1 -1
- package/dist/DrizzleDurableObjectSqliteStorage.d.ts +19 -0
- package/dist/DrizzleDurableObjectSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleDurableObjectSqliteStorage.js +14 -0
- package/dist/DrizzleDurableObjectSqliteStorage.js.map +1 -0
- package/dist/DrizzleEffectSqliteStorage.d.ts +13 -4
- package/dist/DrizzleEffectSqliteStorage.d.ts.map +1 -1
- package/dist/DrizzleEffectSqliteStorage.js +71 -4
- package/dist/DrizzleEffectSqliteStorage.js.map +1 -1
- package/dist/DrizzleNodeSqliteStorage.d.ts +18 -0
- package/dist/DrizzleNodeSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleNodeSqliteStorage.js +11 -0
- package/dist/DrizzleNodeSqliteStorage.js.map +1 -0
- package/dist/DrizzleWasmSqliteStorage.d.ts +23 -0
- package/dist/DrizzleWasmSqliteStorage.d.ts.map +1 -0
- package/dist/DrizzleWasmSqliteStorage.js +15 -0
- package/dist/DrizzleWasmSqliteStorage.js.map +1 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.d.ts +34 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.d.ts.map +1 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.js +499 -0
- package/dist/EffectQbPostgresDelegatedAccessStorage.js.map +1 -0
- package/dist/EffectQbPostgresStorage.d.ts +171 -0
- package/dist/EffectQbPostgresStorage.d.ts.map +1 -0
- package/dist/EffectQbPostgresStorage.js +4280 -0
- package/dist/EffectQbPostgresStorage.js.map +1 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.d.ts +112 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.d.ts.map +1 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.js +602 -0
- package/dist/EffectQbSqliteDelegatedAccessStorage.js.map +1 -0
- package/dist/EffectQbSqliteStorage.d.ts +181 -23
- package/dist/EffectQbSqliteStorage.d.ts.map +1 -1
- package/dist/EffectQbSqliteStorage.js +1728 -135
- package/dist/EffectQbSqliteStorage.js.map +1 -1
- package/dist/EmailAuth.d.ts +65 -0
- package/dist/EmailAuth.d.ts.map +1 -0
- package/dist/EmailAuth.js +171 -0
- package/dist/EmailAuth.js.map +1 -0
- package/dist/EmailIdentityAuth.d.ts +30 -0
- package/dist/EmailIdentityAuth.d.ts.map +1 -0
- package/dist/EmailIdentityAuth.js +142 -0
- package/dist/EmailIdentityAuth.js.map +1 -0
- package/dist/EmailOtp.d.ts +10 -11
- package/dist/EmailOtp.d.ts.map +1 -1
- package/dist/EmailOtp.js +44 -81
- package/dist/EmailOtp.js.map +1 -1
- package/dist/EmailRisk.d.ts +48 -0
- package/dist/EmailRisk.d.ts.map +1 -0
- package/dist/EmailRisk.js +33 -0
- package/dist/EmailRisk.js.map +1 -0
- package/dist/EmailVerification.d.ts +10 -16
- package/dist/EmailVerification.d.ts.map +1 -1
- package/dist/EmailVerification.js +85 -42
- package/dist/EmailVerification.js.map +1 -1
- package/dist/Guard.d.ts +11 -0
- package/dist/Guard.d.ts.map +1 -0
- package/dist/Guard.js +11 -0
- package/dist/Guard.js.map +1 -0
- package/dist/HibpPwnedPasswords.d.ts +56 -0
- package/dist/HibpPwnedPasswords.d.ts.map +1 -0
- package/dist/HibpPwnedPasswords.js +232 -0
- package/dist/HibpPwnedPasswords.js.map +1 -0
- package/dist/HttpApi/AdminPermissionDefinition.d.ts +4 -0
- package/dist/HttpApi/AdminPermissionDefinition.d.ts.map +1 -0
- package/dist/HttpApi/AdminPermissionDefinition.js +4 -0
- package/dist/HttpApi/AdminPermissionDefinition.js.map +1 -0
- package/dist/HttpApi/AdminSecurityTimeline.d.ts +4 -0
- package/dist/HttpApi/AdminSecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/AdminSecurityTimeline.js +4 -0
- package/dist/HttpApi/AdminSecurityTimeline.js.map +1 -0
- package/dist/HttpApi/AdminSession.d.ts +4 -0
- package/dist/HttpApi/AdminSession.d.ts.map +1 -0
- package/dist/HttpApi/AdminSession.js +4 -0
- package/dist/HttpApi/AdminSession.js.map +1 -0
- package/dist/HttpApi/AdminTrustedDevice.d.ts +4 -0
- package/dist/HttpApi/AdminTrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/AdminTrustedDevice.js +4 -0
- package/dist/HttpApi/AdminTrustedDevice.js.map +1 -0
- package/dist/HttpApi/Api.d.ts +879 -877
- package/dist/HttpApi/Api.d.ts.map +1 -1
- package/dist/HttpApi/Api.js +2160 -896
- package/dist/HttpApi/Api.js.map +1 -1
- package/dist/HttpApi/ApiKey.d.ts +4 -0
- package/dist/HttpApi/ApiKey.d.ts.map +1 -0
- package/dist/HttpApi/ApiKey.js +4 -0
- package/dist/HttpApi/ApiKey.js.map +1 -0
- package/dist/HttpApi/Audit.d.ts +6 -0
- package/dist/HttpApi/Audit.d.ts.map +1 -0
- package/dist/HttpApi/Audit.js +10 -0
- package/dist/HttpApi/Audit.js.map +1 -0
- package/dist/HttpApi/ClientApi.d.ts +917 -0
- package/dist/HttpApi/ClientApi.d.ts.map +1 -0
- package/dist/HttpApi/ClientApi.js +101 -0
- package/dist/HttpApi/ClientApi.js.map +1 -0
- package/dist/HttpApi/EmailAuth.d.ts +6 -0
- package/dist/HttpApi/EmailAuth.d.ts.map +1 -0
- package/dist/HttpApi/EmailAuth.js +6 -0
- package/dist/HttpApi/EmailAuth.js.map +1 -0
- package/dist/HttpApi/EmailGuards.d.ts +115 -0
- package/dist/HttpApi/EmailGuards.d.ts.map +1 -0
- package/dist/HttpApi/EmailGuards.js +191 -0
- package/dist/HttpApi/EmailGuards.js.map +1 -0
- package/dist/HttpApi/EmailOtp.d.ts +6 -0
- package/dist/HttpApi/EmailOtp.d.ts.map +1 -0
- package/dist/HttpApi/EmailOtp.js +6 -0
- package/dist/HttpApi/EmailOtp.js.map +1 -0
- package/dist/HttpApi/EmailVerification.d.ts +6 -0
- package/dist/HttpApi/EmailVerification.d.ts.map +1 -0
- package/dist/HttpApi/EmailVerification.js +6 -0
- package/dist/HttpApi/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Endpoints.d.ts +629 -301
- package/dist/HttpApi/Endpoints.d.ts.map +1 -1
- package/dist/HttpApi/Endpoints.js +178 -120
- package/dist/HttpApi/Endpoints.js.map +1 -1
- package/dist/HttpApi/Errors.d.ts +26 -7
- package/dist/HttpApi/Errors.d.ts.map +1 -1
- package/dist/HttpApi/Errors.js +26 -4
- package/dist/HttpApi/Errors.js.map +1 -1
- package/dist/HttpApi/Identity.d.ts +6 -0
- package/dist/HttpApi/Identity.d.ts.map +1 -0
- package/dist/HttpApi/Identity.js +6 -0
- package/dist/HttpApi/Identity.js.map +1 -0
- package/dist/HttpApi/IdentityGuards.d.ts +31 -0
- package/dist/HttpApi/IdentityGuards.d.ts.map +1 -0
- package/dist/HttpApi/IdentityGuards.js +33 -0
- package/dist/HttpApi/IdentityGuards.js.map +1 -0
- package/dist/HttpApi/Jwt.d.ts +4 -0
- package/dist/HttpApi/Jwt.d.ts.map +1 -0
- package/dist/HttpApi/Jwt.js +4 -0
- package/dist/HttpApi/Jwt.js.map +1 -0
- package/dist/HttpApi/JwtDiscovery.d.ts +4 -0
- package/dist/HttpApi/JwtDiscovery.d.ts.map +1 -0
- package/dist/HttpApi/JwtDiscovery.js +4 -0
- package/dist/HttpApi/JwtDiscovery.js.map +1 -0
- package/dist/HttpApi/LoginApproval.d.ts +5 -0
- package/dist/HttpApi/LoginApproval.d.ts.map +1 -0
- package/dist/HttpApi/LoginApproval.js +5 -0
- package/dist/HttpApi/LoginApproval.js.map +1 -0
- package/dist/HttpApi/LoginNotification.d.ts +5 -0
- package/dist/HttpApi/LoginNotification.d.ts.map +1 -0
- package/dist/HttpApi/LoginNotification.js +5 -0
- package/dist/HttpApi/LoginNotification.js.map +1 -0
- package/dist/HttpApi/MagicLink.d.ts +6 -0
- package/dist/HttpApi/MagicLink.d.ts.map +1 -0
- package/dist/HttpApi/MagicLink.js +6 -0
- package/dist/HttpApi/MagicLink.js.map +1 -0
- package/dist/HttpApi/Mfa.d.ts +5 -0
- package/dist/HttpApi/Mfa.d.ts.map +1 -0
- package/dist/HttpApi/Mfa.js +5 -0
- package/dist/HttpApi/Mfa.js.map +1 -0
- package/dist/HttpApi/Middleware.d.ts +14 -0
- package/dist/HttpApi/Middleware.d.ts.map +1 -0
- package/dist/HttpApi/Middleware.js +5 -0
- package/dist/HttpApi/Middleware.js.map +1 -0
- package/dist/HttpApi/OAuth.d.ts +4 -0
- package/dist/HttpApi/OAuth.d.ts.map +1 -0
- package/dist/HttpApi/OAuth.js +4 -0
- package/dist/HttpApi/OAuth.js.map +1 -0
- package/dist/HttpApi/OAuthProviderAuthorization.d.ts +4 -0
- package/dist/HttpApi/OAuthProviderAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/OAuthProviderAuthorization.js +4 -0
- package/dist/HttpApi/OAuthProviderAuthorization.js.map +1 -0
- package/dist/HttpApi/OAuthToken.d.ts +4 -0
- package/dist/HttpApi/OAuthToken.d.ts.map +1 -0
- package/dist/HttpApi/OAuthToken.js +4 -0
- package/dist/HttpApi/OAuthToken.js.map +1 -0
- package/dist/HttpApi/OidcDiscovery.d.ts +4 -0
- package/dist/HttpApi/OidcDiscovery.d.ts.map +1 -0
- package/dist/HttpApi/OidcDiscovery.js +4 -0
- package/dist/HttpApi/OidcDiscovery.js.map +1 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.d.ts +28 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.d.ts.map +1 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.js +5 -0
- package/dist/HttpApi/Operations/AdminPermissionDefinition.js.map +1 -0
- package/dist/HttpApi/Operations/AdminSession.d.ts +16 -0
- package/dist/HttpApi/Operations/AdminSession.d.ts.map +1 -0
- package/dist/HttpApi/Operations/AdminSession.js +5 -0
- package/dist/HttpApi/Operations/AdminSession.js.map +1 -0
- package/dist/HttpApi/Operations/ApiKey.d.ts +16 -0
- package/dist/HttpApi/Operations/ApiKey.d.ts.map +1 -0
- package/dist/HttpApi/Operations/ApiKey.js +5 -0
- package/dist/HttpApi/Operations/ApiKey.js.map +1 -0
- package/dist/HttpApi/Operations/Discovery.d.ts +19 -0
- package/dist/HttpApi/Operations/Discovery.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Discovery.js +7 -0
- package/dist/HttpApi/Operations/Discovery.js.map +1 -0
- package/dist/HttpApi/Operations/EmailAuth.d.ts +12 -0
- package/dist/HttpApi/Operations/EmailAuth.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailAuth.js +5 -0
- package/dist/HttpApi/Operations/EmailAuth.js.map +1 -0
- package/dist/HttpApi/Operations/EmailOtp.d.ts +14 -0
- package/dist/HttpApi/Operations/EmailOtp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailOtp.js +5 -0
- package/dist/HttpApi/Operations/EmailOtp.js.map +1 -0
- package/dist/HttpApi/Operations/EmailVerification.d.ts +14 -0
- package/dist/HttpApi/Operations/EmailVerification.d.ts.map +1 -0
- package/dist/HttpApi/Operations/EmailVerification.js +5 -0
- package/dist/HttpApi/Operations/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Operations/HttpOperation.d.ts +4 -0
- package/dist/HttpApi/Operations/HttpOperation.d.ts.map +1 -0
- package/dist/HttpApi/Operations/HttpOperation.js +2 -0
- package/dist/HttpApi/Operations/HttpOperation.js.map +1 -0
- package/dist/HttpApi/Operations/Identity.d.ts +22 -0
- package/dist/HttpApi/Operations/Identity.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Identity.js +5 -0
- package/dist/HttpApi/Operations/Identity.js.map +1 -0
- package/dist/HttpApi/Operations/Jwt.d.ts +14 -0
- package/dist/HttpApi/Operations/Jwt.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Jwt.js +5 -0
- package/dist/HttpApi/Operations/Jwt.js.map +1 -0
- package/dist/HttpApi/Operations/LoginApproval.d.ts +16 -0
- package/dist/HttpApi/Operations/LoginApproval.d.ts.map +1 -0
- package/dist/HttpApi/Operations/LoginApproval.js +5 -0
- package/dist/HttpApi/Operations/LoginApproval.js.map +1 -0
- package/dist/HttpApi/Operations/MagicLink.d.ts +14 -0
- package/dist/HttpApi/Operations/MagicLink.d.ts.map +1 -0
- package/dist/HttpApi/Operations/MagicLink.js +5 -0
- package/dist/HttpApi/Operations/MagicLink.js.map +1 -0
- package/dist/HttpApi/Operations/Mfa.d.ts +24 -0
- package/dist/HttpApi/Operations/Mfa.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Mfa.js +5 -0
- package/dist/HttpApi/Operations/Mfa.js.map +1 -0
- package/dist/HttpApi/Operations/OAuth.d.ts +20 -0
- package/dist/HttpApi/Operations/OAuth.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuth.js +5 -0
- package/dist/HttpApi/Operations/OAuth.js.map +1 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.d.ts +12 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.js +5 -0
- package/dist/HttpApi/Operations/OAuthProviderAuthorization.js.map +1 -0
- package/dist/HttpApi/Operations/OAuthToken.d.ts +16 -0
- package/dist/HttpApi/Operations/OAuthToken.d.ts.map +1 -0
- package/dist/HttpApi/Operations/OAuthToken.js +5 -0
- package/dist/HttpApi/Operations/OAuthToken.js.map +1 -0
- package/dist/HttpApi/Operations/Passkey.d.ts +22 -0
- package/dist/HttpApi/Operations/Passkey.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Passkey.js +5 -0
- package/dist/HttpApi/Operations/Passkey.js.map +1 -0
- package/dist/HttpApi/Operations/Password.d.ts +22 -0
- package/dist/HttpApi/Operations/Password.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Password.js +5 -0
- package/dist/HttpApi/Operations/Password.js.map +1 -0
- package/dist/HttpApi/Operations/RecoveryCodes.d.ts +20 -0
- package/dist/HttpApi/Operations/RecoveryCodes.d.ts.map +1 -0
- package/dist/HttpApi/Operations/RecoveryCodes.js +5 -0
- package/dist/HttpApi/Operations/RecoveryCodes.js.map +1 -0
- package/dist/HttpApi/Operations/RefreshToken.d.ts +12 -0
- package/dist/HttpApi/Operations/RefreshToken.d.ts.map +1 -0
- package/dist/HttpApi/Operations/RefreshToken.js +5 -0
- package/dist/HttpApi/Operations/RefreshToken.js.map +1 -0
- package/dist/HttpApi/Operations/Security.d.ts +12 -0
- package/dist/HttpApi/Operations/Security.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Security.js +5 -0
- package/dist/HttpApi/Operations/Security.js.map +1 -0
- package/dist/HttpApi/Operations/SecurityTimeline.d.ts +19 -0
- package/dist/HttpApi/Operations/SecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/Operations/SecurityTimeline.js +7 -0
- package/dist/HttpApi/Operations/SecurityTimeline.js.map +1 -0
- package/dist/HttpApi/Operations/Session.d.ts +22 -0
- package/dist/HttpApi/Operations/Session.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Session.js +5 -0
- package/dist/HttpApi/Operations/Session.js.map +1 -0
- package/dist/HttpApi/Operations/StepUp.d.ts +22 -0
- package/dist/HttpApi/Operations/StepUp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/StepUp.js +5 -0
- package/dist/HttpApi/Operations/StepUp.js.map +1 -0
- package/dist/HttpApi/Operations/Totp.d.ts +20 -0
- package/dist/HttpApi/Operations/Totp.d.ts.map +1 -0
- package/dist/HttpApi/Operations/Totp.js +5 -0
- package/dist/HttpApi/Operations/Totp.js.map +1 -0
- package/dist/HttpApi/Operations/TrustedDevice.d.ts +23 -0
- package/dist/HttpApi/Operations/TrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/Operations/TrustedDevice.js +7 -0
- package/dist/HttpApi/Operations/TrustedDevice.js.map +1 -0
- package/dist/HttpApi/Operations/index.d.ts +27 -0
- package/dist/HttpApi/Operations/index.d.ts.map +1 -0
- package/dist/HttpApi/Operations/index.js +27 -0
- package/dist/HttpApi/Operations/index.js.map +1 -0
- package/dist/HttpApi/Passkey.d.ts +5 -0
- package/dist/HttpApi/Passkey.d.ts.map +1 -0
- package/dist/HttpApi/Passkey.js +5 -0
- package/dist/HttpApi/Passkey.js.map +1 -0
- package/dist/HttpApi/Password.d.ts +220 -0
- package/dist/HttpApi/Password.d.ts.map +1 -0
- package/dist/HttpApi/Password.js +237 -0
- package/dist/HttpApi/Password.js.map +1 -0
- package/dist/HttpApi/PasswordContract.d.ts +307 -0
- package/dist/HttpApi/PasswordContract.d.ts.map +1 -0
- package/dist/HttpApi/PasswordContract.js +63 -0
- package/dist/HttpApi/PasswordContract.js.map +1 -0
- package/dist/HttpApi/PasswordGuards.d.ts +82 -0
- package/dist/HttpApi/PasswordGuards.d.ts.map +1 -0
- package/dist/HttpApi/PasswordGuards.js +179 -0
- package/dist/HttpApi/PasswordGuards.js.map +1 -0
- package/dist/HttpApi/RecoveryCodes.d.ts +5 -0
- package/dist/HttpApi/RecoveryCodes.d.ts.map +1 -0
- package/dist/HttpApi/RecoveryCodes.js +5 -0
- package/dist/HttpApi/RecoveryCodes.js.map +1 -0
- package/dist/HttpApi/RefreshToken.d.ts +4 -0
- package/dist/HttpApi/RefreshToken.d.ts.map +1 -0
- package/dist/HttpApi/RefreshToken.js +4 -0
- package/dist/HttpApi/RefreshToken.js.map +1 -0
- package/dist/HttpApi/RequestGuards.d.ts +42 -0
- package/dist/HttpApi/RequestGuards.d.ts.map +1 -0
- package/dist/HttpApi/RequestGuards.js +194 -0
- package/dist/HttpApi/RequestGuards.js.map +1 -0
- package/dist/HttpApi/Schemas.d.ts +361 -84
- package/dist/HttpApi/Schemas.d.ts.map +1 -1
- package/dist/HttpApi/Schemas.js +190 -27
- package/dist/HttpApi/Schemas.js.map +1 -1
- package/dist/HttpApi/Security.d.ts +12 -93
- package/dist/HttpApi/Security.d.ts.map +1 -1
- package/dist/HttpApi/Security.js +65 -356
- package/dist/HttpApi/Security.js.map +1 -1
- package/dist/HttpApi/SecurityTimeline.d.ts +4 -0
- package/dist/HttpApi/SecurityTimeline.d.ts.map +1 -0
- package/dist/HttpApi/SecurityTimeline.js +4 -0
- package/dist/HttpApi/SecurityTimeline.js.map +1 -0
- package/dist/HttpApi/Session.d.ts +5 -0
- package/dist/HttpApi/Session.d.ts.map +1 -0
- package/dist/HttpApi/Session.js +5 -0
- package/dist/HttpApi/Session.js.map +1 -0
- package/dist/HttpApi/SessionGuards.d.ts +15 -0
- package/dist/HttpApi/SessionGuards.d.ts.map +1 -0
- package/dist/HttpApi/SessionGuards.js +37 -0
- package/dist/HttpApi/SessionGuards.js.map +1 -0
- package/dist/HttpApi/StepUp.d.ts +5 -0
- package/dist/HttpApi/StepUp.d.ts.map +1 -0
- package/dist/HttpApi/StepUp.js +5 -0
- package/dist/HttpApi/StepUp.js.map +1 -0
- package/dist/HttpApi/Totp.d.ts +5 -0
- package/dist/HttpApi/Totp.d.ts.map +1 -0
- package/dist/HttpApi/Totp.js +5 -0
- package/dist/HttpApi/Totp.js.map +1 -0
- package/dist/HttpApi/Transport.d.ts +4 -6
- package/dist/HttpApi/Transport.d.ts.map +1 -1
- package/dist/HttpApi/Transport.js +62 -36
- package/dist/HttpApi/Transport.js.map +1 -1
- package/dist/HttpApi/TrustedDevice.d.ts +4 -0
- package/dist/HttpApi/TrustedDevice.d.ts.map +1 -0
- package/dist/HttpApi/TrustedDevice.js +4 -0
- package/dist/HttpApi/TrustedDevice.js.map +1 -0
- package/dist/HttpApi/index.d.ts +9 -3
- package/dist/HttpApi/index.d.ts.map +1 -1
- package/dist/HttpApi/index.js +8 -2
- package/dist/HttpApi/index.js.map +1 -1
- package/dist/Identity.d.ts +138 -0
- package/dist/Identity.d.ts.map +1 -0
- package/dist/Identity.js +105 -0
- package/dist/Identity.js.map +1 -0
- package/dist/IdentityManagement.d.ts +189 -0
- package/dist/IdentityManagement.d.ts.map +1 -0
- package/dist/IdentityManagement.js +317 -0
- package/dist/IdentityManagement.js.map +1 -0
- package/dist/IncidentAction.d.ts +1 -4
- package/dist/IncidentAction.d.ts.map +1 -1
- package/dist/IncidentAction.js +15 -9
- package/dist/IncidentAction.js.map +1 -1
- package/dist/Internal.d.ts +2 -0
- package/dist/Internal.d.ts.map +1 -1
- package/dist/Internal.js +30 -0
- package/dist/Internal.js.map +1 -1
- package/dist/Invitation.d.ts +362 -0
- package/dist/Invitation.d.ts.map +1 -0
- package/dist/Invitation.js +633 -0
- package/dist/Invitation.js.map +1 -0
- package/dist/IpQualityScore.d.ts +38 -0
- package/dist/IpQualityScore.d.ts.map +1 -0
- package/dist/IpQualityScore.js +215 -0
- package/dist/IpQualityScore.js.map +1 -0
- package/dist/Jwt.d.ts +8 -29
- package/dist/Jwt.d.ts.map +1 -1
- package/dist/Jwt.js +67 -56
- package/dist/Jwt.js.map +1 -1
- package/dist/LoginApproval.d.ts +15 -30
- package/dist/LoginApproval.d.ts.map +1 -1
- package/dist/LoginApproval.js +47 -41
- package/dist/LoginApproval.js.map +1 -1
- package/dist/LoginNotification.d.ts +7 -11
- package/dist/LoginNotification.d.ts.map +1 -1
- package/dist/LoginNotification.js +30 -17
- package/dist/LoginNotification.js.map +1 -1
- package/dist/LoginRisk.d.ts +11 -13
- package/dist/LoginRisk.d.ts.map +1 -1
- package/dist/LoginRisk.js +66 -26
- package/dist/LoginRisk.js.map +1 -1
- package/dist/LoginRiskEnrichment.d.ts +145 -0
- package/dist/LoginRiskEnrichment.d.ts.map +1 -0
- package/dist/LoginRiskEnrichment.js +220 -0
- package/dist/LoginRiskEnrichment.js.map +1 -0
- package/dist/MagicLink.d.ts +9 -8
- package/dist/MagicLink.d.ts.map +1 -1
- package/dist/MagicLink.js +40 -73
- package/dist/MagicLink.js.map +1 -1
- package/dist/Mailer.d.ts +19 -12
- package/dist/Mailer.d.ts.map +1 -1
- package/dist/Mailer.js +10 -12
- package/dist/Mailer.js.map +1 -1
- package/dist/OAuth.d.ts +93 -96
- package/dist/OAuth.d.ts.map +1 -1
- package/dist/OAuth.js +404 -217
- package/dist/OAuth.js.map +1 -1
- package/dist/Passkey.d.ts +15 -17
- package/dist/Passkey.d.ts.map +1 -1
- package/dist/Passkey.js +86 -39
- package/dist/Passkey.js.map +1 -1
- package/dist/PasskeyBrowser.d.ts +39 -0
- package/dist/PasskeyBrowser.d.ts.map +1 -0
- package/dist/PasskeyBrowser.js +206 -0
- package/dist/PasskeyBrowser.js.map +1 -0
- package/dist/PasskeySimpleWebAuthn.d.ts.map +1 -1
- package/dist/PasskeySimpleWebAuthn.js +19 -7
- package/dist/PasskeySimpleWebAuthn.js.map +1 -1
- package/dist/Password.d.ts +71 -37
- package/dist/Password.d.ts.map +1 -1
- package/dist/Password.js +295 -81
- package/dist/Password.js.map +1 -1
- package/dist/PasswordRisk.d.ts +63 -0
- package/dist/PasswordRisk.d.ts.map +1 -0
- package/dist/PasswordRisk.js +37 -0
- package/dist/PasswordRisk.js.map +1 -0
- package/dist/Permission.d.ts +308 -0
- package/dist/Permission.d.ts.map +1 -0
- package/dist/Permission.js +827 -0
- package/dist/Permission.js.map +1 -0
- package/dist/Policy.d.ts +31 -18
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js +58 -14
- package/dist/Policy.js.map +1 -1
- package/dist/PostgresDelegatedAccessStorageMigrations.d.ts +7 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.d.ts.map +1 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.js +119 -0
- package/dist/PostgresDelegatedAccessStorageMigrations.js.map +1 -0
- package/dist/PostgresStorageMigrations.d.ts +15 -0
- package/dist/PostgresStorageMigrations.d.ts.map +1 -0
- package/dist/PostgresStorageMigrations.js +620 -0
- package/dist/PostgresStorageMigrations.js.map +1 -0
- package/dist/Privacy.d.ts +0 -3
- package/dist/Privacy.d.ts.map +1 -1
- package/dist/Privacy.js +2 -5
- package/dist/Privacy.js.map +1 -1
- package/dist/RateLimiter.d.ts +0 -3
- package/dist/RateLimiter.d.ts.map +1 -1
- package/dist/RateLimiter.js +1 -4
- package/dist/RateLimiter.js.map +1 -1
- package/dist/RecoveryCode.d.ts +83 -11
- package/dist/RecoveryCode.d.ts.map +1 -1
- package/dist/RecoveryCode.js +273 -75
- package/dist/RecoveryCode.js.map +1 -1
- package/dist/RecoveryPolicy.d.ts +81 -0
- package/dist/RecoveryPolicy.d.ts.map +1 -0
- package/dist/RecoveryPolicy.js +119 -0
- package/dist/RecoveryPolicy.js.map +1 -0
- package/dist/RefreshToken.d.ts +0 -9
- package/dist/RefreshToken.d.ts.map +1 -1
- package/dist/RefreshToken.js +31 -22
- package/dist/RefreshToken.js.map +1 -1
- package/dist/SecurityTimeline.d.ts +1 -4
- package/dist/SecurityTimeline.d.ts.map +1 -1
- package/dist/SecurityTimeline.js +110 -17
- package/dist/SecurityTimeline.js.map +1 -1
- package/dist/Sessions.d.ts +124 -29
- package/dist/Sessions.d.ts.map +1 -1
- package/dist/Sessions.js +626 -94
- package/dist/Sessions.js.map +1 -1
- package/dist/StepUp.d.ts +132 -11
- package/dist/StepUp.d.ts.map +1 -1
- package/dist/StepUp.js +387 -19
- package/dist/StepUp.js.map +1 -1
- package/dist/Storage.d.ts +89 -23
- package/dist/Storage.d.ts.map +1 -1
- package/dist/Storage.js +10 -12
- package/dist/Storage.js.map +1 -1
- package/dist/StorageMigrations.d.ts +6 -1
- package/dist/StorageMigrations.d.ts.map +1 -1
- package/dist/StorageMigrations.js +224 -0
- package/dist/StorageMigrations.js.map +1 -1
- package/dist/StorageSchemaGenerator.d.ts +486 -0
- package/dist/StorageSchemaGenerator.d.ts.map +1 -0
- package/dist/StorageSchemaGenerator.js +1022 -0
- package/dist/StorageSchemaGenerator.js.map +1 -0
- package/dist/StrongFactor.d.ts +64 -0
- package/dist/StrongFactor.d.ts.map +1 -0
- package/dist/StrongFactor.js +100 -0
- package/dist/StrongFactor.js.map +1 -0
- package/dist/Testing.js +2 -2
- package/dist/Testing.js.map +1 -1
- package/dist/Totp.d.ts +88 -13
- package/dist/Totp.d.ts.map +1 -1
- package/dist/Totp.js +192 -34
- package/dist/Totp.js.map +1 -1
- package/dist/TrustedDevice.d.ts +0 -9
- package/dist/TrustedDevice.d.ts.map +1 -1
- package/dist/TrustedDevice.js +15 -17
- package/dist/TrustedDevice.js.map +1 -1
- package/dist/WaitUntil.d.ts +0 -3
- package/dist/WaitUntil.d.ts.map +1 -1
- package/dist/WaitUntil.js +1 -4
- package/dist/WaitUntil.js.map +1 -1
- package/dist/Webhook.d.ts +42 -12
- package/dist/Webhook.d.ts.map +1 -1
- package/dist/Webhook.js +165 -26
- package/dist/Webhook.js.map +1 -1
- package/dist/alchemy/cloudflare/Email.d.ts.map +1 -1
- package/dist/alchemy/cloudflare/Email.js +9 -4
- package/dist/alchemy/cloudflare/Email.js.map +1 -1
- package/dist/cloudflare/Email.js +1 -1
- package/dist/cloudflare/Email.js.map +1 -1
- package/dist/cloudflare/RequestMetadata.d.ts +49 -0
- package/dist/cloudflare/RequestMetadata.d.ts.map +1 -0
- package/dist/cloudflare/RequestMetadata.js +71 -0
- package/dist/cloudflare/RequestMetadata.js.map +1 -0
- package/dist/index.d.ts +0 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -35
- package/dist/index.js.map +1 -1
- package/dist/internal/AuthFlowFinalizer.d.ts +31 -0
- package/dist/internal/AuthFlowFinalizer.d.ts.map +1 -0
- package/dist/internal/AuthFlowFinalizer.js +182 -0
- package/dist/internal/AuthFlowFinalizer.js.map +1 -0
- package/migrations/0001_auth_storage.sql +1 -0
- package/migrations/0006_auth_totp_factor.sql +1 -0
- package/migrations/0024_auth_permission.sql +39 -0
- package/migrations/0025_auth_permission_definition.sql +19 -0
- package/migrations/0026_auth_user_identity.sql +59 -0
- package/migrations/0027_auth_audit_log_storage_order.sql +46 -0
- package/migrations/0028_auth_oauth_client_secret_key.sql +39 -0
- package/migrations/delegated-access/0001_auth_delegated_access.sql +152 -0
- package/migrations/postgres/0001_auth_core.sql +77 -0
- package/migrations/postgres/0002_auth_security_oauth.sql +65 -0
- package/migrations/postgres/0003_auth_credentials_tokens.sql +43 -0
- package/migrations/postgres/0004_auth_security_history.sql +103 -0
- package/migrations/postgres/0005_auth_webhooks.sql +29 -0
- package/migrations/postgres/0006_auth_domain_timeline.sql +50 -0
- package/migrations/postgres/0007_auth_oauth_clients.sql +85 -0
- package/migrations/postgres/0008_auth_oauth_tokens.sql +63 -0
- package/migrations/postgres/0009_auth_permissions.sql +66 -0
- package/migrations/postgres/delegated-access/0001_auth_delegated_access.sql +112 -0
- package/package.json +301 -2
package/README.md
CHANGED
|
@@ -6,44 +6,72 @@ The current alpha surface is primitive-first: service contracts, small helpers,
|
|
|
6
6
|
|
|
7
7
|
## Public API Surface
|
|
8
8
|
|
|
9
|
-
The root
|
|
9
|
+
The root entry is metadata-only:
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
|
-
import {
|
|
12
|
+
import { packageName } from "@effect-auth/core";
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Import every auth primitive, service, layer, identifier, and integration from its named public subpath:
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
```ts
|
|
18
|
+
import { UserId } from "@effect-auth/core/Identifiers";
|
|
19
|
+
import { PasswordLogin } from "@effect-auth/core/Password";
|
|
20
|
+
import { Sessions } from "@effect-auth/core/Sessions";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Runtime-neutral primitive subpaths are stable alpha API. Examples include `@effect-auth/core/Password`, `@effect-auth/core/Sessions`, `@effect-auth/core/OAuth`, `@effect-auth/core/Jwt`, `@effect-auth/core/ApiKey`, `@effect-auth/core/Storage`, and `@effect-auth/core/RateLimiter`.
|
|
24
|
+
|
|
25
|
+
Utility subpaths are stable alpha APIs:
|
|
26
|
+
|
|
27
|
+
```txt
|
|
28
|
+
@effect-auth/core/StorageMigrations
|
|
29
|
+
```
|
|
18
30
|
|
|
19
31
|
Integration subpaths are public but opt-in. They may expose runtime-specific or transport-specific types and require the app to install their adapter packages when used:
|
|
20
32
|
|
|
21
33
|
```txt
|
|
22
34
|
@effect-auth/core/Client
|
|
23
35
|
@effect-auth/core/HttpApi
|
|
24
|
-
@effect-auth/core/
|
|
25
|
-
@effect-auth/core/RateLimiter
|
|
36
|
+
@effect-auth/core/PasskeyBrowser
|
|
26
37
|
```
|
|
27
38
|
|
|
28
|
-
|
|
39
|
+
Storage and runtime adapter subpaths are public alpha adapters. Their names may still be normalized before beta:
|
|
29
40
|
|
|
30
41
|
```txt
|
|
42
|
+
@effect-auth/core/EffectQbSqliteStorage
|
|
43
|
+
@effect-auth/core/DrizzleEffectSqliteStorage
|
|
44
|
+
@effect-auth/core/DrizzleD1SqliteStorage
|
|
45
|
+
@effect-auth/core/DrizzleBunSqliteStorage
|
|
46
|
+
@effect-auth/core/DrizzleNodeSqliteStorage
|
|
47
|
+
@effect-auth/core/DrizzleDurableObjectSqliteStorage
|
|
48
|
+
@effect-auth/core/DrizzleWasmSqliteStorage
|
|
31
49
|
@effect-auth/core/CloudflareEmail
|
|
50
|
+
@effect-auth/core/CloudflareRequestMetadata
|
|
32
51
|
@effect-auth/core/CloudflareRateLimitDurableObject
|
|
33
52
|
@effect-auth/core/AlchemyCloudflareEmail
|
|
34
53
|
@effect-auth/core/AlchemyCloudflareRateLimitDurableObject
|
|
35
54
|
@effect-auth/core/PasskeySimpleWebAuthn
|
|
55
|
+
@effect-auth/core/StorageSchemaGenerator
|
|
36
56
|
```
|
|
37
57
|
|
|
38
58
|
`@effect-auth/core/Testing` is test/dev-only API. Do not wire it into production applications.
|
|
39
59
|
|
|
40
|
-
SQL migrations are packaged as files for copy/read workflows, but the supported TypeScript
|
|
60
|
+
SQL migrations are packaged as files for copy/read workflows, but the supported TypeScript APIs are `authStorageMigrations` from `@effect-auth/core/StorageMigrations` and `postgresAuthStorageMigrations` from `@effect-auth/core/PostgresStorageMigrations`. Raw SQL files are not importable package subpaths.
|
|
61
|
+
|
|
62
|
+
For fresh PostgreSQL + Drizzle schema planning, `@effect-auth/core/StorageSchemaGenerator` exposes the same deterministic feature resolver used by the public API at `https://effect-auth.itsbroly.com/api/generator/v1`. Tools and AI agents should call `/catalog`, then `POST /generate` for both `migration-sql` and `drizzle-schema`; they should not infer physical tables from store service types. The packaged runtime Drizzle/PostgreSQL adapter is not available yet.
|
|
63
|
+
|
|
64
|
+
Before beta, breaking changes are still allowed when they simplify this API surface. Keep the root metadata-only and add public APIs through explicit subpaths.
|
|
65
|
+
|
|
66
|
+
### Cloudflare Request Metadata
|
|
67
|
+
|
|
68
|
+
`@effect-auth/core/CloudflareRequestMetadata` is an opt-in Worker-boundary adapter for login-risk composition. It uses structural request types and reads geographic facts from Cloudflare's `request.cf`. Client IP is omitted unless `trustCloudflareConnectingIp` is explicitly enabled at a verified Cloudflare boundary. It does not require `@cloudflare/workers-types`, `nodejs_compat`, or an IP database.
|
|
41
69
|
|
|
42
|
-
|
|
70
|
+
Call `readCloudflareRequestMetadata(request)` in Worker-owned code, then pass its coarse `request`, `locationKey`, and safe `metadata` fields into custom risk composition. Missing or malformed preview metadata produces unknown fields rather than an error. Never construct the input from browser JSON or forwarded geographic headers. Persist only the returned `durable` projection; the full result may contain transient IP and city values.
|
|
43
71
|
|
|
44
72
|
## HTTP Client
|
|
45
73
|
|
|
46
|
-
`@effect-auth/core/Client` exposes
|
|
74
|
+
`@effect-auth/core/Client` exposes one browser-friendly client for the standard user-facing auth groups. Applications still choose which groups to mount and which policies to apply on the server. The client accepts plain JSON input types, includes cookies by default, and decodes successful/error responses through Effect Schema.
|
|
47
75
|
|
|
48
76
|
```ts
|
|
49
77
|
import { createAuthClient } from "@effect-auth/core/Client";
|
|
@@ -56,13 +84,100 @@ const result = await authClient.password.signIn({
|
|
|
56
84
|
});
|
|
57
85
|
|
|
58
86
|
const session = await authClient.session.currentOrUndefined();
|
|
87
|
+
|
|
88
|
+
if (authClient.passkey.isSupported()) {
|
|
89
|
+
await authClient.passkey.signIn();
|
|
90
|
+
}
|
|
59
91
|
```
|
|
60
92
|
|
|
93
|
+
`createAuthClient()` also includes combined email auth, passkeys, TOTP, recovery codes, login MFA, and step-up. Its passkey methods complete the standard start/browser/finish sequence. The focused `createPasskeyClient`, `createTotpClient`, `createMfaClient`, and other factories remain available for custom paths and low-level protocol control.
|
|
94
|
+
|
|
95
|
+
Authentication continuations such as `requires_mfa`, `requires_email_verification`, and `requires_login_approval` are successful protocol results, not exceptions. Handle the returned discriminated union in the UI.
|
|
96
|
+
|
|
61
97
|
Use `@effect-auth/core/HttpApi` when you are wiring the server or need the raw `HttpApi` contract. Use `@effect-auth/core/Client` in application UI code.
|
|
62
98
|
|
|
99
|
+
### HTTP Operations
|
|
100
|
+
|
|
101
|
+
Applications that own their routes can use the per-feature operation services instead of mounting the built-in API groups. Every built-in HTTP API group has a corresponding portable, typed operations service and `Live` layer. Each layer acquires its feature dependencies once and exposes ready endpoint operations with the same responses, cookies, errors, optional-service behavior, extension hooks, configuration, and security checks as the built-in handlers.
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { Effect } from "effect";
|
|
105
|
+
import {
|
|
106
|
+
PasswordHttpOperations,
|
|
107
|
+
PasswordHttpOperationsLive,
|
|
108
|
+
type PasswordHttpOperationsService,
|
|
109
|
+
} from "@effect-auth/core/HttpApi/Password";
|
|
110
|
+
|
|
111
|
+
const signIn = (
|
|
112
|
+
input: Parameters<PasswordHttpOperationsService["signIn"]>[0]
|
|
113
|
+
) => PasswordHttpOperations.use((operations) => operations.signIn(input));
|
|
114
|
+
|
|
115
|
+
// Provide PasswordLogin, PasswordRegistration, PasswordReset,
|
|
116
|
+
// PasswordManagement, Sessions, SessionCookie, AuthHttp,
|
|
117
|
+
// EmailVerificationFlow, and an explicit AuthRateLimit layer.
|
|
118
|
+
const PasswordRoutesLive = PasswordHttpOperationsLive;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`@effect-auth/core/HttpApi/Password` also exports the standalone `PasswordHttpApiLive` preset and the password endpoint contracts without loading the full server API assembly. The broad `@effect-auth/core/HttpApi` entry remains the aggregate boundary for `CoreAuthHttpApiLive` and cross-feature composition.
|
|
122
|
+
|
|
123
|
+
Feature operation services can also be replaced directly in tests with `FeatureHttpOperations.of(...)`. Secured feature layers always require `AuthRateLimit`; they never install a no-op implementation.
|
|
124
|
+
|
|
125
|
+
### Client Composition
|
|
126
|
+
|
|
127
|
+
The standard client is a starting point rather than an all-or-nothing abstraction. Its `protocol` option is a deep patch:
|
|
128
|
+
|
|
129
|
+
- omitted properties keep the standard implementation,
|
|
130
|
+
- functions and objects replace or extend it,
|
|
131
|
+
- `null` removes an operation or group,
|
|
132
|
+
- `extensions` adds app-owned auth operations under a collision-free namespace.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const auth = createAuthClient({
|
|
136
|
+
protocol: {
|
|
137
|
+
passkey: null,
|
|
138
|
+
password: {
|
|
139
|
+
signUp: customSignUp,
|
|
140
|
+
},
|
|
141
|
+
extensions: {
|
|
142
|
+
organization: {
|
|
143
|
+
select: selectActiveOrganization,
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
await auth.password.signUp(customInput);
|
|
150
|
+
await auth.extensions.organization.select({ organizationId: "org-1" });
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Literal `null` values also remove the corresponding property from the inferred client type.
|
|
154
|
+
|
|
155
|
+
Use `defineAuthHttpApiExtension` for an app-owned auth `HttpApi` contract that should share the standard client's base URL, Fetch configuration, cookies, cancellation, runtime, and disposal:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const appAuthExtension = defineAuthHttpApiExtension(
|
|
159
|
+
AppAuthExtensionApi,
|
|
160
|
+
({ run }) => ({
|
|
161
|
+
discoverSso: (email: string, options?: AuthClientRequestOptions) =>
|
|
162
|
+
run(
|
|
163
|
+
(client) => client.appAuth.discoverSso({ payload: { email } }),
|
|
164
|
+
options
|
|
165
|
+
),
|
|
166
|
+
})
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const auth = createAuthClient({
|
|
170
|
+
protocol: { extensions: appAuthExtension },
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
await auth.extensions.discoverSso("reader@example.com");
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Extension contracts should contain browser-safe endpoint/schema declarations, use unique group identifiers, and require no client-side middleware services. Product APIs that merely require an auth cookie should remain separate from the auth client.
|
|
177
|
+
|
|
63
178
|
## Policy
|
|
64
179
|
|
|
65
|
-
`Policy` is an `Effect` used for authorization. Success means access is allowed. `
|
|
180
|
+
`Policy` is an `Effect` used for authorization. Success means access is allowed. `AuthorizationError` means access is denied. Other failures stay operational errors.
|
|
66
181
|
|
|
67
182
|
```ts
|
|
68
183
|
import { Effect } from "effect";
|
|
@@ -80,6 +195,29 @@ const detailed = Policy.checkDetailed(canEditProject);
|
|
|
80
195
|
|
|
81
196
|
Use `Policy.check` when callers should branch on allowed/denied and let operational errors fail. Use `Policy.checkDetailed` when callers need a value for allowed, denied, or failed.
|
|
82
197
|
|
|
198
|
+
Permission policies read a trusted `CurrentPrincipal`, not session-specific
|
|
199
|
+
`CurrentActor`. `Permissions` checks are subject-first, so the same policy seam
|
|
200
|
+
can authorize a user, service account, API key, or another app-defined subject:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
import { Effect } from "effect";
|
|
204
|
+
import {
|
|
205
|
+
CurrentPrincipal,
|
|
206
|
+
PermissionSubject,
|
|
207
|
+
} from "@effect-auth/core/Permission";
|
|
208
|
+
|
|
209
|
+
const principal = PermissionSubject.user(validated.actor.userId);
|
|
210
|
+
|
|
211
|
+
const authorized = operation.pipe(
|
|
212
|
+
Effect.provideService(CurrentPrincipal, CurrentPrincipal.of(principal))
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`CurrentActor` remains the authenticated session context containing `userId`
|
|
217
|
+
and `sessionId`. Credential adapters must choose the authorization principal
|
|
218
|
+
explicitly at a trusted boundary; never accept it from request input. Machine
|
|
219
|
+
credential scopes and durable permissions are cumulative restrictions.
|
|
220
|
+
|
|
83
221
|
Policies compose with `all`, `any`, and `not`:
|
|
84
222
|
|
|
85
223
|
```ts
|
|
@@ -162,12 +300,13 @@ const AuthPrivacyLive = PrivacyLive({
|
|
|
162
300
|
});
|
|
163
301
|
```
|
|
164
302
|
|
|
165
|
-
The built-in HTTP auth API
|
|
303
|
+
The built-in HTTP auth API consumes standard limits through `AuthRateLimitStandardLive(config)`. Production deployments provide a durable `RateLimiter` store and HMAC `Privacy` secret. In `config`, an undefined operation uses its standard rules, a rule array replaces them, and `null` disables that operation. `AuthServicesLive` below stands for your app-owned auth service wiring.
|
|
166
304
|
|
|
167
305
|
```ts
|
|
168
|
-
import { Layer, Redacted } from "effect";
|
|
306
|
+
import { Duration, Layer, Redacted } from "effect";
|
|
169
307
|
import { RateLimiter as PersistenceRateLimiter } from "effect/unstable/persistence";
|
|
170
|
-
import {
|
|
308
|
+
import { AuthRateLimitStandardLive } from "@effect-auth/core/AuthRateLimit";
|
|
309
|
+
import { CoreAuthHttpApiLive } from "@effect-auth/core/HttpApi";
|
|
171
310
|
import {
|
|
172
311
|
RateLimitStoreDurableObject,
|
|
173
312
|
type CloudflareRateLimitDurableObjectNamespace,
|
|
@@ -184,29 +323,43 @@ export const makeAuthHttpApiLayer = (
|
|
|
184
323
|
Layer.provide(RateLimitStoreDurableObject.layer({ namespace }))
|
|
185
324
|
);
|
|
186
325
|
|
|
187
|
-
return
|
|
326
|
+
return CoreAuthHttpApiLive.pipe(
|
|
188
327
|
Layer.provide(AuthServicesLive),
|
|
328
|
+
Layer.provide(
|
|
329
|
+
AuthRateLimitStandardLive({
|
|
330
|
+
// Keep standard sign-in rules, replace sign-up, disable reset-start.
|
|
331
|
+
"auth.password.sign_up": [
|
|
332
|
+
{
|
|
333
|
+
id: "app.password.sign_up.ip",
|
|
334
|
+
key: "ip",
|
|
335
|
+
limit: 5,
|
|
336
|
+
window: Duration.hours(1),
|
|
337
|
+
},
|
|
338
|
+
],
|
|
339
|
+
"auth.password.reset_start": null,
|
|
340
|
+
})
|
|
341
|
+
),
|
|
189
342
|
Layer.provide(DurableObjectRateLimiterLive),
|
|
190
343
|
Layer.provide(PrivacyLive({ secret: Redacted.make(privacySecret) }))
|
|
191
344
|
);
|
|
192
345
|
};
|
|
193
346
|
```
|
|
194
347
|
|
|
195
|
-
`
|
|
196
|
-
|
|
197
|
-
Advanced apps can replace the `AuthApiRateLimit` service directly. `AuthApiRateLimitMiddlewareLive` delegates request-level checks to that service, so custom policies can still use the built-in endpoint middleware and handler hooks.
|
|
198
|
-
|
|
199
|
-
Use `AuthHttpApiBareLive` only when you explicitly do not want built-in auth rate limits:
|
|
348
|
+
`AuthRateLimitStandardLive()` applies all standard rules. The explicit escape hatch is `AuthRateLimitNoopLive`; use it only when another boundary enforces equivalent controls or while deliberately running without them:
|
|
200
349
|
|
|
201
350
|
```ts
|
|
202
351
|
import { Layer } from "effect";
|
|
203
|
-
import {
|
|
352
|
+
import { AuthRateLimitNoopLive } from "@effect-auth/core/AuthRateLimit";
|
|
353
|
+
import { CoreAuthHttpApiLive } from "@effect-auth/core/HttpApi";
|
|
204
354
|
|
|
205
|
-
export const AuthHttpApiLayer =
|
|
206
|
-
Layer.provide(AuthServicesLive)
|
|
355
|
+
export const AuthHttpApiLayer = CoreAuthHttpApiLive.pipe(
|
|
356
|
+
Layer.provide(AuthServicesLive),
|
|
357
|
+
Layer.provide(AuthRateLimitNoopLive)
|
|
207
358
|
);
|
|
208
359
|
```
|
|
209
360
|
|
|
361
|
+
App-owned workflows can use `RateLimiter.require`, `StepUp`/`Policy` requirements, and `Guard.requireAll` directly. At an HTTP boundary, pipe the composed effect through `mapAuthGuardErrors` so rate-limit, step-up, policy, privacy, and permission failures become the declared auth HTTP errors while unrelated application errors remain unchanged.
|
|
362
|
+
|
|
210
363
|
## AuthFlow
|
|
211
364
|
|
|
212
365
|
Login methods should verify a factor, then hand the result to `AuthFlow`. `AuthFlow` returns a flat `AuthResult` tagged enum: authenticated, step-up/verification requirements, or successful auth outcomes such as invalid credentials.
|
|
@@ -240,7 +393,7 @@ declare const issuedSession: IssuedSession;
|
|
|
240
393
|
|
|
241
394
|
const AuthFlowLive = Layer.succeed(
|
|
242
395
|
AuthFlow,
|
|
243
|
-
AuthFlow.
|
|
396
|
+
AuthFlow.of({
|
|
244
397
|
startPrimaryFactor: () =>
|
|
245
398
|
Effect.succeed(AuthResult.PolicyDenied({ reason: "test" })),
|
|
246
399
|
completePrimaryFactor: () =>
|
|
@@ -255,6 +408,31 @@ const AuthFlowLive = Layer.succeed(
|
|
|
255
408
|
|
|
256
409
|
The same pattern is available on core services such as `AuditLog.make`, `Sessions.make`, `SessionCookie.make`, `Challenge.make`, `Crypto.make`, `Privacy.make`, and `WaitUntil.make`.
|
|
257
410
|
|
|
411
|
+
The reference flow is a resumable pipeline. It assesses risk before deciding whether MFA is required, resumes the same risk and approval path after MFA, and preserves MFA freshness through a later login-approval challenge. Applications can provide `AuthFlowPipeline` to run app-owned policy checks or deny the flow without replacing the reference orchestration. Pipeline stages cannot replace authentication state, claims, risk, or trusted request facts:
|
|
412
|
+
|
|
413
|
+
```ts
|
|
414
|
+
import { Effect, Layer } from "effect";
|
|
415
|
+
import {
|
|
416
|
+
AuthFlowLive,
|
|
417
|
+
AuthFlowPipeline,
|
|
418
|
+
AuthFlowPipelineLive,
|
|
419
|
+
} from "@effect-auth/core/AuthFlow";
|
|
420
|
+
|
|
421
|
+
const AppAuthPipelineLive = AuthFlowPipelineLive([
|
|
422
|
+
{
|
|
423
|
+
phases: ["before-login-approval"],
|
|
424
|
+
run: (context) =>
|
|
425
|
+
invitationIsValid(context.input)
|
|
426
|
+
? Effect.succeed(AuthFlowPipeline.continueWith())
|
|
427
|
+
: Effect.succeed(AuthFlowPipeline.deny("Invitation required")),
|
|
428
|
+
},
|
|
429
|
+
]);
|
|
430
|
+
|
|
431
|
+
const AppAuthFlowLive = AuthFlowLive.pipe(Layer.provide(AppAuthPipelineLive));
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Available phases are `before-risk`, `after-risk`, `before-mfa`, `after-mfa`, and `before-login-approval`. Every stage receives `mfaSatisfied`, so stages can distinguish the initial primary-factor pass from a resumed MFA flow. Stages run again when the flow resumes; side effects that must execute exactly once should use an idempotency key or inspect `mfaSatisfied`.
|
|
435
|
+
|
|
258
436
|
The first default live implementations are available for the phase-3 web session path:
|
|
259
437
|
|
|
260
438
|
```ts
|
|
@@ -340,17 +518,17 @@ const PasswordHashingLive = Layer.mergeAll(
|
|
|
340
518
|
|
|
341
519
|
## HTTP API
|
|
342
520
|
|
|
343
|
-
`@effect-auth/core/HttpApi` contains the first Effect v4 HttpApi contract for the built-in auth surface. It exports `
|
|
521
|
+
`@effect-auth/core/HttpApi` contains the first Effect v4 HttpApi contract for the built-in auth surface. It exports `CoreAuthHttpApi`, module-owned endpoint groups, and handler layers for the core services.
|
|
344
522
|
|
|
345
523
|
```ts
|
|
346
524
|
import { Layer } from "effect";
|
|
347
525
|
import { HttpRouter } from "effect/unstable/http";
|
|
348
|
-
import {
|
|
526
|
+
import { CoreAuthHttpApiLive } from "@effect-auth/core/HttpApi";
|
|
349
527
|
import { PrivacyLive } from "./auth/privacy";
|
|
350
528
|
import { RateLimiterLive } from "./auth/rate-limiter";
|
|
351
529
|
|
|
352
530
|
export const AuthRoutesLive = HttpRouter.serve(
|
|
353
|
-
|
|
531
|
+
CoreAuthHttpApiLive.pipe(
|
|
354
532
|
Layer.provide(AuthServicesLive),
|
|
355
533
|
Layer.provide(RateLimiterLive),
|
|
356
534
|
Layer.provide(PrivacyLive)
|
|
@@ -360,25 +538,25 @@ export const AuthRoutesLive = HttpRouter.serve(
|
|
|
360
538
|
|
|
361
539
|
The contract currently includes these endpoint groups:
|
|
362
540
|
|
|
363
|
-
| Group
|
|
364
|
-
|
|
|
365
|
-
| Password
|
|
366
|
-
| Sessions
|
|
367
|
-
| Email verification | `POST /auth/email-verification/start`, `POST /auth/email-verification/verify`.
|
|
368
|
-
| Email OTP
|
|
369
|
-
| Magic link
|
|
370
|
-
| Login approval
|
|
371
|
-
| Security
|
|
541
|
+
| Group | Endpoints |
|
|
542
|
+
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
543
|
+
| Password | `POST /auth/password/sign-in`, `POST /auth/password/sign-up`, `POST /auth/password/reset/start`, `POST /auth/password/reset/verify`, `POST /auth/password/set`, `POST /auth/password/change`. |
|
|
544
|
+
| Sessions | `GET /auth/session`, `POST /auth/session/refresh`, `POST /auth/logout`, `GET /auth/sessions`, `POST /auth/sessions/revoke`, `POST /auth/sessions/revoke-others`. |
|
|
545
|
+
| Email verification | `POST /auth/email-verification/start`, `POST /auth/email-verification/verify`. |
|
|
546
|
+
| Email OTP | `POST /auth/email-otp/start`, `POST /auth/email-otp/verify`. |
|
|
547
|
+
| Magic link | `POST /auth/magic-link/start`, `POST /auth/magic-link/verify`. |
|
|
548
|
+
| Login approval | `POST /auth/login-approval/approve`, `POST /auth/login-approval/status`, `POST /auth/login-approval/finalize`. |
|
|
549
|
+
| Security | `POST /auth/security/login/report`. |
|
|
372
550
|
|
|
373
|
-
`
|
|
551
|
+
`CoreAuthHttpApiLive` wires the full built-in surface. Apps can own the final HTTP contract and reuse individual endpoints, services, and the public OAuth/WebAuthn protocol adapters when a feature needs app-specific payloads or responses.
|
|
374
552
|
|
|
375
553
|
`Authenticated` results set the configured session cookie and never include the opaque session token in JSON bodies. Invalid credentials and disabled accounts map to the same `401 invalid_credentials` response by default. Duplicate password sign-up emails fail as `EmailAlreadyRegisteredError` in the domain layer and map to a `409 email_already_registered` HTTP API error.
|
|
376
554
|
|
|
377
|
-
`
|
|
555
|
+
`SessionHttpApiGroup` reads the configured session cookie and validates it with `Sessions`, returning a safe current-session JSON body or `401 unauthenticated`. Refresh extends the current session when it is eligible, commits the refreshed session cookie, and returns the safe current-session JSON body. Safe authenticated bodies include session claims when present, but never include the opaque session token. Logout revokes the current session when present and clears the session cookie with a `204` response.
|
|
378
556
|
|
|
379
|
-
`
|
|
557
|
+
`CoreAuthHttpApiLive` includes `AuthOriginCheckMiddlewareLive()` for cookie-based unsafe methods and requires an `AuthRateLimit` service for built-in operation limits. Origin checks allow same-origin requests, reject cross-origin browser requests with `403 request_rejected`, and allow missing `Origin`/`Referer` headers by default for non-browser clients. Browser-only apps can compose their own `HttpApiBuilder.layer(CoreAuthHttpApi)` and provide `AuthOriginCheckMiddlewareLive({ allowMissingOrigin: false })`.
|
|
380
558
|
|
|
381
|
-
`AuthCsrfMiddlewareLive()` is available for apps that want double-submit CSRF checks on unsafe cookie endpoints. It compares the `__Host-csrf` cookie to the `x-csrf-token` header by default and rejects mismatches with `403 request_rejected`. App-owned HTTP handlers should map core
|
|
559
|
+
`AuthCsrfMiddlewareLive()` is available for apps that want double-submit CSRF checks on unsafe cookie endpoints. It compares the `__Host-csrf` cookie to the `x-csrf-token` header by default and rejects mismatches with `403 request_rejected`. App-owned HTTP handlers should use `mapAuthGuardErrors` to map core guard failures to safe HTTP errors without exposing policy reasons or internal details.
|
|
382
560
|
|
|
383
561
|
Apps using `AuthCsrfMiddleware` must issue the CSRF token themselves, usually from an app-owned bootstrap endpoint or page render. The token should be high-entropy, set as the `__Host-csrf` cookie, and echoed by browser code in the `x-csrf-token` header on unsafe cookie requests:
|
|
384
562
|
|
|
@@ -399,127 +577,93 @@ await fetch("/auth/session/refresh", {
|
|
|
399
577
|
});
|
|
400
578
|
```
|
|
401
579
|
|
|
402
|
-
`AuthRequestMetadataMiddlewareLive()` can provide method, URL, origin, user-agent, and trusted proxy IP metadata to app-owned handlers.
|
|
580
|
+
`AuthRequestMetadataMiddlewareLive()` can provide method, URL, origin, user-agent, and trusted proxy IP metadata to app-owned handlers. IP metadata uses direct request headers by default; set `requestMetadata.trustProxyHeaders` when your deployment terminates trusted proxy headers before the app:
|
|
403
581
|
|
|
404
582
|
```ts
|
|
405
|
-
import {
|
|
583
|
+
import { Layer } from "effect";
|
|
584
|
+
import { AuthRateLimitStandardLive } from "@effect-auth/core/AuthRateLimit";
|
|
406
585
|
import {
|
|
407
586
|
AuthHttpApiConfigLive,
|
|
408
|
-
|
|
587
|
+
CoreAuthHttpApiLive,
|
|
409
588
|
} from "@effect-auth/core/HttpApi";
|
|
410
|
-
import { PrivacyLive } from "./auth/privacy";
|
|
411
|
-
import { RateLimiterLive } from "./auth/rate-limiter";
|
|
412
589
|
|
|
413
|
-
export const AuthHttpApiLayer =
|
|
590
|
+
export const AuthHttpApiLayer = CoreAuthHttpApiLive.pipe(
|
|
414
591
|
Layer.provide(
|
|
415
592
|
AuthHttpApiConfigLive({
|
|
416
|
-
|
|
593
|
+
requestMetadata: {
|
|
417
594
|
trustProxyHeaders: true,
|
|
418
|
-
passwordSignIn: {
|
|
419
|
-
byIp: { limit: 20, window: Duration.minutes(10) },
|
|
420
|
-
byEmail: { limit: 5, window: Duration.minutes(10) },
|
|
421
|
-
},
|
|
422
|
-
passwordSignUp: {
|
|
423
|
-
byIp: false,
|
|
424
|
-
byEmail: { limit: 3, window: Duration.hours(1) },
|
|
425
|
-
},
|
|
426
|
-
emailVerificationStart: false,
|
|
427
595
|
},
|
|
428
596
|
})
|
|
429
597
|
),
|
|
598
|
+
Layer.provide(AuthRateLimitStandardLive()),
|
|
430
599
|
Layer.provide(AuthServicesLive),
|
|
431
600
|
Layer.provide(RateLimiterLive),
|
|
432
601
|
Layer.provide(PrivacyLive)
|
|
433
602
|
);
|
|
434
603
|
```
|
|
435
604
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
```ts
|
|
439
|
-
import { AuthHttpApiBareLive } from "@effect-auth/core/HttpApi";
|
|
440
|
-
|
|
441
|
-
export const AuthHttpApiLayer = AuthHttpApiBareLive.pipe(
|
|
442
|
-
Layer.provide(AuthServicesLive)
|
|
443
|
-
);
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
`EmailVerificationApi` exposes `start` and `verify` endpoints. `start` calls `EmailVerificationFlow` to issue and send a verification challenge through the app-owned `EmailDelivery` adapter. `verify` calls `EmailVerification` and returns `204` on success. When the request includes a valid current session cookie for the same user, `verify` also marks that session's claims as email verified and removes the `email_verification` requirement. Error responses are generic and do not include emails, user ids, challenge secrets, or provider details.
|
|
605
|
+
`EmailVerificationHttpApiGroup` exposes `start` and `verify` endpoints. `start` calls `EmailVerificationFlow` to issue and send a verification challenge through the app-owned `EmailDelivery` adapter. `verify` calls `EmailVerification` and returns `204` on success. When the request includes a valid current session cookie for the same user, `verify` also marks that session's claims as email verified and removes the `email_verification` requirement. Error responses are generic and do not include emails, user ids, challenge secrets, or provider details.
|
|
447
606
|
|
|
448
607
|
Password HTTP handlers can start `EmailVerificationFlow` automatically when a custom auth flow returns `RequiresEmailVerification`. The HTTP response remains `requires_email_verification` and does not include the user id, email, challenge secret, or delivery provider details.
|
|
449
608
|
|
|
450
|
-
|
|
609
|
+
Application workflow handlers belong in the app. Compose domain/application effects with guards, then map only guard failures into the endpoint's HTTP error contract:
|
|
451
610
|
|
|
452
611
|
```ts
|
|
453
|
-
import { Effect, Schema } from "effect";
|
|
612
|
+
import { Duration, Effect, Schema } from "effect";
|
|
454
613
|
import {
|
|
455
614
|
HttpApi,
|
|
456
615
|
HttpApiBuilder,
|
|
457
616
|
HttpApiEndpoint,
|
|
458
617
|
HttpApiGroup,
|
|
459
618
|
} from "effect/unstable/httpapi";
|
|
619
|
+
import * as Guard from "@effect-auth/core/Guard";
|
|
620
|
+
import * as RateLimiter from "@effect-auth/core/RateLimiter";
|
|
460
621
|
import {
|
|
461
|
-
AuthBadRequestError,
|
|
462
|
-
AuthEmailAlreadyRegisteredError,
|
|
463
|
-
AuthHttp,
|
|
464
622
|
AuthInternalError,
|
|
465
|
-
AuthOriginCheckMiddleware,
|
|
466
|
-
AuthPolicyDeniedError,
|
|
467
623
|
AuthRateLimitedError,
|
|
468
|
-
|
|
469
|
-
makePasswordSignInHandler,
|
|
470
|
-
passwordSignInEndpoint,
|
|
471
|
-
PasswordAuthSuccess,
|
|
624
|
+
mapAuthGuardErrors,
|
|
472
625
|
} from "@effect-auth/core/HttpApi";
|
|
473
|
-
import { EmailSchema } from "@effect-auth/core/Identifiers";
|
|
474
|
-
import { PasswordLogin } from "@effect-auth/core/Password";
|
|
475
626
|
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
password: Schema.String,
|
|
481
|
-
phone: PhoneNumber,
|
|
627
|
+
const updateProfileEndpoint = HttpApiEndpoint.post("update", "/profile", {
|
|
628
|
+
payload: Schema.Struct({ displayName: Schema.String }),
|
|
629
|
+
success: Schema.Struct({ updated: Schema.Boolean }),
|
|
630
|
+
error: [AuthRateLimitedError, AuthInternalError],
|
|
482
631
|
});
|
|
483
632
|
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
AuthEmailAlreadyRegisteredError,
|
|
490
|
-
AuthPolicyDeniedError,
|
|
491
|
-
AuthRateLimitedError,
|
|
492
|
-
AuthInternalError,
|
|
493
|
-
],
|
|
633
|
+
const UpdateProfileRateLimit = RateLimiter.RateLimitPolicy.fixedWindow({
|
|
634
|
+
id: "app.profile.update",
|
|
635
|
+
key: RateLimiter.RateLimitKey.global,
|
|
636
|
+
limit: 20,
|
|
637
|
+
window: Duration.minutes(1),
|
|
494
638
|
});
|
|
495
639
|
|
|
496
|
-
class
|
|
497
|
-
.add(
|
|
498
|
-
.prefix("/auth
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
);
|
|
519
|
-
})
|
|
640
|
+
class ProfileHttpApiGroup extends HttpApiGroup.make("profile")
|
|
641
|
+
.add(updateProfileEndpoint)
|
|
642
|
+
.prefix("/auth") {}
|
|
643
|
+
|
|
644
|
+
class AppApi extends HttpApi.make("AppApi").add(ProfileHttpApiGroup) {}
|
|
645
|
+
|
|
646
|
+
const updateProfile = (displayName: string) =>
|
|
647
|
+
Effect.succeed({ updated: displayName.length > 0 });
|
|
648
|
+
|
|
649
|
+
export const ProfileHttpApiGroupLive = HttpApiBuilder.group(
|
|
650
|
+
AppApi,
|
|
651
|
+
"profile",
|
|
652
|
+
(handlers) =>
|
|
653
|
+
handlers.handle(
|
|
654
|
+
"update",
|
|
655
|
+
Effect.fn("app.auth.profile.update")(function* ({ payload }) {
|
|
656
|
+
return yield* updateProfile(payload.displayName).pipe(
|
|
657
|
+
Guard.requireAll(RateLimiter.require(UpdateProfileRateLimit)),
|
|
658
|
+
mapAuthGuardErrors
|
|
659
|
+
);
|
|
660
|
+
})
|
|
661
|
+
)
|
|
520
662
|
);
|
|
521
663
|
```
|
|
522
664
|
|
|
665
|
+
Use `Guard.requireAll` with `RateLimiter.require(...)`, `AuthRateLimit.require(...)`, direct `StepUp` effects, direct `Policy` effects, or any app-owned guard. This keeps workflow ownership local instead of importing a thin core handler factory. `mapAuthGuardErrors` preserves unrelated domain errors, so include those separately in the endpoint error schema.
|
|
666
|
+
|
|
523
667
|
## Sessions
|
|
524
668
|
|
|
525
669
|
`Sessions` is the server-side session authority. Transports such as cookies are separate services so browser, API, and custom transports can share the same session strategy.
|
|
@@ -556,15 +700,15 @@ export const createBrowserSession = (userId: UserId) =>
|
|
|
556
700
|
Password auth passes the user's email verification state into `AuthFlow`, where `EmailVerificationSessionPolicy` decides whether unverified users get a normal session or a constrained session. The default mode is `allow-unverified` for compatibility. Use `limited-session` to issue sessions with an `email_verification` requirement. Per-login email approval is a separate `UserSecurityPolicy` / `LoginApprovalPolicy` concern, not an email verification session mode.
|
|
557
701
|
|
|
558
702
|
```ts
|
|
559
|
-
import {
|
|
703
|
+
import { AuthFlowWithEmailVerificationPolicyLive } from "@effect-auth/core/AuthFlow";
|
|
560
704
|
|
|
561
705
|
export const AllowUnverifiedAuthFlowLive =
|
|
562
|
-
|
|
706
|
+
AuthFlowWithEmailVerificationPolicyLive({
|
|
563
707
|
mode: "allow-unverified",
|
|
564
708
|
});
|
|
565
709
|
|
|
566
710
|
export const LimitedSessionAuthFlowLive =
|
|
567
|
-
|
|
711
|
+
AuthFlowWithEmailVerificationPolicyLive({
|
|
568
712
|
mode: "limited-session",
|
|
569
713
|
});
|
|
570
714
|
```
|
|
@@ -721,7 +865,7 @@ import {
|
|
|
721
865
|
} from "@effect-auth/core/EmailVerification";
|
|
722
866
|
import type { ChallengeId, Email, UserId } from "@effect-auth/core/Identifiers";
|
|
723
867
|
|
|
724
|
-
const emailDelivery = EmailDelivery.
|
|
868
|
+
const emailDelivery = EmailDelivery.of({
|
|
725
869
|
sendEmailVerification: ({ email, secret, challengeId }) =>
|
|
726
870
|
sendMail({
|
|
727
871
|
to: email,
|
|
@@ -796,19 +940,19 @@ import {
|
|
|
796
940
|
VerificationStore,
|
|
797
941
|
} from "@effect-auth/core/Storage";
|
|
798
942
|
|
|
799
|
-
const UserStoreLive = UserStore.
|
|
943
|
+
const UserStoreLive = UserStore.of({
|
|
800
944
|
findById: () => Effect.succeed(Option.none()),
|
|
801
945
|
findByEmail: () => Effect.succeed(Option.none()),
|
|
802
946
|
insert: () => Effect.void,
|
|
803
947
|
markEmailVerified: () => Effect.succeed(Option.none()),
|
|
804
948
|
});
|
|
805
949
|
|
|
806
|
-
const CredentialStoreLive = CredentialStore.
|
|
950
|
+
const CredentialStoreLive = CredentialStore.of({
|
|
807
951
|
findPasswordByUserId: () => Effect.succeed(Option.none()),
|
|
808
952
|
insertPassword: () => Effect.void,
|
|
809
953
|
});
|
|
810
954
|
|
|
811
|
-
const SessionStoreLive = SessionStore.
|
|
955
|
+
const SessionStoreLive = SessionStore.of({
|
|
812
956
|
findById: () => Effect.succeed(Option.none()),
|
|
813
957
|
insert: () => Effect.void,
|
|
814
958
|
refresh: () => Effect.succeed(Option.none()),
|
|
@@ -817,7 +961,7 @@ const SessionStoreLive = SessionStore.make({
|
|
|
817
961
|
revokeAllForUser: () => Effect.void,
|
|
818
962
|
});
|
|
819
963
|
|
|
820
|
-
const VerificationStoreLive = VerificationStore.
|
|
964
|
+
const VerificationStoreLive = VerificationStore.of({
|
|
821
965
|
findById: () => Effect.succeed(Option.none()),
|
|
822
966
|
insert: () => Effect.void,
|
|
823
967
|
consume: () => Effect.succeed(Option.none()),
|
|
@@ -829,9 +973,10 @@ The default schema is exported as SQL and as package assets:
|
|
|
829
973
|
|
|
830
974
|
```ts
|
|
831
975
|
import { authStorageMigrations } from "@effect-auth/core/StorageMigrations";
|
|
976
|
+
import { postgresAuthStorageMigrations } from "@effect-auth/core/PostgresStorageMigrations";
|
|
832
977
|
```
|
|
833
978
|
|
|
834
|
-
Effect-QB SQLite/D1 storage is
|
|
979
|
+
Effect-QB SQLite/D1 storage is a first-party durable adapter. The default path uses the auth schema and requires no table mapping:
|
|
835
980
|
|
|
836
981
|
```ts
|
|
837
982
|
import { EffectQbSqliteAuthStorageLive } from "@effect-auth/core/EffectQbSqliteStorage";
|
|
@@ -841,6 +986,18 @@ const StorageLive = EffectQbSqliteAuthStorageLive(executor);
|
|
|
841
986
|
|
|
842
987
|
`EffectQbSqliteAuthStorageLive` provides all durable auth stores in the default schema, including audit log storage, domain verification storage, and the OAuth provider-token vault for already-encrypted provider token ciphertexts. Apps still own provider-token encryption, KMS/secrets-service policy, DNS/HTTP proof checking, and tenant authorization before values reach storage.
|
|
843
988
|
|
|
989
|
+
The native Effect-QB Postgres adapter also provides the complete grouped store set, including `PermissionStore`. Apply the exported Postgres migrations through `0009_auth_permissions`, then provide `EffectQbPostgresCoreStoresLive(sql)` or construct `makeEffectQbPostgresPermissionStore(executor)` directly.
|
|
990
|
+
|
|
991
|
+
Application-owned queries can reuse the adapter's canonical table objects instead of redeclaring `Table.make(...)` metadata:
|
|
992
|
+
|
|
993
|
+
```ts
|
|
994
|
+
import { effectQbPostgresTables } from "@effect-auth/core/EffectQbPostgresStorage";
|
|
995
|
+
|
|
996
|
+
const { user, session, permissionDefinition } = effectQbPostgresTables;
|
|
997
|
+
```
|
|
998
|
+
|
|
999
|
+
Use the public store services for auth mutations unless custom writes preserve the adapter's security and atomicity invariants.
|
|
1000
|
+
|
|
844
1001
|
For Cloudflare D1, create an effect-qb SQLite executor from the D1 binding:
|
|
845
1002
|
|
|
846
1003
|
```ts
|
|
@@ -861,6 +1018,20 @@ import { DrizzleD1SqliteAuthStorageLive } from "@effect-auth/core/DrizzleD1Sqlit
|
|
|
861
1018
|
const StorageLive = DrizzleD1SqliteAuthStorageLive(env.DB);
|
|
862
1019
|
```
|
|
863
1020
|
|
|
1021
|
+
Runtime-specific Drizzle SQLite helpers are available for Node, Bun, Cloudflare Durable Object SQLite storage, and WASM/OPFS-style SQLite. They construct the matching Drizzle Effect SQLite database from the Effect SQL client layer, then reuse the same auth storage bridge:
|
|
1022
|
+
|
|
1023
|
+
```ts
|
|
1024
|
+
import { DrizzleBunSqliteAuthStorageLive } from "@effect-auth/core/DrizzleBunSqliteStorage";
|
|
1025
|
+
|
|
1026
|
+
const StorageLive = DrizzleBunSqliteAuthStorageLive({
|
|
1027
|
+
filename: "auth.sqlite",
|
|
1028
|
+
});
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
Install the matching runtime package when using a runtime-specific subpath, such as `@effect/sql-sqlite-bun`, `@effect/sql-sqlite-node`, `@effect/sql-sqlite-do`, or `@effect/sql-sqlite-wasm`.
|
|
1032
|
+
|
|
1033
|
+
Database and ORM packages used only by storage subpaths are optional peers. The metadata-only root does not load them; install the matching optional peers for the adapter subpath your application imports.
|
|
1034
|
+
|
|
864
1035
|
If your app already builds a Drizzle Effect SQLite database, use the generic subpath instead. This keeps D1-specific dependencies out of non-D1 runtimes:
|
|
865
1036
|
|
|
866
1037
|
```ts
|
|
@@ -874,9 +1045,11 @@ Both Drizzle paths use the same default auth schema and table mapping options as
|
|
|
874
1045
|
```ts
|
|
875
1046
|
import { makeD1DrizzleEffectSqliteDatabase } from "@effect-auth/core/DrizzleD1SqliteStorage";
|
|
876
1047
|
|
|
877
|
-
const drizzle =
|
|
878
|
-
|
|
879
|
-
|
|
1048
|
+
const drizzle =
|
|
1049
|
+
yield *
|
|
1050
|
+
makeD1DrizzleEffectSqliteDatabase(env.DB, {
|
|
1051
|
+
relations,
|
|
1052
|
+
});
|
|
880
1053
|
```
|
|
881
1054
|
|
|
882
1055
|
Applications with their own Effect-QB tables can map semantic auth fields to app-owned columns with `defineEffectQbAuthTables`:
|
|
@@ -932,7 +1105,9 @@ const authTables = defineEffectQbAuthTables({
|
|
|
932
1105
|
// credential/session/verification/audit/review/trusted-device/passkey/TOTP/recovery-code/API-key/refresh-token/OAuth-account/provider-token-vault/domain-verification mappings follow the same pattern.
|
|
933
1106
|
});
|
|
934
1107
|
|
|
935
|
-
const StorageLive = EffectQbSqliteAuthStorageLive(executor, {
|
|
1108
|
+
const StorageLive = EffectQbSqliteAuthStorageLive(executor, atomic, {
|
|
936
1109
|
tables: authTables,
|
|
937
1110
|
});
|
|
938
1111
|
```
|
|
1112
|
+
|
|
1113
|
+
Mappings used by atomic composite stores must select direct bound columns and return literal driver values from mutation functions. Expression-valued mutation mappings require an application-owned store implementation.
|