All checks were successful
Dotnet build and test / build (push) Successful in 25m17s
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
871 lines
47 KiB
Markdown
871 lines
47 KiB
Markdown
# Changelog
|
||
|
||
## [1.0.8-rc25] - unstable
|
||
|
||
### Added
|
||
|
||
* [Yavsc.Api] Notification du performer à la création d'un rendez-vous
|
||
depuis PostIt, selon ses préférences de contact, sans supprimer l'envoi Org.
|
||
* [Yavsc.Api][Yavsc.Server] Notification du performer à la signature
|
||
client d'un devis (JSON ou image), enregistrée pour l'accueil PostIt
|
||
et transmise par e-mail et SignalR.
|
||
* [Yavsc.Api] Nouveau point d'entrée `GET /api/v1/notifications/me`
|
||
pour exposer les notifications publiques et ciblées à PostIt sur la
|
||
Home page ; les notifications d'administration restent filtrées.
|
||
* [PostIt] Affichage des notifications sur la page d'accueil, avec
|
||
actualisation, indicateur de chargement et message d'erreur. Les
|
||
notifications publiques sont accessibles sans connexion et la liste
|
||
est rechargée lors d'un changement de session.
|
||
|
||
### Changed
|
||
|
||
* [PostIt] Insertion des liens de fichiers dès leur ajout au brouillon ;
|
||
les liens provisoires des nouveaux billets sont résolus au premier
|
||
enregistrement. Save conserve l'édition ouverte et est mis en valeur
|
||
lorsque le titre, le corps ou les pièces jointes sont modifiés.
|
||
|
||
* [Projet] Instructions Copilot persistantes : mise à jour du changelog
|
||
par défaut à chaque commit, avec justification explicite des exceptions.
|
||
|
||
### Fixed
|
||
|
||
* [PostIt.Tests] Les tests du bandeau de session utilisent le bandeau
|
||
réellement monté dans la fenêtre headless, au lieu d'un contrôle détaché.
|
||
Les fenêtres sont fermées après chaque test et les quatre boutons
|
||
de navigation sont vérifiés.
|
||
|
||
* [PostIt] Les liens Markdown des pièces jointes utilisent désormais
|
||
le même filtre de nom que l'upload serveur, avant l'encodage URL.
|
||
Le libellé conserve le nom original, notamment ses accents.
|
||
|
||
* [Yavsc.Abstract][Yavsc.Blogs] Encodage des caractères non supportés
|
||
dans les noms de fichiers téléversés avec `_` au lieu de `#`, pour
|
||
éviter les fragments d'URL et permettre le téléchargement via les
|
||
fichiers statiques, notamment pour les noms accentués.
|
||
|
||
* [Yavsc.Api][Yavsc.Blogs] Les appels API et la bande passante sont
|
||
désormais enregistrés côté serveur pour les requêtes authentifiées :
|
||
le middleware de télémétrie est maintenant branché après
|
||
l'authentification, ce qui permet de comptabiliser `ApiCalls` et
|
||
`BandwidthMb` au lieu d'enregistrer des zéros.
|
||
|
||
## [1.0.8-rc24] - unstable
|
||
|
||
### Added
|
||
|
||
* [PostIt] Reconnection automatique aux salons de discussion au reconnect
|
||
|
||
### Changed
|
||
|
||
* [PostIt] La liste des billets et l'éditeur Markdown se partagent
|
||
l'espace disponible et défilent séparément ; un séparateur permet
|
||
de redimensionner les deux zones.
|
||
|
||
### Fixed
|
||
|
||
* [PostIt] Défilement des articles longs en édition et en aperçu :
|
||
suppression de la limite de hauteur qui masquait le contenu Markdown
|
||
et du défilement imbriqué autour d'AvaloniaEdit. Six tests headless
|
||
couvrent les barres automatiques, le redimensionnement et le
|
||
défilement indépendant de la liste.
|
||
|
||
## [1.0.8-rc23] - unstable
|
||
|
||
### Added
|
||
|
||
* [PostIt] Badge « Publié » à côté du titre des billets publiés dans la
|
||
liste, mis à jour lors de la publication ou du retour en brouillon.
|
||
* [PostIt] Gestion native du compte inspirée de `/Manage` : modification
|
||
du nom d'utilisateur, du nom complet et de l'adresse, téléversement
|
||
d'avatar, confirmation e-mail, préférence de courriel mensuel,
|
||
création ou changement de mot de passe et activation/désactivation
|
||
de l'authentification à deux facteurs.
|
||
* [PostIt][Yavsc.Api] Sélection d'un agenda Google, gestion séparée des
|
||
comptes bancaires, dissociation des connexions externes et suppression
|
||
du compte avec confirmation du nom d'utilisateur.
|
||
* [PostIt] Configuration du profil professionnel et des activités,
|
||
navigation vers les cercles et les publications depuis le compte.
|
||
* [PostIt][Yavsc.Api] Administration des utilisateurs avec recherche
|
||
dans les métadonnées du profil et consultation de la consommation
|
||
de ressources.
|
||
* [Yavsc.Server][Yavsc.Api][Yavsc.Blogs] Suivi de la consommation de
|
||
ressources, API de synthèse et migration `ResourceUsageRecords`.
|
||
* [Tests] Couverture des parcours profil et professionnel, de l'API de
|
||
consommation de ressources et du renouvellement des jetons :
|
||
rotation à usage unique, appels simultanés, réponses 401 concurrentes
|
||
et rejet d'un jeton de renouvellement révoqué.
|
||
|
||
### Changed
|
||
|
||
* [PostIt] Réorganisation de la page de compte en sections de profil,
|
||
sécurité et préférences ; actions de modification désactivées tant
|
||
que le profil n'est pas chargé ou qu'une opération est en cours.
|
||
* [PostIt] Utilisation de `PlaceholderText` à la place de `Watermark`
|
||
dans les pages de profil et de configuration professionnelle.
|
||
* [Yavsc.Api] `GET account/me` renvoie le DTO partagé attendu par
|
||
PostIt, avec l'état de sécurité, les connexions externes, les comptes
|
||
bancaires et les compteurs du compte.
|
||
|
||
### Fixed
|
||
|
||
* [Yavsc.Api] Enregistrement des services ASP.NET Identity et des stores
|
||
EF nécessaires à `UserManager<ApplicationUser>` : leur absence
|
||
empêchait l'activation du contrôleur de compte et provoquait une 500.
|
||
* [Yavsc.Api] Chargement du profil : réponse adaptée lorsqu'un jeton
|
||
ne contient pas d'identifiant utilisateur ou que le compte n'existe
|
||
plus, au lieu d'une exception serveur.
|
||
* [PostIt] Synchronisation de tous les chemins de renouvellement des
|
||
jetons, y compris après une 401 et au démarrage : les appels
|
||
concurrents ne réutilisent plus le même `refresh_token`. Un rejet
|
||
`invalid_grant` efface la session et invite à se reconnecter.
|
||
* [PostIt] Effacement des informations obsolètes après un échec de
|
||
rechargement du profil et normalisation des valeurs de calendrier
|
||
lors de la sauvegarde.
|
||
* [PostIt][Yavsc.Api] Préservation de l'identité du profil professionnel
|
||
lors de son enregistrement.
|
||
* [Yavsc.Api] Les coordonnées bancaires ne sont plus modifiées à partir
|
||
d'un résumé agrégé : opérations dédiées avec contrôle de propriété
|
||
et validation de longueur des champs.
|
||
|
||
### Known limitations
|
||
|
||
* [PostIt] L'ajout d'un nouveau fournisseur OAuth et la gestion des
|
||
crédits ne sont pas encore disponibles dans l'interface native.
|
||
|
||
## [1.0.8-rc22] - unstable
|
||
|
||
### Fixed
|
||
|
||
User experience login into PostIt
|
||
|
||
## [1.0.8-rc21] - unstable
|
||
|
||
### Fixed
|
||
|
||
User experience editing the blog article.
|
||
|
||
## [1.0.8-rc20] - unstable
|
||
|
||
Chat SignalR fonctionnel de bout en bout (connexion, salons multiples,
|
||
envoi/réception de messages), enregistreur audio et localisation dans
|
||
PostIt, intégration Live.Avalonia démarrée, et reverse-proxy nginx
|
||
apprêté pour WebSocket.
|
||
|
||
### Added
|
||
|
||
* [PostIt] Interface de chat : page `ChatPage` (connexion au hub,
|
||
saisie du nom de salon, liste des messages et des membres présents),
|
||
entrée depuis la page d'accueil.
|
||
* [PostIt] Envoi de messages dans un salon joint : DTO `ChatMessage`
|
||
(Name/Room/Message) pour l'événement `ReceiveMessage`, saisie avec
|
||
envoi sur `Enter`, commande inactive tant qu'aucune salle n'est en
|
||
focus (le hub refuse l'envoi hors salon, `LabNoJoinNoSend`).
|
||
* [PostIt] Modèle multi-salles côté client : `JoinedRooms`,
|
||
`SelectedRoom` (salle en focus), messages et utilisateurs indexés par
|
||
salle (`FocusedMessages`/`FocusedUsers`), ComboBox de choix de la
|
||
salle active ; un `Join` sur une salle déjà jointe ne fait que
|
||
changer le focus.
|
||
* [PostIt] Enregistreur audio (`AudioRecorder`, interface
|
||
`IPCMProcessor`) et ressources de localisation
|
||
(`Resources.{resx,en-EN,pt-PT}`).
|
||
* [PostIt][WIP] Début d'intégration Live.Avalonia (preview XAML à
|
||
chaud ; encore KO).
|
||
* [contrib] Bloc `location /chathub` dans `template.vhost` : upgrade
|
||
WebSocket (`Upgrade`/`Connection`), `proxy_read_timeout 3600s` et
|
||
`proxy_buffering off` — sans quoi la connexion SignalR tombait au
|
||
premier silence ou l'upgrade échouait derrière nginx.
|
||
|
||
### Changed
|
||
|
||
* [PostIt] `StatusNotice` déplacé de `Models` vers `ViewModels` et
|
||
enrichi d'une commande d'action optionnelle (`CheckCommand` +
|
||
`CheckCommandLabel`, interface `IWithLabel`) : le bandeau de statut
|
||
propose désormais l'action contextuelle (Connecter / Déconnecter /
|
||
Reconnecter / Vérifier la connexion).
|
||
* [PostIt] `ChatViewModel` suit le cycle de vie complet de la
|
||
connexion : handlers `Reconnecting` / `Reconnected` / `Closed` de
|
||
`WithAutomaticReconnect`, pour refléter l'état réel au lieu d'un
|
||
`IsConnected` optimiste.
|
||
* [Yavsc.Api] `AddSignalR().AddJsonProtocol(IncludeFields = true)` :
|
||
`ChatRoomInfo` n'expose que des champs publics, que System.Text.Json
|
||
ne sérialise pas par défaut — le client recevait des objets vides
|
||
(`Name` null, `Users` vide) et la liste des salons joints n'était
|
||
jamais alimentée.
|
||
* [Yavsc.Server] `IConnexionManager.OnConnected` prend le `userName`
|
||
en paramètre (résolu depuis les claims dans `ChatHub`) au lieu de le
|
||
relire depuis un dictionnaire jamais alimenté.
|
||
* [PostIt.Android] `network_security_config.xml` déplacé sous
|
||
`Resources/xml/` (chemin canonique Android).
|
||
|
||
### Fixed
|
||
|
||
* [Yavsc.Server] `KeyNotFoundException` dans
|
||
`HubConnectionManager.OnConnected` à chaque connexion SignalR :
|
||
`ChatUserNames` (et `ChatCxIds`) n'étaient jamais alimentés — relique
|
||
d'un `SetUserName` disparu lors d'une refactorisation. L'exception
|
||
dans `OnConnectedAsync` faisait fermer la connexion par le hub, et
|
||
PostIt affichait « Déconnecté (The server closed the connection…) »
|
||
immédiatement après la connexion.
|
||
* [PostIt] URL du hub SignalR : retrait du préfixe `/api/v1` de
|
||
`ApiUrl` avant d'apposer `Constants.ChatHubPath` (le hub est mappé à
|
||
la racine du service, pas sous le préfixe versionné).
|
||
* [PostIt] La `StatusBar` de la page chat référençait `Grid.Row="4"`
|
||
sur une grille à 3 rangées (rangée hors limites, bandeau invisible).
|
||
|
||
## [1.0.8-rc19] - unstable
|
||
|
||
[PostIt] Blogs UX
|
||
|
||
### Fixed
|
||
|
||
La saisie du billet est maintenant plutôt possible,
|
||
en petit écran.
|
||
|
||
## [1.0.8-rc18] - unstable
|
||
|
||
* [PostIt] Page "About" avec lines vers le dépôt et les issues Forgejo
|
||
|
||
* Accès aux fichiers personnels PostIt rendu fonctionnel de bout en bout
|
||
(arbre de stockage indexé par le login, pas par le `sub`), boutons
|
||
d'action des listes réparés (binding `$parent`), revendication `name`
|
||
enfin présente dans les access tokens (branchement du `ProfileService`),
|
||
et négociation HTTP/3 côté client PostIt.
|
||
|
||
|
||
### Added
|
||
|
||
* [PostIt] Négociation HTTP/3 (QUIC) pour les appels API Yavsc :
|
||
`DefaultRequestVersion = 3.0`, `DefaultVersionPolicy =
|
||
RequestVersionOrLower` sur le `HttpClient` partagé de `YavscApiClient`,
|
||
avec repli h2/h1.1 où QUIC n'est pas disponible (WASM fetch, Android/
|
||
desktop sans libmsquic).
|
||
* [Tests] `MyFilesPageHeadlessTests` : monte `MyFilesPage` via
|
||
`NavigationPage` + `Window.Show()` et vérifie que chaque bouton de
|
||
ligne (Télécharger / Supprimer) a sa `Command` liée, est armé
|
||
(`CanExecute`) et déclenche l'appel API au clic.
|
||
* [Tests] `Remoting.PasswordToken_carries_name_claim_equal_to_login` :
|
||
mint un vrai JWT via le token endpoint IdentityServer (password grant,
|
||
`openid profile`) et asserte que l'access token porte `name`=login et
|
||
que `GetUserName()` résout vers ce login.
|
||
* [Tests] `FileSystemApiTests.Get_fs_lists_files_stored_under_the_user_login` :
|
||
découple `sub` et login, téléverse sous le login, et asserte que
|
||
`GET /api/v1/fs` retourne le fichier (et que le répertoire nommé d'après
|
||
le `sub` n'existe pas).
|
||
|
||
### Changed
|
||
|
||
* [Yavsc.Org] Branchement du `ProfileService` custom
|
||
(`AddProfileService<ProfileService>()` après
|
||
`AddAspNetIdentity<ApplicationUser>()`). La classe était du code mort :
|
||
IdentityServer8 retombait sur son profile service par défaut, qui
|
||
n'émet que les claims listés dans les `UserClaims` des API resources.
|
||
`name` n'en faisait jamais partie, donc tout access token était sans
|
||
`name` et `GetUserName()` résolvait à `null` sur les hosts ressources
|
||
(Blogs/Api) — cause du 500 sur l'upload MyFiles et du
|
||
`User.Identity.Name` injoignable. Le service émet désormais
|
||
`name`=`user.UserName`, `email` et les rôles pour tout client dont
|
||
les `AllowedScopes` contiennent `profile`, indépendamment du caller.
|
||
* [Yavsc.Server] `ServiceExtensions` : `NameClaimType =
|
||
JwtClaimTypes.Name`, `MapInboundClaims = false` (conserver les noms
|
||
courts de claims tels qu'émis).
|
||
* [Yavsc.Blogs] `FileSystemHelpers.EnsureDestinationDirectory` utilise
|
||
`GetUserName()` (claim `name`) au lieu de `User.Identity.Name` pour
|
||
la racine de stockage par utilisateur.
|
||
* [Tests] `WebServerFixture` : `AccessTokenType = 0` (Jwt dans IS8 ;
|
||
1 = Reference, l'inverse de Duende) ; `openid`+`profile` sur le client
|
||
de test ; réensemencement des identity resources openid/profile dans
|
||
`ReseedAuthTestData` (un `ResetAndMigrateDatabase` vide le store
|
||
in-memory partagé et les laissait absentes → `invalid_scope`).
|
||
* [Tests] `TestTokenIssuer.Issue` gagne un paramètre `name` optionnel
|
||
(défaut = subject) pour refléter la forme production où
|
||
`sub` (GUID) ≠ `name` (login).
|
||
* [Tests] `BillingServiceTests` : `[Collection("Yavsc Server")]` pour
|
||
sérialiser avec le build d'hôte qui mute les registres statiques
|
||
`BillingService`/`Config` (race parallèle pré-existante).
|
||
|
||
### Fixed
|
||
|
||
* [Yavsc.Blogs] La liste `GET /api/v1/fs` cherchait sous
|
||
`{Blog}/{sub-GUID}` (`User.GetUserId()`), alors que l'arbre de
|
||
stockage perso est indexé par le login partout ailleurs
|
||
(`EnsureDestinationDirectory` écrit sous `{Blog}/{name-claim}`,
|
||
le endpoint de téléchargement et les avatars utilisent
|
||
`user.UserName`). Une fois l'upload corrigé, les fichiers
|
||
atterrissaient sous `{Blog}/{login}` tandis que la liste cherchait
|
||
sous `{Blog}/{GUID}` — un arbre vide — d'où la page PostIt
|
||
« Mes fichiers » qui ne listait rien. `GetDir` résout désormais
|
||
l'utilisateur en base et liste sous `user.UserName`.
|
||
`UploadedFile.OwnerId` reste `sub`, donc `EnrichWithFileIds`
|
||
interpole toujours par `uid`.
|
||
* [PostIt] Boutons d'action des lignes de liste grisés et inactifs au
|
||
clic (Télécharger / Supprimer / Joindre sur MyFiles ; download/detach
|
||
sur les listes de pièces jointes de `BillingQueryDetailsPage` et
|
||
`EstimateEditionPage`). Le binding `$parent[vm:XxxViewModel].Cmd`
|
||
cherchait un ancêtre CONTRÔLE de type `XxxViewModel` — un viewmodel,
|
||
pas un contrôle — donc résolvait à `null` et le `Button` restait
|
||
désactivé (grisé) et inerte au clic. Corrigé en
|
||
`$parent[ContentPage].((vm:XxxViewModel)DataContext).Cmd` (syntaxe
|
||
déjà en vigueur dans `CirclesPage` / `EstimateListPage`).
|
||
* [PostIt] Les messages de la barre de statut (`StatusBar`) n'étaient
|
||
pas sélectionnables/copiables : le texte était un `TextBlock` (non
|
||
sélectionnable dans Avalonia). Remplacé par `SelectableTextBlock`.
|
||
* [Yavsc.Blogs] La suppression d'un fichier (`DELETE api/v1/fs/{name}`)
|
||
renvoyait un 40x alors que le fichier était bien supprimé du disque.
|
||
`DeleteUserDirOrFile` (et `DeleteUserFile`) lisaient
|
||
`FileInfo.Length` **après** `fi.Delete()` ; or `FileInfo.Length`
|
||
lève `FileNotFoundException` une fois le fichier disparu — le `catch`
|
||
du contrôleur transformait cette exception en 400, d'où le message
|
||
perçu « le fichier n'existe pas sur le serveur » tandis que la
|
||
suppression avait réussi. La taille est désormais capturée avant la
|
||
suppression.
|
||
* PostIt default settings
|
||
|
||
## [1.0.8-rc17] - unstable
|
||
|
||
Fichiers utilisateur et pièces jointes sur les devis/demandes (PostIt +
|
||
API), système de génération `contrib` (vhosts nginx HTTP/3 edge +
|
||
appsettings jq + QUIC logiciel Kestrel), et correction du bug de
|
||
production où `IsPublished` disparaissait du payload de liste du blog API.
|
||
|
||
### Added
|
||
|
||
* [PostIt] Espace de stockage personnel (« MyFiles ») : page de gestion
|
||
des fichiers de l'utilisateur, entrée depuis la page d'accueil.
|
||
* [PostIt] Pièces jointes aux devis et aux demandes : attachement depuis
|
||
le détail de demande et la page d'édition de devis.
|
||
* [Yavsc.Api] Endpoints d'attachement de fichiers sur les devis
|
||
(`EstimateApiController`) et les demandes front-office
|
||
(`FrontOfficeApiController`).
|
||
* [Yavsc.Api.Client] `UserFilesApiClient` + DTOs associés ; méthodes
|
||
d'attachement sur `EstimateApiClient` et `FrontOfficeApiClient`.
|
||
* [Yavsc.Server] Modèles `EstimateAttachedFile`, `QueryAttachedFile`,
|
||
`BlogAttachedFile`, `AttachFileRequest` ; migration EF Core
|
||
`UserFileAttachments`.
|
||
* [contrib] Système de génération `Makefile` : vhosts nginx HTTP/3 edge
|
||
(`template.vhost`, `QUIC_OPTS`), appsettings générés via jq
|
||
(`template.appsettings-{org,api,blogs}.json`, échappement JSON-safe des
|
||
secrets), QUIC logiciel Kestrel (`Http1AndHttp2AndHttp3`), et
|
||
`README.nginx.md`.
|
||
* [Tests] Projet `Yavsc.Server.Tests` : tests du service
|
||
`BlogSpotService.Details` + `ServerServicesFixture` (SQLite `:memory:`
|
||
par défaut, Npgsql opt-in via `YAVSC_SERVER_TEST_DB_PROVIDER`).
|
||
* [Tests] `IBlogPostWireShapeTests` (forme du wire blog),
|
||
`EstimateAttachmentsApiTests`, `FrontOfficeQueryAttachmentsApiTests`,
|
||
`FileSystemApiTests` (pièces jointes et stockage perso).
|
||
* [CI] Intégration Gitleaks / analyse de secrets (`.pre-commit-config.yaml`).
|
||
|
||
### Changed
|
||
|
||
* [contrib] `QUIC_OPTS` (`reuseport`) désormais activé uniquement en
|
||
production sur le vhost Org. La preprod et la prod partageant la même
|
||
IP, `reuseport` — légal une seule fois par `addr:port` (443/udp) —
|
||
serait sinon en conflit entre preprod-Org et prod-Org et ferait refuser
|
||
la config par nginx.
|
||
* [Yavsc.Api.Test] `ApiWebServerFixture` : la connexion admin PostgreSQL
|
||
provient de la variable d'environnement
|
||
`YAVSC_API_TEST_NPGSQL_ADMIN_CONNECTION` ; plus de mot de passe en
|
||
source.
|
||
|
||
### Fixed
|
||
|
||
* [Yavsc.Blogs] Bug de production : `IsPublished` était absent du payload
|
||
de la liste du blog API. Le endpoint `GetBlogspot` retourne
|
||
`IEnumerable<IBlogPost>` sérialisé par System.Text.Json d'après le type
|
||
déclaré (l'interface), qui omet les propriétés du type concret —
|
||
`IsPublished` vivait sur `BlogPost` / `BlogPostDto` mais pas sur
|
||
`IBlogPost`. PostIt lisait donc `IsPublished == false` pour tout billet,
|
||
y compris publiés (https://yavsc.pschneider.fr/BlogSpot/Details/13).
|
||
Corrigé en déclarant `IsPublished` sur `IBlogPost`.
|
||
* [Yavsc.Org] Accès au Swagger UI : les actions MVC scaffoldées de
|
||
`CommentsController` (Index/Details/…) atterrissaient sur la même route
|
||
`POST api/v1/blogcomments` que l'action d'API `Post`, provoquant une
|
||
`SwaggerGeneratorException` (conflit method/path) au chargement de
|
||
`/swagger`. Corrigé par `[ApiExplorerSettings(IgnoreApi = true)]` sur
|
||
les actions scaffoldées.
|
||
|
||
## [1.0.8-rc16] - unstable
|
||
|
||
Flux de signature et de génération de devis : un devis peut désormais être
|
||
signé par les deux parties (fournisseur et client) puis téléchargé en PDF
|
||
ou TeX depuis PostIt, avec les signatures dessinées en vecteur.
|
||
|
||
### Added
|
||
|
||
* [PostIt] Pad de signature sur la page de validation d'un devis : on valide
|
||
ou on refuse en joignant une signature (côté fournisseur ou client), capturée
|
||
au format filaire PostIt (strokes) et envoyée sur l'acceptation.
|
||
* [Yavsc.Api] Finalisation de `POST /api/v1/front/query/accept` et `.../reject` :
|
||
autorisation selon le rôle (fournisseur/client/admin), signature optionnelle
|
||
persistée sur l'estimate avec horodatage `ProviderValidationDate` /
|
||
`ClientValidationDate` selon le côté signataire.
|
||
* [Yavsc.Api] `QueryStatus.Accepted` éclaté en `ProAccepted` / `ClientAccepted`
|
||
pour distinguer l'acceptation de chaque partie.
|
||
* [Yavsc.Api] Endpoints de devis `GET /api/v1/front/query/{id}/estimate.tex` et
|
||
`estimate.pdf` (clé par id de query). Le flux de génération TeX/PDF est
|
||
rapatrié de Yavsc.Org vers Yavsc.Api (`TeXHelpers`, `PdfGenerationViewModel`,
|
||
`BillViewComponent`, modèles Bill/Estimate, `_ViewImports` ; `Program.cs`
|
||
câble `AddControllersWithViews` + `SiteSettings`).
|
||
* [Yavsc.Api] Signatures du devis dessinées en TikZ vectoriel
|
||
(`TeXHelpers.SignatureToTikz`) en bas du document, fournisseur et client
|
||
côte à côte dans deux minipages ; plus de dépendance à un PNG de signature.
|
||
* [Yavsc.Api.Client] `DownloadAsync` sur le client + `GetEstimateTexAsync` /
|
||
`GetEstimatePdfAsync` ; boutons « Télécharger PDF » / « Télécharger TeX »
|
||
dans PostIt sur la page de validation du devis et le détail de commande,
|
||
avec un helper `StorageProvider` d'enregistrement de fichier.
|
||
* [PostIt] La liste des devis se rafraîchit au retour de navigation (pop-back),
|
||
de sorte qu'un devis validé quitte immédiatement la liste du signataire.
|
||
* [PostIt] Renommage des titres de liste : « Devis en attente de signature
|
||
fournisseur » / « Devis en attente de signature client ».
|
||
* [Yavsc.Abstract] `SignatureType` déplacé dans `Yavsc.Abstract.Billing`.
|
||
* [CLI] Option `-c configuration-file.json` au lancement.
|
||
* [Tests] `EstimatePdfGenerationTests` : tests unitaires du pipeline
|
||
signature → TikZ → PDF (devis signé des deux côtés), assertant que le PDF
|
||
existe au chemin de sortie attendu et que seul le PDF persiste (aux/log
|
||
nettoyés) ; skip propre si `lualatex` est absent.
|
||
* [README] Dépendances système au runtime pour la génération PDF :
|
||
`texlive-binaries` (lualatex), `texlive-luatex` (luaotfload),
|
||
`texlive-pictures` (tikz), `texlive-fonts-extra` (bera).
|
||
|
||
### Changed
|
||
|
||
* [Yavsc.Api] `GetOngoingEstimatesAsProvider` filtre désormais sur
|
||
`ProviderValidationDate` : un devis signé par le fournisseur quitte sa liste
|
||
« en attente ».
|
||
* [Yavsc.Api] La génération PDF compile via le `lualatex` système, le TeX fourni
|
||
sur l'entrée standard (`/dev/stdin`), le PDF écrit directement dans le
|
||
répertoire des factures (`Site.Bills`), les artefacts `.aux`/`.log` nettoyés
|
||
afin que seul le `.pdf` persiste.
|
||
|
||
### Fixed
|
||
|
||
* [Yavsc.Api] `Emergency stop` à la génération PDF : `lualatex` sans argument
|
||
fichier lit stdin en mode terminal et s'arrête après la première ligne d'un
|
||
document multi-lignes. Corrigé en passant `/dev/stdin` comme nom de fichier
|
||
d'entrée — stdin est alors traité comme un fichier régulier et le document
|
||
multi-lignes compile. C'était la cause racine de l'échec en production, pas
|
||
`bera` ni `luaotfload` (problèmes réels mais séparés, comblés côté paquets).
|
||
* [Yavsc.Api] `I can't write on file 'estimate-1.log'` : le chemin relatif
|
||
`Site.Bills` (`"bills"`) était imbriqué quand il servait à la fois de
|
||
`-output-directory` et de répertoire de travail ; résolu en chemin absolu.
|
||
* [Yavsc.Api] NRE dans `RenderViewToString` (RouteData / `ViewData.Model`
|
||
nuls) : reconstruit sur le `ControllerContext` du contrôleur ; `IViewEngine`
|
||
résolu via `IRazorViewEngine` (.NET 10 n'enregistre pas de `IViewEngine`
|
||
unique).
|
||
* [Yavsc.Api] `Layout = "null"` (chaîne) dans les modèles TeX cherchait
|
||
`null.cshtml` ; corrigé en `Layout = null` (null C#).
|
||
* [Yavsc.Api] `texi2pdf` (outil Texinfo, inadapté au LaTeX) remplacé par
|
||
`lualatex`.
|
||
* [Yavsc.Api] Les diagnostics lualatex étaient perdus (écrits dans le `.log`
|
||
qu'on supprimait) ; stdout/stderr sont désormais capturés dans le message
|
||
d'erreur, et le `.log` est conservé en cas d'échec.
|
||
|
||
## [1.0.8-rc15] - unstable
|
||
|
||
### Added
|
||
|
||
* [PostIt] Saisie et envoi de pieces jointes sur un billet de blog: le client monte les fichiers en `multipart/form-data` lors du `Save`, ajoute un lien Markdown par piece jointe a l'article, puis re-PUT le billet. Une collection `DraftAttachments` porte les fichiers en cours d'edition.
|
||
* [PostIt] Apercu Markdown dans l'editeur de blogs (integration `MarkdownViewer.Core`) avec bascule edition/preview sur `BlogsPage`.
|
||
* [PostIt] Gestion des devis: page de liste `EstimateListPage` (vues client et prestataire), page d'edition `EstimateEditionPage` avec lignes de devis (`EstimateLineItemViewModel`), et flux de validation d'un devis.
|
||
* [PostIt] Flux des requetes en cours cote prestataire (`ProviderOngoingRequestsPage`) avec tri persistant.
|
||
* [Yavsc.Api] Endpoints devis `GET /api/v1/estimate/asclient` et `GET /api/v1/estimate/asprovider` pour lister les devis en cours selon le role.
|
||
* [Yavsc.Api] Endpoint `GET /api/v1/billing/provider/ongoing` et `POST /api/v1/billing/prosign/{billingCode}/{id}` pour le flux prestataire.
|
||
* [Yavsc.Api.Client] `EstimateApiClient` + DTOs (`EstimateDto`, `EstimateLineDto`) pour le pipeline devis cote client lourd.
|
||
* [Yavsc.Api.Client] Reprise de l'upload de fichiers blog dans `BlogApiClient` (`CreateMultipartContent`, `BlogUploadFile`) — la meme forme filaire que PostIt utilise en production.
|
||
* [Yavsc.Abstract] `FileServerUrlHelpers` pour deriver les URLs publiques des fichiers utilisateur depuis l'autorite OIDC (alignement sur `UserFilesPath`).
|
||
* [Yavsc.Server] `BlogSpotService.AttachFiles` : ecrit les pieces jointes sous la racine des fichiers utilisateur (`{UserFilesDirName}/{user}/blogs/{postId}/{fileName}`).
|
||
* [Yavsc.Blogs] `BlogApiController` accepte `multipart/form-data` (champ `blog` + parts `file`) sur `POST` et `PUT /api/v1/blogspot`, en plus du payload JSON existant.
|
||
* [PostIt] Variable d'environnement `POSTIT_SETTINGS_JSON` pour surcharger les parametres au lancement (utile en CI/test).
|
||
* [Yavsc.Server] Migration EF `fileACL`: `CircleAuthorizationToFile` gagne `OwnerId` + `Access` et un graphe proprieetaire, base du controle d'acces fichier par cercle.
|
||
* [Yavsc.Server] Migration EF `genericEstimate`: `Estimate.Query` passe de `RdvQuery` a `NominativeServiceCommand?` pour supporter des devis non lies a un RDV.
|
||
* [Yavsc.Server] Migrations EF `NominativeServiceCommand` et `AddHairCutQueryLocationId` (localisation de la coupe).
|
||
* [CI] Integration du scan de secrets Gitleaks dans le pipeline Forgejo + `.gitleaksignore`.
|
||
* [Tests] Non-regressions: round-trip multipart blog (`BlogApiTests`, `CreateMultipartContentTests` forme + serveur), `BlogAttachmentLinkTests`, `FileServerUrlHelpersTests`, `EstimateApiControllerTests`, VMs `EstimateList`/`EstimateEdition`/`ProviderOngoingRequests`, `BillingControllerTests` (filtrage par utilisateur), `GetOpenIdConfiguration` contre l'hote de test.
|
||
|
||
### Changed
|
||
|
||
* [PostIt] Renommage `MainPage` -> `BlogsPage` (et `PushMainPageAsync` -> `PushBlogsPageAsync`) pour refletter le role de la page.
|
||
* [PostIt] Refacto des `SiteSettings` : reorganisation des parametres, nouvelles valeurs par defaut, et indications plus claires dans les `appsettings`.
|
||
* [Yavsc.Api] `BillingController` ne liste plus que les codes billing de l'utilisateur authentifie (filtre par `UserId`), au lieu de l'ensemble des requetes prestataire.
|
||
* [Yavsc.Api] Mutualisation d'un `YavscMessageSender` partage dans l'hote API (au lieu d'une instance par controller).
|
||
* [Yavsc.Org] La detection du doublon d'email a l'inscription utilise desormais le code erreur generic `DbException` 23505 (fournisseur-agnostique) au lieu de `PostgresException`, pour rester correct en test SQLite.
|
||
* [PostIt] `YavscApiClient` tolere les corps vides (`204 No Content` sur `PUT /blogspot/{id}`) au lieu de lever un `JsonException`.
|
||
* [CI] Le pipeline compile avant les tests, installe les dependances natives, et retire le `ItemGroup.Using Include=Xunit` superflu.
|
||
|
||
### Fixed
|
||
|
||
* [PostIt] Suppression d'un faux message d'erreur affiche apres un `PUT /blogspot/{id}` reussi (204 traite comme succes, plus comme une reponse vide invalide).
|
||
* [PostIt] Correction de la creation des liens de pieces jointes (`TryAppendAttachmentLinks`) : segment proprietaire et chemin `blogs/{id}/{fileName}` alignes sur ce que `AttachFiles` ecrit reellement.
|
||
* [Yavsc.Blogs] Correction de l'upload / de la persistance des pieces jointes (`FileSystemHelpers` + `BlogApiController` multipart).
|
||
* [Tests] Stabilisation des suites: seeds billing avec metadonnees d'audit, `GetOpenIdConfiguration_returns_ok` contre l'hote de test, retraits d'assertions abusives, tests SQLite verts.
|
||
* [PostIt] Nettoyage de fichiers temporaires accidentels et ignore des repertoires `tmp` dans le depot.
|
||
|
||
## [1.0.8-rc14] - unstable
|
||
|
||
### Added
|
||
|
||
* [PostIt] Ajout d'un `BillingQueryDetailsPageViewModel` et de sa page associee pour afficher le detail d'une commande billing depuis l'historique.
|
||
* [PostIt] Ajout d'un mode detail avec section metier (statut, date, description, motif, infos) et section technique repliable (code, client, provision, lieu, prestations).
|
||
* [PostIt] Ajout d'un badge de statut enrichi (couleur + pictogramme) sur le detail d'une commande pour visualiser l'etat en un coup d'oeil.
|
||
* [PostIt] Ajout d'un bloc d'actions rapide en tete du detail (`Retour`, `Ouvrir en edition`) pour eviter le scroll jusqu'au bas de page.
|
||
* [PostIt] Ajout d'un style monospace sur les metadonnees techniques (code billing, client, provision, lieu, prestations) pour faciliter la lecture des identifiants et valeurs brutes.
|
||
|
||
### Changed
|
||
|
||
* [PostIt] Le bouton d'ouverture depuis la liste billing ouvre maintenant une page de detail dediee avant l'eventuelle edition.
|
||
* [PostIt] Amelioration UX des pages billing: badges de statut colores, actions remontees en haut de page, et typographie monospace sur les metadonnees techniques.
|
||
|
||
### Fixed
|
||
|
||
* [Yavsc.Api] Correction d'un 500 sur le refresh du catalogue d'activites lorsque `Activity.Description` est `NULL` en base (nullabilite explicite + projection null-safe + gardes sur codes vides).
|
||
* [Yavsc.Api] Correction des erreurs 400/500 sur les routes billing (`Rdv`, `Brush`, `MBrush`) en imposant `ClientId` depuis l'utilisateur authentifie et en ignorant les champs server-owned lors de la validation modele.
|
||
* [Yavsc.Api] Correction du `PUT /api/v1/billing/Rdv/{id}`: mise a jour controlee de l'entite existante (et non remplacement brut du graphe JSON), ce qui supprime les `BadRequest` parasites.
|
||
* [Yavsc.Api] Correction PostgreSQL `timestamptz` sur RDV: normalisation UTC de `EventDate` sur `POST/PUT /api/v1/billing/Rdv` pour eviter l'erreur `Cannot write DateTime with Kind=Local`.
|
||
* [Yavsc.Api] Correction du flux FrontOffice accept/reject de query: sauvegarde avec contexte utilisateur et fallback d'injection pour `IBillingService` afin d'eviter les erreurs serveur en environnement de test.
|
||
* [Yavsc.Blogs] Correction des `BadRequest` sur `POST/PUT /api/v1/blogspot` avec payload JSON (PostIt): les proprietes de navigation/serveur (`Author`, `Tags`, `Comments`, audit) ne bloquent plus la validation.
|
||
* [Yavsc.Org] Correction du flux MVC de creation de commentaire: `SaveChangesAsync(userId)` est utilise pour renseigner les champs d'audit requis (`UserCreated`/`UserModified`).
|
||
* [Yavsc.Api.Test] Stabilisation des fixtures de seed billing: remplissage des metadonnees d'audit (`UserCreated`, `UserModified`, dates) pour eviter les echecs SQLite `NOT NULL`.
|
||
|
||
## [1.0.8-rc13] - unstable
|
||
|
||
### Added
|
||
|
||
* [PostIt] Integration d'un selecteur de lieu RDV base sur Mapsui (carte interactive dans le formulaire `Rdv`).
|
||
* [PostIt] Ajout d'un marqueur de position et d'une action de recentrage sur la carte RDV.
|
||
* [PostIt] Ajout d'un service de reverse geocoding pour suggerer une adresse a partir des coordonnees carte.
|
||
* [PostIt] Cache et debounce des resolutions d'adresse RDV pour limiter les appels reseau et lisser l'UX.
|
||
* [PostIt.Tests] Nouvelles non-regressions sur le panneau d'adresse suggeree RDV et le comportement de la carte.
|
||
* [Yavsc.Abstract] Activation de `#nullable enable annotations` sur les fichiers legacy avec annotations nullable.
|
||
* [Yavsc.Server] Activation de `#nullable enable annotations` sur les fichiers legacy avec annotations nullable.
|
||
|
||
### Changed
|
||
|
||
* [PostIt] Generalisation de la barre de statut d'action (severite explicite) sur pages principales, dialogues et formulaires billing.
|
||
* [PostIt] Harmonisation des messages de statut utilisateur en francais.
|
||
* [PostIt] Renforcement des gardes de navigation dans les flux de gestion des membres de cercle.
|
||
* [PostIt] Le flux RDV conserve l'adresse saisie manuellement et propose l'adresse resolue comme suggestion explicite.
|
||
* [PostIt] Le flux de geolocalisation RDV tolere les positions proches dans le cache de suggestion d'adresse.
|
||
|
||
### Fixed
|
||
|
||
* [PostIt.Desktop] Correction d'un crash au demarrage OIDC (`No authority specified`) via durcissement des valeurs par defaut de configuration d'authentification.
|
||
* [PostIt] Correction de la persistance des settings: l'etat runtime de statut n'est plus serialize dans le JSON utilisateur.
|
||
* [PostIt.Tests] Ajout d'un verrou de non-regression sur le premier chargement des settings.
|
||
* [PostIt] Correction du binding de la date RDV: `DatePicker.SelectedDate` est aligne sur un proxy `DateTimeOffset?` (`EventDateSelection`).
|
||
|
||
## [1.0.8-rc12] - unstable
|
||
|
||
### Added
|
||
|
||
* [PostIt] Nouveau helper d'image `ImageHelper` pour charger des bitmaps depuis les ressources et depuis le web.
|
||
* [PostIt] Affichage de l'avatar XS dans la liste des performers d'activites, avec fallback visuel (initiale utilisateur).
|
||
* [PostIt.Tests] Nouveaux tests autour des URLs avatar et de la source d'autorite.
|
||
* [contrib] Ajout d'un `README.md` utilitaire pour les symboles/icones.
|
||
|
||
### Changed
|
||
|
||
* [PostIt] Les avatars ne sont plus relies en string sur `Image.Source`: ils sont telecharges et lies en `Bitmap`.
|
||
* [Yavsc.Api.Client] `ActivityApiClient` accepte une base d'avatar dediee et construit les URLs avatar depuis l'autorite d'identification.
|
||
* [PostIt] Les clients Activites/Billing utilisent maintenant `ApiUrl` en lecture dynamique: un changement via Parametres prend effet sans redemarrer l'application (apres sauvegarde et rafraichissement de la page).
|
||
* [PostIt] Le header de `MainPage` n'utilise plus `ScrollViewer`; remplacement par une barre de commandes basee sur `WrapPanel`.
|
||
* [PostIt] Alignement de la navigation blogs: renommage `PushMainPageAsync` -> `PushBlogsPageAsync` et ajustement de `HomePageViewModel`.
|
||
|
||
### Fixed
|
||
|
||
* [PostIt.Android] Correction d'un 404 sur la page Activites au premier lancement: la configuration embarquee pointait `ApiUrl` vers le host Blogs au lieu de l'API metier.
|
||
* [PostIt] Correction du bouton Sauver de la page Parametres: binding vers `SaveCommand` pour persister correctement `ApiUrl`/`BlogsApiUrl`.
|
||
|
||
## [1.0.8-rc11] - unstable
|
||
|
||
### Added
|
||
|
||
nothing
|
||
|
||
### Changed
|
||
|
||
* [Yavsc.Api.Test] Mise a jour de `Microsoft.EntityFrameworkCore.Sqlite` vers `10.0.11` afin de supprimer l'alerte NU1903 liee a `SQLitePCLRaw.lib.e_sqlite3` 2.1.11.
|
||
* [Yavsc.Org] Nettoyage de la configuration NuGet pour le restore: suppression du fichier local `Directory.Packages.props` au profit du fichier racine centralise.
|
||
* [Yavsc.Org] Suppression de references de packages redondantes dans le projet, sans impact fonctionnel attendu.
|
||
|
||
### Fixed
|
||
|
||
* [Yavsc.Api.Test] Le restore n'emet plus le warning de vulnerabilite `NU1903` sur `SQLitePCLRaw.lib.e_sqlite3`.
|
||
* [Yavsc.Org] Suppression d'une vulnerabilite de severite elevee sur AutoMapper apres publication et consommation de la nouvelle version candidate de `HigginsSoft.IdentityServer8`.
|
||
|
||
## [1.0.8-rc10] - unstable
|
||
|
||
### Added
|
||
|
||
* [PostIt] Une page d'historique des commandes billing permet maintenant d'ouvrir une commande existante.
|
||
* [PostIt] Une vue "Demandes en cours" en lecture seule est disponible pour le performer, filtrée sur les statuts actifs (Inserted, Accepted, InProgress).
|
||
* [Yavsc.Org] Nouvelles entités `Country` et `PerformerCodeInputValidation` pour piloter la validation du code entreprise performer par pays.
|
||
|
||
### Changed
|
||
|
||
* [PostIt] La page détail billing se préremplit depuis une commande existante (Rdv, Brush, MBrush) et passe en mode mise à jour.
|
||
* [Yavsc.Org] Le formulaire `Manage/SetActivity` inclut désormais le pays d'exercice (`fr`, `en`, `pt`) et applique la regex associée au champ `SIREN`.
|
||
* [Yavsc.Org] La vérification externe du numéro d'entreprise est conservée uniquement pour le pays `fr`.
|
||
|
||
### Fixed
|
||
|
||
* [PostIt] Le flux historique n'est plus limité à une simple liste: l'action d'ouverture charge la commande cible puis navigue vers la page détail.
|
||
* [Yavsc.Org] Le champ `SIREN` n'est plus validé avec une règle unique indépendante du pays d'exercice.
|
||
|
||
## [1.0.8-rc9] - unstable
|
||
|
||
### Added
|
||
|
||
nothing
|
||
|
||
### Changed
|
||
|
||
masquage non-owner côté backend de l'ACL du billet
|
||
|
||
### Fixed
|
||
|
||
On a maintenant le comportement attendu bout en bout:
|
||
|
||
ACL chargée depuis le BlogPostDto
|
||
noms de cercles affichés dans le dialogue ACL côté PostIt
|
||
|
||
## [1.0.8-rc8] - unstable
|
||
|
||
### Added
|
||
|
||
nothing
|
||
|
||
### Changed
|
||
|
||
nothing
|
||
|
||
### Fixed
|
||
|
||
The PostIt publish toggle button
|
||
|
||
## [1.0.8-rc7] - unstable
|
||
|
||
### Added
|
||
|
||
* [PostIt] The search pattern now persists
|
||
|
||
### Changed
|
||
|
||
* The blog spot path is now `/api/v1/blogspot` (yet in last release)
|
||
|
||
### Fixed
|
||
|
||
* [Yavsc.Org] (Ticket #45) La forme de l'email de l'utilisateur est maintenant validée avant l'envoi du formulaire d'enregistrement
|
||
|
||
## [1.0.8-rc6] - unstable
|
||
|
||
### Added
|
||
|
||
* a code cleanup,
|
||
* a first Xamarin.UITest is successful, but disabled, because breaking the actual CI process,
|
||
* Android app starts, the login process succeeds
|
||
|
||
### Changed
|
||
|
||
L'identifiant de l'application client Android a changé, il passe en minuscules :
|
||
`fr.pschneider.postit`
|
||
|
||
### Fixed
|
||
|
||
a bug posting and retrieving ACL from the backend,
|
||
the ACL now comes along with the article,
|
||
[TODO][PostIt] keep ACL along with the article
|
||
|
||
## [1.0.8-rc1] - unstable
|
||
|
||
### Added
|
||
- `BlogAclApiTests.PostCircleAuthorization_returns_201_when_payload_mirrors_PostIt_shape_against_existing_circle_named_test`
|
||
: test de non-régression qui épingle la forme exacte du payload
|
||
que PostIt envoie à `POST /api/v1/blogacl` (un objet
|
||
`PostAccessControlRulePayload` avec `CircleId` et `BlogPostId`).
|
||
C'est le verrou côté test du fix applicatif PostIt + serveur.
|
||
- `BlogAclApiTests.PostCircleAuthorization_never_returns_500` : une
|
||
`[Theory]` couvrant quatre shapes de payload (`{ circleId }`,
|
||
corps vide, `{ blogPostId }` seul, `{ circleId, blogPostId: 0 }`)
|
||
qui doivent tous retourner un statut différent de 500. Toute
|
||
réintroduction d'un chemin 500 dans le futur fera rougir ce test.
|
||
- `BlogAclApiTests.PostCircleAuthorization_dosent_return_500` et
|
||
`..._dosent_return_500_on_success` : entry points `[Fact]` qui
|
||
appellent la `[Theory]` ci-dessus avec un payload spécifique
|
||
chacun, pour pouvoir filtrer en isolation depuis la ligne de
|
||
commande ou le CI.
|
||
- Règle « Pas de `object` dans le code source applicatif » ajoutée
|
||
à `CONTRIBUTING.md` : types de retour, paramètres, champs,
|
||
propriétés, variables locales doivent être typés statiquement.
|
||
`dynamic` est interdit pour les mêmes raisons.
|
||
|
||
### Changed
|
||
- `BlogAclApiController.CheckOwner` devient `CheckOwnerAsync` et
|
||
utilise `FirstOrDefaultAsync` au lieu de `First`, supprimant
|
||
l'appel LINQ synchrone sur le fil de la requête et retournant
|
||
`false` sur cercle manquant (le contrôleur mappe déjà cela vers
|
||
`ChallengeResult`).
|
||
- `BlogsWebServerFixture` seed `alice`, son `Circle` et son
|
||
`BlogPost` une seule fois au démarrage du host, sur la
|
||
`SqliteConnection` partagée (`Cache=Shared`). Le précédent
|
||
`EnsureDeleted` au début de chaque test fermait la connexion
|
||
statique et détruisait le store `:memory:` pour tous les autres
|
||
`DbContext` ; il est retiré au profit d'un `EnsureCreated`
|
||
idempotent.
|
||
|
||
### Fixed
|
||
- `POST /api/v1/blogacl` ne retourne plus 500 sur les payloads
|
||
dont `BlogPostId` est absent ou à zéro. Le contrôleur rejette
|
||
`BlogPostId <= 0` avec `400 BadRequest` avant que la requête
|
||
n'atteigne `SaveChangesAsync`. L'incident de prod du 2026-08-21
|
||
sur mercure (PostIt envoyant seulement `circleId`, le serveur
|
||
voyant `BlogPostId = default(long) = 0` et EF Core levant
|
||
`InvalidOperationException` sur l'INSERT) n'est plus atteignable.
|
||
- PostIt `PostAclDialogViewModel.AddAsync` envoie désormais le
|
||
payload explicite `PostAccessControlRulePayload { CircleId,
|
||
BlogPostId }` au lieu de l'ancien `CircleAuthorization {
|
||
CircleId }`. Le DTO serveur `PostAccessControlRulePayload` est
|
||
introduit dans `Yavsc.Abstract` pour porter le contrat.
|
||
|
||
## [1.0.7] - preview
|
||
|
||
### Added
|
||
- Per-post ACL in PostIt: a new “Manage ACL” page, opened from the ACL
|
||
button on a selected post, lets the post author grant or revoke
|
||
grants for individuals or circles. The server scopes each grant
|
||
operation to `caller == post.AuthorId` and returns `404` (not `403`)
|
||
for posts the caller does not own, so the existence of another
|
||
user's post is not leaked.
|
||
- Circle membership API + UI: three new REST endpoints under
|
||
`/api/circle/{id}/members` (`GET` list, `POST` add, `DELETE`
|
||
remove) and a new “Members” column on the *My Circles* page with an
|
||
“Add a member” button that opens a search modal. The search modal
|
||
reuses `IUserDirectory` (introduced by the `IContactService` split
|
||
in this same release) — exactly the use case the abstraction was
|
||
carved out for.
|
||
- Publish toggle for blog posts: a new `PUT /api/BlogApi/{id}/publish`
|
||
endpoint, and a `Published` checkbox in the post toolbar that
|
||
toggles a `BlogSpotPublication` row for the post. The publish
|
||
signal flows through the pre-existing `PermissionHandler.IsPublic`
|
||
path, so no new column was needed and the server-side authorisation
|
||
logic is unchanged.
|
||
- `UserSearchApiController` in `Yavsc.Blogs`:
|
||
`GET /api/user-search?q=...&e=...&take=...`. Any-authenticated-
|
||
caller endpoint that exposes the user's email under a closed-
|
||
community assumption (documented in the controller's XML doc).
|
||
Wired to the PostIt Desktop address book so the user search modal
|
||
picks it up.
|
||
- `IYavscApiClient` abstraction in `Yavsc.Api.Client`. The transport
|
||
for the blog/circle/blog-acl/user-search clients is now accessed
|
||
through this interface, so `PostIt.Tests` can stub the HTTP layer
|
||
without spinning up a real WebAPI host.
|
||
- Forgejo Actions release workflow: a `.forgejo/workflows/release.yml`
|
||
pipeline that builds and publishes a release with the PostIt APK
|
||
on tag push. Written in pure bash (the runner image has no Node),
|
||
uses `jq` for JSON body construction and response parsing, uses the
|
||
runner-provided `GITHUB_TOKEN` (no repo-level secret needed),
|
||
validates the CHANGELOG section heading before allowing the tag
|
||
to ship.
|
||
- `make release V=<version>` target: creates a `release/<V>` branch
|
||
from `main`, bumps the `<Version>` property in every `.csproj` via
|
||
`dotnet-gitversion /updateprojectfiles`, commits the bump on the
|
||
release branch, and pushes to `origin`. Fails fast if the working
|
||
tree is dirty or if `HEAD` is not on `main`.
|
||
- Forgejo status badges in the README.
|
||
|
||
### Changed
|
||
- The new Publish toggle replaces the “Visibility enum” approach
|
||
originally drafted in this branch: the existing `BlogSpotPublication`
|
||
table already carried enough information to expose a publish
|
||
switch, so no schema change was needed. The original `feat(blog):
|
||
add Visibility { Private, Public }` commit and its EF migration
|
||
were reverted in favour of the endpoint-only toggle.
|
||
- `BlogPost` DTO and `IBlogPost` moved from `PostIt.Models` to
|
||
`Yavsc.Abstract.Blogspot`, the shared assembly where the server-side
|
||
entity and the wire DTO both live. Renamed `Yavsc.Blogspot.BlogPost`
|
||
to `BlogPostDto` to make the wire/entity distinction explicit.
|
||
- `BlogAclApiController` and `CircleApiController` moved from
|
||
`Yavsc.Api` (not yet enabled in production) to `Yavsc.Blogs`, where
|
||
they belong next to the `BlogSpotService` they depend on.
|
||
- `IContactService` split from `IUserDirectory`: the two interfaces
|
||
previously conflated the local address-book access (mobile-only,
|
||
via `Contacts.Default`) and the Yavsc user-search access
|
||
(Desktop-only, via `/api/user-search`) behind a single facade. The
|
||
split restores the `ContactDto.Emails` multi-value shape that was
|
||
being silently flattened to a single string before.
|
||
- CI: the Forgejo Actions build now compiles `.csproj` projects
|
||
directly inside the runner container (which ships the .NET SDK +
|
||
Android workload), instead of relying on a separate Docker build
|
||
step. Node-based third-party actions were replaced with bash + curl
|
||
+ `jq`. The validate-release job parses the CHANGELOG section
|
||
heading to derive the channel (`stable` / `preview` / `unstable`)
|
||
rather than the patch-version parity alone.
|
||
|
||
### Fixed
|
||
- `CircleApiController` used to read the caller's user id via
|
||
`FindFirstValue(ClaimTypes.NameIdentifier)`, which does not match
|
||
when JWT Bearer middleware has `MapInboundClaims = false`. Switched
|
||
to `User.GetUserId()` (tries `sub` first, then
|
||
`ClaimTypes.NameIdentifier`, then `nameid`). This was a latent
|
||
bug visible in tests but easy to ship to production if a host
|
||
ever disabled the remap.
|
||
- `CircleApiController` and `BlogAclApiController` reads and writes
|
||
were not always scoped to the caller's own data. Tightened the
|
||
authorisation checks: cross-user reads now return `404`, not the
|
||
raw record.
|
||
- `validate-release` CHANGELOG channel check used to parse the
|
||
patch-version parity only, which disagreed with the channel
|
||
suffix in the section heading (e.g. `## [1.0.7] - preview`
|
||
would be flagged as `stable` from the parity alone). The job now
|
||
inspects the heading line and trusts the suffix when present.
|
||
- `.forgejo/workflows/release.yml`: the asset-upload URL now carries
|
||
the asset name as a query-string parameter instead of a `curl`
|
||
positional argument. The previous shape triggered Forgejo's
|
||
“Missing `name` parameter” 400 in some cases.
|
||
|
||
### Removed
|
||
- The `## [Unreleased]` block has been moved into this section.
|
||
- The abandoned `Visibility { Private, Public }` enum and its EF
|
||
migration, reverted in this release. The publish toggle covers
|
||
the same user-visible switch without a schema change.
|
||
|
||
[Unreleased]: https://forgejo.pschneider.fr/notazof/yavsc/compare/HEAD
|
||
[1.0.8-rc16]: https://forgejo.pschneider.fr/notazof/yavsc/compare/1.0.8-rc15...1.0.8-rc16
|
||
[1.0.8-rc17]: https://forgejo.pschneider.fr/notazof/yavsc/compare/1.0.8-rc16...1.0.8-rc17
|
||
[1.0.8-rc18]: https://forgejo.pschneider.fr/notazof/yavsc/compare/1.0.8-rc17...1.0.8-rc18
|
||
[1.0.8-rc15]: https://forgejo.pschneider.fr/notazof/yavsc/compare/1.0.8-rc14...1.0.8-rc15
|
||
[1.0.8-rc1]: https://forgejo.pschneider.fr/notazof/yavsc/compare/1.0.7...1.0.8-rc1
|
||
[1.0.7]: https://forgejo.pschneider.fr/notazof/yavsc/compare/1.0.6...1.0.7
|
||
[1.0.6]: https://forgejo.pschneider.fr/notazof/yavsc/compare/1.0.5...1.0.6
|
||
|
||
## [1.0.6] - stable
|
||
|
||
### Added
|
||
- Self-hosted Forgejo Actions runner now drives the CI build for the
|
||
yavsc repository, using the
|
||
`pazof/yavsc-build-env:debian12-dotnet10-android36-v2` image pulled
|
||
from Docker Hub. Workflow runs end-to-end: clone, restore, build,
|
||
test, with NuGet.config picking up the `isn.pschneider.fr` feed.
|
||
- The build-env image now ships `jq` (Debian package, ≥ 1.7), so the
|
||
release workflow can build JSON bodies and parse API responses
|
||
without a hand-rolled `sed`-based extractor that was matching the
|
||
wrong `id` field on minified responses.
|
||
|
||
### Changed
|
||
- CI workflow `.forgejo/workflows/buildAndTest.yml` no longer relies on
|
||
`actions/checkout` (the runner image has no Node); clones yavsc via
|
||
`git`, fetches the ref under test, and initializes submodules over
|
||
HTTPS.
|
||
|
||
### Fixed
|
||
- `Dockerfile` and `Dockerfile.backend` no longer carry a redundant
|
||
`dotnet nuget add source` step that conflicted with the GitHub
|
||
Actions APK build (`--allow-insecure-connections` on an HTTPS
|
||
endpoint, exit 1). `NuGet.config` at the repo root supplies the
|
||
`isn.pschneider.fr` feed for every restore, including inside Docker.
|
||
- `.forgejo/workflows/release.yml`: PATCH on `/releases/{id}` no longer
|
||
404s on existing releases. The previous `sed`-based `json_field`
|
||
matched the last `id` on the line (the author's), so it tried to
|
||
PATCH `/releases/1` (the first user of the instance) instead of the
|
||
actual release id. Switched to `jq` for both body construction and
|
||
field extraction.
|
||
|
||
[1.0.6]: https://forgejo.pschneider.fr/notazof/yavsc/compare/1.0.5...1.0.6
|