Commit Graph
29 Commits
Author SHA1 Message Date
MaashkinoozheandClaude Opus 5.5 e9da27e688 Greatest: serve catalog covers from a local copy (BL-0053)
The page hotlinked ~100 AniList CDN covers per load and some failed at random.
The reader now downloads each catalog cover once (sequential, ~1/s, stops on
401/403/429, images up to 2 MB) into data/greatest-covers/ and serves it from
/api/greatest-cover with a year-long browser cache; until a copy exists the
route redirects to the catalog URL. The page also accepts the server's
relative cover URLs, so owned titles show their library cover again.
GREATEST_COVER_WARM=0 turns the downloads off (tests, offline installs).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 00:38:55 +01:00
MaashkinoozheandClaude Opus 5.5 cd6a30a76b Discovery final review fixes: lean publish, robust scoring, cheap prune (BL-0051)
- Cache prune counts directory entries first and only reads files when over
  the cap; tests for cross-kind prune, schema-mismatch and corrupt entries.
- Scoring tolerates malformed manga.json and cached records (non-list tags,
  object or null relations, non-object items); a tag without a rank no longer
  passes the top-tag filter; authors without an integer AniList id are dropped.
- discovery.json publishes only candidates some feed shows; examined/clipped
  still describe the pool. Tests that asserted the published count equals the
  pool size now check the pool via candidatePool() and the published set
  against the feeds.
- The post-harvest rescore failure test now breaks discovery.json right before
  the publish (via a scraper stand-in) instead of relying on tags: 5, and a
  following successful harvest clears the stale lastError.
- Consent text names everything sent to AniList; paused label mentions admin
  harvests; the UI test asserts the XSS seed instead of skipping it.
- Slot-mix test proves the fresh/outside reservations matter.
- Docs: privacy note, fresh fallback reason, per-period cap, dry-run wording,
  published-candidate rule; plan/spec hygiene and spec status.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:43:31 +01:00
MaashkinoozheandClaude Opus 5.5 613db96355 Discover page: refresh, harvest admin and seed reasons; docs (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:28:38 +01:00
MaashkinoozheandClaude Opus 5.5 0f87fbe948 Discovery harvest routes, nightly schedule and per-user refresh (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:15:55 +01:00
MaashkinoozheandClaude Opus 5.5 5de5eb6a08 Discovery scores AniList seeds with slot mix and isAdult filter (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:07:53 +01:00
MaashkinoozheandClaude Opus 5.5 552a599475 Harvester pauses user refreshes after AniList stops (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:02:03 +01:00
MaashkinoozheandClaude Opus 5.5 23a87099c5 Discovery store keeps harvest, settings and nightly state (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:00:41 +01:00
MaashkinoozheandClaude Opus 5.5 62ec69bc0d Single-flight discovery harvester with budgets and stop reasons (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:58:48 +01:00
MaashkinoozheandClaude Opus 5.5 41437c5321 Discovery anchors and top tags (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:52:18 +01:00
MaashkinoozheandClaude Opus 5.5 60a25bacac Discovery AniList client: drop removed recommendations (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:51:16 +01:00
MaashkinoozheandClaude Opus 5.5 3e7b1ca49f Discovery AniList client: spec sorts, challenge on 5xx, strict list validation (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:50:11 +01:00
MaashkinoozheandClaude Opus 5.5 461a37e924 Rate-limited AniList client for discovery seeds (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:47:52 +01:00
MaashkinoozheandClaude Opus 5.5 aad2761dc9 Discovery cache with per-kind TTL and size cap (BL-0051)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 08:45:47 +01:00
MaashkinoozheandClaude Opus 5.5 e0dacd81c6 Chapter dates: read date setting and tiered release dates (BL-0047)
- Chapter rows show when you first finished a chapter (setting: date + hour,
  date, off) from a new durable progress doneAt; older reads fall back to the
  reading clock's earliest remembered completion.
- chapter.json keeps added (arrival in this library, now kept on replace) plus
  x-dates.source (source upload, bulk imports flagged), x-dates.release
  (official, for a later metadata job) and x-dates.ecosystem (first entry into
  any Manga Circus library; carried over peering, earliest wins, clamped).
- Rows show one release date by tier: official > source upload > ecosystem >
  library, with all known dates in the tooltip (setting to hide).
- Fixes: WeebCentral dates came from the chapter page, which has none (every
  chapter got the download time); they now come from the full chapter list.
  MangaDex no longer writes a group's publishAt into added. Peering sends dates.
- tools/backfill-chapter-dates.js migrates an existing library (dry run default).
- Coverage dry run on the server: docs/chapter-dates-coverage-2026-10-24.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 01:01:33 +02:00
MaashkinoozheandClaude Opus 5.5 b2bb34174c Fold the sentinel into the scraper and drop the sentinel service (BL-0046)
The stall watchdog now runs inside the scraper (ScraperService.checkStalls,
every 30 s from the work loop): same rule as before, one checkpoint-safe
restart, quarantine on the second stall, missing checkpoint is no evidence,
and paused time no longer counts. Stalls are recorded as scraper incidents
(failure.kind 'stall'). The private /api/recovery endpoint is gone.

Dropped with the service: reader/scraper-unreachable incidents (supervisor
and Docker handle crashes; the health page shows "Scraper: unreachable"),
duplicate job-failure incidents and the unused /metrics endpoint.
The stack is now reader + scraper (+ optional peer-gateway).
The supervisor test moved to runtime/test (npm run test:runtime stays).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 22:58:03 +02:00
MaashkinoozheandClaude Opus 5.5 5e14e54286 Faster first library scan: bounded concurrency and a 32 KB first read
An uncached scan probed one image at a time and read 256 KB of each. On
a NAS that is bound by per-file latency (the server/Synology: ~20 ms per
image, ~100 min for 298k images). Now chapter folders of a book and
their images are probed SCAN_CONCURRENCY (default 8, 1-64) at a time
and assembled in folder order, and imageSize() reads 32 KB first, then
256 KB, then the whole file: a prefix gives either no size or the same
size, so results do not change. Tests: every format and read stage
equals the whole-file answer; concurrency 1 and 8 build the same index
and cache; the limiter keeps its bound and per-task errors. (BL-0043)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:07:29 +02:00
MaashkinoozheandClaude Opus 5.5 d6254a8be5 Admins can grant or revoke admin rights in Settings (BL-0045)
New POST /api/admin/user/role {name, admin}: admin-only (checked on the
server), keeps the password and sessions, takes effect on the target's
current session at once, logs who changed whom. Revoking your own
rights is refused, so at least one admin always remains. Settings ->
Users & access shows "Make admin" / "Remove admin" next to every other
user, with a confirmation. Test: normal users and anonymous callers are
refused, input checks, promotion and revocation apply immediately and
are saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 19:35:04 +02:00
MaashkinoozheandClaude Opus 5.5 f8f21ab42a Backup: probe the target with a real write instead of access(W_OK)
On the server the backup folder is a Synology NFS share with "map all
users to admin": access(W_OK) returns EACCES for uid 1000 although
writes succeed, so the first scheduled run failed with "not usable".
Create and remove a probe file instead; test that it leaves nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 18:12:41 +02:00
MaashkinoozheandClaude Opus 5.5 086f6353f8 Add built-in backup of the data folder (BL-0044)
The reader owns a scheduled backup into BACKUP (Compose: BACKUP_PATH mounted at
/backup, off when unset). A run pauses the scraper queue through its control
API, waits (bounded) until no job is active, writes a verified tar.gz of DATA
with db.json from memory and scraper/queue.json stored paused, excludes
runtime/lock/pid/temp files, resumes only a queue it paused, then applies
count- or day-based retention to its own archive names only. Schedule,
retention, "Back up now" and last result live in Settings > Service health.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 18:03:21 +02:00
Codex ddd9c62c40 Show read-only server reading hours in settings 2026-10-14 22:42:54 +02:00
Codex d8eba9169f Add deployment reading windows and progress-aware quiz unlock 2026-10-14 15:34:55 +02:00
Codex 47de081721 Checkpoint peering identity and opt-in discovery 2026-10-13 22:00:54 +02:00
Codex 605fa5b9d8 Add per-user page tone modes to reader 2026-10-12 23:49:02 +02:00
Codex d0275223a7 Expose Greatest source links and safe scraper inspection 2026-10-09 14:53:52 +02:00
Codex bedd0bc3b3 Show Greatest inclusion reasons on catalog tiles 2026-10-09 10:25:18 +02:00
Codex f713d0c0a9 Complete Greatest covers and use Japanese navigation label 2026-10-09 10:22:01 +02:00
Codex 5df94db9a3 Add Greatest of All Time manga dashboard 2026-10-09 10:10:34 +02:00
Codex 8ac27e1f3d Cache library index and refresh changed manga 2026-10-08 21:53:08 +02:00
Maashkinoozhe eef4ffa07c Consolidate MangaCircus app, scraper, and Compose baseline 2026-10-07 23:28:20 +02:00