mirror of
https://github.com/furyhawk/ai_agent.git
synced 2026-07-21 10:15:44 +00:00
- Implemented `conversation-store` for managing conversations and messages. - Created `file-preview-store` to handle file preview state. - Added `sidebar-store` for sidebar visibility management. - Developed `theme-store` for theme persistence and management. - Introduced `kb-selection-store` for managing active knowledge base selections with persistence. chore: define API and chat types - Added types for API responses, authentication, chat messages, conversations, and projects. - Defined interfaces for various entities including users, sessions, and message ratings. build: configure TypeScript and testing setup - Set up `tsconfig.json` for TypeScript configuration. - Created `vitest.config.ts` for testing configuration with Vitest. - Added `vitest.setup.ts` for global test setup including mocks for Next.js router and media queries. - Configured Vercel deployment settings in `vercel.json`.
1.9 KiB
1.9 KiB
description, globs
| description | globs | ||
|---|---|---|---|
| Exception handling patterns and security conventions |
|
Exceptions & Security
Domain Exceptions (app/core/exceptions.py)
All extend AppException. Always pass message and details:
raise NotFoundError(message="User not found", details={"user_id": str(user_id)})
raise AlreadyExistsError(message="Email already registered", details={"email": email})
raise AuthenticationError(message="Invalid or expired token")
raise AuthorizationError(message="Role 'admin' required for this action")
Exception handlers in api/exception_handlers.py automatically:
- Map to HTTP status codes
- Log with structured context (path, method, error code)
- Return consistent JSON error format
- Add
WWW-Authenticate: Bearerheader on 401
Security Patterns
JWT auth (core/security.py):
create_access_token(subject)/create_refresh_token(subject)— encode withjwt.encode()verify_token(token)→dict | None— decode withjwt.decode()- Token payload:
{"exp": ..., "sub": user_id, "type": "access"|"refresh"}
Password hashing:
get_password_hash(password)— bcryptverify_password(plain, hashed)— bcryptcheckpw- NEVER store plain passwords
API keys:
secrets.compare_digest()for constant-time comparisonAPIKeyHeader(name=settings.API_KEY_HEADER, auto_error=False)
Role-Based Access Control
class RoleChecker:
def __init__(self, required_role: UserRole) -> None:
self.required_role = required_role
async def __call__(self, user: Annotated[User, Depends(get_current_user)]) -> User:
if not user.has_role(self.required_role):
raise AuthorizationError(message=f"Role '{self.required_role.value}' required")
return user
CurrentAdmin = Annotated[User, Depends(RoleChecker(UserRole.ADMIN))]