HTTP Operations
Bind standard effect-auth workflows to an application-owned HTTP contract.
HTTP Operations sit between domain services and HttpApi. Each *HttpOperations service exposes endpoint-shaped functions with the built-in request, success, error, and requirement types, but without a fixed route or group.
| Operation retains | Custom endpoint owns |
|---|---|
| Standard workflow and domain orchestration | Path, method, group, decoding, and API layout |
| Operation-specific request security, including rate limiting where defined | Origin/CSRF behavior, caller guards, and additional app policy |
| Public error translation and continuation results | Compatible success/error schemas and any request/result adaptation |
| Session issuance, rotation, revocation, and cookie consequences | Which methods are exposed and the matching browser client contract |
For password sign-in this preserves response-level account-existence concealment, continuation handling, unexpected-infrastructure-error hiding, and session commitment. After identity normalization and password-size validation, account-dependent lookup failures perform one provider-owned dummy password verification; an existing credential performs only its real verification. Malformed or unsupported identities, oversized passwords, and earlier guard rejection remain cheap. Network and storage work can still differ, so end-to-end request timing is not guaranteed to be identical.
Bind a method
An Alchemy-deployed auth Worker can expose the standard sign-in workflow at an application-owned route:
import {
HttpLoginApprovalFinalizerCapability,
HttpLoginApprovalStatusCapability,
LoginNotificationReportCapability,
PasswordEmailVerificationCapability,
layerNoDeps as httpEndpointCapabilitiesLayerNoDeps,
} from "@effect-auth/core/HttpApi/HttpEndpointCapabilities";
const HttpEndpointCapabilitiesLayer = httpEndpointCapabilitiesLayerNoDeps({
passwordEmailVerification: PasswordEmailVerificationCapability.Disabled(),
loginNotificationReport: LoginNotificationReportCapability.Disabled(),
loginApprovalStatus: HttpLoginApprovalStatusCapability.Disabled(),
loginApprovalFinalizer: HttpLoginApprovalFinalizerCapability.Disabled(),
});
const AppPasswordGroupLive = HttpApiBuilder.group(
AppAuthApi,
"password",
Effect.gen(function* (handlers) {
const password = yield* PasswordHttpOperations;
return handlers.handle("signIn", password.signIn);
})
).pipe(
Layer.provide(
PasswordHttpOperationsLive.pipe(
Layer.provide(AuthRateLimitStandardLive()),
Layer.provide(HttpAuthenticationCapabilitiesLive),
Layer.provide(HttpEndpointCapabilitiesLayer),
Layer.provide(AppAuthServicesLive)
)
)
);AppAuthServicesLive can contain D1 stores and Cloudflare runtime adapters supplied from Alchemy bindings. HttpAuthenticationCapabilitiesLive and HttpEndpointCapabilitiesLayer are application assemblies built with their focused layerNoDeps functions. The first selects one snapshotted request-IP source and explicit tagged bot-verifier, trusted-device-cookie, and login-risk choices; the second selects four explicit endpoint choices. PasswordHttpOperationsLive constructs the complete password service, including reset operations and dependencies, although this group binds only signIn: Layers assemble per feature, handlers expose per endpoint.
Captured and execution-time requirements
Maintained secured operation Layers explicitly capture AuthRateLimit and HttpAuthenticationCapabilities when constructed. Generic rate limits, OAuth protocol/device limits, passkey risk context, identity, TOTP/recovery, MFA, and step-up paths all derive request data from that same immutable metadata snapshot. Adding a capability or a different metadata policy later to request context does not alter an existing operations service.
AdminPermissionDefinitionHttpOperations is the important exception: its returned Effects retain execution-time requirements for permission administration, sessions, cookies, and mandatory app authorization. Its focused preset installs middleware for those requirements; a custom group must provide an equivalent trusted context. See the permission-definition API.
Standard group middleware does not travel with a function. In particular:
| Concern | Custom binding action |
|---|---|
| Schema errors | Attach AuthSchemaErrorMiddleware or define another explicit public shape |
| Origin/CSRF | Configure the custom group/API boundary |
| Standard operation policy | Provide it while constructing operations; do not execute it twice |
| Application authorization | Compose it around the operation |
| CORS | Configure response headers and preflight independently |
| Cache policy | Preserve required headers such as OAuth no-store at the custom boundary |
Catalog
| Area | Operation service prefixes |
|---|---|
| Primary authentication | Password, EmailAuth, EmailOtp, MagicLink, Passkey, EmailVerification |
| Sessions and assurance | Session, Mfa, StepUp, Totp, RecoveryCodes, LoginApproval, LoginNotification |
| Identity and security | Identity, TrustedDevice, SecurityTimeline, AdminSession, AdminTrustedDevice, AdminSecurityTimeline, AdminPermissionDefinition |
| Tokens and federation | OAuth, OAuthProviderAuthorization, OAuthDeviceAuthorization, OAuthDeviceApproval, OAuthToken, OAuthTokenIntrospection, OAuthTokenRevocation, ApiKey, RefreshToken, Jwt, JwtDiscovery, OidcDiscovery |
Each prefix names PrefixHttpOperations and normally PrefixHttpOperationsLive; TypeScript exposes the exact methods and environment requirements from the owning public subpath.
OAuth device start and browser approval are separate services because they have different callers and policy boundaries. Token exchange, introspection, and revocation are separate too. The token operation dispatches through explicit OAuthTokenGrantRegistry registrations; it does not discover optional grants from ambient context. Operation methods do not carry the standard groups' no-store or origin middleware into a custom route.
If custom routes diverge from the standard client protocol, define the application contract explicitly. createAuthClient({ protocol }) and defineAuthHttpApiExtension can replace, remove, or add typed client operations; they cannot infer an arbitrary server API. Continue with Custom Auth API.