Pick up the three things the rebase left behind - #125
Conversation
An audit of the June working tree against what the five preceding changes actually landed found 20 files unaccounted for. Seventeen were deliberate and are explained in those changes -- the concern upstream rewrote better, the locale files for languages no longer served, a Yarn 1 lockfile, a schema dump. Three were not deliberate. They were missed. MERCHANDISE. The page advertises a single T-shirt three times: the same image, the same .shirt_1 keys and the same link, pasted into three cards. It has read as a catalogue of one product in triplicate on the live site for as long as the file has existed. One card now, and a test that counts them. THE OPEN WALL SAYS WHAT IT IS. The wall is in the navigation and the footer since the cutover, so it now gets visitors who have never seen it and cannot tell from a grid of stills whether these images were collected or volunteered. A line under the heading says they were volunteered, and that they are deleted after two days -- which is PurgeImagesJob::RETENTION, checked rather than assumed. THE SURVIVING PAGES HAD NO TESTS. /green_life, /merchandise, /stages-of-firmware-development, /utilities and the partition and timer calculators are served by the app and were rendered by no test at all. They are the pages nobody thinks about, and they render through the layout, navbar and footer that the relaunch rewrote -- so a mistake in any of those shows up there first, or not at all. Ten of them are rendered now, checked for their own title and for translation-missing, and held to the layout wrapper, which pins the other side of the content_for(:fullwidth) switch against pages that depend on it. 303 runs, 1390 assertions, 0 failures. i18n-tasks reports no missing translations and 72 unused, unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hvzXBErEjEGMyRme2K3hi
The existing link test walks whatever the page renders and requires each href to resolve. That cannot notice a link which stopped being rendered at all -- a pillar card losing its href, or a whole section dropped in a refactor -- because a page with fewer links still passes. This is the one assertion from the June test file that the two replacements did not carry between them. 304 runs, 1404 assertions, 0 failures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015hvzXBErEjEGMyRme2K3hi
PR Summary by QodoRestore missed page fixes and legacy coverage
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1. Unverified upload consent claim
|
| have not seen it before and cannot tell from a grid of stills whether | ||
| these were collected or volunteered. Two days is the retention | ||
| PurgeImagesJob::RETENTION actually enforces. %> | ||
| <p class="text-body-secondary small" style="max-width: 70ch"><i class="bi bi-camera-video me-1"></i><%= t('.intro_html') %></p> |
There was a problem hiding this comment.
1. Unverified upload consent claim 🐞 Bug ≡ Correctness
The new intro presents every wall image as voluntarily uploaded by an OpenIPC camera, but SnapshotsController#create accepts unauthenticated uploads and neither requires OpenIPC firmware nor records/verifies an Open Wall opt-in. Arbitrary clients can therefore publish images that the page falsely represents as owner-volunteered camera submissions.
Agent Prompt
## Issue description
The Open Wall intro asserts consent and OpenIPC-camera provenance that the upload endpoint does not verify. Either add enforceable uploader authentication/opt-in provenance or revise every locale to describe only what the system can guarantee.
## Issue Context
`SnapshotsController#create` is CSRF-exempt, permits firmware as optional metadata, and saves snapshots without authentication or a consent/opt-in field. Model validations only cover the image, MAC address, blacklist, and upload interval.
## Fix Focus Areas
- app/views/snapshots/index.html.erb[12-16]
- config/locales/en.yml[191-191]
- config/locales/ru.yml[193-193]
- config/locales/zh.yml[191-191]
- app/controllers/snapshots_controller.rb[15-24]
- app/models/snapshot.rb[61-64]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| these were collected or volunteered. Two days is the retention | ||
| PurgeImagesJob::RETENTION actually enforces. %> | ||
| <p class="text-body-secondary small" style="max-width: 70ch"><i class="bi bi-camera-video me-1"></i><%= t('.intro_html') %></p> |
There was a problem hiding this comment.
2. Two-day deletion overpromised 🐞 Bug ≡ Correctness
The intro says images are deleted after two days, but the two-day constant is only a cutoff for a once-nightly purge, so snapshots can remain published for nearly three days even when cron succeeds and longer when it fails. This makes the new user-facing retention assurance stricter than the behavior actually implemented.
Agent Prompt
## Issue description
The copy promises deletion after two days although cleanup runs only once nightly after records cross the two-day threshold. Revise all translations to communicate the real upper-bound/best-effort behavior, or schedule per-snapshot deletion so the stated retention is enforced.
## Issue Context
`PurgeImagesJob::RETENTION` selects records older than two days at execution time. The deployment cron invokes that job only at 01:30 daily, leaving an additional delay of up to almost 24 hours.
## Fix Focus Areas
- app/views/snapshots/index.html.erb[12-16]
- config/locales/en.yml[191-191]
- config/locales/ru.yml[193-193]
- config/locales/zh.yml[191-191]
- app/jobs/purge_images_job.rb[11-18]
- deploy/purge-snapshots.sh[3-13]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
You asked whether the whole working tree was covered. It wasn't — this is what
the audit found.
Stacked on #124. Method: diff the June tree's 106 changed files against
everything the five PRs landed. 20 unaccounted for; 17 deliberate and
explained in those PRs (the concern upstream rewrote better, locale files for
languages no longer served, a Yarn 1 lockfile, a schema dump). Three were
not.
1. The merchandise page shows one T-shirt three times
Same image, same
.shirt_1keys, same link — pasted into three cards. It hasread as a catalogue of one product in triplicate on the live site for as long as
the file has existed. One card now, and a test that counts them.
2. The Open Wall didn't say what it is
It's in the navigation and the footer since #124, so it now gets visitors who
have never seen it and can't tell from a grid of stills whether these images
were collected or volunteered. A line under the heading says they were
volunteered, and that they're deleted after two days — which is
PurgeImagesJob::RETENTION, checked rather than assumed. en/ru/zh.3. Six surviving pages had no tests at all
/green_life,/merchandise,/stages-of-firmware-development,/utilities,and the partition and timer calculators are served by the app and were rendered
by no test whatsoever.
They're the pages nobody thinks about — and they render through the layout,
navbar and footer that #122 and #124 rewrote, so a mistake in any of those shows
up there first, or not at all. Ten pages are rendered now, each checked for its
own title and for
translation missing, and held to the layout wrapper — whichalso pins the other side of the
content_for(:fullwidth)switch against pagesthat depend on it.
Verification
bin/rails testi18n-tasks missingi18n-tasks unusedrubocopon the new testThe merchandise test fails on master (finds 3, expects 1), which is the check
worth repeating.
🤖 Generated with Claude Code
https://claude.ai/code/session_015hvzXBErEjEGMyRme2K3hi