# Database Schema

## Overview

Headquarter uses PostgreSQL with SQLAlchemy ORM and Alembic for migrations. All tables use UUID primary keys and include `created_at`/`updated_at` timestamps.

## Entity Relationship Diagram

```
┌──────────────┐       ┌─────────────────┐       ┌──────────────┐
│    users     │       │  git_repository │       │   project    │
├──────────────┤       ├─────────────────┤       ├──────────────┤
│ id (PK)      │       │ id (PK)         │       │ id (PK)      │
│ email        │       │ project_id (FK) │──┐    │ name         │
│ name         │       │ name            │  │    │ description  │
│ authentik_id │       │ remote_url      │  │    │ created_by_id│──┐
│ avatar_url   │       │ local_path      │  │    │              │  │
│ created_at   │       │ is_mirror       │  │    │              │  │
│ updated_at   │       │ created_by_id   │──┤    │              │  │
└──────────────┘       │ created_at      │  │    └──────────────┘  │
        │              │ updated_at      │  │         ▲            │
        │              └─────────────────┘  │         │            │
        │                      │             │         │            │
        │              ┌───────┘             │         │            │
        │              │                     │         │            │
┌───────▼──────┐      ┌▼────────────────┐   │         │            │
│  ssh_keys    │      │   user_config   │   │         │            │
├──────────────┤      ├─────────────────┤   │         │            │
│ id (PK)      │      │ user_id (FK)    │───┘         │            │
│ user_id (FK) │      │ theme           │             │            │
│ name         │      │ git_name        │             │            │
│ public_key   │      │ git_email       │             │            │
│ private_key  │      │ default_editor  │             │            │
│ created_at   │      │ created_at      │             │            │
│ updated_at   │      │ updated_at      │             │            │
└──────────────┘      └─────────────────┘             │            │
                                                      │            │
                              ┌───────────────────────┘            │
                              │                                    │
                              ▼                                    │
                       ┌─────────────────┐                         │
                       │   tool_types    │                         │
                       ├─────────────────┤                         │
                       │ id (PK)         │                         │
                       │ name            │                         │
                       │ display_name    │                         │
                       │ description     │                         │
                       │ compose_template│                         │
                       │ required_vars   │                         │
                       │ is_builtin      │                         │
                       │ created_by_id   │─────────────────────────┘
                       │ created_at      │
                       │ updated_at      │
                       └─────────────────┘
```

## Table Definitions

### users

Stores user accounts synchronized from Authentik.

| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | UUID | PK | Unique identifier |
| email | VARCHAR(255) | NOT NULL, UNIQUE | User email |
| name | VARCHAR(255) | | Display name |
| authentik_id | VARCHAR(255) | UNIQUE | Authentik user ID |
| avatar_url | VARCHAR(500) | | Profile avatar URL |
| created_at | TIMESTAMP | DEFAULT now() | Creation timestamp |
| updated_at | TIMESTAMP | DEFAULT now() | Last update timestamp |

**Relationships**:
- One-to-Many: `users` → `git_repository` (created_by_id)
- One-to-Many: `users` → `project` (created_by_id)
- One-to-Many: `users` → `ssh_keys` (user_id)
- One-to-One: `users` → `user_config` (user_id)
- One-to-Many: `users` → `tool_types` (created_by_id)

### project

Organizes repositories into logical groups.

| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | UUID | PK | Unique identifier |
| name | VARCHAR(255) | NOT NULL | Project name |
| description | TEXT | | Project description |
| created_by_id | UUID | FK → users.id | Creator |
| created_at | TIMESTAMP | DEFAULT now() | Creation timestamp |
| updated_at | TIMESTAMP | DEFAULT now() | Last update timestamp |

**Relationships**:
- One-to-Many: `project` → `git_repository` (project_id)

### git_repository

Git repositories (bare/mirror clones).

| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | UUID | PK | Unique identifier |
| project_id | UUID | FK → project.id, NOT NULL | Parent project |
| name | VARCHAR(255) | NOT NULL | Repository name |
| remote_url | VARCHAR(500) | NOT NULL | Remote git URL |
| local_path | VARCHAR(500) | | Local filesystem path |
| is_mirror | BOOLEAN | DEFAULT false | Is mirror clone |
| created_by_id | UUID | FK → users.id | Creator |
| created_at | TIMESTAMP | DEFAULT now() | Creation timestamp |
| updated_at | TIMESTAMP | DEFAULT now() | Last update timestamp |

**Indexes**:
- `idx_repo_project`: (project_id)
- `idx_repo_name`: (project_id, name) - UNIQUE

### ssh_keys

User SSH keys for git authentication.

| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | UUID | PK | Unique identifier |
| user_id | UUID | FK → users.id, NOT NULL | Owner |
| name | VARCHAR(255) | NOT NULL | Key name |
| public_key | TEXT | NOT NULL | Public key |
| private_key | TEXT | NOT NULL, ENCRYPTED | Encrypted private key |
| created_at | TIMESTAMP | DEFAULT now() | Creation timestamp |
| updated_at | TIMESTAMP | DEFAULT now() | Last update timestamp |

**Indexes**:
- `idx_ssh_user`: (user_id)

### user_config

User preferences and settings.

| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | UUID | PK | Unique identifier |
| user_id | UUID | FK → users.id, NOT NULL, UNIQUE | Owner |
| theme | VARCHAR(50) | DEFAULT 'system' | UI theme (system/light/dark) |
| git_name | VARCHAR(255) | | Git user name |
| git_email | VARCHAR(255) | | Git user email |
| default_editor | VARCHAR(50) | DEFAULT 'vscode' | Preferred editor |
| created_at | TIMESTAMP | DEFAULT now() | Creation timestamp |
| updated_at | TIMESTAMP | DEFAULT now() | Last update timestamp |

### tool_types

Types of development tools that can be spawned.

| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | UUID | PK | Unique identifier |
| name | VARCHAR(255) | NOT NULL, UNIQUE | Machine name |
| display_name | VARCHAR(255) | NOT NULL | Human-readable name |
| description | TEXT | | Description |
| compose_template | TEXT | NOT NULL | Docker Compose template |
| required_variables | JSONB | NOT NULL | Template variables |
| is_builtin | BOOLEAN | DEFAULT false | Built-in type |
| created_by_id | UUID | FK → users.id | Creator (null for built-in) |
| created_at | TIMESTAMP | DEFAULT now() | Creation timestamp |
| updated_at | TIMESTAMP | DEFAULT now() | Last update timestamp |

**Indexes**:
- `idx_tool_builtin`: (is_builtin)

## Migration History

| Version | Date | Description |
|---------|------|-------------|
| 0001_initial_schema | 2024-01-XX | Initial tables: users, projects, git_repositories |
| 0002_refresh_tokens | 2024-01-XX | Added refresh_tokens table |
| 0003_user_configs | 2024-05-18 | Added user_config table |
| 0004_tool_types | 2024-05-18 | Added tool_types table |

## Data Types

### PostgreSQL Types
- **UUID**: `uuid` - All primary keys
- **Timestamps**: `TIMESTAMP WITH TIME ZONE`
- **JSONB**: `JSONB` - For flexible config (user_config, tool_types)
- **Strings**: `VARCHAR(n)` - With appropriate length limits
- **Text**: `TEXT` - For unbounded content
- **Boolean**: `BOOLEAN` - True/false flags

### SQLAlchemy Configuration
```python
# Base model features
class Base:
    id: UUID = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    created_at: datetime = Column(DateTime(timezone=True), server_default=func.now())
    updated_at: datetime = Column(DateTime(timezone=True), onupdate=func.now())
```

## Backup Strategy

### Automated Backups
- **Frequency**: Daily at 2 AM
- **Retention**: 7 daily, 4 weekly, 12 monthly
- **Method**: `pg_dump` to S3/object storage
- **Encryption**: AES-256 encrypted backups

### Manual Backup
```bash
# Full backup
pg_dump -Fc -f headquarter_backup.dump postgresql://user:pass@host/db

# Restore
pg_restore -d postgresql://user:pass@host/db headquarter_backup.dump
```

## Performance

### Query Optimization
- All foreign keys indexed
- Frequently queried columns indexed
- Composite indexes for multi-column queries

### Connection Pooling
- SQLAlchemy async pool: 5-20 connections
- PgBouncer for production: transaction mode

## Future Schema Changes

Planned additions:
- [ ] **teams** table - Group users into teams
- [ ] **team_memberships** table - Link users to teams
- [ ] **tool_instances** table - Running tool containers
- [ ] **audit_logs** table - Track important actions
- [ ] **notifications** table - User notifications
