# Newtouch System - Project Constitution

> **Version**: 1.0  
> **Last Updated**: 2026-02-06  
> **Status**: MANDATORY - Must be followed by all developers and AI assistants

---

## 🎯 Project Vision

The Newtouch Website control panel management system is an enterprise-grade platform for managing the complete lifecycle of investment opportunities. This constitution defines the unchanging principles that govern all development work.

---

## 🏗️ Architectural Principles

### Domain-Driven Design (DDD) - NON-NEGOTIABLE

All backend code MUST follow strict 4-layer DDD architecture:

#### 1. Domain Layer (Pure Business Logic)
```
modules/{ModuleName}/Domain/
├── Entities/              # Business entities with behavior
├── ValueObjects/          # Immutable value objects
├── Events/                # Domain events
├── Enums/                 # Type-safe enumerations
├── Exceptions/            # Domain-specific exceptions
└── Contracts/
    └── Repositories/      # Repository interfaces
```

**Rules:**
- ✅ Entities contain business logic and validation
- ✅ Value Objects are immutable
- ✅ Domain Events for all significant state changes
- ✅ No framework dependencies (Laravel-agnostic)
- ❌ NO database queries in Domain layer
- ❌ NO HTTP/API code in Domain layer

#### 2. Application Layer (Use Case Orchestration)
```
modules/{ModuleName}/Application/
├── Commands/              # Write operations (Create, Update, Delete)
├── Queries/               # Read operations
├── DTOs/                  # Data Transfer Objects
└── EventHandlers/         # Domain event handlers
```

**Rules:**
- ✅ Commands/Queries orchestrate Domain entities
- ✅ DTOs for data transfer between layers
- ✅ Transaction management here
- ❌ NO business logic (delegate to Domain)

#### 3. Infrastructure Layer (Technical Details)
```
modules/{ModuleName}/Infrastructure/
├── Persistence/
│   ├── Eloquent/
│   │   ├── Models/        # Laravel Eloquent models
│   │   ├── Repositories/  # Repository implementations
│   │   └── Migrations/    # Database migrations
│   └── Mappers/           # Domain ↔ Model mapping
└── Listeners/             # Event listeners
```

**Rules:**
- ✅ Eloquent Models are data containers ONLY
- ✅ Repositories implement Domain interfaces
- ✅ Mappers convert between Domain entities and Models
- ❌ NO business logic in Repositories

#### 4. Presentation Layer (API Interface)
```
modules/{ModuleName}/Presentation/
└── Http/
    ├── Controllers/       # API controllers
    ├── Requests/          # Validation requests
    ├── Resources/         # Response transformers
    └── Routes/            # Route definitions
```

**Rules:**
- ✅ Controllers are thin (delegate to Application layer)
- ✅ Form Requests for validation
- ✅ API Resources for response formatting
- ❌ NO business logic in Controllers

### Event Sourcing Pattern

**All critical operations MUST dispatch Domain Events:**

```php
// Example: OpportunityEntity
public function transitionToStage(UniqueId $newStageId, UniqueId $performedBy): void {
    $oldStageId = $this->currentStageId;
    $this->currentStageId = $newStageId;
    
    // ✅ REQUIRED: Dispatch event
    Event::dispatch(new OpportunityStageChanged(
        $this->uuid,
        $oldStageId,
        $newStageId,
        $performedBy
    ));
}
```

**Benefits:**
- Complete audit trail
- Loose coupling between modules
- Event-driven architecture
- Future support for Event Sourcing storage

---

## 💻 Code Quality Standards

### PHP

#### Type Safety (MANDATORY)
```php
// ✅ CORRECT
public function calculateTotal(float $amount, float $tax): float {
    return $amount + ($amount * $tax);
}

// ❌ FORBIDDEN
public function calculateTotal($amount, $tax) {  // No types
    return $amount + ($amount * $tax);
}
```

**Rules:**
- ✅ Type hints for ALL parameters
- ✅ Return type declarations for ALL methods
- ✅ Nullable types when appropriate: `?string`
- ✅ Union types for PHP 8.0+: `string|int`
- ❌ NO missing type declarations

#### Documentation (REQUIRED)
```php
/**
 * Create a new opportunity with full validation.
 *
 * @param OpportunityReference $reference Unique reference (AL-YYYY-NNNN)
 * @param string $name Opportunity name (max 255 chars)
 * @param OpportunityType $type Investment type enum
 * @param Location $location Geographic location value object
 * @param UniqueId $ownerUserId Owner user UUID
 * 
 * @return self New opportunity instance
 * 
 * @throws InvalidArgumentException If name is empty
 * @throws DomainException If validation fails
 */
public static function createNew(
    OpportunityReference $reference,
    string $name,
    OpportunityType $type,
    Location $location,
    UniqueId $ownerUserId
): self {
    // Implementation
}
```

**Rules:**
- ✅ PHPDoc for all public methods
- ✅ Explain parameters and return values
- ✅ Document thrown exceptions
- ✅ Include example usage for complex methods

#### Static Analysis
```bash
# REQUIRED: Must pass with no errors
./vendor/bin/psalm --level=4
./vendor/bin/phpstan analyse --level=8
```

---

## 🧪 Testing Requirements

### Coverage: Minimum 80%

**Test Pyramid:**
```
E2E Tests (10%)         ← Critical user flows
    ↓
Integration Tests (30%)  ← API endpoints, DB interactions
    ↓
Unit Tests (60%)         ← Domain logic, Value Objects
```

### Unit Tests (Domain Layer)
```php
// ✅ REQUIRED for all Entities and Value Objects
class OpportunityEntityTest extends TestCase {
    /** @test */
    public function it_transitions_to_new_stage_and_dispatches_event(): void {
        Event::fake();
        
        $opportunity = OpportunityEntity::reconstitute(/* ... */);
        $newStageId = UniqueId::generate();
        
        $opportunity->transitionToStage($newStageId, $userId);
        
        $this->assertEquals($newStageId, $opportunity->getCurrentStageId());
        Event::assertDispatched(OpportunityStageChanged::class);
    }
}
```

### Integration Tests (API Layer)
```php
// ✅ REQUIRED for all endpoints
class OpportunityControllerTest extends TestCase {
    /** @test */
    public function it_creates_opportunity_with_valid_data(): void {
        $response = $this->postJson('/api/opportunities', [
            'name' => 'Test Opportunity',
            'type' => 'real_estate',
            // ... more data
        ]);
        
        $response->assertStatus(201);
        $this->assertDatabaseHas('opportunities', ['name' => 'Test Opportunity']);
    }
}
```

### E2E Tests
```php
// ✅ REQUIRED for critical flows
/** @test */
public function user_can_complete_full_opportunity_lifecycle(): void {
    // Create → Screen → Approve → Complete
    // Test full workflow from start to finish
}
```

---

## 🌐 API Standards

### RESTful Design (MANDATORY)

```
GET    /api/opportunities              - List opportunities
POST   /api/opportunities              - Create opportunity
GET    /api/opportunities/{uuid}       - Get single opportunity
PUT    /api/opportunities/{uuid}       - Update opportunity
DELETE /api/opportunities/{uuid}       - Delete opportunity

POST   /api/opportunities/{uuid}/screening/accept  - Stage transitions
POST   /api/opportunities/{uuid}/screening/reject
```

**Rules:**
- ✅ Use nouns for resources
- ✅ Use HTTP verbs correctly (GET, POST, PUT, DELETE)
- ✅ UUID in URLs, not integer IDs
- ✅ Nested routes for sub-resources
- ❌ NO verbs in URLs (use HTTP methods)

### API Response Trait (MANDATORY)

**ALL controllers MUST use `ApiResponse` trait from SharedKernel:**

```php
use SharedKernel\Presentation\Traits\ApiResponse;

class OpportunityController extends Controller {
    use ApiResponse;
    
    public function index() {
        $opportunities = Opportunity::paginate(15);
        
        return $this->successResponse(
            data: OpportunityResource::collection($opportunities),
            message: 'Opportunities retrieved successfully'
        );
    }
    
    public function store(CreateOpportunityRequest $request) {
        $opportunity = CreateOpportunityAction::run($request->validated());
        
        return $this->successResponse(
            data: new OpportunityResource($opportunity),
            message: 'Opportunity created successfully',
            statusCode: 201
        );
    }
}
```

### Response Formats (STANDARDIZED)

#### Success Response
```json
{
  "success": true,
  "status_code": 200,
  "message": "Operation successful",
  "data": {
    "uuid": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Riyadh Project",
    "reference": "AL-2024-0001"
  },
  "errors": null,
  "meta": {
    "timestamp": "2024-02-06T12:00:00.000Z",
    "api_version": "v1",
    "execution_time_ms": 45.23,
    "request_id": "req-abc123",
    "locale": "ar"
  }
}
```

#### Paginated Response
```json
{
  "success": true,
  "status_code": 200,
  "message": "Data retrieved successfully",
  "data": [
    { "uuid": "...", "name": "..." }
  ],
  "pagination": {
    "total_items": 100,
    "per_page": 15,
    "current_page": 1,
    "last_page": 7,
    "next_page_url": "http://api.com/opportunities?page=2",
    "prev_page_url": null,
    "from": 1,
    "to": 15,
    "type": "page_based"
  },
  "errors": null,
  "meta": { ... }
}
```

#### Error Response
```json
{
  "success": false,
  "status_code": 422,
  "message": "Validation failed",
  "data": null,
  "errors": [
    {
      "field": "name",
      "message": "The name field is required."
    }
  ],
  "meta": { ... }
}
```

### ApiResponse Methods (REQUIRED)

```php
// Success with data
protected function successResponse(
    $data = null, 
    string $message = 'Operation successful', 
    int $statusCode = 200, 
    array $additionalMeta = []
): JsonResponse

// Paginated data (auto-detects page/cursor pagination)
protected function paginatedResponse(
    ResourceCollection $resourceCollection, 
    string $message = 'Data retrieved successfully', 
    int $statusCode = 200, 
    array $additionalMeta = []
): JsonResponse

// Error response
protected function errorResponse(
    string $message, 
    int $statusCode = 400, 
    $errors = null, 
    string $errorCode = null, 
    array $additionalMeta = []
): JsonResponse

// Validation errors (formatted)
protected function validationErrorResponse(
    array $errors, 
    string $message = 'Validation failed', 
    int $statusCode = 422
): JsonResponse
```

### Usage Examples

```php
// Simple success
return $this->successResponse(
    data: $opportunity,
    message: 'Opportunity retrieved'
);

// Paginated list
return $this->paginatedResponse(
    resourceCollection: OpportunityResource::collection($paginated
Opportunities),
    message: 'Opportunities list retrieved'
);

// Error handling
if (!$opportunity) {
    return $this->errorResponse(
        message: 'Opportunity not found',
        statusCode: 404,
        errorCode: 'RESOURCE_NOT_FOUND'
    );
}

// Validation error
catch (ValidationException $e) {
    return $this->validationErrorResponse(
        errors: $e->errors()
    );
}
```

### HTTP Status Codes
- `200 OK` - Successful GET/PUT
- `201 Created` - Successful POST
- `204 No Content` - Successful DELETE
- `400 Bad Request` - Validation error
- `401 Unauthorized` - Not authenticated
- `403 Forbidden` - Not authorized
- `404 Not Found` - Resource doesn't exist
- `422 Unprocessable Entity` - Business logic error
- `500 Internal Server Error` - Server error

### API Versioning (REQUIRED)
```php
// routes/api.php
Route::prefix('v1')->group(function () {
    Route::apiResource('opportunities', OpportunityControllerV1::class);
});

Route::prefix('v2')->group(function () {
    Route::apiResource('opportunities', OpportunityControllerV2::class);
});
```

### OpenAPI Documentation (REQUIRED)
All endpoints MUST be documented in OpenAPI/Swagger format.

---

## 🔒 Security Standards

### Authentication
- ✅ Laravel Sanctum for API authentication
- ✅ Token-based auth for SPA
- ✅ Secure token storage
- ❌ NO session-based auth for API

### Authorization
- ✅ Role-Based Access Control (RBAC)
- ✅ Permission checking in controllers
- ✅ Policy classes for complex logic
```php
// ✅ REQUIRED
$this->authorize('update', $opportunity);
```

### Input Validation
```php
// ✅ REQUIRED: Form Request validation
class CreateOpportunityRequest extends FormRequest {
    public function rules(): array {
        return [
            'name' => 'required|string|max:255',
            'type' => 'required|in:real_estate,industrial,commercial',
            // ... more rules
        ];
    }
}
```

### SQL Injection Prevention
- ✅ Always use Eloquent Query Builder or prepared statements
- ❌ NEVER concatenate user input into SQL

### XSS Prevention
- ✅ Sanitize all user input
- ✅ Use `{{ }}` in Blade (auto-escapes)
- ❌ Never use `{!! !!}` with user input

---

## ⚡ Performance Requirements

### Response Times
- Simple queries (single record): **< 200ms**
- Complex queries (aggregations): **< 1s**
- Reports: **< 5s**

### Database
- ✅ Indexes on all foreign keys
- ✅ Indexes on frequently queried columns
- ✅ Eager loading to prevent N+1 queries
```php
// ✅ CORRECT
$opportunities = Opportunity::with(['properties', 'contacts'])->get();

// ❌ FORBIDDEN (causes N+1)
$opportunities = Opportunity::all();
foreach ($opportunities as $opp) {
    $opp->properties; // N+1!
}
```

### Caching
```php
// ✅ REQUIRED for expensive computations
Cache::remember('opportunity-'.$uuid, 3600, function () use ($uuid) {
    return $this->repository->findByUuid($uuid);
});
```

---

## 📝 Commit Standards

### Conventional Commits (REQUIRED)
```
feat: add approval matrix workflow
fix: resolve N+1 query in opportunity list
docs: update API documentation
refactor: extract validation to service class
test: add unit tests for OpportunityEntity
chore: update dependencies
```

**Types:**
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation
- `refactor`: Code refactoring
- `test`: Tests
- `chore`: Maintenance

---

## 🚫 Forbidden Practices

### NEVER:
- ❌ Business logic in Controllers
- ❌ Business logic in Models (Eloquent)
- ❌ Direct database queries in Domain layer
- ❌ Missing type hints
- ❌ Missing tests for new code
- ❌ Pushing code that doesn't pass static analysis
- ❌ Exposing internal IDs in API
- ❌ Hardcoded values (use config)
- ❌ `dd()` or `dump()` in committed code
- ❌ Commented-out code

---

## ✅ Code Review Checklist

Before submitting PR:
- [ ] Follows DDD layer separation
- [ ] All methods have type hints
- [ ] PHPDoc comments present
- [ ] Unit tests written (80%+ coverage)
- [ ] Passes `psalm --level=4`
- [ ] Passes `phpstan --level=8`
- [ ] API documented in OpenAPI
- [ ] No N+1 queries
- [ ] Authorization checks present
- [ ] Input validated
- [ ] Conventional commit messages

---

## 📚 Required Reading

- [Domain-Driven Design](https://martinfowler.com/bliki/DomainDrivenDesign.html)
- [Laravel Best Practices](https://github.com/alexeymezenin/laravel-best-practices)
- [PHP: The Right Way](https://phptherightway.com/)
- [RESTful API Design](https://restfulapi.net/)

---

**This constitution is mandatory and non-negotiable. All code must adhere to these principles.**
