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