Development Guide

Guide for developers contributing to VulnerabilityHub.

Development Setup

Prerequisites

  • Python 3.9+

  • Node.js 16+ and npm

  • Docker and Docker Compose

  • Git

  • MySQL/MariaDB client tools

Local Development Environment

1. Clone and Setup

git clone <repository-url>
cd vulnerability-scanner

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install backend dependencies
cd backend
pip install -r requirements.txt
pip install -r requirements-dev.txt  # Development dependencies

# Install frontend dependencies
cd ../frontend/app
npm install

2. Database Setup

# Start database only
docker-compose up -d db

# Initialize schema (password is in secrets/db_root_password.txt)
mariadb -h 127.0.0.1 -P 3306 -u root -p$(cat secrets/db_root_password.txt) vulnerabilityhub < src/database/vulnerability_scanner.sql

3. Environment Configuration

Create backend/.env:

ENV=development
SECRET_KEY=dev-secret-key
SMTP_SERVER=localhost
SMTP_PORT=1025
SMTP_SENDER=VulnerabilityHub <noreply@localhost>
BACKEND_URL=http://localhost:8000
# Database (defaults are usually fine for local docker db)
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=appuser
DB_PASSWORD=appuser_password_from_secret

Note

Ensure DB_PASSWORD matches secrets/db_password.txt.

4. Run Development Servers

Backend: .. code-block:: bash

cd backend uvicorn main:app –reload –host 0.0.0.0 –port 8000

Frontend:

cd frontend/app
npm run dev

Access: - Frontend: http://localhost:5173 (Vite dev server) - Backend API: http://localhost:8000 - API Docs: http://localhost:8000/docs

Project Structure

vulnerability-scanner/
├── backend/                 # Python FastAPI backend   ├── core/               # Core utilities (DB, config, email)   ├── crud/               # Database operations   ├── models/             # SQLAlchemy models   ├── routes/             # API endpoints   ├── schemas/            # Pydantic schemas   ├── services/           # Business logic   ├── importers/          # Pluggable import system   ├── main.py             # Application entry point   └── requirements.txt    # Python dependencies
├── frontend/app/           # Vue 3 frontend   ├── src/
│      ├── components/     # Vue components      ├── views/          # Page components      ├── stores/         # Pinia stores      ├── router.ts       # Vue Router config      └── main.ts         # App entry point   ├── package.json        # Node dependencies   └── vite.config.ts      # Vite configuration
├── database/               # SQL schemas
├── grafana/                # Grafana dashboards
├── docs/                   # Documentation
└── docker-compose.yml      # Docker services

Backend Development

Adding a New API Endpoint

  1. Create Route (backend/routes/my_feature.py):

from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from core.db import get_db
from routes.auth import get_current_admin_user

router = APIRouter()

@router.get("/my-feature")
def get_my_feature(
    db: Session = Depends(get_db),
    current_user = Depends(get_current_admin_user)
):
    return {"message": "Hello from my feature"}
  1. Register Router (backend/main.py):

from routes import my_feature

app.include_router(my_feature.router)
  1. Test:

curl http://localhost:8000/my-feature \
  -H "Authorization: Bearer $TOKEN"

Adding a Database Model

  1. Create Model (backend/models/my_model.py):

from sqlalchemy import Column, Integer, String
from core.db import Base

class MyModel(Base):
    __tablename__ = "my_table"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(255), nullable=False)
  1. Create Schema (backend/schemas/my_model.py):

from pydantic import BaseModel

class MyModelBase(BaseModel):
    name: str

class MyModelCreate(MyModelBase):
    pass

class MyModel(MyModelBase):
    id: int

    class Config:
        from_attributes = True
  1. Create CRUD (backend/crud/my_model.py):

from sqlalchemy.orm import Session
from models.my_model import MyModel
from schemas.my_model import MyModelCreate

def create_my_model(db: Session, data: MyModelCreate):
    db_obj = MyModel(**data.dict())
    db.add(db_obj)
    db.commit()
    db.refresh(db_obj)
    return db_obj
  1. Update Database:

-- Add to database/vulnerability_scanner.sql
CREATE TABLE IF NOT EXISTS my_table (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

Testing

Unit Tests

cd backend
pytest tests/

Integration Tests

pytest tests/integration/

Test Coverage

pytest --cov=. --cov-report=html

Frontend Development

Adding a New Component

  1. Create Component (frontend/app/src/components/MyComponent.vue):

<template>
  <v-card>
    <v-card-title>{{ title }}</v-card-title>
    <v-card-text>
      <p>{{ message }}</p>
    </v-card-text>
  </v-card>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const title = ref('My Component');
const message = ref('Hello from my component!');
</script>

<style scoped>
/* Component-specific styles */
</style>
  1. Use Component:

<template>
  <MyComponent />
</template>

<script setup>
import MyComponent from '@/components/MyComponent.vue';
</script>

Adding a New Route

  1. Create View (frontend/app/src/views/MyView.vue)

  2. Register Route (frontend/app/src/router.ts):

{
  path: '/my-view',
  component: () => import('./views/MyView.vue'),
  meta: { requiresAuth: true }
}

State Management with Pinia

  1. Create Store (frontend/app/src/stores/myStore.ts):

import { defineStore } from 'pinia';
import axios from 'axios';

export const useMyStore = defineStore('myStore', {
  state: () => ({
    items: [] as any[],
    loading: false
  }),

  actions: {
    async fetchItems() {
      this.loading = true;
      try {
        const response = await axios.get('/api/items');
        this.items = response.data;
      } finally {
        this.loading = false;
      }
    }
  }
});
  1. Use Store:

<script setup>
import { useMyStore } from '@/stores/myStore';

const store = useMyStore();
store.fetchItems();
</script>

Code Style Guidelines

Python (Backend)

  • Follow PEP 8

  • Use type hints

  • Maximum line length: 100 characters

  • Use docstrings for functions and classes

def process_scan(
    db: Session,
    scan_id: int,
    options: Optional[Dict[str, Any]] = None
) -> Scan:
    """
    Process a vulnerability scan.

    Args:
        db: Database session
        scan_id: ID of scan to process
        options: Optional processing options

    Returns:
        Processed scan object
    """
    # Implementation
    pass

TypeScript/Vue (Frontend)

  • Use TypeScript for type safety

  • Composition API for Vue components

  • Use <script setup> syntax

  • Component names in PascalCase

interface User {
  id: number;
  username: string;
  isAdmin: boolean;
}

const fetchUser = async (id: number): Promise<User> => {
  const response = await axios.get(`/users/${id}`);
  return response.data;
};

SQL

  • Uppercase keywords

  • Descriptive table and column names

  • Always use indexes for foreign keys

CREATE TABLE IF NOT EXISTS my_table (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

CREATE INDEX idx_my_table_user ON my_table(user_id);

Git Workflow

Branch Naming

  • feature/description - New features

  • bugfix/description - Bug fixes

  • hotfix/description - Critical fixes

  • refactor/description - Code refactoring

Commit Messages

Follow conventional commits:

type(scope): description

[optional body]

[optional footer]

Types: feat, fix, docs, style, refactor, test, chore

Examples:

feat(predictions): add Prophet-based forecasting
fix(reports): correct 24-hour retention logic
docs(api): update endpoint documentation

Pull Request Process

  1. Create feature branch from main

  2. Make changes and commit

  3. Write/update tests

  4. Update documentation

  5. Create pull request

  6. Request review

  7. Address feedback

  8. Merge after approval

Debugging

Backend Debugging

Using Python Debugger:

import pdb; pdb.set_trace()  # Set breakpoint

VS Code launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "FastAPI",
      "type": "python",
      "request": "launch",
      "module": "uvicorn",
      "args": ["main:app", "--reload"],
      "cwd": "${workspaceFolder}/backend"
    }
  ]
}

Frontend Debugging

Browser DevTools: - Vue DevTools extension - Network tab for API calls - Console for errors

VS Code Debugging:

{
  "type": "chrome",
  "request": "launch",
  "name": "Vue: Chrome",
  "url": "http://localhost:5173",
  "webRoot": "${workspaceFolder}/frontend/app/src"
}

Database Migrations

Manual Migration

  1. Update database/vulnerability_scanner.sql

  2. Create migration script:

-- migrations/001_add_my_feature.sql
ALTER TABLE my_table ADD COLUMN new_field VARCHAR(255);
  1. Apply migration:

mariadb -u root -p vulnerabilityhub < migrations/001_add_my_feature.sql

Future: Alembic Integration

Consider adding Alembic for automated migrations:

pip install alembic
alembic init alembic
alembic revision --autogenerate -m "Add my feature"
alembic upgrade head

Performance Optimization

Backend

  • Use database indexes

  • Implement caching (Redis)

  • Async operations where possible

  • Batch database operations

Frontend

  • Lazy load components

  • Virtual scrolling for large lists

  • Debounce user inputs

  • Code splitting

Database

  • Optimize queries (EXPLAIN)

  • Use materialized views (if available plugins) or summary tables

  • Regular OPTIMIZE TABLE / ANALYZE TABLE

  • Connection pooling

Contributing

  1. Fork the repository

  2. Create feature branch

  3. Make changes

  4. Add tests

  5. Update documentation

  6. Submit pull request

Resources