schema-base-de-donnees.md 16474 octets

Schéma de la base de données

Référence des tables PostgreSQL de gitrust, avec colonnes, index, contraintes et relations. Cette page concerne les tables visibles par un administrateur — pour les détails internes du code (migrations SeaORM, patterns de contribution), voir le manuel développeur.


Diagramme entité-relation

erDiagram
    users {
        uuid id PK
        string username UK
        string email UK
        string password_hash
        boolean must_change_password
        timestamptz last_login_at
        boolean email_verified
        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
    }

    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
    }

    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
    }

    labels {
        uuid id PK
        uuid owner_id FK
        uuid repository_id FK
        string name
        string color
        string description
        string label_type
        timestamptz created_at
    }

    app_settings {
        uuid id PK
        string key UK
        text value
        text description
        uuid updated_by FK
        timestamptz updated_at
    }

    audit_log {
        uuid id PK
        uuid actor_id FK
        string action
        string resource_type
        uuid resource_id
        string ip_address
        text details
        timestamptz created_at
    }

    users ||--o{ repositories : "possède"
    users ||--o{ ssh_keys : "enregistre"
    users ||--o{ teams : "crée"
    users ||--o{ resources : "possède"
    users ||--o{ resource_shares : "partage avec"
    users ||--o{ personal_access_tokens : "crée"
    users ||--o{ audit_log : "acteur"
    repositories ||--o| resources : "enregistré dans"
    resources ||--o{ resource_shares : "partagé"
    teams ||--o{ team_members : "contient"
    users ||--o{ team_members : "membre de"
    teams ||--o{ team_repository_access : "accède à"
    repositories ||--o{ team_repository_access : "accessible par"
    repositories ||--o{ issues : "contient"
    repositories ||--o{ pull_requests : "contient"

Tables rustwarden-core (framework)

Ces tables sont gérées par le framework. Ne les modifiez pas directement.

TableRôle
usersComptes utilisateurs (authentification, profil)
roles / permissions / role_permissions / user_rolesRBAC global (admin, user)
resourcesRegistre générique de ressources (ownership, visibilité publique/privée)
resource_sharesPartage de ressources avec niveaux (read/write/admin)
refresh_tokensRefresh tokens JWT
jwt_blacklistTokens JWT révoqués (invalidation après déconnexion)
app_settingsConfiguration dynamique de l'application
audit_logJournal d'audit de toutes les actions significatives
oauth_accountsComptes OAuth liés

Tables gitrust

repositories

Dépôts Git hébergés sur la plateforme.

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
owner_idUUIDFK → users.id CASCADE, NOT NULLPropriétaire du dépôt
slugVARCHAR(64)NOT NULLNom URL du dépôt (ex. mon-projet)
descriptionVARCHAR(500)NULLDescription affichée dans l'UI
disk_pathVARCHAR(512)NOT NULLChemin absolu du bare repo sur disque
default_branchVARCHAR(255)NOT NULL, DEFAULT 'main'Branche par défaut
is_emptyBOOLEANNOT NULL, DEFAULT trueVrai si aucun commit poussé
created_atTIMESTAMPTZNOT NULLDate de création
updated_atTIMESTAMPTZNOT NULLDate de dernière modification

Index : UNIQUE(owner_id, slug), INDEX(owner_id)

Chaque dépôt est aussi enregistré dans resources avec resource_type = "repository" pour gérer la visibilité (public/privé) et le partage via resource_shares.

ssh_keys

Clés publiques SSH des utilisateurs pour l'authentification Git.

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
user_idUUIDFK → users.id CASCADE, NOT NULLPropriétaire de la clé
titleVARCHAR(255)NOT NULLLibellé (ex. MacBook Pro)
fingerprintVARCHAR(128)UNIQUE, NOT NULLFingerprint SHA256 calculé à l'insertion
key_typeVARCHAR(32)NOT NULLType : ssh-ed25519, ssh-rsa, ecdsa-*
key_dataTEXTNOT NULLClé au format authorized_keys
last_used_atTIMESTAMPTZNULLDernière utilisation SSH
created_atTIMESTAMPTZNOT NULLDate d'ajout

Validation : types autorisés — Ed25519, RSA ≥ 4096 bits, ECDSA P-256/P-384.

teams

Groupes d'utilisateurs pour le partage d'accès aux dépôts.

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
owner_idUUIDFK → users.id CASCADE, NOT NULLCréateur / administrateur de l'équipe
slugVARCHAR(64)NOT NULLNom URL de l'équipe
descriptionVARCHAR(500)NULLDescription
created_atTIMESTAMPTZNOT NULLDate de création
updated_atTIMESTAMPTZNOT NULLDate de dernière modification

Index : UNIQUE(owner_id, slug)

team_members

Appartenance d'un utilisateur à une équipe avec un rôle.

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
team_idUUIDFK → teams.id CASCADE, NOT NULLÉquipe
user_idUUIDFK → users.id CASCADE, NOT NULLMembre
roleVARCHAR(20)NOT NULL, DEFAULT 'read'Rôle dans l'équipe
created_atTIMESTAMPTZNOT NULLDate d'ajout

Index : UNIQUE(team_id, user_id), INDEX(user_id)

team_repository_access

Permissions d'accès d'une équipe sur un dépôt.

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
team_idUUIDFK → teams.id CASCADE, NOT NULLÉquipe
repository_idUUIDFK → repositories.id CASCADE, NOT NULLDépôt
permissionVARCHAR(20)NOT NULL, DEFAULT 'read'Niveau : read, write, admin
created_atTIMESTAMPTZNOT NULLDate d'attribution

Index : UNIQUE(team_id, repository_id), INDEX(repository_id)

personal_access_tokens

Jetons d'accès personnels pour l'authentification API et Git HTTPS.

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
user_idUUIDFK → users.id CASCADE, NOT NULLPropriétaire du jeton
nameVARCHAR(255)NOT NULLNom descriptif (ex. CI pipeline)
token_hashVARCHAR(128)UNIQUE, NOT NULLHash SHA-256 du jeton (le jeton brut n'est jamais stocké)
scopesVARCHAR(255)NOT NULLPortées autorisées (séparées par espace)
expires_atTIMESTAMPTZNULLExpiration (NULL = sans expiration)
last_used_atTIMESTAMPTZNULLDernière utilisation
created_atTIMESTAMPTZNOT NULLDate de création

issues

Tickets de suivi (bugs, tâches, demandes de fonctionnalité).

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
repository_idUUIDFK → repositories.id CASCADEDépôt propriétaire
numberINTEGERNOT NULL (auto-incrémenté par dépôt)Numéro affiché (#1, #2…)
author_idUUIDFK → users.id CASCADEAuteur
titleVARCHAR(255)NOT NULLTitre
bodyTEXTNOT NULL DEFAULT ''Corps (Markdown)
stateVARCHAR(20)NOT NULL DEFAULT 'open'État : open, closed
closed_byUUIDFK → users.id NULLUtilisateur qui a fermé l'issue
created_atTIMESTAMPTZNOT NULLDate de création
updated_atTIMESTAMPTZNOT NULLDate de dernière modification

Index : UNIQUE(repository_id, number), INDEX(repository_id, state)

pull_requests

Propositions de merge d'une branche source vers une branche cible.

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
repository_idUUIDFK → repositories.id CASCADEDépôt
numberINTEGERNOT NULL (auto-incrémenté par dépôt)Numéro affiché
author_idUUIDFK → users.id CASCADEAuteur
titleVARCHAR(255)NOT NULLTitre
bodyTEXTNOT NULL DEFAULT ''Description
source_branchVARCHAR(255)NOT NULLBranche source
target_branchVARCHAR(255)NOT NULLBranche cible (ex. main)
stateVARCHAR(20)NOT NULL DEFAULT 'open'État : open, merged, closed
merged_atTIMESTAMPTZNULLDate de merge
merged_byUUIDFK → users.id NULLUtilisateur qui a mergé
merge_commit_shaVARCHAR(40)NULLSHA du commit de merge
created_atTIMESTAMPTZNOT NULLDate de création
updated_atTIMESTAMPTZNOT NULLDate de dernière modification

Index : UNIQUE(repository_id, number), INDEX(repository_id, state)

labels

Étiquettes à deux niveaux : classification (scope owner) et subject (scope dépôt).

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
owner_idUUIDFK → users.id NULLPropriétaire (labels de classification)
repository_idUUIDFK → repositories.id NULLDépôt (labels de sujet)
nameVARCHAR(50)NOT NULLNom du label
colorVARCHAR(7)NOT NULLCouleur hexadécimale (ex. #e11d48)
descriptionVARCHAR(255)NULLDescription
label_typeVARCHAR(20)NOT NULL'classification' ou 'subject'
created_atTIMESTAMPTZNOT NULLDate de création

Index : UNIQUE(owner_id, repository_id, name, label_type)

app_settings

Configuration dynamique de l'application (modifiable à chaud via /admin/settings).

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
keyVARCHAR(100)UNIQUE, NOT NULLClé de configuration (ex. allow_registration)
valueTEXTNOT NULLValeur sous forme de texte
descriptionTEXTNULLDescription affichée dans l'UI admin
updated_byUUIDFK → users.id ON DELETE SET NULLDernier administrateur ayant modifié
updated_atTIMESTAMPTZNOT NULLDate de dernière modification

audit_log

Journal d'audit de toutes les actions significatives.

ColonneTypeContraintesDescription
idUUIDPKIdentifiant unique
actor_idUUIDFK → users.id NULLUtilisateur auteur de l'action
actionVARCHAR(50)NOT NULLType d'action (create, update, delete, reset_password…)
resource_typeVARCHAR(50)NULLType de ressource concernée
resource_idUUIDNULLIdentifiant de la ressource
ip_addressVARCHAR(45)NULLAdresse IP source
detailsTEXTNULLDétails supplémentaires (JSON)
created_atTIMESTAMPTZNOT NULLHorodatage

Modèle de permissions

graph TB
    subgraph "Accès individuel"
        Owner["Owner (resources.owner_id)"]
        Share["resource_shares (read/write/admin)"]
        Public["Accès public (resources.is_public)"]
    end

    subgraph "Accès équipe"
        TM["team_members (rôle dans l'équipe)"]
        TRA["team_repository_access (permission sur le dépôt)"]
    end

    subgraph "Rôle effectif"
        Eff["max(individuel, équipe)"]
    end

    Owner -->|"Owner (full)"| Eff
    Share -->|"read/write/admin"| Eff
    Public -->|"read only"| Eff
    TM --> TRA
    TRA -->|"read/write/admin"| Eff
RôlePermissions
ReaderClone, navigation (lecture seule)
DeveloperReader + push
MaintainerDeveloper + paramètres, collaborateurs, protections de branche
OwnerMaintainer + suppression, transfert

Ordre des migrations

#MigrationTables créées
1m20260305_000001_initial_schemausers, refresh_tokens, jwt_blacklist… (core)
2m20260306_000002_create_app_settings_tableapp_settings (core)
3m20260309_000003_create_permissions_tablesroles, permissions, role_permissions, user_roles (core)
4m20260309_000004_create_resources_tablesresources, resource_shares (core)
5m20260310_000005_create_oauth_accounts_tableoauth_accounts (core)
6m20260325_000001_create_repositoriesrepositories
7m20260325_000002_create_ssh_keysssh_keys
8m20260325_000003_create_teamsteams
9m20260325_000004_create_team_membersteam_members
10m20260325_000005_create_team_repository_accessteam_repository_access
11m20260327_000006_create_personal_access_tokenspersonal_access_tokens
12m20260327_000007_create_issuesissues
13m20260327_000008_create_issue_commentsissue_comments
14m20260327_000009_create_labelslabels, issue_labels
15m20260327_000010_add_label_typealter labels
16m20260327_000011_labels_owner_scopealter labels
17m20260327_000012_create_pull_requestspull_requests
18m20260327_000013_create_pr_commentspr_comments

Toutes les migrations sont appliquées automatiquement au démarrage par AppMigrator. Elles sont idempotentes.


Pour aller plus loin