@@ -42,10 +42,13 @@ securechain-auth/
4242│ │ ├── patterns/ # Regex patterns for validation
4343│ │ └── validators/ # Custom validators
4444│ ├── utils/ # Utilities
45- │ │ ├── jwt_encoder.py # JWT encoding/decoding
46- │ │ ├── password_encoder.py # Password hashing (bcrypt)
47- │ │ └── json_encoder.py # Custom JSON encoders
48- │ └── exceptions/ # Custom exceptions
45+ │ │ ├── jwt_encoder.py # JWT encoding/decoding (JWTBearer class)
46+ │ │ ├── password_encoder.py # Password hashing (PasswordEncoder class)
47+ │ │ └── json_encoder.py # Custom JSON encoder (JSONEncoder class)
48+ │ └── exceptions/ # Custom exceptions (one class per file)
49+ │ ├── not_authenticated_exception.py
50+ │ ├── expired_token_exception.py
51+ │ └── invalid_token_exception.py
4952├── tests/ # Tests with pytest
5053│ ├── conftest.py # Pytest configuration
5154│ ├── controllers/ # Controller tests
@@ -62,6 +65,67 @@ securechain-auth/
6265
6366```
6467
68+ ### Code Organization Pattern
69+
70+ The project follows a ** direct instantiation pattern** for services and utilities:
71+
72+ #### Controllers (` app/controllers/ ` )
73+ Each controller creates module-level instances of services and utilities:
74+
75+ ``` python
76+ # Example: auth_controller.py
77+ from app.services import AuthService
78+ from app.utils import JWTBearer, JSONEncoder, PasswordEncoder
79+
80+ # Module-level instances (singletons per module)
81+ auth_service = AuthService()
82+ jwt_bearer = JWTBearer()
83+ json_encoder = JSONEncoder()
84+ password_encoder = PasswordEncoder()
85+
86+ @router.post (" /endpoint" )
87+ async def endpoint ():
88+ # Direct usage of instances
89+ user = await auth_service.read_user_by_email(email)
90+ payload = await jwt_bearer.verify_access_token(token)
91+ response = json_encoder.encode(data)
92+ hashed = await password_encoder.hash(password)
93+ ```
94+
95+ ** Benefits** :
96+ - ✅ Simple and explicit
97+ - ✅ No dependency injection complexity
98+ - ✅ Easy to understand and maintain
99+ - ✅ Consistent pattern across the codebase
100+
101+ #### Services (` app/services/ ` )
102+ - ** AuthService** : Business logic for authentication
103+ - Direct instantiation: ` AuthService() `
104+ - Manages Neo4j and MongoDB connections internally
105+
106+ #### Utilities (` app/utils/ ` )
107+ All utilities are classes that are instantiated directly:
108+
109+ - ** JWTBearer** : JWT token operations (create, verify, set cookies)
110+ ``` python
111+ jwt_bearer = JWTBearer()
112+ token = await jwt_bearer.create_access_token(data)
113+ payload = await jwt_bearer.verify_access_token(token)
114+ ```
115+
116+ - ** JSONEncoder** : JSON serialization with custom types (ObjectId, datetime)
117+ ``` python
118+ json_encoder = JSONEncoder()
119+ result = json_encoder.encode(data) # Handles ObjectId and datetime
120+ ```
121+
122+ - ** PasswordEncoder** : Password hashing and verification (bcrypt)
123+ ``` python
124+ password_encoder = PasswordEncoder()
125+ hashed = await password_encoder.hash(password)
126+ is_valid = await password_encoder.verify(password, hashed)
127+ ```
128+
65129## 🔧 Technology Stack
66130
67131### Core Dependencies
@@ -227,6 +291,35 @@ pytest tests --cov=app --cov-report=html
227291- ` tests/models/ ` : Data model tests
228292- ` conftest.py ` : Shared fixtures (HTTP client, DB mocks)
229293
294+ ### Testing Strategy
295+
296+ The project uses ** patch-based mocking** for testing controllers:
297+
298+ ``` python
299+ # Example: test_auth_controller.py
300+ @pytest.fixture (scope = " session" , autouse = True )
301+ def patch_jwt ():
302+ # Patch JWT at class level before app import
303+ with patch(" app.utils.jwt_encoder.JWTBearer.__call__" ,
304+ new = AsyncMock(return_value = {" user_id" : " abc123" })):
305+ yield
306+
307+ @pytest.fixture (autouse = True )
308+ def mock_services ():
309+ # Patch service instances
310+ with patch(" app.controllers.auth_controller.auth_service" ) as mock_auth:
311+ mock_auth.read_user_by_email = AsyncMock()
312+ mock_auth.create_user = AsyncMock()
313+ # ... more async methods
314+ yield mock_auth
315+ ```
316+
317+ ** Key points** :
318+ - Patch ` JWTBearer.__call__ ` at ** session scope** before importing ` app `
319+ - Patch service instances at ** function scope** for each test
320+ - Use ` AsyncMock ` for all async methods
321+ - Configure return values as needed per test
322+
230323## 📊 Logging
231324
232325The system uses structured logging:
@@ -297,6 +390,36 @@ uv sync --upgrade
2973906 . ** Logging** : Structured logging with relevant context
2983917 . ** Testing** : Tests for new features before merge
2993928 . ** Security** : Never commit ` .env ` files, use ` template.env `
393+ 9 . ** Code Organization** : Direct instantiation pattern for services and utilities
394+ 10 . ** No Comments** : Code should be self-documenting (no inline comments)
395+
396+ ### Architecture Patterns
397+
398+ #### ✅ Direct Instantiation (Current Pattern)
399+ ``` python
400+ # In controllers
401+ auth_service = AuthService()
402+ jwt_bearer = JWTBearer()
403+ json_encoder = JSONEncoder()
404+
405+ # Usage
406+ user = await auth_service.read_user_by_email(email)
407+ ```
408+
409+ ** Why** : Simple, explicit, easy to understand and test
410+
411+ #### ❌ Avoid Dependency Injection
412+ The project intentionally avoids FastAPI's ` Depends() ` pattern to keep code simple and explicit.
413+
414+ #### ✅ Class-based Utilities
415+ All utilities are classes that encapsulate related functionality:
416+ - ` JWTBearer ` : JWT operations
417+ - ` JSONEncoder ` : JSON encoding with custom types
418+ - ` PasswordEncoder ` : Password hashing and verification
419+ - ` AuthService ` : Authentication business logic
420+
421+ #### ✅ Module-level Instances
422+ Create instances at module level (singleton per module) for reuse across endpoint handlers.
300423
301424## 🔗 Important Links
302425
@@ -326,6 +449,53 @@ uv sync --upgrade
326449- PascalCase for classes
327450- Docstrings in public functions
328451- Type hints mandatory
452+ - ** No inline comments** - code should be self-documenting
453+ - ** Direct instantiation** - avoid dependency injection patterns
454+ - ** Class-based utilities** - group related functions in classes
455+ - ** One class per file** - following Single Responsibility Principle
456+
457+ ### Common Patterns:
458+
459+ #### Creating a new utility class:
460+ ``` python
461+ # app/utils/my_utility.py
462+ class MyUtility :
463+ def __init__ (self ):
464+ # Initialize if needed
465+ pass
466+
467+ def method (self , param : str ) -> str :
468+ # Implementation
469+ return result
470+
471+ # In controller
472+ from app.utils import MyUtility
473+
474+ my_utility = MyUtility()
475+ ```
476+
477+ #### Adding a new endpoint:
478+ ``` python
479+ # In controller
480+ @router.post (" /endpoint" )
481+ @limiter.limit (" 25/minute" )
482+ async def endpoint (request : Request, data : Schema) -> JSONResponse:
483+ result = await auth_service.method(data)
484+ return JSONResponse(
485+ status_code = status.HTTP_200_OK ,
486+ content = json_encoder.encode({" detail" : result})
487+ )
488+ ```
489+
490+ #### Testing pattern:
491+ ``` python
492+ def test_endpoint (mock_services ):
493+ mock_auth = mock_services
494+ mock_auth.method.return_value = expected_value
495+
496+ response = client.post(" /endpoint" , json = {" data" : " value" })
497+ assert response.status_code == 200
498+ ```
329499
330500### Debugging:
331501- Logs in ` errors.log `
@@ -334,5 +504,5 @@ uv sync --upgrade
334504
335505---
336506
337- ** Last updated** : October 12 , 2025
507+ ** Last updated** : October 15 , 2025
338508** Maintained by** : Secure Chain Team
0 commit comments