Files
MaashkinoozheandClaude Opus 5.5 f53b92a7dc Prepare the repository for a public release
- docs/deployment.md: step-by-step Docker deployment for anyone (setup,
  configuration, LAN/HTTPS/VPN access, adding manga, operation, prebuilt
  images, backups, peering, troubleshooting, rules for agents).
- deploy/circus.sh: host helper without Node (status, up/down with queue
  pause, logs, pause/resume, update, rescan, restore-test); deploy/compose.https.yml
  + Caddyfile for automatic HTTPS.
- README rewritten for public readers (Docker first, sources/copyright note,
  docs index); AGENTS.md + CLAUDE.md for contributors and coding agents.
- Removed notes about one particular installation (Windows host, handoffs,
  audits of a private library, benchmarks with local paths, wishlist, reading
  map) and the unused ops/proxmox templates; generalized remaining mentions of
  hosts, VPN and Windows-only commands.
- Defaults: TZ and reading time zone UTC; .gitattributes keeps shell/YAML LF.
- Personal agent coordination files are git-ignored (CLAUDE.local.md,
  .claude/skills/manga-org/).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 11:09:00 +02:00

7.7 KiB

Collections and relationships

Collections are a presentation layer, not a filesystem migration. Creating, reordering, or removing one never renames manga/chapter folders or changes reading IDs.

Using the UI

Open Settings → Admin → Collections & metadata (or Manage collections on the dashboard). Create a collection, add library manga, choose each member's role and reading order, and save. Choose a member cover, a mosaic of up to four covers, or upload a custom image under 600 KB. Dashboard display can be grouped, expanded, or individual; the choice is remembered per browser. A collection page shows aggregate progress and continues the first unfinished member in the chosen order.

New collection starts an unsaved draft using an ungrouped library manga. Rename it, add members and choose Save collection (or Save all changes). Each manga can belong to one collection. If all manga are grouped, remove a member from another collection first; a collection's final member is retained until you delete the collection. Deletion never removes manga or reading progress.

Save feedback and errors appear above the editor. Controls are locked during a save; failed saves retain drafts. If another admin has changed the catalog, the stale write is rejected. Reload catalog fetches the latest revision, with confirmation before discarding edits; copy any wanted changes first. Unsaved JSON survives collection selection and must use Validate & save JSON, not an ordinary collection save. Metadata imports/research are blocked while drafts exist so they cannot silently replace them. Relationship edits save immediately when there is no collection draft.

Creation works on HTTPS, localhost and ordinary HTTP LAN/VPN addresses. The browser uses secure random bytes when its secure-context-only randomUUID API is unavailable. This does not change networking or the server's revision/validation rules.

Tag combinations match a single member, not tags scattered across unrelated members. Reading-time totals only include the current account's visible Reading Story. Collection publication status is ongoing if any member is ongoing, completed if all are completed, otherwise mixed. Collections do not control scraping or merge editions.

Three distinct concepts

Concept Meaning Owner
Relationship Directed fact: target is a prequel/sequel/adaptation/etc. of source Reader's Catalog Curator
Collection Which library manga share a dashboard tile Admin decision
Reading order Recommended order within that collection Admin decision, independent of chronology

One manga belongs to at most one collection, preventing duplicate dashboard tiles and double-counted progress. Relationships can connect any number of works across groups. Only confirmed relationships appear on reader manga pages. Suggestions, rejections and conflicts remain visible to the admin. Removing a collection leaves its manga, reading history and relationships intact.

Metadata and agent responsibilities

The metadata provider, not the image scraper, supplies relationships. AniList metadata now retains manga relationship edges in manga.json → x-anilist.relations. Existing metadata will not magically gain these fields: use Research relationships for a manga with a verified AniList ID, or import already-cached suggestions. Research uses one public metadata lookup with a 30-day cache, never image-host traffic. Only relationships whose two exact AniList identities already exist in the library become suggestions. This does not auto-enqueue missing manga or guess title matches.

An agent is a catalog researcher/curator assistant. It can read the admin JSON export, research public evidence, identify conflicting claims and propose relationships or membership edits. It should preserve rejected decisions and report uncertainty. It must not turn a shared-universe link into an automatic collection or an unquestioned reading order. No embedded LLM, API credentials, automatic research loop, or autonomous catalog approval is enabled in this release. That optional capability belongs behind this same evidence/review boundary, not inside adapters or the scraper's stall watchdog.

Persistence and API contract

data/catalog.json is reader-owned, version 1, atomically replaced on save. Its revision supports optimistic concurrency; stale writes return 409. Unknown members, duplicate membership, invalid relationships and cover paths are rejected. Existing members absent from a temporary mount are retained rather than erased. Custom covers are content-addressed in data/collection-covers/. Include both in backups.

Authenticated reader APIs:

  • GET /api/collections, GET /api/collection?id=… — account-specific public views.
  • GET /api/admin/catalog — admin export plus available manga, roles and relation types.
  • POST /api/admin/catalog — validated full replacement, with current revision.
  • POST /api/admin/catalog/suggest — import cached edges, with current revision.
  • POST /api/admin/catalog/research — {m: libraryMangaId, revision}; verified metadata lookup.
  • POST /api/admin/collection-cover — {id, revision, base64}; validated image upload.

Example proposal (use real IDs and the latest revision from the export):

{
  "version": 1,
  "revision": 0,
  "collections": [{
    "id": "moon-garden",
    "title": "Moon Garden Universe",
    "description": "Main story, then the prequel.",
    "grouped": true,
    "coverMode": "mosaic",
    "coverMangaId": "Moon Garden",
    "members": [
      {"mangaId": "Moon Garden", "role": "main", "readingOrder": 1},
      {"mangaId": "Before the Rain", "role": "prequel", "readingOrder": 2}
    ]
  }],
  "relations": [{
    "from": "Moon Garden", "to": "Before the Rain", "type": "prequel",
    "state": "suggested", "method": "agent-research", "confidence": 0.8,
    "explanation": "Verify the publisher's chronology before accepting.",
    "evidence": [{"provider": "Publisher", "url": "https://example.com/work", "note": "Chronology"}]
  }]
}

Provider contract: AniList relationship connections.

Repeatable functional acceptance

Run npm test, build docker compose build reader, then:

# Playwright is optional developer tooling; not a deployed application dependency.
# Set NODE_PATH to its installed package root if it is not on normal resolution paths.
node tools/test-compose.js --collections-ui --settings-ui

The runner creates an isolated Compose project on loopback 8180 with three synthetic manga, disposable accounts, paused scraper and disabled discovery. It never mounts the real library, DB or queue. Headless Edge (override QA_BROWSER_CHANNEL if needed) proxies a synthetic http://manga-qa.test:8180 origin to that fixture, reproducing the browser restrictions of a non-localhost HTTP address without using a real tailnet account. Screenshots: data/qa/collections/desktop-editor.png and mobile-editor.png.

Coverage: creation, validation, persistence after reload, member add/remove/role/order, selected/mosaic/custom covers and upload limits, JSON round-trip/draft protection, relationship creation/rejection/duplicates/removal, cached import, missing verified metadata identity, desktop/mobile edits, dashboard grouping and collection reading order, delete/cancel, overlapping saves, transient save failure/retry, concurrent-admin revision conflicts, and ordinary-reader read/write denial. No external manga or metadata research is performed; provider lookup success remains a separate test. The earlier settings test checked collections navigation only; this suite exercises the actual collection workflow and the insecure-origin failure it missed.