Repository navigation
ui: fix digest shortening and the rebuild lock on full storage - #1305
Conversation
|
Thanks for opening this pull request! A SPACE maintainer will take a look. CONTRIBUTING.md explains how we review outside contributions. |
Review — 2 findingsMedium
Low
Verified against |
the-gigi-pplx
left a comment
There was a problem hiding this comment.
Approved. 2 non-blocking findings in the review comment above.
exclusiveWith now runs work without the fallback lock only when acquiring it throws QuotaExceededError or SecurityError; any other error propagates. The comment says what full storage still accepts: removals and writes that do not grow the stored run, which land unlocked. The fallback lock's TTL moves into lib/exclusive.ts, beside the loop it depends on.
|
Thanks, both fixed in 7a7bb59.
At 7a7bb59 and on its merge with main, in |
Review follow-up — both findings resolvedI checked
Reproduced in |
Summary
Follow-up to #1278, fixing the two low findings its review left open.
shortHashnow strips any<algorithm>:prefix (/^[a-z0-9]+:/) before keeping 12 characters. It removed onlysha256:, so ablake3:<64 hex>digest, the default for new releases, showed asblake3:01234(5 hex characters). The Templates page's Hash and releases columns, its sort, and the rebuild panel share the helper, so they all show 12 hex characters now.exclusivehelper now catches aQuotaExceededErrororSecurityErrorfrom the localStorage fallback lock (used where Web Locks is unavailable), and runswork()without the lock. Any other error from taking the lock still propagates. Before, the throw escaped beforepersistorstorecould report "could not save ...", so the click did nothing visible and the promote dialog kept spinning. It does not retry the lock after that error, since retrying cannot store it. With blocked storage,work()'s own writes fail too and report through the existing messages. Full storage still accepts removals and writes that do not grow the stored run, so those land without the lock.To test
exclusive, its body moved intoui/src/lib/exclusive.ts, unchanged except for the new catch, taking its lock functions as parameters. The fallback lock's TTL moved with it, beside the loop it depends on. The component passes the real Web Locks andview-refreshfunctions.Validation
At this head, in
ui/:npm ci,npm test(125 pass, 0 fail),npx tsc --noEmit -p ., andnpm run buildall exit 0.template-format.test.mjs: theblake3:case fails onmain(blake3:01234instead of0123456789ab) and passes here;sha256:, no-prefix, and fallback cases are also covered.exclusive.test.mjs: covers Web Locks, hold and release in the fallback, waiting on a held lock, the throwing acquisition (work runs once, no waiting, no release), errors fromworkpropagating, an unrelated acquisition error propagating without runningwork, and the TTL the fallback asks for. I did not run the throwing-acquisition test against the oldexclusive, which lived in the component and could not be imported; the old code let the throw escape.Not validated: a real browser with full or blocked storage; the dialog behavior is covered by the unit test of the helper only.
Severity and risk
Severity: low. A cosmetic digest display and an unreported failure in an admin UI edge case (storage full or blocked, no Web Locks).
Risk: digests display differently, only for prefixes other than
sha256:. Where storage refuses the lock and Web Locks is unavailable, writes run unlocked. With full storage, a dismiss or a write that does not grow the stored run can then land and be overwritten by another tab's write in the same moment; before, both clicks threw. Roll back by reverting the PR.AI assistance: Claude Code drafted the code, tests, and this description.