diff --git a/.ai/shared/agents/pm.md b/.ai/shared/agents/pm.md new file mode 100644 index 0000000..2c77af6 --- /dev/null +++ b/.ai/shared/agents/pm.md @@ -0,0 +1,31 @@ +# Product Manager (PM) + +CRITICAL: Read the YAML below to operate. Follow y your activation-instructions to alter your state of being, stay in this being until told to exit this mode: + +```yaml +agent: + name: Peter PM + description: | + You are an experienced, thoughtful Product Manager (PM) for the BoosterAuth monorepo. Your role is to ensure that the development process aligns with product goals, user needs, and business objectives. You will work closely with developers, designers, and stakeholders to prioritize features, manage the product backlog, and ensure successful delivery of the authentication platform. + activation-instructions: + - read the architectural context and product requirements in `.ai/shared/architectural-context.md` and `.ai/shared/library-prd.md`. + - Deeply consider the library prd. It is the canonical source of truth for the BoosterAuth monorepo. Use this information to guide your decisions and interactions with the development team. + persona: + role: Product Manager + goals: + - Ensure alignment of product features with business value + - Prioritize the product backlog balancing business value and complexity of implementation + - Facilitate communication between stakeholders and the development team + - Advocate for superior user experience and product quality + responsibilities: + - Define product vision and strategy aligned with business goals + - Manage the product roadmap + - Conduct user research and gather feedback + - Collaborate with developers to refine requirements and acceptance criteria + - Eliminate blockers and ensure smooth development processes + - Monitor project progress and adjust priorities as needed + commands: + - help: Show numbered list of the following commands to allow selection + - write-epic: Write a new epic for the product backlog. Epics should be prefixed with a YYYYMMDD_ prefix in the ./ai/shared/epics directory. + - write-user-story: Write a new user story for the product backlog. User stories should be prefixed with a YYYYMMDD_ prefix in the ./ai/shared/user-stories/ directory with a YYYYMMDD_ prefix. A supporting epic file must be referenced. Do not write user stories without a supporting epic. +``` diff --git a/.ai/shared/architectural-context.md b/.ai/shared/architectural-context.md new file mode 100644 index 0000000..95ff179 --- /dev/null +++ b/.ai/shared/architectural-context.md @@ -0,0 +1,67 @@ +# Architectural Context: Booster Auth + +This monorepo contains a suite of npm packages focused solely on implementing modular, secure, and extensible authentication systems for NodeJS / React applications. The packages are designed to be used independently or together, allowing developers to choose the components that best fit their needs. + +This monorepo contains a suite of npm packages focused solely on implementing modular, secure, and extensible authentication systems for SaaS applications. + +## ๐Ÿงฑ Monorepo Philosophy + +- **All code lives in `libs/`** as independently publishable npm packages. +- **`apps/` contains implementation examples only**, such as an Express or React app consuming the auth packages. +- **The system is AI-first**: Claude and Gemini CLI agents are used to scaffold, test, and iterate on new features. + +## AI Philosophy + +This repository treats AI prompts and context as code. The AI agents are expected to: + +- Propose clean, minimal TypeScript implementations using dependency injection (DI). +- Generate tests for every public function or class. +- Avoid implementation in `core` packages (interfaces only). +- Avoid tight coupling to Prisma in core logic. +- Use Zod for schema validation. +- Respect architectural boundaries (e.g., no cross-dependencies without DI). +- Record important context in the `.ai/` directory, including architectural decisions, system prompts, and AI assistant agents and rules. + +## ๐Ÿ” Security Principles + +- Follows [Lucia](https://lucia-auth.com/) principles: no opaque abstractions, explicit session control, security-first. +- Sessions are stored securely and validated on every request. +- Passwords are hashed using a configurable `PasswordHasher` (default: bcrypt). +- OAuth and SSO providers may be added via pluggable strategies. +- Consider alternative authentication methods such as JWT, magic links, and passkeys. + +## ๐Ÿงช Testing Philosophy + +- TDD-first: tests must be generated before implementations. +- Unit tests are located contextually in `__tests__` subdirectories with a suffix that indicates they are explicitly test files. (`*.test.ts`). +- Each library is independently testable. +- End-to-end tests are planned with Playwright via example `apps/`. +- test runs should take advantage of Nx's caching, affected, and parallelization capabilities. + +## ๐Ÿง  Agent Expectations + +Claude, Gemini, or other agents should: + +- Propose clean, minimal TypeScript implementations using DI +- Generate tests for every public function or class +- Avoid implementation in `core` packages (interfaces only) +- Avoid tight coupling to Prisma in core logic +- Use Zod for schema validation +- Respect architectural boundaries (e.g., no cross-dependencies without DI) + +## โš™๏ธ Tooling & Platform Defaults + +With the exception of typescript, all tooling suggested below is the **default** for the monorepo. You may override these defaults, but do so consistently with the architectural context. + +- Language: TypeScript (`strict` mode) +- Package Manager: pnpm +- Monorepo: Nx +- Linting: ESLint (flat config via internal libraries) +- Backend: Express + tRPC +- ORM: Prisma (PostgreSQL preferred) +- Validation: Zod +- Default deployment targets: AWS ECS Fargate (server), CloudFront (client) + +## ๐Ÿ”Œ DI & Extensibility + +- Core services (`SessionService`, `IdentityService`) receive dependencies via constructor injection. diff --git a/.ai/shared/epics/20250709_traditional-web-authentication.md b/.ai/shared/epics/20250709_traditional-web-authentication.md new file mode 100644 index 0000000..17294b8 --- /dev/null +++ b/.ai/shared/epics/20250709_traditional-web-authentication.md @@ -0,0 +1,207 @@ +# Epic: Traditional Web-Based Authentication + +## Overview + +Implement a complete traditional web-based authentication system that enables users to securely sign up, sign in, and manage their accounts within the BoosterAuth monorepo ecosystem. + +## Business Value + +- **Developer Experience**: Provides a foundational authentication system that developers can easily integrate into their SaaS applications +- **Security First**: Implements industry-standard security practices following Lucia principles +- **Modularity**: Allows developers to pick and choose authentication components as needed +- **Time to Market**: Reduces development time for teams needing secure authentication +- **Compliance**: Meets security standards required for enterprise SaaS applications + +## Success Criteria + +- [ ] Users can successfully sign up with email and password +- [ ] Users can sign in with valid credentials +- [ ] Users can securely sign out and invalidate sessions +- [ ] Users can reset forgotten passwords via email +- [ ] All authentication flows are secure and follow best practices +- [ ] System prevents enumeration attacks +- [ ] Password policies are configurable +- [ ] All packages are independently publishable and testable + +## Architectural Considerations + +### Package Structure + +Following the monorepo philosophy, authentication functionality will be distributed across multiple packages in `libs/`: + +- **Core Interfaces** (`@booster-auth/core`): Abstract interfaces and types only +- **Session Management** (`@booster-auth/session`): Session creation, validation, and lifecycle +- **Identity Management** (`@booster-auth/identity`): User identity and credential management +- **Password Management** (`@booster-auth/password-authentication`): Password hashing, validation, and reset +- **Email Services** (`@booster-auth/email`): Email provider abstraction and templates + +### Security Principles + +- **No Opaque Abstractions**: Clear, explicit session control +- **Secure Defaults**: bcrypt password hashing, secure session storage +- **Configurable Security**: Customizable password policies and session timeouts +- **Protection Against Attacks**: Enumeration attack prevention, token expiration + +### Dependency Injection + +- Core services (`SessionService`, `IdentityService`, `PasswordService`) receive dependencies via constructor injection +- No tight coupling to Prisma in core logic +- Pluggable strategies for different authentication methods + +### Testing Strategy + +- TDD-first approach: tests generated before implementations +- Unit tests in `__tests__` subdirectories with `*.test.ts` suffix +- Each library independently testable +- Comprehensive coverage of security scenarios + +## Technical Requirements + +### Data Layer + +- **User Accounts**: User accounts with email, hashed passwords, metadata +- **Session Storage**: Secure session tokens with expiration +- **Password Reset Tokens**: Temporary, single-use tokens with TTL +- **Audit Logging**: Authentication events for security monitoring + +### API Contracts + +- **Zod Schema Validation**: All inputs validated with Zod schemas +- **TypeScript Strict Mode**: Full type safety across all packages +- **Error Handling**: Consistent error responses that don't leak information +- **Rate Limiting**: Protection against brute force attacks + +### Integration Points + +- **Email Provider Abstraction**: Support for SMTP, SendGrid, Postmark +- **Database Abstraction**: Prisma integration without tight coupling - consider how drizzle can similarly be used +- **Middleware Integration**: Express middleware for session validation + +## User Flows Covered + +### 1. User Sign Up + +- Email and password validation +- Password hashing and secure storage +- Account creation with proper error handling +- Welcome email (optional) + +### 2. User Sign In + +- Credential validation without enumeration +- Session creation and token generation +- Secure session storage +- Failed attempt handling + +### 3. User Sign Out + +- Session invalidation +- Token cleanup +- Secure logout confirmation + +### 4. Password Reset Flow + +- Reset request with email validation +- Secure token generation and email delivery +- Password reset with token validation +- Token invalidation after use +- Confirmation email after reset + +## Non-Functional Requirements + +### Performance + +- Session validation in < 100ms +- Password hashing optimized for security vs. performance +- Efficient token lookup and validation + +### Security + +- Passwords hashed with bcrypt (configurable rounds) +- Session tokens cryptographically secure +- Protection against timing attacks +- Secure token expiration and cleanup + +### Scalability + +- Stateless session validation +- Horizontal scaling support +- Database connection pooling +- Rate limiting and abuse protection + +## Dependencies and Constraints + +### Technology Stack + +- **Language**: TypeScript (strict mode) +- **Validation**: Zod schemas +- **Hashing**: bcrypt (configurable) +- **Database**: Prisma (PostgreSQL preferred) +- **Testing**: Jest with comprehensive coverage + +### External Dependencies + +- Email service providers (SMTP, SendGrid, Postmark) +- Database for persistent storage +- Redis for session storage (optional) +- Rate limiting service (optional) + +## Risks and Mitigation + +### Security Risks + +- **Risk**: Password brute force attacks +- **Mitigation**: Rate limiting, account lockout, secure password policies + +- **Risk**: Session hijacking +- **Mitigation**: Secure token generation, HTTPS only, proper expiration + +- **Risk**: Enumeration attacks +- **Mitigation**: Consistent response times, generic error messages + +### Technical Risks + +- **Risk**: Package dependency complexity +- **Mitigation**: Clear interfaces, dependency injection, independent testing + +- **Risk**: Performance bottlenecks +- **Mitigation**: Efficient algorithms, caching, performance monitoring + +## Acceptance Criteria + +### Functional + +- All user flows work end-to-end +- Security measures prevent common attacks +- Error handling provides appropriate feedback +- Email delivery is reliable and configurable + +### Technical + +- All packages pass independent tests +- Code coverage > 90% +- Performance benchmarks met +- Security audit passes +- Documentation complete + +### Architectural + +- Dependency injection properly implemented +- No cross-package dependencies without DI +- Interfaces clearly defined in core packages +- Modular design allows independent usage + +## Definition of Done + +- [ ] All user stories completed and tested +- [ ] Security review passed +- [ ] Performance benchmarks met +- [ ] Documentation updated +- [ ] Examples in `apps/` directory functional +- [ ] All packages independently publishable +- [ ] CI/CD pipeline passing +- [ ] Ready for beta testing with real applications + +--- + +*This epic will be decomposed into specific user stories covering each authentication flow, package implementation, and integration requirement.* diff --git a/.ai/shared/library-prd.md b/.ai/shared/library-prd.md new file mode 100644 index 0000000..3cc54ee --- /dev/null +++ b/.ai/shared/library-prd.md @@ -0,0 +1,75 @@ +# Booster Auth Library + +This monorepo contains a suite of npm packages focused solely on implementing modular, secure, and extensible authentication systems for SaaS applications. + +## Key Features + +- **Modular Design**: Each package is independently publishable and can be used in isolation or together. +- **Security First**: Follows best practices for secure authentication, including session management and password hashing. +- **Extensible**: Easily add new authentication methods or providers through pluggable strategies. +- **Embrace Open Standards**: Supports OAuth, OIDC, SAML, and other common authentication protocols. +- **AI-First Development**: Utilizes AI agents for code generation, testing, PR review, and refactoring. +- **TDD Approach**: Tests are generated before implementations, ensuring high code quality and reliability. +- **TypeScript**: Built with TypeScript for type safety and developer experience. + +## Development Philosophy + +- **Convention over Configuration**: Provides sensible defaults while allowing customization. +- **Semantic Versioning**: Follows semantic versioning for all packages to ensure compatibility and stability. +- **Test-Driven Development**: All features are developed with tests first, ensuring reliability and maintainability. +- **AI-Assisted Development**: Leverages AI tools for code generation, testing, and refactoring to enhance productivity and code quality. +- **Security as a Priority**: Implements security best practices from the ground up, ensuring that authentication systems are robust and secure. +- **Extensible Architecture**: Designed to be easily extended with new authentication methods, providers, and features. +- **Modular Packages**: Each package serves a specific purpose, allowing developers to pick and choose components as needed. +- **Documentation-Driven**: Comprehensive documentation is provided for each package, including usage examples and API references. + +## Architectural Decision Records + +Each architectural decision is documented in the `apps/docs/adr` directory. These records provide context and rationale for design choices, helping maintain clarity and consistency as the project evolves. + +## Glossary + +Login, logout, and registration are not acceptable terms in this project. Instead, we use the following terminology: + +- **Sign In**: The process of authenticating a user with their credentials. +- **Sign Out**: The process of terminating a user's session, effectively logging them out. +- **Sign Up**: The process of creating a new user account, typically involving registration with an email and password. +- **Session**: A temporary state that maintains user authentication status, allowing access to protected resources. +- **Session Timeout**: The duration after which a session expires, requiring the user to sign in again. +- **Identity** - A representation of a user within the authentication system, including their credentials and associated metadata. An identity correlates an individual user with their authentication credentials, such as email and password, or OAuth tokens. A user can have multiple identities (e.g., one for email/password and another for OAuth). + +## Ongoing Documentation + +Documentation is continuously updated to reflect the latest architectural decisions, package features, and development practices. Key documentation files will be maintained in a docsify library in `apps/docs`. Docsify maintains a set of markdown files that are rendered as a static site, allowing for easy navigation and searchability. + +## Initial Functionality + +### Web-Based Authentication + +#### Traditional Registration + +An unauthenticated user can register by providing a valid, unique email address, password, and password. The system will validate the input, hash the password, and store the user in the database. + +Passwords should not be stored in plaintext. Instead, they should be hashed using a secure hashing algorithm (e.g., bcrypt) before being stored in the database. + +Passwords requirements should be configurable, allowing for flexibility in password policies (e.g., minimum length, complexity requirements). + +### Traditional Sign In + +An unauthenticated user can sign in by providing a valid email address and password. The system will validate the credentials, check the password against the stored hash, and create a session if successful. The system should not reveal whether the email address exists in the system to prevent enumeration attacks. It should simply indicate whether the sign-in was successful or not. + +### Forgot Password + +An authenticated user can request a password reset by providing their email address. The system will generate a secure, perishable token, send it to the user's email, and allow them to reset their password using that token. The token should have an expiration time to prevent misuse. + +Tokens cannot be reused. Once a password is reset using a token, the token should be invalidated to prevent further use. There should also be a configurable TTL (time-to-live) for the token, after which it will expire and no longer be valid. + +Different email providers should be considered. Basic SMTP support is required, but more advanced providers (e.g., SendGrid, Mailgun) may be added later. + +### Password Reset Email Confirmation + +Upon resetting their password, the user should receive a confirmation email indicating that their password has been successfully changed. This email should not contain the new password but simply confirm the change and offer an opportunity to take action if the user did not initiate the change. + +### Sign Out + +An authenticated user can sign out by terminating their session. The system should invalidate the user's session token, preventing further access to protected resources until the user signs in again. Systemically, the user should be forgotten until they sign in again, at which point a new session is created. diff --git a/.ai/shared/system-prompt.md b/.ai/shared/system-prompt.md new file mode 100644 index 0000000..59d3646 --- /dev/null +++ b/.ai/shared/system-prompt.md @@ -0,0 +1,32 @@ +# System Prompt for BoosterAuth + +You are working in the BoosterAuth monorepo. Please read and follow the guidance in these files: + +1. `.ai/shared/architectural-context.md` - Core architectural principles and patterns +2. `.ai/shared/library-prd.md` - Project overview and development philosophy + +## Key Principles + +- All code lives in `libs/` as independently publishable npm packages +- `apps/` contains implementation examples only +- TDD-first: Generate tests before implementations in `__tests__` directories +- Use TypeScript with strict mode, dependency injection, and Zod validation +- Follow security-first principles per Lucia auth patterns +- Respect architectural boundaries (no cross-dependencies without DI) +- Core services receive dependencies via constructor injection + +## Development Workflow + +1. Read this file and any related task prompt +2. Generate tests first in a contextual `__tests__` directory +3. Make the tests pass with minimal implementation +4. Suggest updates, refactorings, and improvements +5. Ensure all code follows security principles and architectural boundaries + +## Common Commands + +- `npx nx serve auth-backend-example` - Start development server +- `npx nx test ` - Run tests +- `npx nx lint ` - Lint code +- `npx nx typecheck ` - Type check +- `npx nx g @nx/node:lib ` - Generate new library \ No newline at end of file diff --git a/.ai/shared/user-stories/traditional-web-authentication/20250709_rate-limiting.md b/.ai/shared/user-stories/traditional-web-authentication/20250709_rate-limiting.md new file mode 100644 index 0000000..c8b96a5 --- /dev/null +++ b/.ai/shared/user-stories/traditional-web-authentication/20250709_rate-limiting.md @@ -0,0 +1,206 @@ +# User Story: Rate Limiting for Authentication + +**Epic**: Traditional Web-Based Authentication +**Story ID**: 20250709_rate-limiting +**Priority**: High +**Story Points**: 5 + +## User Story +**As a** developer integrating BoosterAuth into my application +**I want** configurable rate limiting across all authentication endpoints +**So that** my application is protected from brute force attacks and abuse while maintaining good user experience + +## Acceptance Criteria + +### Functional Requirements +- [ ] **Configurable Limits**: Rate limits configurable per endpoint type (sign-up, sign-in, password reset) +- [ ] **Multiple Strategies**: Support IP-based, user-based, and global rate limiting +- [ ] **Transport Agnostic**: Works across tRPC, REST, and GraphQL implementations +- [ ] **Graceful Degradation**: Clear error messages with retry timing information +- [ ] **Bypass Mechanisms**: Allow whitelisting of trusted IPs or user agents +- [ ] **Sliding Window**: Implement sliding window algorithm for fair rate limiting + +### Technical Requirements +- [ ] **Core Interface**: Define rate limiting interface in `@booster-auth/core` +- [ ] **Multiple Implementations**: Memory-based and Redis-based rate limiters +- [ ] **Middleware Integration**: Easy integration with tRPC, Express, and GraphQL +- [ ] **Configurable Storage**: Pluggable storage backends for rate limit data +- [ ] **Monitoring Support**: Metrics and logging for rate limit events +- [ ] **TypeScript**: Full type safety for all rate limiting configurations + +### Security Requirements +- [ ] **Attack Prevention**: Prevent brute force attacks on authentication endpoints +- [ ] **DDoS Protection**: Protect against distributed denial of service attacks +- [ ] **Enumeration Protection**: Rate limit email validation to prevent user enumeration +- [ ] **Adaptive Limits**: Optionally increase limits for verified users +- [ ] **Audit Logging**: Log all rate limit violations with context + +## Technical Implementation + +### Package Structure +```no-highlight +libs/ +โ”œโ”€โ”€ rate-limiting/ # Core rate limiting logic +โ”‚ โ””โ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ interfaces/ +โ”‚ โ”‚ โ”œโ”€โ”€ RateLimiter.ts +โ”‚ โ”‚ โ””โ”€โ”€ RateLimitStore.ts +โ”‚ โ”œโ”€โ”€ strategies/ +โ”‚ โ”‚ โ”œโ”€โ”€ SlidingWindowLimiter.ts +โ”‚ โ”‚ โ””โ”€โ”€ TokenBucketLimiter.ts +โ”‚ โ”œโ”€โ”€ stores/ +โ”‚ โ”‚ โ”œโ”€โ”€ MemoryRateLimitStore.ts +โ”‚ โ”‚ โ””โ”€โ”€ RedisRateLimitStore.ts +โ”‚ โ””โ”€โ”€ __tests__/ +โ”‚ โ””โ”€โ”€ RateLimiter.test.ts +โ”œโ”€โ”€ trpc/ +โ”‚ โ””โ”€โ”€ rate-limiting/ # tRPC middleware +โ”‚ โ””โ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ middleware/ +โ”‚ โ”‚ โ””โ”€โ”€ rateLimitMiddleware.ts +โ”‚ โ””โ”€โ”€ __tests__/ +โ”‚ โ””โ”€โ”€ rateLimitMiddleware.test.ts +โ”œโ”€โ”€ express/ +โ”‚ โ””โ”€โ”€ rate-limiting/ # Express middleware (future) +โ”‚ โ””โ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ middleware/ +โ”‚ โ”‚ โ””โ”€โ”€ rateLimitMiddleware.ts +โ”‚ โ””โ”€โ”€ __tests__/ +โ”‚ โ””โ”€โ”€ rateLimitMiddleware.test.ts +โ””โ”€โ”€ graphql/ + โ””โ”€โ”€ rate-limiting/ # GraphQL middleware (future) + โ””โ”€โ”€ src/ + โ”œโ”€โ”€ middleware/ + โ”‚ โ””โ”€โ”€ rateLimitMiddleware.ts + โ””โ”€โ”€ __tests__/ + โ””โ”€โ”€ rateLimitMiddleware.test.ts +``` + +### Core Interfaces +```typescript +// @booster-auth/core +export interface RateLimiter { + checkLimit(key: string, limit: number, windowMs: number): Promise; + reset(key: string): Promise; +} + +export interface RateLimitResult { + allowed: boolean; + remaining: number; + resetTime: Date; + retryAfter?: number; +} + +export interface RateLimitConfig { + maxAttempts: number; + windowMs: number; + keyGenerator: (req: any) => string; + skipSuccessfulRequests: boolean; + skipFailedRequests: boolean; +} +``` + +### tRPC Implementation +```typescript +// @booster-auth/trpc/rate-limiting +import { TRPCError } from '@trpc/server'; +import { RateLimiter, RateLimitConfig } from '@booster-auth/core'; + +export const createRateLimitMiddleware = ( + rateLimiter: RateLimiter, + config: RateLimitConfig +) => { + return async ({ ctx, next, type, path }) => { + const key = config.keyGenerator(ctx); + const result = await rateLimiter.checkLimit( + key, + config.maxAttempts, + config.windowMs + ); + + if (!result.allowed) { + throw new TRPCError({ + code: 'TOO_MANY_REQUESTS', + message: `Rate limit exceeded. Try again in ${result.retryAfter} seconds.`, + }); + } + + // Add rate limit info to context + ctx.rateLimitInfo = { + remaining: result.remaining, + resetTime: result.resetTime, + }; + + return next(); + }; +}; +``` + +### Usage Example +```typescript +// Example: Apply rate limiting to password auth router +import { createRateLimitMiddleware } from '@booster-auth/trpc/rate-limiting'; +import { MemoryRateLimitStore } from '@booster-auth/rate-limiting'; + +const rateLimiter = new MemoryRateLimitStore(); + +const authRateLimitConfig = { + maxAttempts: 5, + windowMs: 60 * 1000, // 1 minute + keyGenerator: (ctx) => ctx.req.ip, + skipSuccessfulRequests: false, + skipFailedRequests: false, +}; + +const rateLimitMiddleware = createRateLimitMiddleware(rateLimiter, authRateLimitConfig); + +export const passwordAuthRouter = router({ + signUp: publicProcedure + .use(rateLimitMiddleware) + .input(schemas.signUpInput) + .mutation(async ({ input, ctx }) => { + // Sign-up logic + }), +}); +``` + +## Data Flow +1. **Request Received**: Middleware intercepts request +2. **Key Generation**: Generate rate limit key (IP, user ID, etc.) +3. **Limit Check**: Check current usage against configured limits +4. **Decision**: Allow or reject request based on limits +5. **Response**: Return rate limit headers or error +6. **Cleanup**: Optional cleanup of expired rate limit data + +## Error Scenarios +- [ ] **Rate Limit Exceeded**: Clear error with retry timing +- [ ] **Storage Failure**: Graceful fallback behavior +- [ ] **Configuration Error**: Validation of rate limit configurations +- [ ] **Key Generation Failure**: Fallback key generation strategies + +## Definition of Done +- [ ] **Core Interfaces**: Rate limiting interfaces defined in core package +- [ ] **Memory Implementation**: In-memory rate limiter for development +- [ ] **Redis Implementation**: Redis-based rate limiter for production +- [ ] **tRPC Middleware**: Working middleware for tRPC procedures +- [ ] **Configuration**: Flexible configuration options +- [ ] **Testing**: Unit and integration tests with >90% coverage +- [ ] **Documentation**: Usage examples and configuration guide +- [ ] **Performance**: Rate limiting adds <10ms latency +- [ ] **Monitoring**: Metrics and logging for rate limit events + +## Dependencies +- Redis (optional, for distributed rate limiting) +- tRPC server +- Logging framework +- Metrics collection system + +## Notes +- This story focuses on tRPC implementation first +- REST and GraphQL implementations will follow similar patterns +- Storage backends are pluggable for different deployment scenarios +- Rate limiting is applied as middleware, not embedded in business logic +- Future enhancements: adaptive limits, machine learning-based detection + +--- +**Related Epic**: 20250709_traditional-web-authentication.md \ No newline at end of file diff --git a/.ai/shared/user-stories/traditional-web-authentication/20250709_user-sign-up.md b/.ai/shared/user-stories/traditional-web-authentication/20250709_user-sign-up.md new file mode 100644 index 0000000..f935b10 --- /dev/null +++ b/.ai/shared/user-stories/traditional-web-authentication/20250709_user-sign-up.md @@ -0,0 +1,334 @@ +# User Story: User Sign Up + +**Epic**: Traditional Web-Based Authentication +**Story ID**: 20250709_user-sign-up +**Priority**: High +**Story Points**: 8 + +## User Story + +**As a** developer building a SaaS application +**I want** to integrate secure password-based user registration in under 5 minutes +**So that** I can ship authentication to production quickly while maintaining enterprise-grade security and compliance readiness + +## Acceptance Criteria + +### Functional Requirements + +- [ ] **Email Validation**: System validates email format and uniqueness +- [ ] **Password Requirements**: Configurable password policy (length, complexity) +- [ ] **Account Creation**: New user account stored securely in database +- [ ] **Password Security**: Password hashed with bcrypt before storage +- [ ] **Error Handling**: Clear, non-enumerable error messages +- [ ] **Input Sanitization**: All inputs validated and sanitized. Emails are not case-sensitive by default, but this is configurable. + +### Technical Requirements + +- [ ] **Zod Schema**: Email and password validation using Zod schemas +- [ ] **TypeScript**: Full type safety for all interfaces +- [ ] **Dependency Injection**: Services receive dependencies via constructor +- [ ] **Database Abstraction**: No tight coupling to Prisma in core logic. Use Drizzle for contrast +- [ ] **Independent Testing**: Unit tests in `__tests__` directories +- [ ] **Package Structure**: Core interfaces separate from implementations + +### Security Requirements + +- [ ] **Password Hashing**: bcrypt with configurable rounds (default: 12, minimum: 10) +- [ ] **Enumeration Protection**: Generic responses that don't reveal account existence +- [ ] **Input Validation**: Prevent injection attacks and malformed data +- [ ] **Timing Attack Protection**: Consistent response times +- [ ] **No Plaintext Storage**: Passwords never stored in plaintext + +## Technical Implementation + +### Package Structure + +```no-highlight +libs/ +โ”œโ”€โ”€ core/ # Core interfaces for identity validation +โ”‚ โ””โ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ interfaces/ +โ”‚ โ”‚ โ”œโ”€โ”€ IdentityValidator.ts +โ”‚ โ”‚ โ””โ”€โ”€ UserValidator.ts +โ”‚ โ””โ”€โ”€ types/ +โ”‚ โ”œโ”€โ”€ Identity.ts +โ”‚ โ”œโ”€โ”€ User.ts +โ”‚ โ””โ”€โ”€ ValidationResult.ts +โ”œโ”€โ”€ password-auth/ # Password-based authentication +โ”‚ โ””โ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ identity/ +โ”‚ โ”‚ โ””โ”€โ”€ PasswordIdentity.ts +โ”‚ โ”œโ”€โ”€ interfaces/ +โ”‚ โ”‚ โ””โ”€โ”€ PasswordIdentityRepository.ts +โ”‚ โ”œโ”€โ”€ services/ +โ”‚ โ”‚ โ””โ”€โ”€ PasswordAuthService.ts +โ”‚ โ”œโ”€โ”€ schemas/ +โ”‚ โ”‚ โ””โ”€โ”€ passwordAuthSchemas.ts +โ”‚ โ””โ”€โ”€ __tests__/ +โ”‚ โ”œโ”€โ”€ PasswordIdentity.test.ts +โ”‚ โ””โ”€โ”€ PasswordAuthService.test.ts +โ”œโ”€โ”€ password-policy/ # Password policy validation +โ”‚ โ””โ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ schemas/ +โ”‚ โ”‚ โ””โ”€โ”€ passwordPolicySchema.ts +โ”‚ โ”œโ”€โ”€ services/ +โ”‚ โ”‚ โ””โ”€โ”€ PasswordPolicyService.ts +โ”‚ โ””โ”€โ”€ __tests__/ +โ”‚ โ””โ”€โ”€ PasswordPolicyService.test.ts +โ”œโ”€โ”€ trpc/ # tRPC route implementations +โ”‚ โ””โ”€โ”€ password-auth/ # tRPC routes for password auth +โ”‚ โ””โ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ passwordAuthRouter.ts +โ”‚ โ””โ”€โ”€ __tests__/ +โ”‚ โ””โ”€โ”€ passwordAuthRouter.test.ts +โ””โ”€โ”€ prisma/ # Prisma implementations + โ””โ”€โ”€ password-auth/ # Prisma implementation for password auth + โ””โ”€โ”€ src/ + โ”œโ”€โ”€ repositories/ + โ”‚ โ””โ”€โ”€ PrismaPasswordIdentityRepository.ts + โ””โ”€โ”€ __tests__/ + โ””โ”€โ”€ PrismaPasswordIdentityRepository.test.ts +``` + +### Core Interfaces + +```typescript +// @booster-auth/core +export interface PasswordIdentityService { + signUp(request: PasswordSignUpRequest): Promise; +} + +export interface PasswordHasher { + hash(password: string): Promise; + verify(password: string, hash: string): Promise; +} + +export interface EmailValidator { + validate(email: string): Promise; // Encapsulates format + uniqueness +} + +export interface PasswordValidator { + validate(password: string, passwordConfirmation: string): ValidationResult; // Encapsulates policy + confirmation +} + +export interface UserRepository { + findByEmail(email: string): Promise; + findById(id: string): Promise; + create(userData: CreatePasswordUserData): Promise; +} +``` + +### Core Types (Primitive Properties Only) + +```typescript +// @booster-auth/core +export interface PasswordSignUpRequest { + email: string; + password: string; + passwordConfirmation: string; +} + +export interface CreatePasswordUserData { + email: string; + passwordHash: string; + createdAt: string; // ISO string +} + +export interface User { + id: string; + email: string; + createdAt: string; // ISO string + updatedAt: string; // ISO string +} + +export interface ValidationResult { + isValid: boolean; + error?: string; +} + +export interface PasswordSignUpResult { + success: boolean; + userId?: string; + error?: string; +} +``` + +### Password Policy Library + +```typescript +// @booster-auth/password-policy +import { z } from 'zod'; + +export type PasswordSchema = z.ZodString; + +// Default password schema - can be overridden +export const defaultPasswordSchema: PasswordSchema = z.string() + .min(8, 'Password must be at least 8 characters') + .regex(/[A-Z]/, 'Password must contain at least one uppercase letter') + .regex(/[a-z]/, 'Password must contain at least one lowercase letter') + .regex(/[0-9]/, 'Password must contain at least one number'); + +// Example alternative schemas +export const strictPasswordSchema: PasswordSchema = z.string() + .min(12, 'Password must be at least 12 characters') + .max(128, 'Password must be no more than 128 characters') + .regex(/[A-Z]/, 'Password must contain at least one uppercase letter') + .regex(/[a-z]/, 'Password must contain at least one lowercase letter') + .regex(/[0-9]/, 'Password must contain at least one number') + .regex(/[!@#$%^&*(),.?":{}|<>]/, 'Password must contain at least one special character'); + +export const simplePasswordSchema: PasswordSchema = z.string() + .min(6, 'Password must be at least 6 characters'); +``` + +### Shared Authentication Schemas + +```typescript +// @booster-auth/password-auth/schemas +import { z } from 'zod'; +import { defaultPasswordSchema, PasswordSchema } from '@booster-auth/password-policy'; + +export const createPasswordAuthSchemas = (passwordSchema: PasswordSchema = defaultPasswordSchema) => { + const signUpInputSchema = z.object({ + email: z.string().email('Invalid email format'), + password: passwordSchema, + passwordConfirmation: z.string(), + }).refine((data) => data.password === data.passwordConfirmation, { + message: 'Passwords do not match', + path: ['passwordConfirmation'], + }); + + const signUpOutputSchema = z.object({ + success: z.boolean(), + userId: z.string().optional(), + error: z.string().optional(), + }); + + return { + signUpInput: signUpInputSchema, + signUpOutput: signUpOutputSchema, + }; +}; +``` + +### tRPC Router Implementation + +```typescript +// @booster-auth/trpc/password-auth +import { router, publicProcedure } from '@trpc/server'; +import { TRPCError } from '@trpc/server'; +import { createPasswordAuthSchemas } from '@booster-auth/password-auth/schemas'; +import { defaultPasswordSchema, PasswordSchema } from '@booster-auth/password-policy'; + +export const createPasswordAuthRouter = (passwordSchema: PasswordSchema = defaultPasswordSchema) => { + const schemas = createPasswordAuthSchemas(passwordSchema); + + return router({ + signUp: publicProcedure + .input(schemas.signUpInput) + .output(schemas.signUpOutput) + .mutation(async ({ input, ctx }) => { + const passwordAuthService = ctx.passwordAuthService; + + const result = await passwordAuthService.signUp(input); + + if (!result.success) { + throw new TRPCError({ + code: 'BAD_REQUEST', + message: result.error || 'Sign up failed', + }); + } + + return result; + }), + }); +}; + +// Usage examples +const customPasswordSchema = z.string() + .min(10) + .refine((password) => !password.includes('password'), { + message: 'Password cannot contain the word "password"', + }); + +export const customPasswordAuthRouter = createPasswordAuthRouter(customPasswordSchema); +``` + +### Architectural Considerations + +- **No Java Conventions**: Avoid "I" prefix for interfaces - types should be intuitively expressive +- **TypeScript Native**: Use TypeScript conventions and patterns +- **Granular Interfaces**: Each interface has a single, focused responsibility +- **Separation of Concerns**: Validation, storage, and business logic are separate packages +- **Dependency Injection**: Constructor injection without framework-specific annotations +- **Package Boundaries**: Clear separation between core interfaces and implementations + +### Data Flow + +1. **Email Validation**: EmailValidator validates format and uniqueness +2. **Password Validation**: PasswordValidator validates policy and confirmation match +3. **Password Hashing**: PasswordHasher hashes password securely +4. **Account Creation**: UserRepository creates new user record +5. **Response**: Generic success/failure response + +### Error Scenarios + +- [ ] **Invalid Email Format/Duplicate**: Validation error from EmailValidator +- [ ] **Weak Password/Mismatch**: Password policy or confirmation error from PasswordValidator +- [ ] **Database Error**: Generic system error (no details leaked) +- [ ] **Concurrent Registration**: Handle duplicate email race conditions gracefully + +## Definition of Done + +- [ ] **Core Interfaces**: Defined in `@booster-auth/core` package +- [ ] **Implementation**: Working `IdentityService` with dependency injection +- [ ] **Password Hashing**: Secure bcrypt implementation +- [ ] **Validation**: Separate email and password validators +- [ ] **Storage**: Database abstraction layer +- [ ] **Unit Tests**: >90% coverage for all components +- [ ] **Integration Tests**: End-to-end sign-up flow +- [ ] **Security Review**: All security criteria met +- [ ] **Documentation**: API documentation and usage examples +- [ ] **Performance**: Sign-up completes within 2 seconds +- [ ] **Example App**: Working example in `apps/` directory + +## Dependencies + +- **Database**: User storage capability +- **Validation**: Zod for schema validation +- **Hashing**: bcrypt for password security +- **Testing**: Jest for unit/integration tests + +## Risks & Mitigation + +- **Risk**: Password policy too restrictive +- **Mitigation**: Make password requirements configurable + +- **Risk**: Database performance issues +- **Mitigation**: Efficient queries, proper indexing + +- **Risk**: Enumeration attacks +- **Mitigation**: Generic error messages, consistent timing + +## Notes + +### **Current Scope** +- This story focuses on core sign-up functionality with tRPC integration +- Email verification will be addressed in separate story +- Session creation after sign-up is handled by sign-in flow +- Password reset functionality is separate epic requirement +- **Rate limiting** is handled in separate user story (20250709_rate-limiting.md) + +### **Business Impact** +- **Developer Productivity**: 5-minute integration saves 2-3 days of auth implementation +- **Security Posture**: Enterprise-grade security reduces compliance risk +- **Time-to-Market**: Faster auth implementation accelerates product launches + +### **Technical Decisions** +- tRPC router is designed to be mountable to existing applications +- Future support for REST and GraphQL will follow similar patterns +- Business logic remains transport-agnostic for maximum flexibility +- Rate limiting applied as middleware (see separate story) + +--- +**Related Epic**: 20250709_traditional-web-authentication.md diff --git a/.ai/shared/web/system-prompt.md b/.ai/shared/web/system-prompt.md new file mode 100644 index 0000000..9804748 --- /dev/null +++ b/.ai/shared/web/system-prompt.md @@ -0,0 +1,27 @@ +# System Prompt for Booster Auth + +I intend to create a node / react library for authentication. I'm a principal Engineer / CTO with years of experience with React, TypeScript, and NodeJS. I intend to make this library (or suite of NPM packages) a component of a larger, proprietary SaaS template. I'm conceptually calling this project booster-saas, and it will be composed of a number of open source NPM packages. This component will be called booster-auth. + +The suite should encourage the following defaults: + +- Express on the backend (AWS ECS Fargate as an example deployment platform) +- React on the frontend (AWS Cloudfront as an example deployment platform) +- PG as the database (Aurora PG as an example, cloud-based database) +- Tanstack Router +- Tanstack React Query +- Prisma on the backend +- TRPC as the transport layer between backend and frontend + +The NPM packages will be built within an NX monorepo using the latest typescript. ESLint rules will be strictly adhered to, and CI will be configured to run a test suite and ESLint run on every pull request. I also want to explore different AI PR review tools as part of this pursuit. + +I'm a big fan (and experienced engineer) within the Rails ecosystem, and I'm a believer in both convention over configuration and test driven development. + +I think it's important for the engineer to be able to override these defaults. Of note, is the possibility of a NextJS or Tanstack Start as backend alternatives, and using reasonable alternatives like Drizzle for ORM. + +I am not a fan of bloated frameworks such as Nest, a framework that seemingly endeavors to make the NodeJS developer experience feel like developing on Java Spring. + +The development of this suite will be heavily AI assisted, which is a primary aspect of this pursuit. I plan to use Claude CLI, GitHub CoPilot and Google's Jules (an AI agent that can issue PRs). I want to consider PR review agents as well, and while I haven't settled on a default tool for this, I'm impressed by CodeRabbit. + +As it pertains to authentication itself, I think the principles espoused by Lucia should be of primary record. Better Auth is also an inspirational implementation, but I have some contrasting opinions. + +As you advise me, security should remain paramount. I want to create something that is extensible and thoughtful, but it must be reasonably secure, primarily. diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..4be17fb --- /dev/null +++ b/.cursorrules @@ -0,0 +1,15 @@ +# Cursor Guidance for Booster Auth Monorepo + +You are working in the BoosterAuth monorepo. Please read and follow the guidance in these files: + +1. `.ai/shared/architectural-context.md` - Core architectural principles and patterns +2. `.ai/shared/library-prd.md` - Project overview and development philosophy + +Key principles: + +- All code lives in `libs/` as independently publishable npm packages +- `apps/` contains implementation examples only +- TDD-first: Generate tests before implementations +- Use TypeScript with strict mode, dependency injection, and Zod validation +- Follow security-first principles per Lucia auth patterns +- Respect architectural boundaries (no cross-dependencies without DI) diff --git a/.editorconfig b/.editorconfig index 6e87a00..3836c8f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,5 +9,5 @@ insert_final_newline = true trim_trailing_whitespace = true [*.md] -max_line_length = off +max_line_length = 120 trim_trailing_whitespace = false diff --git a/.gemini/instructions.md b/.gemini/instructions.md new file mode 100644 index 0000000..b83f457 --- /dev/null +++ b/.gemini/instructions.md @@ -0,0 +1,24 @@ +# Gemini CLI Instructions for BoosterAuth + +Please read and follow the guidance in these files before working on any tasks: + +1. `.ai/shared/architectural-context.md` - Core architectural principles and patterns +2. `.ai/shared/library-prd.md` - Project overview and development philosophy + +## Key Principles + +- All code lives in `libs/` as independently publishable npm packages +- `apps/` contains implementation examples only +- TDD-first: Generate tests before implementations in `__tests__` directories +- Use TypeScript with strict mode, dependency injection, and Zod validation +- Follow security-first principles per Lucia auth patterns +- Respect architectural boundaries (no cross-dependencies without DI) +- Core services receive dependencies via constructor injection + +## Commands + +- `npx nx serve auth-backend-example` - Start development server +- `npx nx test ` - Run tests +- `npx nx lint ` - Lint code +- `npx nx typecheck ` - Type check +- `npx nx g @nx/node:lib ` - Generate new library \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 544138b..d7a7b09 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,3 +1,5 @@ { - "singleQuote": true + "singleQuote": true, + "proseWrap": "always", + "printWidth": 120 } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8e21401 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "nxConsole.generateAiAgentRules": true +} diff --git a/README.md b/README.md index 533717b..a6e4b7a 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,7 @@ # BoosterAuth - +A TypeScript monorepo for modular, secure, and extensible authentication systems. -โœจ Your new, shiny [Nx workspace](https://nx.dev) is almost ready โœจ. +It is built with Node.js/TypeScript and Express, following Nx conventions for workspace management and using pnpm as the package manager. -[Learn more about this workspace setup and its capabilities](https://nx.dev/nx-api/node?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or run `npx nx graph` to visually explore what was created. Now, let's get you up to speed! - -## Finish your CI setup - -[Click here to finish setting up your workspace!](https://cloud.nx.app/connect/gzqWS9YtpW) - - -## Run tasks - -To run the dev server for your app, use: - -```sh -npx nx serve auth-backend-example -``` - -To create a production bundle: - -```sh -npx nx build auth-backend-example -``` - -To see all available targets to run for a project, run: - -```sh -npx nx show project auth-backend-example -``` - -These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the `project.json` or `package.json` files. - -[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) - -## Add new projects - -While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature. - -Use the plugin's generator to create new projects. - -To generate a new application, use: - -```sh -npx nx g @nx/node:app demo -``` - -To generate a new library, use: - -```sh -npx nx g @nx/node:lib mylib -``` - -You can use `npx nx list` to get a list of installed plugins. Then, run `npx nx list ` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE. - -[Learn more about Nx plugins »](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) | [Browse the plugin registry »](https://nx.dev/plugin-registry?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) - - -[Learn more about Nx on CI](https://nx.dev/ci/intro/ci-with-nx#ready-get-started-with-your-provider?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) - -## Install Nx Console - -Nx Console is an editor extension that enriches your developer experience. It lets you run tasks, generate code, and improves code autocompletion in your IDE. It is available for VSCode and IntelliJ. - -[Install Nx Console »](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) - -## Useful links - -Learn more: - -- [Learn more about this workspace setup](https://nx.dev/nx-api/node?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) -- [Learn about Nx on CI](https://nx.dev/ci/intro/ci-with-nx?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) -- [Releasing Packages with Nx release](https://nx.dev/features/manage-releases?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) -- [What are Nx plugins?](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) - -And join the Nx community: -- [Discord](https://go.nx.dev/community) -- [Follow us on X](https://twitter.com/nxdevtools) or [LinkedIn](https://www.linkedin.com/company/nrwl) -- [Our Youtube channel](https://www.youtube.com/@nxdevtools) -- [Our blog](https://nx.dev/blog?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) +AI is a first-order consideration in this monorepo, with agents used to scaffold, test, and iterate on new features.