timescale.info
Sign inSign up

How OpenChronology was built

Every merged pull request of openchronology/timeline-app, its first week of commits and its releases; and before them the 2020 PureScript editor, from snapshots of its deleted repositories in the Wayback Machine. Written to this server through the HTTP API.

327 moments · 2020-03-09T00:15:08Z CE – 2026-11-02T20:11:21Z CE · by @athan · @athan

#194 · Five bugs found writing #177's comments, each with a test

  • timeline-app
  • pull request

Follow-up to #177 (#192). Writing the comments meant reading every function closely, and five bugs turned up that I could confirm. Each fix here comes with a test that fails without it and passes with it. The rest of what the reading found is in #193, for triage. ## The fixes - **Turnstile could be skipped (`server/challenge.mjs`).** Desktop and API-key sessions are given proof of work, because they can't show Cloudflare's widget. But `require()` accepted any valid proof-of-work answer, whatever kind of session was asking. So a browser asked for Turnstile could send a solved proof of work, fetched as a desktop session, instead. An answer now counts only as the kind this request asks for. - Test: `challenge.test.mjs`. - **Reset links failed for an address with capitals (`server/account-security.mjs`).** The reset link stores the address lowercased, but `reset()` compared it with the account's address as stored. An account kept with capitals, such as the bootstrap administrator's from the configuration, could never use a reset link: "This reset link is no longer valid." - Test: `account-security-postgres.mjs` resets an account stored in capitals. - **History comparisons could miss changes (`server/history.mjs`, `candidates()`).** Each part of the query was cut to a page of 20,000 *rows* before being made distinct. A key saved several times in the range takes several rows, so a part could return fewer than 20,000 keys. The scan then took that as the end, or the cursor passed keys it never returned. Comparisons feed merges, syncs and pull request summaries. - Test: `shared-history-postgres.mjs` saves 7,000 moments twice and compares the first and last revisions. Before the fix, 6,667 changes were reported; now all 7,000 are. - **Log ingest ignored its backoff (`server/moment-ingest.mjs`).** When a timeline was failing, every new message to a queue of 500 or more rescheduled the flush at 0 ms. That cancelled the 2–30 s backoff and retried the struggling server once per message. Now a full batch goes at once only when the timeline isn't failing. - Test: new `moment-ingest.test.mjs`. - **"Keep the labels" never showed (`platform/components/admin-reports.jsx`).** The server lets an administrator uphold an appealed label, as it does an appealed restriction. But the queue showed the button only for restrictions. - Test: new `admin-reports.test.mjs` renders the case with esbuild and React, and checks the buttons for both kinds, with and without an appeal. ## Checks Locally: - **Unit tests:** 292 pass, and typecheck passes. - **Prettier:** the changed files are clean. - **Database suite:** all 45 tests pass. - **Without the fixes:** each new test fails.

Sources

Open #194 · Five bugs found writing #177's comments, each with a test in the timeline