diff --git a/.env.sample b/.env.sample new file mode 100644 index 00000000..8ba5ba93 --- /dev/null +++ b/.env.sample @@ -0,0 +1,7 @@ +APP_NAME=Yavsc +YAVSC_CONNECTION_HOST=localhost +YAVSC_CONNECTION_PORT=5432 +YAVSC_CONNECTION_DATABASE=Yavsc +YAVSC_CONNECTION_USERNAME=Yavsc +YAVSC_CONNECTION_PASSWORD=lame-YAVSC_CONNECTION_PASSWORD +DESTDIR=/srv/www/Yavsc diff --git a/.vscode/settings.json b/.vscode/settings.json index cf480807..9a0ff7f3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,5 +16,6 @@ "cSpell.language": "fr,fr-FR,en,en-GB", "chat.tools.terminal.autoApprove": { "dotnet test": true - } + }, + "makefile.configureOnOpen": false } diff --git a/Makefile b/Makefile index c9b8d020..ee44956b 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ clean: dotnet clean src/Yavsc/bin/output/wwwroot: - dotnet --project src/Yavsc/Yavsc.csproj publish + dotnet --project src/Yavsc.Org/Yavsc.Org.csproj publish test: dotnet test @@ -27,15 +27,14 @@ src/Yavsc.Server/bin/$(CONFIG)/$(FRAMEWORK)/Yavsc.Server.dll: dotnet build -p:Configuration=$(CONFIG) --project src/Yavsc.Server/Yavsc.Server.csproj src/Yavsc/bin/$(CONFIG)/$(FRAMEWORK)/Yavsc.dll: - dotnet build -p:Configuration=$(CONFIG) --project src/Yavsc/Yavsc.csproj + dotnet build -p:Configuration=$(CONFIG) --project src/Yavsc.Org/Yavsc.Org.csproj $(DESTDIR): mkdir $(DESTDIR) install: $(DESTDIR) - dotnet publish src/Org/Org.csproj -c Release -o $(APP_FULL_PATH) + dotnet publish src/Yavsc.Org/Yavsc.Org.csproj -c Release -o $(APP_FULL_PATH) dotnet publish src/Api/Api.csproj -c Release -o $(APP_FULL_PATH) - dotnet publish src/Web/Web.csproj -c Release -o $(APP_FULL_PATH) sudo chown -R www-data:www-data $(APP_FULL_PATH) docker-image: diff --git a/src/Yavsc.Server/Makefile b/src/Yavsc.Server/Makefile index 991ad411..15c4527d 100644 --- a/src/Yavsc.Server/Makefile +++ b/src/Yavsc.Server/Makefile @@ -1,2 +1,3 @@ -listConnections: - dotnet ef migrations list --connection "$(YAVSC_CONNECTION_STRING)" +listMigrations: + dotnet ef migrations list + diff --git a/src/Yavsc.Server/Models/Kyc/RegesAlertPattern.cs b/src/Yavsc.Server/Models/Kyc/RegesAlertPattern.cs new file mode 100644 index 00000000..7327e6d0 --- /dev/null +++ b/src/Yavsc.Server/Models/Kyc/RegesAlertPattern.cs @@ -0,0 +1,43 @@ +// Yavsc.Models.Kyc/RegexAlertPattern.cs +namespace Yavsc.Models.Kyc +{ + using System.ComponentModel.DataAnnotations; + + public enum PatternSeverity { Warning, Blocking } + + /// + /// Expression régulière configurée par l'admin. + /// Appliquée automatiquement à chaque déclaration soumise. + /// + public class RegexAlertPattern + { + [Key] + public int Id { get; set; } + + [Required, MaxLength(500)] + public string Pattern { get; set; } + + [MaxLength(200)] + public string Description { get; set; } + + public PatternSeverity Severity { get; set; } + + public bool IsActive { get; set; } = true; + } + + public class DeclarationFlag + { + [Key] + public long Id { get; set; } + + public long DeclarationId { get; set; } + public virtual TrustDeclaration Declaration { get; set; } + + public int PatternId { get; set; } + public virtual RegexAlertPattern Pattern { get; set; } + + // Extrait du texte qui a matché (tronqué, jamais le texte complet) + [MaxLength(100)] + public string MatchExcerpt { get; set; } + } +} \ No newline at end of file diff --git a/src/Yavsc.Server/Models/Kyc/TrustDeclaration.cs b/src/Yavsc.Server/Models/Kyc/TrustDeclaration.cs new file mode 100644 index 00000000..0a97eb6a --- /dev/null +++ b/src/Yavsc.Server/Models/Kyc/TrustDeclaration.cs @@ -0,0 +1,55 @@ +// Yavsc.Models.Kyc/TrustDeclaration.cs +namespace Yavsc.Models.Kyc +{ + using System; + using System.ComponentModel.DataAnnotations; + + public enum DeclarationSentiment { Positive, Neutral, Negative } + + public class TrustDeclaration + { + [Key] + public long Id { get; set; } + + // Vers qui porte la déclaration (pseudonyme) + [Required] + public Guid TrustTokenId { get; set; } + public virtual TrustToken Subject { get; set; } + + // Qui déclare — pseudonymisé aussi + [Required] + public Guid DeclarantTokenId { get; set; } + + /// + /// Texte libre soumis par le déclarant. + /// Passé à la modération + regex avant tout effet sur le score. + /// + [MaxLength(2000)] + public string Content { get; set; } + + public DeclarationSentiment Sentiment { get; set; } + + public DateTime SubmittedAt { get; set; } = DateTime.UtcNow; + + // État de modération + public ModerationStatus Status { get; set; } = ModerationStatus.Pending; + + /// + /// Score d'impact sur le TrustToken, attribué par la modération. + /// Entre -10 et +10. Null = pas encore traité. + /// + public int? ScoreDelta { get; set; } + + // Flags regex levés automatiquement avant modération humaine + public virtual ICollection Flags { get; set; } + } + + public enum ModerationStatus + { + Pending, // en attente + Flagged, // regex alarmante détectée, modération prioritaire + Approved, // validé, ScoreDelta appliqué + Rejected, // rejeté, aucun effet sur le score + Redacted // accepté mais contenu expurgé + } +} \ No newline at end of file diff --git a/src/Yavsc.Server/Models/Kyc/TrustToken.cs b/src/Yavsc.Server/Models/Kyc/TrustToken.cs new file mode 100644 index 00000000..47084cb0 --- /dev/null +++ b/src/Yavsc.Server/Models/Kyc/TrustToken.cs @@ -0,0 +1,43 @@ +// Yavsc.Models.Kyc/TrustToken.cs +namespace Yavsc.Models.Kyc +{ + using System; + using System.ComponentModel.DataAnnotations; + using System.ComponentModel.DataAnnotations.Schema; + + /// + /// Token opaque représentant une entité sans l'identifier. + /// Généré soit par un tiers de confiance (référence externe), + /// soit par hash d'un e-mail confirmé (fallback interne). + /// Jamais réversible côté consultant. + /// + public class TrustToken + { + [Key] + public Guid Id { get; set; } = Guid.NewGuid(); + + /// + /// Token fourni par le tiers de confiance, OU + /// HMAC-SHA256(email_confirmé, clé_secrète_serveur). + /// Stocké tel quel — pas l'email, pas l'identité. + /// + [Required, MaxLength(128)] + public string TokenHash { get; set; } + + /// + /// Source du token : "trusted_party" | "confirmed_email" + /// + [Required, MaxLength(32)] + public string TokenSource { get; set; } + + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + + /// + /// Score de confiance agrégé, calculé par la modération. + /// Null si jamais évalué. + /// + public int? TrustScore { get; set; } + + public virtual ICollection Declarations { get; set; } + } +} \ No newline at end of file