This release includes 3 breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
ReleasePort's take
Light signalThe Axum server has been removed and replaced with a .NET 9 ASP.NET Core Minimal API implementation. This breaking change affects all server‑related code paths.
Why it matters: Affects the entire server surface; operators must update deployment configurations to use the new .NET 9 implementation before upgrading.
Summary
AI summaryBroad release touches Source priority tuning, Bug fixes, Highlights, and What's new.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Breaking | High |
Rust/Axum server removed; replaced with .NET 9 ASP.NET Core Minimal API implementation. Rust/Axum server removed; replaced with .NET 9 ASP.NET Core Minimal API implementation. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Feature | Medium |
Adds manga18fx plugin for explicit manhwa content with correct search URL and sidebar‑contamination fix. Adds manga18fx plugin for explicit manhwa content with correct search URL and sidebar‑contamination fix. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Feature | Medium |
Adds PATCH /api/sources/:id endpoint to accept a `priority` field for source ordering. Adds PATCH /api/sources/:id endpoint to accept a `priority` field for source ordering. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Feature | Medium |
Adds full end‑to‑end Playwright test suite against a real Docker Compose stack. Adds full end‑to‑end Playwright test suite against a real Docker Compose stack. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Feature | Medium |
Adds LOG_LEVEL environment variable to control Docker console and in‑app log verbosity. Adds LOG_LEVEL environment variable to control Docker console and in‑app log verbosity. Source: llm_adapter@2026-05-30 Confidence: low |
— |
| Feature | Low |
LOG_LEVEL env var controls Docker console and in‑app log verbosity (debug/info/warn/error). LOG_LEVEL env var controls Docker console and in‑app log verbosity (debug/info/warn/error). Source: granite4.1:30b@2026-05-30-audit Confidence: low |
— |
| Feature | Low |
GET /api/version is now public (no auth required) for server‑ready checks in e2e tests. GET /api/version is now public (no auth required) for server‑ready checks in e2e tests. Source: granite4.1:30b@2026-05-30-audit Confidence: low |
— |
| Feature | Low |
AniList source now stores all synonyms (romaji, english) as TitleAliases for improved fuzzy matching during sync. AniList source now stores all synonyms (romaji, english) as TitleAliases for improved fuzzy matching during sync. Source: granite4.1:30b@2026-05-30-audit Confidence: low |
— |
| Deprecation | Low |
Removes MangaFire plugin, source, and related tests/docs entirely. Removes MangaFire plugin, source, and related tests/docs entirely. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Fixes download status stuck issue; DownloaderService now sets status to `"downloading"` instead of `"in_progress"`. Fixes download status stuck issue; DownloaderService now sets status to `"downloading"` instead of `"in_progress"`. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Corrects manga18fx search URL to use `/search?q=` instead of WordPress `/?s=` fallback. Corrects manga18fx search URL to use `/search?q=` instead of WordPress `/?s=` fallback. Source: llm_adapter@2026-05-30 Confidence: high |
— |
| Bugfix | Medium |
Prevents amber warning badge from firing per‑source misses when at least one source succeeds; only fires on total sync miss. Prevents amber warning badge from firing per‑source misses when at least one source succeeds; only fires on total sync miss. Source: llm_adapter@2026-05-30 Confidence: low |
— |
| Bugfix | Medium |
Fixes manga18fx lazy‑load pages that used `data-src` placeholder, now returns correct page URLs. Fixes manga18fx lazy‑load pages that used `data-src` placeholder, now returns correct page URLs. Source: llm_adapter@2026-05-30 Confidence: low |
— |
| Bugfix | Low |
Sync warning now only fires when zero sources link after a full sync cycle; per‑source misses no longer trigger amber badge. Sync warning now only fires when zero sources link after a full sync cycle; per‑source misses no longer trigger amber badge. Source: granite4.1:30b@2026-05-30-audit Confidence: low |
— |
| Bugfix | Low |
GHCR build cache switched from SAS token to registry type, eliminating expiry issues. GHCR build cache switched from SAS token to registry type, eliminating expiry issues. Source: granite4.1:30b@2026-05-30-audit Confidence: low |
— |
| Refactor | Low |
Setup wizard adds guard to prevent re‑registration on already‑configured instances; UI polish includes reader zoom control and pill tags. Setup wizard adds guard to prevent re‑registration on already‑configured instances; UI polish includes reader zoom control and pill tags. Source: granite4.1:30b@2026-05-30-audit Confidence: low |
— |
Full changelog
*ARRgh v0.1.2 — .NET Migration + New Sources + Testing Layer
Released: 2026-05-30
Highlights
- Full .NET migration — Rust server replaced with C# / ASP.NET Core. The project has grown beyond a weekend experiment; the maintainer is professionally fluent in C# but cannot read or debug Rust without AI assistance, making self-recovery from incidents impossible. .NET removes that dependency.
- manga18fx source — new explicit manhwa plugin with correct search URL and sidebar-contamination fix
- E2e Playwright layer — full test suite against a real Docker Compose stack
- LOG_LEVEL env var — quiet the docker console without rebuilding
- Source priority PATCH — change source ordering via API
- manga18fx lazy-load fix — chapter pages that use
data-srcplaceholder pattern now return correct page URLs instead of 0 pages - MangaFire removed — plugin, seeded source, and all related tests/docs deleted; was CF-protected and unreliable without CloakBrowser
- Sync warning cleanup — amber warning badge no longer fires per-miss; only fires when zero sources linked after full sync cycle
What's new
.NET server (replaces Rust)
The Rust/Axum server has been removed. server/ is now the .NET 9 / ASP.NET Core Minimal API implementation — feature-complete, same SQLite schema, same API contract.
Why: ARRgh started as a weekend project. It has grown into something maintained long-term. The maintainer writes C# professionally and can read, debug, and recover incidents in C# without AI assistance. Rust required AI for every server change. That is not sustainable for a solo project.
See ADR 0030.
manga18fx plugin
New explicit manhwa source (default_explicit: true). Covers the gap left by CF-protected sources (Toonily, MangaFire, AsuraScans) that frequently return 502 without CloakBrowser.
- Search:
/search?q=endpoint (not WordPress/?s=fallback) - Chapters: scoped to
a[href^="/manga/{slug}/chapter-"]— fixes sidebar contamination where "Most Popular Manga" chapter links from other series were being scraped into unrelated titles - Pages:
img[src*="img01.manga18fx.com/uploads"]
Source priority PATCH
PATCH /api/sources/:id now accepts a priority field. GET /api/sources returns priority in each row. Allows reordering download fallback preference without recreating sources.
LOG_LEVEL env var
Set LOG_LEVEL=warn (or debug/info/error) in docker-compose.yml to control both the Docker console output and the in-app log viewer simultaneously. Default: info.
environment:
LOG_LEVEL: warn # quiets per-chapter download lines and other Info noise
Source priority tuning
- AsuraScans demoted to last priority (110) among all sources — CF-protected, frequently returns no results without CloakBrowser
- MangaFire marked CF-protected in
plugin-index.json— requires CloakBrowser - MangaDex removed from manhwa
ContentTypes— title name formats differ, was producing false "no match" errors on manhwa titles
E2e test layer (Playwright)
Full end-to-end test suite against a real Docker Compose stack.
plugins/fixture/— deterministic standalone Express fixture server (4 modes: happy path, no-match, 502, empty pages)docker-compose.test.yml— isolated test stack (fixture replaces plugin-host, no CloakBrowser, isolated volume)e2e/— Playwright +allure-playwrightwithglobalSetup(seeds admin →storageState).github/workflows/e2e.yml— runs on push tomain, results feed shared Allure report at/test-reports/
Allure dark theme
Test reports at /test-reports/ use the Obsidian Immersive palette. Applied via CSS injection after allure generate.
Setup guard + UI polish
- Setup wizard guard prevents re-registration on already-configured instances
- Reader zoom control (50–150% via popover)
- Tags rendered as pills instead of plain text
- E-Hentai gate — explicit titles require
allow_explicitflag
manga18fx lazy-load support
Some manga18fx chapters serve placeholder GIF images in src and put the real CDN URL in data-src (lazy-loading pattern). The pages scraper previously only checked src, returning 0 pages for these chapters.
Fixed selectors now match both src*= and data-src*= attributes, with data-src taking precedence:
$([
'img[src*="manga18fx.com/uploads"]',
'img[src*="img01.manga18fx.com"]',
'img[data-src*="manga18fx.com/uploads"]',
'img[data-src*="img01.manga18fx.com"]',
].join(', ')).each((_, el) => {
const src = $(el).attr('data-src') || $(el).attr('src')
if (src?.startsWith('http')) urls.push(src)
})
MangaFire plugin removed
MangaFire is Cloudflare-protected and requires CloakBrowser to return results. Without it, every sync attempt produces false "no results" warnings and never links chapters. Removed entirely:
plugins/mangafire/directory deleted- Seeded
ExternalSourcerow removed fromProgram.cs - Entry removed from
plugin-index/index.json - All contract/behavior tests removed
- Docker build steps removed
Sync warning accuracy
MatchSourcesAsync previously appended a SyncWarnings row for every source that returned no results or no title match. This created spurious amber badges on titles that were successfully linked via other sources.
New behaviour: warning only appended when zero TitleSources rows exist after the full source loop completes.
AniList synonym storage
When adding a title via the AniList source, all synonyms returned by the AniList API (including title.romaji and title.english) are now stored as TitleAliases rows. These aliases are used during MatchSourcesAsync to improve fuzzy matching across plugins that use translated or romanized titles.
Bug fixes
- Download status stuck —
DownloaderServicewas setting status to"in_progress"instead of"downloading". Frontend polling and progress indicators were all checking"downloading"— none detected the active state. - Manhwa titles getting no chapters — fixture plugin only handled its own source key; extended to wildcard
/:source/*routes. - manga18fx chapter contamination —
a[href*="/chapter-"]matched sidebar "Most Popular Manga" links, pulling in chapters from other series (e.g. Secret Class ch.307) into unrelated titles. Selector narrowed toa[href^="/manga/${seriesId}/chapter-"]. - manga18fx search URL — plugin was using WordPress
/?s=fallback; correct URL is/search?q=. - 502 on chapter sync fails silently —
sync_chaptersnow returnsErron 502 so a sync warning row is created instead of silently leaving 0 chapters. GET /api/versionrequired auth — moved to public router; used as server-ready check in e2eglobalSetup.- GHCR build cache SAS token expiry — Docker layer cache switched from
type=ghatotype=registry(no SAS token expiry). - 0 pages on manga18fx chapters using lazy-load —
data-srcattribute was ignored; now preferred oversrcplaceholder - Amber warning badge on clean syncs — per-source miss warnings fired even when another source succeeded; now only fires on total miss
- MangaFire false misses — removed source eliminates all CF-related sync noise
Removed
- Rust server —
server/is now the .NET implementation. See ADR 0030. - Royal Road plugin — no meaningful catalogue; frequent false matches on novel titles.
- Comick plugin — stub chapter listings (no real page data), unreliable.
New API behaviour
| Method | Path | Change |
|--------|------|--------|
| PATCH | /api/sources/:id | Now accepts priority field |
| GET | /api/sources | Now returns priority per source |
| GET | /api/version | No longer requires auth |
| GET | /api/titles/:id/sync-log | Sync progress log entries |
DB migrations
No new migrations in this release. All migrations from v0.1.1 are compatible with the .NET server.
Upgrading
docker compose pull
docker compose up -d
No breaking API changes. No new DB migrations required.
Existing installs — update AsuraScans priority (optional, demotes it to last):
# Get source ID
curl -H "Authorization: Bearer <token>" http://localhost:8080/api/sources \
| jq '.[] | select(.name=="AsuraScans") | .id'
# Update priority
curl -X PATCH -H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"enabled":true,"priority":110}' \
http://localhost:8080/api/sources/<id>
Breaking Changes
- Rust/Axum server removed; replaced with .NET 9 / ASP.NET Core Minimal API implementation (full migration).
- MangaFire plugin, seeded source, and all related tests/docs deleted.
- Royal Road and Comick plugins removed.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About t2vi/arrgh](https:
All releases →Related context
Related tools
Beta — feedback welcome: [email protected]