A comprehensive FastAPI-based system for validating Colony Specialty garage insurance applications with insurance domain intelligence.
- PDF Extraction: Upload filled PDF applications and extract structured data using PyMuPDF and Tesseract OCR
- Multi-Layer Validation: Six validation layers with insurance domain expertise
- Red Flag Detection: Automatic detection of critical underwriting concerns
- Supplemental Detection: Identifies required supplemental questionnaires
- State-Specific Rules: Missouri Q8 exemption, distance thresholds, etc.
- RESTful API: Full CRUD operations with OpenAPI documentation
- Syntactic Validation: Required fields, data types, formats
- Semantic Validation: Business naming conventions, license state matching
- Cross-Field Validation: Operations totals, location-security matching
- Business Logic Validation: Hobbyist detection, plate ratios, CDL requirements
- Red Flag Detection: Plate loaning, extended test drives, street parking
- State-Specific Rules: Missouri Q8 exemption, distance thresholds
# Clone and navigate to directory
cd garage-validation-api
# Copy environment file
cp .env.example .env
# Start services
docker-compose up -d
# View logs
docker-compose logs -f api
# Access API documentation
open http://localhost:8000/docs# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Copy environment file
cp .env.example .env
# Start PostgreSQL and Redis (or use Docker)
docker-compose up -d db redis
# Run migrations
alembic upgrade head
# Start the API
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000# Validate application data
POST /api/v1/validation/validate
Content-Type: application/json
{
"application_data": {
"applicant": {
"business_trade_name": "ABC Motors LLC",
"state": "TX",
"years_in_operation": 5
},
"drivers": [
{"name": "John Smith", "license_state": "TX"}
],
"sales_operations": {
"annual_sales": 50,
"auto_plates": 3
}
}
}# Upload PDF for extraction (async)
POST /api/v1/extraction/upload
Content-Type: multipart/form-data
# Check extraction status
GET /api/v1/extraction/{job_id}/status
# Get extraction result
GET /api/v1/extraction/{job_id}/result
# Direct extraction (sync, for small files)
POST /api/v1/extraction/extract-direct
Content-Type: multipart/form-data# List all rules
GET /api/v1/rules/
# Get rules by type
GET /api/v1/rules/?rule_type=RED_FLAG
# Get rules by severity
GET /api/v1/rules/?severity=CRITICAL
# Create custom rule
POST /api/v1/rules/{
"overall_status": "ERRORS",
"submission_ready": false,
"summary": {
"critical_count": 0,
"error_count": 3,
"warning_count": 2,
"info_count": 1
},
"errors": {
"critical": [],
"errors": [
{
"rule_id": "REQ_BUSINESS_NAME",
"severity": "ERROR",
"field_path": "applicant.business_trade_name",
"error_message": "Required field is missing: Business Trade Name",
"insurance_context": "The business name must exactly match...",
"suggestion": "Please provide the business trade name."
}
],
"warnings": [],
"info": []
},
"errors_by_section": {
"Applicant Information": [...],
"Sales Questions": [...]
},
"red_flags": [],
"required_supplementals": ["motorcycle_offroad_questionnaire"]
}The system detects critical underwriting concerns:
| Red Flag | Severity | Question |
|---|---|---|
| Plate Loaning | CRITICAL | Q17 |
| Extended Test Drives | CRITICAL | Q39 |
| Street Parking | WARNING | Q21 |
| No License Verification | WARNING | Q38 |
| High Plate Ratio (>3:1) | WARNING | Q28 |
Automatically identifies required supplemental questionnaires when operations exceed 10%:
- Antique/Classic Auto Restoration
- Boat/Watercraft
- Heavy Vehicle
- Motorcycle & Off-Road
- Salvage Yard
- Towing Operations
- And more...
garage-validation-api/
├── app/
│ ├── api/v1/
│ │ ├── endpoints/
│ │ │ ├── validation.py
│ │ │ ├── extraction.py
│ │ │ ├── applications.py
│ │ │ └── rules.py
│ │ └── router.py
│ ├── core/
│ ├── db/
│ │ └── session.py
│ ├── models/
│ │ ├── application.py
│ │ └── validation.py
│ ├── schemas/
│ │ ├── application.py
│ │ ├── validation.py
│ │ └── extraction.py
│ ├── services/
│ │ ├── extraction/
│ │ │ ├── extractor.py
│ │ │ └── field_mapper.py
│ │ └── validation/
│ │ ├── engine.py
│ │ └── validators/
│ │ ├── syntactic.py
│ │ ├── semantic.py
│ │ ├── cross_field.py
│ │ ├── business_logic.py
│ │ ├── red_flags.py
│ │ └── state_specific.py
│ ├── config.py
│ └── main.py
├── docker/
│ └── Dockerfile
├── tests/
├── docker-compose.yml
├── requirements.txt
└── README.md
Key environment variables:
| Variable | Description | Default |
|---|---|---|
| DATABASE_URL | PostgreSQL connection string | postgresql+asyncpg://... |
| REDIS_URL | Redis connection string | redis://localhost:6379/0 |
| USE_AWS_TEXTRACT | Use AWS Textract for OCR | false |
| MAX_UPLOAD_SIZE_MB | Maximum PDF upload size | 50 |
| CORS_ORIGINS | Allowed CORS origins | ["http://localhost:3000"] |
# Run tests
pytest
# Run with coverage
pytest --cov=app --cov-report=html
# Run specific test file
pytest tests/test_validation/test_engine.py- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- OpenAPI JSON: http://localhost:8000/openapi.json
MIT License
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests
- Submit a pull request