144 Commits
Author SHA1 Message Date
jason5ng32 2d244a129d Improvements 2026-10-27 12:41:09 +08:00
jason5ng32andClaude Opus 5.5 825db1638f Chore: bump version to 8.1.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 11:12:28 +08:00
jason5ng32andClaude Fable 5.1 4c9ab04bc5 Improvements
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-22 11:37:55 +08:00
jason5ng32 b616b7e00e Improvements 2026-10-06 10:48:50 +08:00
jason5ng32 b1875562fc Improvements 2026-10-05 14:43:48 +08:00
jason5ng32andClaude Opus 5.5 02476aec7e Fix(datasets): abort on a lost lock, roll back new files, validate watched files
- A compromised lock (failed heartbeat; another process may take it over)
  aborts the update holding it, download included, before it publishes,
  instead of only being logged.
- A failed publish removes files it had just added when the dataset had none
  before, as well as restoring replaced ones from backup: never half a set.
- The watcher reloads hand-placed or externally published files only once
  they have held still for the settle interval and passed the row's
  validator, so a file still being copied never replaces healthy data.
- Back to write-file-atomic 8, with engines aligned to its range
  (^24.15.0 || >=26.0.0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 02:31:28 +08:00
jason5ng32andClaude Opus 5.5 65e8432768 Fix(datasets): bound scheduled runs, catch up by schedule, retry failed reloads
- Scheduled and catch-up runs give each dataset 30 minutes, download
  included, so a stalled upstream can't hold up the rest or, under croner's
  overrun protection, every later run.
- Downloads go through fetchUpstream (project User-Agent, a timeout on the
  wait for a response); the body stays bounded by the caller's signal.
- Catch-up asks whether a scheduled run fell between the last check and now,
  instead of a 25-hour age that missed a check skipped just after one.
- A remote that names no version (no Last-Modified) is always fetched, not
  taken for unchanged; maxmindIdentifier is null when an edition omits it.
- The watcher records a dataset's files as loaded only after the reload
  succeeds, so a failed load is retried on their next change.
- write-file-atomic 7, which supports the project's Node >=24 (8 needs 24.15).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 02:29:48 +08:00
jason5ng32andClaude Opus 5.5 287c50fe1a Feat(datasets): one updater engine for every offline dataset
MaxMind and CAIDA each had their own updater with its own lock, state file,
publish step, boot download and timer. One engine (common/dataset-updater.js)
now owns all of that, and each dataset is a row in common/datasets.js that
holds only its own logic: find the newest remote version, fetch or distill
it, validate, reload.

- Locks: proper-lockfile, a heartbeat lock shared by every process, so a
  crashed holder's lock goes stale on its own; a booting server waits for a
  live holder and loads what it published.
- State: one file per dataset, written with write-file-atomic; the old
  .maxmind-update-state.json / .caida-update-state.json are read once, so an
  upgrade doesn't re-download.
- Schedule: croner at a fixed time (DATASET_UPDATE_CRON, default 04:30 local)
  instead of 24 h from process start, plus a catch-up run at boot for a check
  a downtime skipped. DATASET_AUTO_UPDATE (default on) replaces
  MAXMIND_AUTO_UPDATE / CAIDA_AUTO_UPDATE, which still apply when it is unset.
- Reload: the engine watches every dataset's files, so a publish by another
  process or a hand-placed .mmdb is picked up; MaxMind's own watcher goes.

MaxMind's City and ASN editions now publish together under one version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 02:21:58 +08:00
jason5ng32andClaude Fable 5.1 04079783af Fix(tests): keep the logger off its worker thread during specs
The pino-pretty transport runs in a worker thread. In a loaded parallel
run, a spec that logs shortly before finishing could occasionally be kept
alive by that thread and never exit, stalling the whole suite until the
CI timeout. `pnpm test` now preloads tests/setup.js, which switches the
logger to its synchronous JSON output unless LOG_FORMAT is already set.

Runtime logging is unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-04 00:00:39 +08:00
jason5ng32 d77342cc83 Improvements 2026-09-21 23:21:46 +08:00
jason5ng32 45be0e711c Improvements 2026-09-17 10:33:38 +08:00
jason5ng32andGPT-6 cc0053ac16 Refactor(ipinfo): share Intl country names with the frontend
Replace country-code-lookup with the existing Intl.DisplayNames helper.

Co-Authored-By: GPT-6 <noreply@openai.com>
2026-09-16 18:29:19 +08:00
jason5ng32 a1ee760d88 Improvements 2026-09-13 22:47:01 +08:00
jason5ng32 c596a15b30 Improvements 2026-09-05 21:14:57 +08:00
jason5ng32 65145ca5e8 Improvements 2026-09-03 19:10:40 +08:00
jason5ng32andClaude Fable 5.1 e7074cc12c Chore(release): open v7.6.0 with the IP Calculator changelog entry
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 18:40:10 +08:00
jason5ng32 0199902495 Improvements 2026-09-03 18:25:16 +08:00
fly1dandOpenAI Codex 79a5269fbc Chore(dns): align resolver diagnostics with runtime usage
Keep resolver health checks on demand and surface actionable runtime availability failures through the shared logger. Remove the GitHub Actions workflow so transient resolver connectivity does not affect code CI.

Co-authored-by: OpenAI Codex <codex@openai.com>
2026-08-24 16:44:46 +08:00
taljeon e9808e31db docs: require Node.js 24 for contributor setup 2026-08-24 00:52:40 +09:00
jason5ng32 89cbb35401 Chore(deps): bump @cloudflare/speedtest and vite 2026-08-23 12:00:10 +08:00
jason5ng32andClaude Fable 5 e61a1992f3 Feat(i18n): empty-value skeletons with scaffolding and build-time pruning
A beta pack is now en's full skeleton with untranslated values left as
"", so translation review is always a `"" -> text` diff and English left
in place can't masquerade as translated. pnpm i18n-new scaffolds a pack
and its registry line (--privacy / --checklist for the optional files,
which ship finished or not at all); pnpm i18n-sync realigns packs when
en changes. The gate flips accordingly (exact key parity everywhere, ""
legal only in beta main packs) and a Vite plugin prunes empty values at
build time, so shipped chunks carry only translated strings and ""
behaves exactly like an absent key at runtime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 21:17:20 +08:00
jason5ng32andClaude Fable 5 6301d8b838 Feat(i18n): beta locale support with fallback chains, pack gate and status dashboard
A locale can now ship partially translated: registry status drives a Beta
badge in the picker, missing keys walk variant -> base -> en (one chain
definition feeds vue-i18n, the privacy/checklist datasets and the
changelog), and matchLocale gained family matching so pt-PT finds a
pt-BR pack. Changelog history is only required of full locales, removing
the biggest barrier for new-language PRs. tests/locale-packs.test.js is
the hard gate a pack must pass; scripts/i18n-status.js (un-gitignored
for contributors) reports coverage without ever failing. Only visible
behavior change: ?hl= resolves regional tags (?hl=zh-CN -> zh) instead
of dropping to English.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 20:13:14 +08:00
jason5ng32andClaude Fable 5 d325144f83 Feat(connectivity): ship the favicon fetcher and auto-heal missing icons
The fetch script was gitignored while the data test hard-required its
output, so outside contributors were blocked by a tool they couldn't
see. The script is now committed (pnpm fetch-favicons) and the data
test auto-downloads missing icons on local runs; CI stays offline and
keeps enforcing that PNGs are committed. Also adds a locale-coverage
check for list names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 17:23:41 +08:00
jason5ng32 46ce6138e0 Improvements 2026-08-22 10:37:57 +08:00
jason5ng32 2eddb7287e Improvements 2026-08-20 11:35:55 +08:00
jason5ng32andClaude Fable 5 0ff2615bab Chore: Add vue-input-otp dependency
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 10:11:57 +08:00
jason5ng32 6e18ba2ded Improvements 2026-08-13 16:27:48 +08:00
jason5ng32andClaude Opus 5 83bdd54674 Feat(ip-infos): show each IP's time zone, derived from its own coordinates
Every geo route now returns an IANA zone name, added on the way out by the
withTimeZone() middleware rather than by any handler — including the private
API pass-through, which needs no new upstream field.

The zone is derived from the latitude/longitude the response itself carries,
not from a second lookup of the same IP. Asking another database would
eventually place the address elsewhere and print a zone that contradicts the
city next to it. Coordinate accuracy measured against MaxMind's own time_zone
over 30k sampled addresses: 99.80% exact, 99.98% correct offset; the rest are
neighbouring zones across a land border that share an offset anyway.

Only the name ships. Geo routes sit behind a 24h edge cache, so a cached UTC
offset would be an hour wrong for everyone between a DST switch and the
entry's expiry — the frontend renders the offset per view instead, reusing
the formatter the analytics path already had.

The field travels the full report path: event payload, builder, schema (as a
typed timeZone kind, not a free string), the /r/:id table, the Markdown
export and the JSON download.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 17:44:18 +08:00
jason5ng32 f1728105ab Change word map dependent 2026-08-09 18:56:29 +08:00
jason5ng32 cebef7ee59 Improvements 2026-08-06 12:42:18 +08:00
jason5ng32andClaude Fable 5 ae0eaee838 Chore(deps): bump dependencies
Routine minor/patch bumps (vue 3.5.41, vite 8.2, sentry 10.69, firebase
12.17.1, …) plus @tanstack/vue-table 8 → 9; pnpm 11.20. Vue 3.5.41
packages allow-listed in the workspace minimumReleaseAge exclusions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 12:15:37 +08:00
jason5ng32 007d81cb98 Improvements 2026-07-25 10:11:10 +08:00
jason5ng32andClaude Fable 5 ab7cc4a391 Chore: bump version to 7.2.0 and fill changelog in all locales
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 23:07:22 +08:00
jason5ng32 6926045317 Improvements 2026-07-21 22:33:50 +08:00
jason5ng32 1aca785105 Improvements 2026-07-16 00:26:25 +08:00
jason5ng32 7243d5185e Improvements 2026-07-16 00:07:59 +08:00
jason5ng32 3da6bd8808 Improvements 2026-07-15 22:56:25 +08:00
jason5ng32 39c051c704 Improvements 2026-07-14 01:07:14 +08:00
jason5ng32andClaude Fable 5 9bfbf21a60 Feat(monitoring): integrate Sentry across frontend and backend, env-gated end to end
Frontend (@sentry/vue, loaded via build-time-gated dynamic import — no
VITE_SENTRY_DSN_FRONTEND, no Sentry in the bundle; init joins the mount
gate so instrumentation precedes the first render):
- uncaught errors, route-change tracing / Web Vitals, error-only masked
  Session Replay, console.error capture fingerprinted per message prefix
  so each fallback source stays a distinct issue
- explicit ip-source:exhausted signal via the app-events bus
- hidden source maps uploaded (then deleted) by @sentry/vite-plugin,
  gated on SENTRY_AUTH_TOKEN

Backend (@sentry/node, bootstrapped by sentry-instrument.js via
node --import so ESM loader hooks land before express; never loaded
without SENTRY_DSN_BACKEND):
- Express error capture + per-route tracing
- logger hook mirrors warn+ lines to Sentry Logs and elevates error+
  to grouped, alertable Issues
- Sentry Crons check-ins for the MaxMind / CAIDA / service-status jobs
  via the no-op-without-DSN wrapper common/sentry-cron.js

Delivery & ops:
- first-party tunnel /api/monitoring relays envelopes past ad blockers;
  DSN-allowlisted (never an open relay), exempt from the shared rate
  limiter with its own generous ceiling
- rate-limit ledger file becomes opt-in now that the warn line reaches
  Sentry Logs; ecosystem.config.cjs carries the --import flag for pm2

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 11:16:17 +08:00
jason5ng32 38a0db748f Update Packages 2026-07-08 11:54:42 +08:00
jason5ng32 53265e0bcd Improvements 2026-06-30 10:48:33 +08:00
jason5ng32 d72cff6449 Improvements 2026-06-28 12:02:39 +08:00
jason5ng32 691924aa9c Improvements 2026-06-24 09:06:00 +08:00
jason5ng32 4fe3cd0948 Improvements 2026-06-14 18:55:44 +08:00
jason5ng32 18fa8cef2b Improvements 2026-06-06 12:02:38 +08:00
jason5ng32 1d8854e0bb Bug fixed 2026-06-01 13:28:32 +08:00
jason5ng32 fed344a286 Improvements 2026-05-31 15:04:11 +08:00
jason5ng32 1d09e2b60f Improvements 2026-05-31 10:34:01 +08:00
jason5ng32 a238b4a032 Improvements 2026-05-28 00:03:18 +08:00
jason5ng32 f41c16f72c Improvements 2026-05-27 18:52:54 +08:00