fix: index CW:28 body, validate API contracts, repair broken data pointer
opencode
fe038ce
- Convert CW/1/革命时期的爱情.txt from GB18030 to UTF-8 (203,548 -> 304,547
bytes, 102,538 characters, zero replacement characters, exact round-trip) and
drop its LFS attribute so the text ships as ordinary content.
- build_fulltext_db.py now decodes source TXT with the same strict UTF-8 then
strict GB18030 fallback as app.py. It previously used lenient UTF-8, so CW:28
was indexed as mojibake and its body could not be searched.
- /api/random accepts the canonical plural sources filter and returns 404 for an
unknown source instead of silently returning an unrelated record.
- /api/folders and /api/folders/.../contents return a JSON 404 for an unknown
source, matching /api/search/{source}.
- Unknown /api/* paths return a JSON 404 instead of the SPA HTML with HTTP 200.
- data/sources.json.gz: the LFS object has been absent from the Hub since the
first upload, so the file is rebuilt from the verified source contract in
data/sidebar/global.json and data/search_data.json.gz, and it i…