# Zephyr Framework - Cursor AI Rules

# Ack To user

"Hi, I'm following the rules strictly from the `.cursorrules`"
this one should be the very first response from you.


# ASK RULES:

DO NOT ALWAYS GIVE OR DUMP CODE/IMPLEMENTATION IF NOT ASKED FOR!! GIVE SNIPPETS IF REQUIRED.

AND DO NOT CREATE A DOC/MD FILES IF NOT ASKED TO CREATE ONE.
And, USE MERMAID CHARTS OVER ASCII BASED ONE.


## Project Architecture

This is **Zephyr** - a modern, high-performance Python ASGI web framework with enterprise-grade capabilities including JWT authentication, RBAC, rate limiting, advanced caching, and comprehensive security features.

**Project Root:** `/projects/bbdevs/work/bbdevs_projects/zephyr`

## Python Code Standards

### File Structure

- Use standard Python project layout with `zephyr/` as main package
- Keep modules focused and single-responsibility
- Use meaningful module and package names
- Organize by functionality: `core/`, `security/`, `app/`, `middleware/`

### File Naming Convention

**Module Files (lowercase with underscores):**
- ✅ `auth_service.py` (service/business logic)
- ✅ `jwt.py` (auth utilities)
- ✅ `cache.py` (caching utilities)
- ✅ `middleware.py` (middleware)
- ✅ `models.py` (data models)
- ❌ `AuthService.py` (PascalCase for modules - Python convention is lowercase)
- ❌ `JWTManager.py` (PascalCase for modules)

**Class Names (PascalCase):**
- ✅ `class JWTManager:` (classes use PascalCase)
- ✅ `class RBACManager:` (classes use PascalCase)
- ✅ `class SessionManager:` (classes use PascalCase)
- ❌ `class jwt_manager:` (lowercase for classes)

**Function/Variable Names (snake_case):**
- ✅ `def authenticate_user():` (functions use snake_case)
- ✅ `def validate_token():` (functions use snake_case)
- ✅ `user_id = 123` (variables use snake_case)
- ❌ `def authenticateUser():` (camelCase for functions)

**Constant Names (UPPER_SNAKE_CASE):**
- ✅ `MAX_TOKEN_AGE = 3600`
- ✅ `JWT_ALGORITHM = "HS256"`
- ✅ `RATE_LIMIT_WINDOW = 60`
- ❌ `max_token_age = 3600` (lowercase for constants)

## TypeScript/Type Hints

### Type Hints REQUIRED

- Use modern Python type hints (3.11+)
- Use built-in types: `list`, `dict`, `tuple`, `set` (not `List`, `Dict`, `Tuple`, `Set`)
- Use `|` for unions instead of `Union` (e.g., `str | int | None`)
- Use `None` instead of `Optional`
- Always include `from __future__ import annotations` for forward references

### Unified Type Aliases (MANDATORY - defined in `zephyr/_types.py`)

**NEVER use `Any` or raw `**kwargs: Any`/`**args: Any`**

Instead, use these unified types from `zephyr._types`:

```python
from zephyr._types import ALL, KWARGS, ARGS

# ALL - represents any primitive or collection value
ALL = str | int | float | bool | None | list | dict

# KWARGS - for **kwargs parameters (use instead of **kwargs: Any)
KWARGS = dict[str, ALL]

# ARGS - for *args parameters (use instead of *args: Any)
ARGS = tuple[ALL, ...]
```

**Usage Examples:**

```python
# ✅ CORRECT - Using unified types
def process_data(**kwargs: ALL) -> None:
    pass

def batch_operation(*args: ALL) -> None:
    pass

def handle_metadata(metadata: KWARGS) -> None:
    pass

# ❌ WRONG - Using Any
def process_data(**kwargs: Any) -> None:  # DO NOT USE
    pass

def batch_operation(*args: Any) -> None:  # DO NOT USE
    pass
```

**CORRECT:**
```python
from __future__ import annotations

def get_user(user_id: int) -> dict | None:
    pass

def process_tokens(tokens: list[str]) -> None:
    pass

def validate_request(data: str | bytes, ttl: int = 3600) -> dict:
    pass
```

**WRONG:**
```python
from typing import Optional, List, Dict, Union

def get_user(user_id: int) -> Optional[Dict]:
    pass

def process_tokens(tokens: List[str]) -> None:
    pass

def validate_request(data: Union[str, bytes], ttl: int = 3600) -> Dict:
    pass
```

## Code Style

- Follow **ruff** linting standards strictly (`ruff check --fix`)
- Use **4 spaces** for indentation (no tabs)
- Maximum line length: **120 characters** (Zephyr standard)
- Follow **PEP 8** conventions
- Use type hints for all function parameters and return types
- Docstrings for modules, classes, and public functions
- Use `TYPE_CHECKING` block for avoiding circular imports

**Docstring Format (Google Style):**
```python
def authenticate_user(username: str, password: str) -> bool:
    """Authenticate a user with username and password.
    
    Args:
        username: The user's username.
        password: The user's password.
        
    Returns:
        True if authentication succeeds, False otherwise.
        
    Raises:
        AuthenticationError: If authentication fails.
    """
    pass
```

## Project Structure

```
zephyr/
├── zephyr/                      # Main package
│   ├── __init__.py
│   ├── __version__.py           # Version info
│   ├── _types.py                # Type definitions
│   ├── app/                     # Core framework
│   │   ├── __init__.py
│   │   ├── application.py       # Main Zephyr app class
│   │   ├── routing.py           # Router implementation
│   │   ├── requests.py          # Request handling
│   │   ├── responses.py         # Response handling
│   │   ├── middleware/          # Middleware components
│   │   ├── openapi/             # OpenAPI schema generation
│   │   ├── dependencies/        # Dependency injection
│   │   ├── security/            # Security utilities
│   │   └── websockets.py        # WebSocket support
│   ├── security/                # Security module
│   │   ├── __init__.py
│   │   ├── jwt.py               # JWT token management
│   │   ├── password.py          # Password hashing
│   │   ├── tokens.py            # Token utilities
│   │   ├── rbac/                # Role-Based Access Control
│   │   ├── sessions/            # Session management
│   │   ├── oauth2/              # OAuth2 implementation
│   │   ├── sso/                 # Single Sign-On
│   │   ├── mfa/                 # Multi-Factor Authentication
│   │   ├── webauthn/            # WebAuthn support
│   │   ├── ldap/                # LDAP integration
│   │   └── keycloak/            # Keycloak integration
│   ├── core/                    # Core utilities
│   │   ├── __init__.py
│   │   ├── logging/             # Structured logging
│   │   ├── zserver/             # Server implementation
│   │   ├── storage/             # Storage backends
│   │   └── loops.py             # Event loop management
│   ├── conf/                    # Configuration
│   │   ├── __init__.py
│   │   └── base.py              # BaseSettings
│   ├── middleware/              # Middleware
│   └── exceptions.py            # Custom exceptions
├── tests/                       # Test suite
│   ├── __init__.py
│   ├── conftest.py
│   ├── unit/                    # Unit tests
│   └── integration/             # Integration tests
├── docs/                        # Documentation
├── examples/                    # Example applications
├── stubs/                       # Type stubs (.pyi files)
├── pyproject.toml              # Project configuration
├── uv.lock                     # Dependency lock file
├── Makefile                    # Development tasks
└── README.md                   # Project documentation
```

## Package Manager

- Use **uv** for Python dependency management (modern, fast)
- Lock file: `uv.lock`
- pyproject.toml for all dependency management
- Install: `uv sync`
- Add packages: `uv add package-name`

## Testing

- Test files colocated in `tests/` directory
- Use `.py` extension (standard Python convention)
- Use **pytest** framework
- Run: `pytest` or `make test`
- Coverage: `pytest --cov=zephyr`
- Markers: `@pytest.mark.unit`, `@pytest.mark.integration`, `@pytest.mark.security`, `@pytest.mark.jwt`, `@pytest.mark.auth`

## Best Practices

1. Keep modules focused and single-responsibility (SOLID)
2. Use dependency injection for loose coupling
3. Handle errors explicitly with custom exceptions
4. Use type hints everywhere (strict mypy mode)
5. Write docstrings for all public APIs
6. Keep functions small and focused
7. Use meaningful variable/function names
8. Implement proper structured logging (use `structlog`)
9. Use async/await for I/O operations
10. Implement proper security (no hardcoded secrets, use environment variables)

## Security Best Practices (MANDATORY)

- ✅ Use environment variables for secrets (via `BaseSettings`)
- ✅ Implement input validation (Pydantic models)
- ✅ Hash passwords with bcrypt/Argon2 (never plaintext)
- ✅ Use secure JWT algorithms (HS256, RS256, not HS128)
- ✅ Implement rate limiting (Redis-backed for production)
- ✅ Use HTTPS in production (enforce SSL/TLS)
- ✅ Implement CSRF protection for state-changing operations
- ✅ Set secure headers (Content-Security-Policy, etc.)
- ✅ Validate all user inputs
- ✅ Use parameterized queries (SQLAlchemy ORM)
- ✅ Never log sensitive data (passwords, tokens, PII)
- ✅ Implement proper authentication and authorization

## What NOT to Do

- ❌ **DO NOT use `Any` type hints** - Use `ALL`, `KWARGS`, or `ARGS` from `zephyr._types`
- ❌ **DO NOT use `**kwargs: Any`** - Use `**kwargs: ALL` instead
- ❌ **DO NOT use `*args: Any`** - Use `*args: ALL` instead
- ❌ Don't use PascalCase for module names
- ❌ Don't use relative imports across packages
- ❌ Don't hardcode secrets in code
- ❌ Don't skip type hints
- ❌ Don't use `from module import *`
- ❌ Don't mix business logic with route handlers
- ❌ Don't ignore error cases
- ❌ Don't create circular imports
- ❌ Don't use `print()` for logging (use `structlog` or `logging`)
- ❌ Don't store passwords in plaintext
- ❌ Don't disable CSRF protection
- ❌ Don't implement weak authentication

---

## Linting Standards (MANDATORY)

### Rules That Must Be Followed During Code Generation

**CRITICAL - Zero Tolerance:**
1. ❌ **NO `assert` in production code** (S101) - Use custom exceptions
2. ❌ **NO timezone-naive datetime** (DTZ003) - Always use `datetime.now(timezone.utc)`
3. ❌ **NO undefined names** (F821) - All names must be defined/imported
4. ❌ **NO print statements** (T201) - Use logging
5. ❌ **NO commented-out code** (ERA001) - Remove or document why kept

**Code Quality - Must Follow:**
1. ✅ **No unused arguments** (ARG001/ARG002) - Prefix with `_` if intentional
2. ✅ **Specific exception catching** (BLE001) - Never use bare `except Exception:`
3. ✅ **Limit function arguments** (PLR0913) - Max 5 args, use config objects for more
4. ✅ **No magic values** (PLR2004) - Define constants for numbers/strings
5. ✅ **Boolean args keyword-only** (FBT001/FBT002) - Use `*,` or Enums
6. ✅ **Use custom exceptions** - Never use built-in exceptions (ValueError, TypeError, etc.)

**Exception Handling - Use Custom Exceptions:**
```python
# ❌ WRONG - Built-in exception with f-string
raise ValueError(f"Error: {message}")

# ❌ WRONG - Built-in exception even with variable
msg = f"Error: {message}"
raise ValueError(msg)

# ✅ CORRECT - Custom exception with clear error
class InvalidUserError(ZephyrException):
    """Raised when user validation fails."""
    def __init__(self, message: str) -> None:
        super().__init__(message)

msg = f"Error: {message}"
raise InvalidUserError(msg)

# ✅ BEST - Custom exception with predefined message
class EmptyTokenError(TokenError):
    """Raised when token is empty."""
    def __init__(self) -> None:
        super().__init__("Token cannot be empty")

raise EmptyTokenError()
```

**Custom Exception Hierarchy:**
```python
# Base exception
class ZephyrException(Exception):
    """Base exception for all Zephyr errors."""
    pass

# Domain-specific exceptions
class AuthenticationError(ZephyrException):
    """Authentication failed."""
    pass

class TokenError(AuthenticationError):
    """Token-related errors."""
    pass

class SessionError(ZephyrException):
    """Session-related errors."""
    pass

class ValidationError(ZephyrException):
    """Input validation errors."""
    pass
```

**Typing - NO `Any` types (ANN401):**
```python
from zephyr._types import ALL, KWARGS, ARGS

# ❌ WRONG - Using Any
def process(**kwargs: Any) -> Any:
    pass

def batch(*args: Any) -> Any:
    pass

# ✅ CORRECT - Using unified types
def process(**kwargs: ALL) -> None:
    pass

def batch(*args: ALL) -> None:
    pass

def handle_data(data: KWARGS) -> None:
    pass
```

**Datetime Usage:**
```python
# ❌ WRONG
from datetime import datetime
now = datetime.utcnow()

# ✅ CORRECT
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
```

**Assert Usage:**
```python
# ❌ WRONG (production code)
assert user is not None, "User required"

# ✅ CORRECT - Use custom exception
if user is None:
    raise UserNotFoundError("User required")

# ✅ OK (test files only)
def test_user():
    assert user.id == "123"
```

**Logging:**
```python
# ❌ WRONG
print(f"Processing {count} items")

# ✅ CORRECT
logger.info("Processing %d items", count)
```

**Method Arguments:**
```python
# ❌ WRONG
@validator("field")
def validate_field(cls, v):  # Should be @classmethod
    return v

# ✅ CORRECT
@field_validator("field")
@classmethod
def validate_field(cls, v: str) -> str:
    return v
```

**Function Design:**
```python
# ❌ WRONG - Too many args, boolean positional
def create_session(user_id, duration, ip, agent, secure, http_only, same_site, domain, path):
    pass

# ✅ CORRECT - Config object, keyword-only booleans
@dataclass
class SessionConfig:
    duration: int = 3600
    secure: bool = False
    http_only: bool = True

def create_session(user_id: str, *, config: SessionConfig | None = None):
    pass
```

### Enforcement in Code Generation

**When generating ANY code, the AI must:**
1. ✅ Use `datetime.now(timezone.utc)` instead of `datetime.utcnow()`
2. ✅ Use custom exceptions instead of asserts
3. ✅ Use custom exceptions instead of built-in exceptions
4. ✅ Use logger instead of print
5. ✅ Define constants for magic values
6. ✅ Make boolean arguments keyword-only
7. ✅ Catch specific exceptions, not bare `Exception`
8. ✅ Limit function arguments to 5 or use config objects
9. ✅ Prefix unused arguments with `_`
10. ✅ Never leave commented-out code

**These rules apply to:**
- New code generation
- Code refactoring
- Bug fixes
- Feature additions
- Test code (except asserts are allowed in tests)

**Separate linting fixes are only allowed when:**
- Fixing existing legacy code
- Batch cleanup operations
- Automated refactoring tools

---

## ⚠️ MANDATORY ENFORCEMENT - AI ACKNOWLEDGMENT REQUIRED

**BEFORE making ANY code changes, Cursor AI MUST state:**

```
📋 Rules Source: .cursorrules (Zephyr Framework Root: /projects/bbdevs/work/bbdevs_projects/zephyr)
🏗️  Architecture: Python ASGI Web Framework
📁 Creating/Modifying: [list files with names]
✅ Modern type hints (list, dict, | None, | instead of Union)
✅ snake_case for modules/functions/variables
✅ PascalCase for classes
✅ UPPER_SNAKE_CASE for constants
✅ Ruff-compliant code style (line length: 120)
✅ No `typing` module (Optional, List, Dict, Union)
✅ `from __future__ import annotations` for forward references
✅ Security best practices enforced
❌ DO NOT CREATE DOC OR MD FILES UNLESS ASKED TO CREATE ONE FOR EACH TASK OR REQUEST
❌ DO NOT CREATE ANY DOC files (with any extetnions!!!) or dump all in the chat unwanetedly unless asked for!!!!
❌ DO NOT IMPLEMENT OR PROVIDE CODE UNLESS EXPLICITLY ASKED FOR IT (ASK MODE)
❌ DO NOT HARDCODE SECRETS or API KEYS
❌ DO NOT INCLUDE NAMES OF EXTERNAL SERVICES OR FRAMEWORKS IN THE CODE OR DOCUMENTATION like FastAPI, Django, etc.
```

---

## Git Commit Message Standards (MANDATORY)

### Commit Message Format

**Subject Line (First Line):**
- ✅ **Maximum 50 characters** (STRICT LIMIT)
- ✅ Use imperative mood ("fix", "add", "update", not "fixed", "added", "updated")
- ✅ Start with type prefix: `fix:`, `feat:`, `chore:`, `docs:`, `test:`, `refactor:`
- ✅ No period at the end
- ✅ Capitalize first letter after colon

**Body (Optional, after blank line):**
- ✅ Wrap at 72 characters per line
- ✅ Explain what and why, not how
- ✅ Use bullet points for multiple changes
- ✅ Keep max 5-8 lines on body if possible.


**Examples:**

```
✅ CORRECT (50 chars or less):
fix(sso): replace Any types with KWARGS/ALL
feat(auth): add JWT token refresh endpoint
chore(deps): update pydantic to v2.11.0
docs(api): update authentication guide
test(sso): add OAuth2 flow integration tests

❌ WRONG (>50 chars):
fix(sso): replace generic types with KWARGS/ALL and fix all linting issues
feat(authentication): implement comprehensive JWT token refresh endpoint with validation
```

**Type Prefixes:**
- `fix:` - Bug fixes
- `feat:` - New features
- `chore:` - Maintenance tasks (deps, config, etc.)
- `docs:` - Documentation changes
- `test:` - Test additions/changes
- `refactor:` - Code refactoring
- `perf:` - Performance improvements
- `style:` - Code style changes (formatting, etc.)
- `ci:` - CI/CD changes

**Scope (Optional but Recommended):**
- Use parentheses after type: `fix(sso):`, `feat(auth):`, `chore(deps):`
- Keep scope short: `sso`, `auth`, `jwt`, `rbac`, `cache`, `db`, `api`

### AI Enforcement

**BEFORE committing, Cursor AI MUST:**
1. ✅ Count subject line characters (including type prefix)
2. ✅ Ensure subject ≤ 50 characters
3. ✅ Use imperative mood
4. ✅ Include type prefix
5. ✅ If >50 chars, shorten or move details to body

**If commit message is too long:**
- Move detailed explanation to commit body
- Use shorter scope names
- Remove redundant words
- Focus on the primary change in subject

---

### Enforcement Mechanisms

**Rules are enforced by:**

1. **Ruff** - Code style and type checking (`ruff check --fix`)
2. **MyPy** - Type checking (strict mode: `mypy --strict`)
3. **Pre-Commit Hooks** - Validates code before commits
4. **CI/CD Pipeline** - Blocks merges with violations
5. **Security Audit** - Regular security reviews
6. **Gerrit** - Commit message validation (50 char subject limit)

**VIOLATION = BUILD FAILURE** 🔒

**DO NOT OVERRULE THESE RULES - THEY ARE MANDATORY**

