Ajoute la section [1.0.8-rc1] au CHANGELOG.md, en français, au format Keep a Changelog (### Added / ### Changed / ### Fixed). Couvre : - le fix backend du 500 sur POST /api/v1/blogacl (commitd2a0c263) - le fix client PostIt (commitb82b6722) - le passage de CheckOwner en async (commite48ede1e) - le seed one-shot de la fixture BlogsWebServerFixture - les tests de non-régression (sentinelles 'never 500' et 'shape PostIt') - la règle 'Pas de object' dans CONTRIBUTING.md Met aussi à jour le bloc de liens de comparaison en bas du fichier pour pointer [1.0.8-rc1] vers 1.0.7...1.0.8-rc1.
11 KiB
11 KiB
Changelog
Toutes les modifications notables de PostIt et de la plateforme Yavsc sont documentées dans ce fichier.
Le format suit Keep a Changelog, et ce projet adhère au Semantic Versioning.
À noter : la parité du numéro de patch porte une signification de canal :
- patch pair (ex.
1.0.0,1.0.2) → stable - patch impair (ex.
1.0.1,1.0.3) → preview - suffixe (ex.
1.0.0-rc1,1.0.0-alpha) → instable
Cette convention est partagée avec le dépôt
postit-debian
pour la production des paquets .deb.
1.0.8-rc1 - 2026-08-21
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 objetPostAccessControlRulePayloadavecCircleIdetBlogPostId). 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_500et..._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
objectdans le code source applicatif » ajoutée àCONTRIBUTING.md: types de retour, paramètres, champs, propriétés, variables locales doivent être typés statiquement.dynamicest interdit pour les mêmes raisons.
Changed
BlogAclApiController.CheckOwnerdevientCheckOwnerAsyncet utiliseFirstOrDefaultAsyncau lieu deFirst, supprimant l'appel LINQ synchrone sur le fil de la requête et retournantfalsesur cercle manquant (le contrôleur mappe déjà cela versChallengeResult).BlogsWebServerFixtureseedalice, sonCircleet sonBlogPostune seule fois au démarrage du host, sur laSqliteConnectionpartagée (Cache=Shared). Le précédentEnsureDeletedau début de chaque test fermait la connexion statique et détruisait le store:memory:pour tous les autresDbContext; il est retiré au profit d'unEnsureCreatedidempotent.
Fixed
POST /api/v1/blogaclne retourne plus 500 sur les payloads dontBlogPostIdest absent ou à zéro. Le contrôleur rejetteBlogPostId <= 0avec400 BadRequestavant que la requête n'atteigneSaveChangesAsync. L'incident de prod du 2026-08-21 sur mercure (PostIt envoyant seulementcircleId, le serveur voyantBlogPostId = default(long) = 0et EF Core levantInvalidOperationExceptionsur l'INSERT) n'est plus atteignable.- PostIt
PostAclDialogViewModel.AddAsyncenvoie désormais le payload explicitePostAccessControlRulePayload { CircleId, BlogPostId }au lieu de l'ancienCircleAuthorization { CircleId }. Le DTO serveurPostAccessControlRulePayloadest introduit dansYavsc.Abstractpour 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.AuthorIdand returns404(not403) 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(GETlist,POSTadd,DELETEremove) and a new “Members” column on the My Circles page with an “Add a member” button that opens a search modal. The search modal reusesIUserDirectory(introduced by theIContactServicesplit 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}/publishendpoint, and aPublishedcheckbox in the post toolbar that toggles aBlogSpotPublicationrow for the post. The publish signal flows through the pre-existingPermissionHandler.IsPublicpath, so no new column was needed and the server-side authorisation logic is unchanged. UserSearchApiControllerinYavsc.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.IYavscApiClientabstraction inYavsc.Api.Client. The transport for the blog/circle/blog-acl/user-search clients is now accessed through this interface, soPostIt.Testscan stub the HTTP layer without spinning up a real WebAPI host.- Forgejo Actions release workflow: a
.forgejo/workflows/release.ymlpipeline that builds and publishes a release with the PostIt APK on tag push. Written in pure bash (the runner image has no Node), usesjqfor JSON body construction and response parsing, uses the runner-providedGITHUB_TOKEN(no repo-level secret needed), validates the CHANGELOG section heading before allowing the tag to ship. make release V=<version>target: creates arelease/<V>branch frommain, bumps the<Version>property in every.csprojviadotnet-gitversion /updateprojectfiles, commits the bump on the release branch, and pushes toorigin. Fails fast if the working tree is dirty or ifHEADis not onmain.- Forgejo status badges in the README.
Changed
- The new Publish toggle replaces the “Visibility enum” approach
originally drafted in this branch: the existing
BlogSpotPublicationtable already carried enough information to expose a publish switch, so no schema change was needed. The originalfeat(blog): add Visibility { Private, Public }commit and its EF migration were reverted in favour of the endpoint-only toggle. BlogPostDTO andIBlogPostmoved fromPostIt.ModelstoYavsc.Abstract.Blogspot, the shared assembly where the server-side entity and the wire DTO both live. RenamedYavsc.Blogspot.BlogPosttoBlogPostDtoto make the wire/entity distinction explicit.BlogAclApiControllerandCircleApiControllermoved fromYavsc.Api(not yet enabled in production) toYavsc.Blogs, where they belong next to theBlogSpotServicethey depend on.IContactServicesplit fromIUserDirectory: the two interfaces previously conflated the local address-book access (mobile-only, viaContacts.Default) and the Yavsc user-search access (Desktop-only, via/api/user-search) behind a single facade. The split restores theContactDto.Emailsmulti-value shape that was being silently flattened to a single string before.- CI: the Forgejo Actions build now compiles
.csprojprojects 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 + curljq. The validate-release job parses the CHANGELOG section heading to derive the channel (stable/preview/unstable) rather than the patch-version parity alone.
Fixed
CircleApiControllerused to read the caller's user id viaFindFirstValue(ClaimTypes.NameIdentifier), which does not match when JWT Bearer middleware hasMapInboundClaims = false. Switched toUser.GetUserId()(triessubfirst, thenClaimTypes.NameIdentifier, thennameid). This was a latent bug visible in tests but easy to ship to production if a host ever disabled the remap.CircleApiControllerandBlogAclApiControllerreads and writes were not always scoped to the caller's own data. Tightened the authorisation checks: cross-user reads now return404, not the raw record.validate-releaseCHANGELOG 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] - previewwould be flagged asstablefrom 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 acurlpositional argument. The previous shape triggered Forgejo's “Missingnameparameter” 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.
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-v2image pulled from Docker Hub. Workflow runs end-to-end: clone, restore, build, test, with NuGet.config picking up theisn.pschneider.frfeed. - 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-rolledsed-based extractor that was matching the wrongidfield on minified responses.
Changed
- CI workflow
.forgejo/workflows/buildAndTest.ymlno longer relies onactions/checkout(the runner image has no Node); clones yavsc viagit, fetches the ref under test, and initializes submodules over HTTPS.
Fixed
DockerfileandDockerfile.backendno longer carry a redundantdotnet nuget add sourcestep that conflicted with the GitHub Actions APK build (--allow-insecure-connectionson an HTTPS endpoint, exit 1).NuGet.configat the repo root supplies theisn.pschneider.frfeed for every restore, including inside Docker..forgejo/workflows/release.yml: PATCH on/releases/{id}no longer 404s on existing releases. The previoussed-basedjson_fieldmatched the lastidon 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 tojqfor both body construction and field extraction.