Skip to content

chore: close the restructuring's follow-ups (roles in the reader's language, e2e split, canvas ceiling, config readers) - #366

Merged
InstaZDLL merged 10 commits into
mainfrom
chore/restructure-followups
Oct 27, 2026
Merged

InstaZDLL merged 10 commits into
mainfrom
chore/restructure-followups

Conversation

@InstaZDLL

@InstaZDLL InstaZDLL commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

The loose ends the backend (#351–#358) and webapp (#359–#365) restructurings noted but did not fix, because those pull requests only moved code. One commit per subject.

Web client

  • Roles and the library count in the reader's language (fix(webapp)). The account rows printed the API's admin/user and a hard-coded English "N libraries"; the membership panel printed owner/manager/listener and offered them as the role picker's labels. They now go through the translations (admin.role*, admin.accountLibraries with its plural). English reads exactly as before; French reads administrateur · 1 bibliothèque, propriétaire, auditeur, gestionnaire. The <option> values are unchanged, so what is sent is unchanged.
  • Player (refactor(webapp)): the queueLength ref was written on every render and read nowhere — removed. The order effect's comment said the queue is compared "by identity and by prefix"; continuationOf compares entry by entry and its own comment says why a prefix test was dropped — the comment now says so. onEnd's "stay on the last track" explanation was written twice; the copy outside the handler is gone.
  • Queries: the filedTreeQuery doc comment sat above the "Needs attention" block, two doc comments stacked on one export; it is back on filedTreeQuery.

e2e

  • smart-playlists-and-podcasts.spec.ts (1,102 lines) split by subject into smart-playlists.spec.ts (234) and podcasts.spec.ts (452), with the shared mock in e2e/fixtures/smart-playlists-and-podcasts.ts (389). Its state was eight module-level lets, which an importing spec cannot reassign; they are now the fields of one state object, as fixtures/state.ts does for the rest, reset to the same eight values before each test. The layout gate's allowlist is now empty.
  • Copied helpers replaced by the fixtures, only where the copy was identical: session, albums, library(...), expectNoWcagViolations, navigateWithin, the one-pixel PNG (PIXEL, seven copies) and silentWav(30) (whose removed copy's comment said "one second"; it was thirty). Copies that differ (other defaults, other fields, inline accessibility checks with other options) are left as they are.
  • A test for the roles above, in French: names the roles and the library count in the reader's language.

Proof that nothing was lost: playwright test --list gave 508 tests before the split and 508 after, with the sorted titles identical; 510 with the new test (one test × two projects).

Server

  • The canvas body ceiling has a finite fallback (fix(app)). boot turned config.canvas.max_bytes (an i64) into the route's body ceiling with unwrap_or(usize::MAX). Config::from_env refuses a value that does not fit, but a Config built by hand never meets that check, and a negative value then meant no ceiling at all on the one route that takes a whole video in a body. It now goes through canvas_body_limit in app/state.rs, beside chunk_body_limit, and falls back to the default 4 MiB. Unit test a_canvas_size_that_does_not_fit_keeps_a_finite_ceiling; inverted: with the fallback put back to usize::MAX it fails.
  • config: seven settings where zero is a value (API_TOKEN_TTL_SECS, SCAN_INTERVAL_SECS, UNAVAILABLE_RETENTION_DAYS, PURGE_GRACE_HOURS, QUALITY_PARALLELISM, MIGRATION_BACKUPS, PODCAST_REFRESH_INTERVAL_SECS) each re-wrote var → default → parse → "invalid NAME: error" by hand, which is parse_env word for word. They call it now; defaults and error messages are unchanged.
  • cli: the module comment said the CLI was "used before the M4 web administration surface exists". It now says what it is for, and why restore and key run without the AppState.

CI

  • Both layout gates move to the repository root first. Run from a subfolder, their find met no file and they passed having measured nothing. Inverted for each: from webapp/, a 601-line src/lib file passes the old webapp gate and fails the new one; from src/, an 801-line file passes the old Rust gate and fails the new one.

Checks run

  • cargo fmt --check, scripts/check-rust-layout.sh, clippy -D warnings, cargo doc -D warnings, cargo test --all-features: 667 passed (666 + the canvas test).
  • webapp/: biome check (the same 2 warnings as main), bun run typecheck (src, node configs and e2e), bun run test 327 passed, bun run build, scripts/check-webapp-layout.sh.
  • Playwright left to CI (local runs saturate the machine): the split specs and the new French admin test run here for the first time. The new test has not been inverted locally for the same reason.

Noticed, not changed

  • The smart-playlists/podcasts fixture and workspace-pages.spec.ts set the CSRF cookie for http://127.0.0.1:4173, ignoring baseURL, so under WAVEFLOW_E2E_PORT it would go to the wrong origin. Kept as it was: changing it changes behaviour.
  • workspace-pages.spec.ts has its own Episode type and channelOf, identical to the podcast fixture's; sharing them would make it import from the podcasts fixture.
  • The role picker's aria-label reads Rôle: guest in French, without the space French puts before a colon.

Summary by CodeRabbit

  • Nouvelles fonctionnalités

    • Les rôles et le nombre de bibliothèques des comptes sont affichés avec des libellés traduits en français et en anglais.
    • Les tests automatisés couvrent davantage les parcours d’administration, de playlists intelligentes et de podcasts.
  • Corrections

    • Les scripts de vérification fonctionnent désormais depuis n’importe quel répertoire.
    • Une limite de requête Canvas finie est conservée même si la valeur configurée ne peut pas être convertie.
    • La lecture et les podcasts bénéficient d’une couverture accrue des cas de fin de lecture et des requêtes tardives.
  • Documentation

    • La documentation de la CLI décrit davantage ses usages, notamment avant le démarrage du serveur.

Signed-off-by: InstaZDLL <github.105mh@8shield.net>
…tale comments

Signed-off-by: InstaZDLL <github.105mh@8shield.net>
Signed-off-by: InstaZDLL <github.105mh@8shield.net>
…se_env

Signed-off-by: InstaZDLL <github.105mh@8shield.net>
Signed-off-by: InstaZDLL <github.105mh@8shield.net>
…pec.ts

The file is about to be split by subject, and podcasts is the larger
half. Renamed alone, so that its history follows it; the layout
allowlist follows the path until the split removes the entry.

Signed-off-by: InstaZDLL <github.105mh@8shield.net>
The spec was 1,102 lines, the one file the layout check allowed past
its limit. Its two subjects shared one mock whose state was
module-level `let`s, which an importing spec cannot reassign; that
state is now the fields of one object in
`fixtures/smart-playlists-and-podcasts.ts`, beside the mock itself and
a hook that resets every field and installs the routes, as the old
`beforeEach` did. `smart-playlists.spec.ts` and `podcasts.spec.ts`
each install it and hold their own tests, unchanged but for reading
and writing that object.

The spec's copy of `expectNoWcagViolations`, identical to the one in
`fixtures/accessibility.ts`, gives way to it. The allowlist entry goes; the mechanism
stays, with nothing on it.

Signed-off-by: InstaZDLL <github.105mh@8shield.net>
Where a spec held its own copy of something `e2e/fixtures/` already
exports, and the copy is the same, the spec now imports it:

- `session` from `catalogue.ts`, in editorial-pages, themes,
  workspace-pages and the smart playlists and podcasts mock;
- `albums` from `catalogue.ts`, in editorial-pages and themes, and the
  themes spec's library from `library("library-1", "Ma musique")`,
  which answers the same object;
- `expectNoWcagViolations` from `accessibility.ts`, in editorial-pages
  and workspace-pages;
- `navigateWithin` from `radio.ts`, in podcasts;
- `PIXEL` from `media.ts`, for the one-pixel PNG built inline in
  artist, editorial-pages, library-cache, player and podcasts;
- `silentWav(30)` from `media.ts`, for the thirty-second WAV themes and
  the smart playlists and podcasts mock built by hand, byte for byte the
  same.

Copies that differ from the fixture, by their fields or their
signature, stay where they are.

Signed-off-by: InstaZDLL <github.105mh@8shield.net>
…are called

Signed-off-by: InstaZDLL <github.105mh@8shield.net>
Signed-off-by: InstaZDLL <github.105mh@8shield.net>
@github-actions github-actions Bot added ignore-for-release Excluded from release notes scope: server Server core (Rust) scope: web Embedded web player (React) scope: components Web UI components scope: api Native /api/v2 surface size: xl > 500 lines and removed ignore-for-release Excluded from release notes labels Oct 27, 2026
@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 042ca9c and 2da94c5.

Files selected for processing: 26
  • scripts/check-rust-layout.sh
  • scripts/check-webapp-layout.sh
  • src/app/boot.rs
  • src/app/state.rs
  • src/app/tests.rs
  • src/cli/mod.rs
  • src/config/from_env.rs
  • src/config/podcasts.rs
  • webapp/e2e/admin.spec.ts
  • webapp/e2e/artist.spec.ts
  • webapp/e2e/editorial-pages.spec.ts
  • webapp/e2e/fixtures/smart-playlists-and-podcasts.ts
  • webapp/e2e/library-cache.spec.ts
  • webapp/e2e/player.spec.ts
  • webapp/e2e/podcasts.spec.ts
  • webapp/e2e/smart-playlists-and-podcasts.spec.ts
  • webapp/e2e/smart-playlists.spec.ts
  • webapp/e2e/themes.spec.ts
  • webapp/e2e/workspace-pages.spec.ts
  • webapp/src/api/queries/maintenance.ts
  • webapp/src/pages/settings/admin-page/index.tsx
  • webapp/src/pages/settings/admin-page/libraries.tsx
  • webapp/src/player/player.tsx
  • webapp/src/player/queue-element.ts
  • webapp/src/state/i18n/en/admin.ts
  • webapp/src/state/i18n/fr/admin.ts
Files with no reviewable changes: 2
  • webapp/src/player/queue-element.ts
  • webapp/e2e/smart-playlists-and-podcasts.spec.ts

Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Walkthrough

Le changement ajuste le calcul de la limite Canvas et le parsing de paramètres Rust. Il traduit les libellés des pages d’administration, étend les tests E2E des playlists et podcasts, et met à jour des scripts ainsi que des fixtures partagées.

Changes: Vérifications de structure du dépôt

Layer / File(s) Summary
Exécution des contrôles depuis la racine
scripts/check-rust-layout.sh, scripts/check-webapp-layout.sh
Les scripts se placent à la racine du dépôt avant leurs vérifications. Le script web retire l’exception du test des playlists intelligentes et des podcasts.

Configuration et initialisation Rust

Layer / File(s) Summary
Lecture des paramètres d’environnement
src/config/from_env.rs, src/config/podcasts.rs, src/cli/mod.rs
Le parsing de plusieurs paramètres utilise parse_env, avec les valeurs par défaut conservées. La documentation CLI décrit les commandes et les configurations utilisées.
Calcul de la limite du corps Canvas
src/app/state.rs, src/app/boot.rs, src/app/tests.rs
canvas_body_limit convertit la limite configurée en usize et utilise 4 Mio si la conversion échoue. Le démarrage appelle cette fonction et un test vérifie les deux cas.

Traductions de l’administration

Layer / File(s) Summary
Libellés et vérification en français
webapp/src/state/i18n/{en,fr}/admin.ts, webapp/src/pages/settings/admin-page/{index.tsx,libraries.tsx}, webapp/e2e/admin.spec.ts
Les pages affichent des libellés traduits pour les rôles et le nombre de bibliothèques. Le test Playwright vérifie les libellés français et la valeur du sélecteur de rôle.

Couverture E2E des playlists et podcasts

Layer / File(s) Summary
Réutilisation des fixtures E2E
webapp/e2e/{artist,editorial-pages,library-cache,player,themes,workspace-pages}.spec.ts
Les tests utilisent des fixtures partagées de catalogue, de média et d’accessibilité à la place de données ou d’utilitaires locaux.
Mock stateful des API de playlists et podcasts
webapp/e2e/fixtures/smart-playlists-and-podcasts.ts
La fixture ajoute des routes simulées qui conservent l’état des playlists, podcasts, épisodes et signets entre les requêtes.
Scénarios des playlists intelligentes
webapp/e2e/smart-playlists.spec.ts, webapp/e2e/smart-playlists-and-podcasts.spec.ts
Les tests couvrent la création, l’aperçu, l’édition, la suppression, la lecture et la sélection d’une bibliothèque. L’ancien fichier regroupant les tests de playlists et de podcasts est supprimé.
Scénarios des podcasts
webapp/e2e/podcasts.spec.ts
Les tests couvrent l’abonnement, le téléchargement, la lecture, la reprise, les jaquettes, les signets retardés, la déconnexion et les contrôles selon les permissions.

Commentaires et état du lecteur

Layer / File(s) Summary
Requête de maintenance et lecteur
webapp/src/api/queries/maintenance.ts, webapp/src/player/player.tsx, webapp/src/player/queue-element.ts
Le commentaire de la requête est déplacé. Le lecteur retire queueLength et ajuste ou supprime des commentaires; les résumés ne signalent pas de changement du traitement de fin de lecture.

Priority: Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: Minimal · up to 2da94

No merge-blocking issue is established. The Canvas upload ceiling is enforced; the unrun Playwright suites remain for normal CI validation.

Security architecture risk: Minimal · up to 2da94

The Canvas change replaces an effectively unlimited fallback with a finite limit without expanding upload permissions. The inspected configuration refactoring preserves existing settings, and the administration changes preserve submitted role values. No introduced or materially worsened security risk was identified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — Canvas request bytes are extracted before authentication inside the handler, so unauthenticated callers can exercise the body-buffering boundary. That ordering predates this PR. For conversion-failing configurations, the change reduces the per-request ceiling to 4 MiB; it does not establish an aggregate concurrency limit.

Trust Boundaries and Controls

  • observed — The request ceiling is a resource control, not mutation authorization. Canvas placement retains downstream checks of authenticated identity, library membership, upload permission and accepts_canvas, including authoritative checks within the write transaction. The fallback does not grant access to another library or bypass those controls.

Resilience and Maintainability Implications

  • observed — The fallback does not introduce a new Canvas storage transition. Negative configured limits are rejected before staging; accepted requests retain the existing quota-checked transactional replacement path and cleanup behavior. Deletion remains independently authorized and is not disabled by closing a library to new canvases.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 53.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surv… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed Le titre décrit plusieurs changements réels de la PR : rôles traduits, découpage des specs e2e, plafond canvas et lecteurs de configuration. Il est précis et relié au contenu, mais il est long (119 ca…
Description check Passed La description suit le modèle : résumé, liste des changements par domaine, notes sur les vérifications et points signalés. Il manque une référence explicite au format de la section Test plan (cases à …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

Le titre décrit plusieurs changements réels de la PR : rôles traduits, découpage des specs e2e, plafond canvas et lecteurs de configuration. Il est précis et relié au contenu, mais il est long (119 caractères) et énumère plusieurs sujets au lieu d'un seul changement principal. Il reste donc partiellement adapté, sans être hors sujet.

Full details: Description check

Explanation

La description suit le modèle : résumé, liste des changements par domaine, notes sur les vérifications et points signalés. Il manque une référence explicite au format de la section Test plan (cases à cocher du modèle), et la section Notes n'est pas formatée selon le modèle. Les vérifications exécutées sont décrites en prose, ce qui couvre l'essentiel. La description est donc presque complète.

Full details: Docstring Coverage

Explanation

Docstring coverage is 53.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 15 functions across 24 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

Biome (2.5.15)
webapp/e2e/admin.spec.ts

Biome could not lint this file: nested root configuration. Check the repository's Biome configuration and plugins.

webapp/e2e/artist.spec.ts

Biome could not lint this file: nested root configuration. Check the repository's Biome configuration and plugins.

webapp/e2e/editorial-pages.spec.ts

Biome could not lint this file: nested root configuration. Check the repository's Biome configuration and plugins.

  • 13 others

Comment @coderabbitai help to get the list of available commands.

@InstaZDLL InstaZDLL self-assigned this Oct 27, 2026
@github-actions github-actions Bot added the ignore-for-release Excluded from release notes label Oct 27, 2026
@InstaZDLL
InstaZDLL merged commit e736c98 into main Oct 27, 2026
16 checks passed
@InstaZDLL
InstaZDLL deleted the chore/restructure-followups branch October 27, 2026 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ignore-for-release Excluded from release notes scope: api Native /api/v2 surface scope: components Web UI components scope: server Server core (Rust) scope: web Embedded web player (React) size: xl > 500 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant