Reach every recording a fault kept, not just the newest - #95
Merged
Conversation
A fault can now hold several black-box recordings. The detail refetches on expand so one written while the page is open is reachable, the dashboard keys its cache by entity as well as code so two entities reporting the same code stop showing each other's evidence, each download button names its recording, and the saved file keeps the extension the gateway put on it. Adds a Playwright stack with a fault manager and specs covering all of it.
Distinct filenames alone would pass on a build that resolved both ids to one recording and labelled the responses differently.
A fetch in beforeAll threw before the skip guard could run, so CI went red on a missing fixture rather than reporting it as skipped.
bburda
reviewed
Aug 17, 2026
bburda
left a comment
Contributor
There was a problem hiding this comment.
Three things outside this diff that I think also need a change:
CONTRIBUTING.mdstill describes one stack. The new stack, the separate compose project name, the image override and the seeding step are not written down anywhere, so nobody can reproduce the run from the repo. It also tells developers to move the gateway to port 8081 when 8080 is taken, and that is the port the new stack takes by default.- The CI workflow only starts the old stack, so
npm run test:e2eruns the new project and reports three skips. They show up as skipped, but nothing fails. Skipping is the right behaviour until the gateway change lands, but could you wire the stack into CI in the same change that pins the published image, so these specs do not stay dormant after that? - Nothing that runs in CI covers the two behaviour fixes (the entity aware cache key, the refetch on expand). There is no test file for
FaultsDashboardorFaultsPanel. I wrote three vitest cases while reading this and all three reproduce the problems flagged inline, so they are cheap to cover.
Per-entity faultKey shared by the dashboard and the entity panel - expand, loading, clearing and the detail cache no longer tie colliding codes together, clear takes the Fault, and expansion opens before the refetch without blanking cached evidence on a 404. RFC 8187 charset+language filename parsing. The e2e stack gets its own compose project, sources ROS in the parent shell, runs the seeder as a watched job, and the seeder survives for discovery and checks both service responses.
Brought the stack up for real: '&' still bound the whole 'source && source && fault_manager' chain, so the gateway leg ran unsourced and exited 127. Semicolons scope each '&' to one command. Verified live: all three jobs up, two recordings seeded, specs' data visible in the browser.
bburda
approved these changes
Aug 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ros2_medkit#620 lets one fault hold several black-box recordings instead of overwriting on every re-confirmation. This is the web UI side of that: the extra recordings have to be visible, distinguishable and downloadable, and three existing behaviours got in the way.
Verified in a browser against a real gateway holding two real bags produced by the real capture pipeline. Every fix below has a spec that fails without it - all three specs go red when the source changes are reverted.
What was wrong
LIDAR_RANGE_INVALIDrendered each other's environment data - download buttons pointing at another entity's recordings. The key now includes the entity. This was reachable before #620; several recordings per fault only make it easier to hit.<id> recording <timestamp>) rather than from the gateway'sContent-Disposition, so a bag landed on disk with no.mcapand neither the OS norros2 bag playcould open it without a rename. The server is the only party that knows the storage format, so its name is the one to use; this also drops a listing round-trip per download.Testing
e2e/rosbag-recordings.spec.ts- three specs in a real browser: the detail shows every recording with distinct names, each downloads as its own bag with a real extension, and re-expanding refetches. Reverting the source changes turns all three red.e2e/docker-compose.rosbag.yml- a stack with a fault manager, which the scripts stack does not run, plus a seed that confirms, acknowledges and re-confirms one fault so it ends up owning two bags.src/lib/store-download.test.ts- theContent-Dispositionparser, including the RFC 5987 form and the empty-filename case that an earlier draft got wrong.Ordering
E2E_ROSBAG_GATEWAY_IMAGEat a local build to run them now.