Security & Rate Limiting
Relevant source files
The following files were used as context for generating this wiki page:
Security and Rate Limiting within the TREAD Talks platform protect the system from abuse and ensure authorized access to sensitive operations. The architecture combines JWT-based authentication via Better Auth with granular rate limiting implemented through Convex components and custom plugins. These mechanisms primarily target authentication endpoints, such as sign-in and password resets, as well as data-altering mutations.
Sources: README.md:4-22, convex/lib/plugins.ts:20-35, convex/_generated/ai/guidelines.md:144-165
Authentication & Authorization
The project implements authentication using Better Auth and Convex's JWT-based identity system. Server-side functions verify the requester's identity before performing restricted actions.
Identity Verification
Convex derives user identity via ctx.auth.getUserIdentity(). This method returns a UserIdentity object containing a tokenIdentifier, which serves as the canonical stable identifier for database lookups and ownership checks. The platform explicitly forbids accepting a userId as a function argument for authorization purposes to prevent ID spoofing.
Sources: convex/_generated/ai/guidelines.md:148-158, convex/model/auth/utils.ts
Mutation Guards
Sensitive database operations, such as creating or destroying topics, require an authenticated session. The requireAuth(ctx) helper validates that a user is logged in before the mutation logic executes. If the check fails, the system throws an unauthorized error.
The diagram shows the standard authorization flow for mutations that modify data.
Sources: convex/model/topics/mutations.ts:18-20, convex/model/topics/mutations.ts:57-59
Rate Limiting Architecture
The system employs the @convex-dev/rate-limiter component to manage quotas and cooldowns. This approach prevents race conditions common in hand-rolled counter implementations.
Auth Rate Limit Plugin
The authRateLimitPlugin intercepts incoming requests to specific authentication endpoints. It identifies clients using their IP address, retrieved from headers such as cf-connecting-ip or x-forwarded-for.
| Protected Endpoint | Purpose | Error Message |
|---|---|---|
/change-password | Prevents brute-forcing password changes | Too many password change attempts. |
/request-password-reset | Throttles reset email generation | Too many reset requests. |
/sign-in/email | Blocks credential stuffing | Too many login attempts. |
/sign-up/email | Prevents automated registration | Too many registration attempts. |
Sources: convex/lib/plugins.ts:20-35, package.json:52, convex/_generated/ai/guidelines.md:188-190
Request Interception Flow
When a request matches a protected suffix, the plugin triggers an internal mutation to check the rate limit status. If the limit is exceeded, the system returns a 429 Too Many Requests status with a Retry-After header.
This sequence diagram illustrates the interception of authentication requests to enforce rate limits based on client IP.
Sources: convex/lib/plugins.ts:71-106, convex/lib/plugins.ts:37-52
Implementation Details
The rate limiter uses an internal mutation to ensure atomicity. If the rate limiter itself fails, the system "fails closed" by returning a 429 error to ensure security is not bypassed.
try {
result = await actionCtx.runMutation(mutation, { key: ip });
} catch (error) {
// Rate limiter mutation failed, failing closed
return {
response: rateLimitedResponse(
'Service temporarily unavailable. Please try again later.',
HOUR
),
};
}
Sources: convex/lib/plugins.ts:88-99, convex/lib/plugins.ts:54-62
Data Security & Validation
The platform ensures data integrity through schema-level validators and logic-based checks in mutations.
Argument Validation
All Convex functions use v.object and other validators from convex/values to enforce type safety at the API boundary. This prevents malformed data from reaching the database.
Sources: convex/_generated/ai/guidelines.md:37-75, convex/model/topics/mutations.ts:52-54
Resource Integrity
Mutations perform pre-execution checks to ensure logical consistency. For example, the destroyTopic mutation verifies that a topic has no associated talks before allowing a hard delete, preventing orphaned records in the talksOnTopics join table.
Sources: convex/model/topics/mutations.ts:79-92
Summary
The security architecture of TREAD Talks prioritizes identity-based authorization for all write operations and IP-based rate limiting for authentication entry points. By leveraging the @convex-dev/rate-limiter component and the authRateLimitPlugin, the system mitigates brute-force attacks and ensures that sensitive mutations are restricted to authenticated users.