Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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