chore: drop asuracomic.net from the userscript, CORS allowlist and docs (#97)

Closes #96.

## What

Removes every reference that still invites a Reader onto `asuracomic.net`.
The domain's deep links 301 to the `asurascans.com` **root**, discarding the
path (re-checked 2026-07-25), so a page on it never yields a series document
client-side and a stored address on it never yields a series page server-side.
#95 already pinned each Site to one hostname, so the backend rejects such an
address cleanly; this is the cleanup around that.

| File | Change |
|---|---|
| `userscript/manga-bookmark.user.js` | drops the `@match`, narrows the asura adapter to `/(^\|\.)asurascans\.com$/` |
| `userscript/test/logic.test.js` | new test pinning the narrowed host match |
| `.env.example`, `docker-compose.yml` | origin dropped from the `ALLOWED_ORIGINS` default |
| `DEPLOY.md` | same, and the sample list gains the two novel origins it was missing |
| `backend/api_test.go` | CORS fixtures and round-trip seed move to `asurascans.com` |
| `README.md`, `AGENTS.md` | notes say the host is dropped, not "stays matched" |

## Behaviour

- A Reader landing on `asuracomic.net` gets no userscript UI. Previously the
  script loaded and could do nothing useful — the redirect had already
  discarded the path.
- A request whose `Origin` is `https://asuracomic.net` is no longer reflected
  by a deployment using the shipped defaults.
- No backend logic changed: the CORS rule, the address gate and the poller are
  untouched. `AllowedOrigins` is data, not code.

## Security invariant preserved

CORS still reflects `Origin` only when it appears in `ALLOWED_ORIGINS`, with
`GET,PUT,DELETE,OPTIONS` and a `204` preflight — `TestCORSPreflight` and
`TestCORSDisallowedOrigin` still pin both halves, now against a live origin.
This change only removes a value from the allowlist, which is a narrowing.

## Verification

- `go test ./...` — full backend suite green (real Postgres per package).
- `node --test test/*.test.js` — 66/66 green, up one from the new match test.

## Deploy note (does not happen on merge)

The live allowlist comes from the VPS `.env`, not from these defaults, so the
origin must be dropped there in the same deploy. The one-off row repair for any
stored `asuracomic.net` address is in #96.

Reviewed-on: #97
Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com>
Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
This commit was merged in pull request #97.
This commit is contained in:
2026-08-12 05:53:17 +07:00
committed by sulthan
parent 21615be2bd
commit c62c3bb07b
13 changed files with 1351 additions and 1992 deletions
-29
View File
@@ -15,10 +15,8 @@
"13": "Web UI Handlers",
"14": "Go Error Handling",
"15": "CDP Browser Client",
"16": "Store",
"17": "Go Code Style Guide",
"18": "Agent Skills",
"19": "Open",
"20": "I/O Performance Patterns",
"21": "CPU Optimization",
"22": "Caching Patterns",
@@ -29,7 +27,6 @@
"27": "Find Skills Guide",
"28": "Allocation Patterns",
"29": "Observability & Alerting",
"30": "PG Test Infrastructure",
"31": "Memory Layout",
"32": "Repo Hard Constraints",
"33": "Go Testing Guide",
@@ -40,8 +37,6 @@
"38": "novel-logic.test.js",
"39": "UI Critique 2026-07-26A",
"40": "UI Critique 2026-07-26B",
"41": "DB Cutover Runbook",
"42": "Memory Layout Patterns",
"43": "Issue Tracker & Triage",
"44": "Ticket Workflow",
"45": "Go Perf Alert Rules",
@@ -124,7 +119,6 @@
"122": "Identity comes from Discord OAuth; we store no passwords and send no email",
"123": "The wire format stays flat and deliberately does not mirror the schema",
"124": "ADR-0005: On-demand browser sidecar",
"125": "Duration",
"126": "Bookmark Manager",
"127": "triage-labels.md",
"128": "Cross-Ticket Contract",
@@ -152,14 +146,6 @@
"150": "Reviewer Subagent (opencode)",
"151": "Finding Severity Rubric",
"152": "Spec Compliance Review",
"153": "CDP Browser Unit (chrome/)",
"154": "Cinder Design System",
"155": "Cloudflare Challenge Behaviour",
"156": "Ember Means New Chapter Only",
"157": "Gitea + tea CLI",
"158": "Graphify Knowledge Graph",
"159": "novel-bookmark.user.js",
"160": "Security Invariants",
"161": "Why Use samber/oops",
"162": "singleflight Cache Stampede Prevention",
"163": "Struct Field Alignment",
@@ -184,15 +170,6 @@
"194": "SQLite-to-Postgres Cutover Runbook",
"195": "Import SQL Generation Rules",
"196": "Throwaway Import Generator",
"197": "ADR-0002 (Discord OAuth Sign-In)",
"198": "ADR-0006 (Browser Out of API Stack)",
"199": "ADR-0007 (Absolute Cover URLs)",
"200": "bookmark-api Service",
"201": "Deployment Runbook",
"202": "Issue #24 (Derived Credentials)",
"203": "Tailscale ACL Tagging",
"204": "TOKEN_KEY Credential Derivation",
"205": "Traefik Reverse Proxy",
"206": "Real scaling limit is the poller outbound fetch budget",
"207": "PostgreSQL (jackc/pgx/v5)",
"208": "SQLite (modernc.org/sqlite)",
@@ -249,12 +226,6 @@
"259": "Dark-First Design Constraint",
"260": "Discord Guild Membership",
"261": "Reader Isolation Invariant",
"262": "Site Adapters",
"263": "Go Backend (backend/)",
"264": "localStorage Cache and Retry Queue",
"265": "Latest Chapter Poller",
"266": "Postgres Store (postgres:17-alpine)",
"267": "README Config and Endpoint Reference",
"268": "Browser Unit Redeploy",
"269": "pg_dump Hot Backup",
"270": "Redeploy Runbook",