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
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
├── 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

See Testing Guide for the current backend, frontend, and Playwright e2e test commands, including how to run the browser suite in headed mode when you want to watch the tests live.

Unit Tests

cd src/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