Fix the extension's four 0.6.0 issues #58

Merged
tiagoagueda merged 5 commits from 0.6.0-fixes into main 2026-11-12 01:59:10 +00:00
Owner

The extension's four 0.6.0 issues, one commit each.

  • Closes #20: scripts/corpus.mjs, the script the corpus test tells a contributor to run, now exists: node scripts/corpus.mjs <page.html> [address] prints what the readers return, in a fixture's own shape. A test runs it on a fixture.
  • Closes #18: the popup, the review window, the settings footer, PRIVACY.md and the README now say that /captures/known is asked before Send (with the address, title and company; the server stores nothing), instead of "nothing leaves this browser until you send it". English only: the other 39 catalogues still carry the old sentence until they are retranslated in Weblate.
  • Closes #54: a sent capture keeps only its title, company, place and address (12.3 kB to 386 bytes each), sent captures go after 30 days, and a delivery writes its log once (81 writes and 6.85 MB to 1 write and 84 kB for 40 captures).
  • Closes #53: the toolbar is recounted once per delivery (40 to 1), and an unreachable Postulo is asked once per alarm instead of twice.

Tested: npm test (196), the guard, the build, and web-ext lint on the Firefox build. postulo-firefox gets these changes when its source.json pin moves; postulo-thunderbird shares none of the changed files.

🤖 Generated with Claude Code

The extension's four 0.6.0 issues, one commit each. - Closes #20: `scripts/corpus.mjs`, the script the corpus test tells a contributor to run, now exists: `node scripts/corpus.mjs <page.html> [address]` prints what the readers return, in a fixture's own shape. A test runs it on a fixture. - Closes #18: the popup, the review window, the settings footer, `PRIVACY.md` and the README now say that `/captures/known` is asked before Send (with the address, title and company; the server stores nothing), instead of "nothing leaves this browser until you send it". English only: the other 39 catalogues still carry the old sentence until they are retranslated in Weblate. - Closes #54: a sent capture keeps only its title, company, place and address (12.3 kB to 386 bytes each), sent captures go after 30 days, and a delivery writes its log once (81 writes and 6.85 MB to 1 write and 84 kB for 40 captures). - Closes #53: the toolbar is recounted once per delivery (40 to 1), and an unreachable Postulo is asked once per alarm instead of twice. Tested: `npm test` (196), the guard, the build, and `web-ext lint` on the Firefox build. postulo-firefox gets these changes when its `source.json` pin moves; postulo-thunderbird shares none of the changed files. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The corpus test's paragraph on adding a board starts with
`node scripts/corpus.mjs <url>`, a script that never existed, so the one written
way to grow the only accuracy test failed at its first step.

The script reads a saved page (a file, no fetching) with jsdom exactly as the
corpus test does and prints what readPosting() and readPostings() return, the
single posting in a fixture's own shape (url, source, data). The address the
page was read at is the second argument, or a fixture's .json beside the page.
The paragraph now names it as it is called, the README lists it in its layout
table, and a test runs it on a fixture so it cannot go missing again.

Closes #20

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The popup, the review window and PRIVACY.md said nothing leaves the browser
until the person presses Send, while the review window (each time it opens on
a capture not sent yet) and the popup (on a page of results) already ask
POST /api/v1/captures/known with the postings' address, title and company.
The policy's own table listed that request and the paragraphs either side
denied it.

The three hints (captureHint, reviewHint, nothingRead) and the settings'
shortcutHint now say that the address, title and company are asked about and
the page and the corrections go on Send. Only English changes, as the
repository's rules say: the other catalogues keep their old sentence until
they are retranslated in Weblate, which marks them for editing when the
source changes. PRIVACY.md says the same in its opening and closing
paragraphs, states when the question is asked and what goes (the address
without a fragment, the title and company as read, not as corrected), and
counts its requests right: six, the token on all but GET /healthz. The
README's privacy paragraph follows.

Closes #18

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A sent capture kept its whole reading twice (`read` and `data`, description
included) for ever, while the lists show only its title, company, place and
review link, so months of use could fill the 10 MB of storage.local and make
Keep fail (#16). And each delivery rewrote the whole log (up to 1,000 entries)
about three times per capture.

On sending, a record now keeps only the shown fields (title, company_name,
location, url) with `read` dropped; Postulo has the reading and `reviewUrl` is
the way back. On the five-minute alarm and at start, store.tidySent() removes
sent captures sent more than 30 days ago and slims those sent before this
change, in one read and only the writes needed, never touching a page (a
batch's shared page stays for its captures still to go). The log gains
addMany() and batch(): a delivery notes its entries in memory, each stamped
when it happened, and writes them once at the end whatever the outcome; the
log still never throws, and the 1,000-entry limit stays, as decided.

Measured on a delivery of 40 captures with a full log and a 5.7 kB
description each: log writes 81 -> 1 (6.85 MB -> 84 kB of JSON written); a
sent record 12,323 -> 386 bytes (40 of them: 493 kB -> 15 kB).

Closes #54

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Recount the toolbar once per delivery, and ask an unreachable Postulo once
Some checks failed
CI / check (pull_request) Failing after 28s
2d542062b8
The background recounted the badge on every storage change of a capture, and
a delivery of N captures makes one or more per capture, so it did about N full
recounts, each reading every record, the waiting list and the connection and
setting badge, title and icon, for a value only the last one shows. dropPage
listed every capture once per sent capture. And with nothing to send, an alarm
asked /healthz and then GET /captures even when the first had just found
Postulo unreachable, two failing requests where one says it.

- coalesce() (waiting.js): calls made before a run starts join it, calls made
  while it runs get one more run after it; the background gates it with
  afterDelivery() (outbox.js), a shared hold on the outbox Web Lock, so the
  recount waits for a delivery in any page to end and runs once. The last run
  starts after the last change, so the badge and title end where they did.
- deliverAndRead() (connection.js, from the background): the list is not read
  when the send or the check has just learnt unreachable, noPermission or
  tokenRefused; the last list stays, as waiting.js promises. The alarm keeps
  its five minutes, as decided.
- dropPage() reads only the batch's neighbours in the index (a batch is added
  as one block and the index is only prepended to or filtered), and nothing
  for a capture of its own.

Measured on a batch of 40 off one results page with 100 other captures kept:
recounts 40 -> 1, capture records read during the delivery 11,460 -> 2,740;
requests on an alarm with Postulo unreachable 2 -> 1.

Closes #53

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Give the recount test its own Web Locks, as Node 22 has none
Some checks failed
CI / check (pull_request) Has been cancelled
44a7d82551
The test "a delivery of forty is recounted once on the toolbar, at its end"
passed on Node 26 and failed in CI (node:22-bookworm) with 40 recounts.
Node 22 has `navigator` but no `navigator.locks`, so `exclusively` and
`afterDelivery` fell back to running at once: no delivery lock, no gate,
and each recount finished before the next capture's change.

The extension's own code is not affected: every browser it runs in (Chromium,
Firefox, Thunderbird) has Web Locks, and with them every change a delivery
makes happens under the exclusive lock, so the gated recount runs once, after
it. The test now brings an in-memory Web Locks (one lock, exclusive or
shared, granted in order) and passes it to both, and the answer's delay is a
few turns of the event loop instead of a timer, so it no longer depends on the
Node it runs on or on timing. It still fails with the recount uncoalesced.

Refs #53

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tiagoagueda force-pushed 0.6.0-fixes from 44a7d82551
Some checks failed
CI / check (pull_request) Has been cancelled
to 4d5bdd853d
All checks were successful
CI / check (pull_request) Successful in 33s
2026-11-12 01:36:33 +00:00
Compare
tiagoagueda deleted branch 0.6.0-fixes 2026-11-12 01:59:11 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo-chromium!58
No description provided.