Schéma de la base de données — Référence développeur
Ce document décrit le schéma complet de la base de données gitrust, orienté développeur : types SeaORM côté Rust, enums, contraintes de modèle, et ordre des migrations.
Pour la vue admin (sauvegardes, supervision), consultez le manuel d'administration.
ERD — Diagramme entité-relation
erDiagram
%% ===== Tables rustwarden-core =====
users {
uuid id PK
string username UK
string email UK
string password_hash
boolean must_change_password
boolean email_verified
timestamptz last_login_at
timestamptz created_at
timestamptz updated_at
}
resources {
uuid id PK
string resource_type
uuid resource_id
uuid owner_id FK
boolean is_public
timestamptz created_at
}
resource_shares {
uuid id PK
uuid resource_id FK
uuid shared_with_user_id FK
string permission_level
uuid shared_by_user_id FK
timestamptz created_at
}
user_totp {
uuid id PK
uuid user_id FK
text encrypted_secret
boolean enabled
text backup_codes_json
timestamptz enabled_at
timestamptz created_at
timestamptz updated_at
}
%% ===== Tables gitrust-core =====
repositories {
uuid id PK
uuid owner_id FK
string slug
string description
string disk_path
string default_branch
boolean is_empty
timestamptz created_at
timestamptz updated_at
}
ssh_keys {
uuid id PK
uuid user_id FK
string title
string fingerprint UK
string key_type
text key_data
timestamptz last_used_at
timestamptz created_at
}
teams {
uuid id PK
uuid owner_id FK
string slug
string description
timestamptz created_at
timestamptz updated_at
}
team_members {
uuid id PK
uuid team_id FK
uuid user_id FK
string role
timestamptz created_at
}
team_repository_access {
uuid id PK
uuid team_id FK
uuid repository_id FK
string permission
timestamptz created_at
}
personal_access_tokens {
uuid id PK
uuid user_id FK
string name
string token_hash UK
string scopes
timestamptz expires_at
timestamptz last_used_at
timestamptz created_at
}
issues {
uuid id PK
uuid repository_id FK
integer number
uuid author_id FK
string title
text body
string state
uuid closed_by FK
timestamptz created_at
timestamptz updated_at
}
issue_comments {
uuid id PK
uuid issue_id FK
uuid author_id FK
text body
timestamptz created_at
timestamptz updated_at
}
labels {
uuid id PK
uuid owner_id FK
uuid repository_id FK
string name
string color
string description
string label_type
timestamptz created_at
}
issue_labels {
uuid id PK
uuid issue_id FK
uuid label_id FK
timestamptz created_at
}
pull_requests {
uuid id PK
uuid repository_id FK
integer number
uuid author_id FK
string title
text body
string source_branch
string target_branch
string state
timestamptz merged_at
uuid merged_by FK
string merge_commit_sha
timestamptz created_at
timestamptz updated_at
}
pr_comments {
uuid id PK
uuid pull_request_id FK
uuid author_id FK
text body
timestamptz created_at
}
import_jobs {
uuid id PK
uuid repository_id FK
uuid owner_id FK
text source_url
text target_slug
string status
string phase
int received_objects
int total_objects
bigint received_bytes
text error_message
timestamptz started_at
timestamptz finished_at
int duration_ms
timestamptz created_at
timestamptz updated_at
}
%% Relations
users ||--o{ repositories : "possède"
users ||--o{ ssh_keys : "enregistre"
users ||--o{ teams : "crée"
users ||--o{ resources : "possède"
users ||--o| user_totp : "configure"
repositories ||--o| resources : "enregistre dans"
resources ||--o{ resource_shares : "partage"
teams ||--o{ team_members : "contient"
teams ||--o{ team_repository_access : "accède à"
repositories ||--o{ team_repository_access : "accessible par"
repositories ||--o{ issues : "contient"
issues ||--o{ issue_comments : "a"
issues ||--o{ issue_labels : "étiquetée"
labels ||--o{ issue_labels : "appliquée"
repositories ||--o{ pull_requests : "contient"
pull_requests ||--o{ pr_comments : "a"
users ||--o{ personal_access_tokens : "crée"
users ||--o{ import_jobs : "lance"
Tables rustwarden-core (framework — read-only pour gitrust)
Ces tables sont gérées exclusivement par le framework rustwarden-core. Ne les modifiez jamais directement depuis gitrust.
| Table | Rôle |
users | Comptes utilisateurs |
roles / permissions / role_permissions / user_roles | RBAC global |
resources / resource_shares | Registre générique de ressources et partages |
refresh_tokens / jwt_blacklist | Gestion JWT |
app_settings | Configuration applicative clé-valeur |
audit_logs | Journal d'audit |
user_totp / totp_challenges | Authentification 2FA TOTP |
email_queue / email_delivery_status | File d'emails asynchrone |
password_reset_tokens / password_change_requests | Flux de changement de mot de passe |
Tables gitrust-core
repositories
| Colonne | Type Rust (SeaORM) | Contrainte PG | Notes |
id | Uuid | PK | |
owner_id | Uuid | FK → users ON DELETE CASCADE | |
slug | String | VARCHAR(64) NOT NULL | Newtype RepoSlug à la frontière |
description | Option<String> | VARCHAR(500) NULL | |
disk_path | String | VARCHAR(512) NOT NULL | Chemin absolu du bare repo |
default_branch | String | VARCHAR(255) NOT NULL DEFAULT 'main' | |
is_empty | bool | BOOLEAN NOT NULL DEFAULT true | Passe à false après le premier push |
created_at | DateTimeUtc | TIMESTAMPTZ NOT NULL | |
updated_at | DateTimeUtc | TIMESTAMPTZ NOT NULL | |
Index : UNIQUE(owner_id, slug), INDEX(owner_id)
Lien ResourceService : chaque dépôt est enregistré dans resources avec resource_type = "repository" et resource_id = repositories.id.
ssh_keys
| Colonne | Type Rust | Contrainte PG | Notes |
id | Uuid | PK | |
user_id | Uuid | FK → users CASCADE | |
title | String | VARCHAR(255) NOT NULL | |
fingerprint | String | VARCHAR(128) UNIQUE NOT NULL | SHA256, format SHA256:xxx |
key_type | String | VARCHAR(32) NOT NULL | ssh-ed25519, ssh-rsa, ecdsa-sha2-nistp256/384 |
key_data | String | TEXT NOT NULL | Format authorized_keys complet |
last_used_at | Option<DateTimeUtc> | TIMESTAMPTZ NULL | Mis à jour par le serveur SSH |
created_at | DateTimeUtc | TIMESTAMPTZ NOT NULL | |
Validation : RSA ≥ 4096 bits obligatoire. Fingerprint calculé à l'insertion.
teams et team_members
| Colonne | Type Rust | Notes |
teams.slug | String | Newtype TeamSlug ; UNIQUE(owner_id, slug) |
team_members.role | String | "read" (défaut), "write", "admin" |
team_repository_access.permission | String | "read", "write", "admin" |
personal_access_tokens
| Colonne | Type Rust | Notes |
token_hash | String | SHA-256 du token en clair. Le token en clair n'est retourné qu'à la création. |
scopes | String | Espace-séparé : "repo:read repo:write issues:write" |
expires_at | Option<DateTimeUtc> | NULL = pas d'expiration |
issues
| Colonne | Type Rust | Notes |
number | i32 | Auto-incrémenté par dépôt (pas global). UNIQUE(repository_id, number) |
state | String | "open" (défaut) ou "closed" |
body | String | Markdown brut |
labels
| Colonne | Type Rust | Notes |
label_type | String | "classification" (scope owner) ou "subject" (scope repo) |
owner_id | Option<Uuid> | Non-null pour classification, null pour subject |
repository_id | Option<Uuid> | Non-null pour subject, null pour classification |
color | String | Hex #RRGGBB, validé à l'insertion |
Index : UNIQUE(owner_id, repository_id, name, label_type)
pull_requests
| Colonne | Type Rust | Notes |
number | i32 | Auto-incrémenté par dépôt. UNIQUE(repository_id, number) |
state | String | "open", "closed", "merged" |
merge_commit_sha | Option<String> | SHA40, null avant merge |
import_jobs
| Colonne | Type Rust | Notes |
status | String | State machine : pending → running → success/failed/cancelled |
phase | Option<String> | "cloning", "resolving", "finalizing" |
repository_id | Option<Uuid> | Null pendant le clonage, rempli au succès uniquement |
Ordre des migrations
| # | Nom | Tables créées |
| 1 | m20260305_000001_initial_schema | users, refresh_tokens, jwt_blacklist, audit_logs (core) |
| 2 | m20260306_000002_create_app_settings_table | app_settings (core) |
| 3 | m20260309_000003_create_permissions_tables | roles, permissions, role_permissions, user_roles (core) |
| 4 | m20260309_000004_create_resources_tables | resources, resource_shares (core) |
| 5 | m20260310_000005_create_oauth_accounts_table | oauth_accounts (core) |
| 6 | m20260325_000001_create_repositories | repositories |
| 7 | m20260325_000002_create_ssh_keys | ssh_keys |
| 8 | m20260325_000003_create_teams | teams |
| 9 | m20260325_000004_create_team_members | team_members |
| 10 | m20260325_000005_create_team_repository_access | team_repository_access |
| 11 | m20260327_000006_create_personal_access_tokens | personal_access_tokens |
| 12 | m20260327_000007_create_issues | issues |
| 13 | m20260327_000008_create_issue_comments | issue_comments |
| 14 | m20260327_000009_create_labels | labels, issue_labels |
| 15 | m20260327_000010_add_label_type | ALTER labels (label_type) |
| 16 | m20260327_000011_labels_owner_scope | ALTER labels (owner_id, repository_id nullable) |
| 17 | m20260327_000012_create_pull_requests | pull_requests |
| 18 | m20260327_000013_create_pr_comments | pr_comments |
| 19 | m20260409_000006_create_totp_tables | user_totp, totp_challenges (core) |
| 20+ | m20260416_000022_create_import_jobs | import_jobs |
Toutes les migrations sont exécutées par AppMigrator (combine core + gitrust) dans gitrust_core::migrations::run_migrations().
Voir aussi