refac: DELETE /v1/user/{id}?expected_role_id=N, user.remove audit event, 409 target_role_not_found, GetAll returns its error, Own-scope visibility filter moved into repos, JSON tags removed from use-case types

This commit is contained in:
Florian Sylvain committed 2026-10-29 16:28:25 +01:00
1 parent 5d6f378fce
commit b39a41be88
124 files changed
+8816 -523

No files matched your search

+101
View File
@@ -0,0 +1,101 @@
Feature: Read = Own surfaces of the roles-sync design (group 14)
As a person whose role reads only their own content
I want the editor, the Articles list and the entry list to say what I can see
So that hidden items are not hinted at and the counts match what I can open
Background:
Given the backend contract of features/roles_permissions_content_scope.feature: a caller with content.read=own gets online articles plus their own drafts, and only the entries they created, with counts, total, page and size computed over the visible set
And the spec of record is docs/design/screens/roles.md group 14, its table "Read = Own: what each surface returns", and docs/design/change-log-roles-sync.md section 4
And the SPA never computes visibility: every count, total and pager value shown comes from the API (GET /v1/article counts and total, GET /v1/content-type/{key}/entry total)
And the SPA knows a person reads Own through scopeOf("content.read", type) of stores/permissions.ts
And Update or Delete set to Own keep the "View only" rows of slice 5; only Read = Own hides rows
And the SPA lives in web/src, Nuxt UI only, design tokens only, EN and FR in i18n/messages.ts, no comments in code
Rule: Role editor
Scenario: Info alert when Read is Own
Given the editor shows a role where Read is Own on at least one type row
Then an info alert under the grid reads "Read: Own · Articles show online articles plus the person's own drafts. Custom content types show only entries the person created. Status counts follow the same rule."
And in FR "Lecture : Les siennes · Les articles affichent les articles en ligne et les brouillons de la personne. Les types de contenu personnalisés n'affichent que les entrées créées par la personne. Les compteurs de statut suivent la même règle."
And it is absent when no Read cell is Own, and it appears and disappears live as the cell changes
Scenario Outline: Type-specific preview sentences
Given the Read cell of <row> is Own
Then the preview line for <row> reads <sentence>
Examples:
| row | sentence |
| Articles | Can read online articles and their own drafts, create entries and edit only their own. |
| a custom type (Events) | Can read only entries they created, create entries and edit only their own. |
| All content types | one line per kind of type: the Articles sentence and the custom-type sentence |
And "read only their own" is gone from the preview
And a row with Read All still reads "Can read any entry, ..." as before
Scenario: Read-only editor
Given the person holds roles.view only and opens a role whose Read is Own
Then the alert and the sentences render the same way, with no Save bar
Rule: Articles list
Scenario: Read = Own with drafts of their own
Given the person is Pedro Lima, Junior writer, with content.read=own
And GET /v1/article answers 3 online articles by others and 2 own drafts, counts all 5, online 3, draft 2
When the person opens /articles
Then the header reads "Articles" with "Online articles and the drafts you created."
And a banner reads "Drafts by others are hidden · Your role reads online articles and the drafts you created. The counts follow the same rule."
And the tabs read All 5, Online 3, Draft 2, taken from the counts of the answer
And "New article" is enabled when content.create allows it
Scenario: No drafts of their own
Given GET /v1/article?status=draft answers no items and counts all 3, online 3, draft 0
When the person opens the Draft tab
Then the empty state reads "You have no drafts · Drafts you create appear here. Your role can't see drafts by other people." with "New article"
And the tabs read All 3, Online 3, Draft 0
Scenario Outline: The banner and the empty state depend on Read being Own
Given the person has content.read=<scope>
Then the banner "Drafts by others are hidden" is <banner>
And an empty Draft tab shows <empty>
Examples:
| scope | banner | empty |
| own | shown | "You have no drafts" |
| all | absent | the existing empty state of the articles list |
Rule: Entry list of a custom type
Scenario: Read = Own with entries of their own
Given content.read=own on Events and GET /v1/content-type/events/entry answers 3 items, total 3
When the person opens /content/events
Then the header reads "Events" with "Your role shows only entries you created."
And a banner reads "Entries by others aren't shown · Your role reads only entries you created. Ask an owner or admin if you need to see more."
And the count line reads "3 entries" from total, and no pager shows when total fits one page
And "New entry" is enabled when content.create allows it
Scenario: No entries of their own
Given the answer has no items and total 0
Then the empty state reads "You haven't created an event yet · Your role shows only entries you created, so other people's events aren't listed here. Use New entry to add one." with "New entry"
And nothing hints that other people's entries exist
Scenario Outline: The singular noun is derived from the type name
Given the content type is named <name>
Then the empty state title reads <title>
And the body reads "Your role shows only entries you created, so other people's <plural> aren't listed here. Use New entry to add one."
Examples:
| name | title | plural |
| Events | You haven't created an event yet | events |
| Recipes | You haven't created a recipe yet | recipes |
| Press mentions | You haven't created a press mention yet | press mentions |
| Categories | You haven't created a category yet | categories |
And the derivation reuses the helper that already singularises type names for the relation sentences (lib/relationSentences.ts), lowercased
And irregular names (for example "People", "Series") are a design gap of the qa
Scenario: Direct link to a hidden item
Given GET /v1/content-type/events/entry/1 answers 404 entry_not_found
Then the existing "Entry not found" page shows, with no hint that the entry exists
And GET /v1/article/{id} of someone else's draft answers 404 and shows the existing article-not-found page
Rule: Scope of the change
Scenario: The SPA does not recompute
Given the API answers counts all 2, online 2, draft 0 for a reader with Read = Own
Then the tabs read exactly those numbers whatever the person's scope