DingTalk exports empty online documents to valid but contentless docx/xlsx;
WeKnora then rejects them with a generic remote_parse_failed. Detect blank
exports (no text, no embedded media) at fetch time and report the cause in
Chinese, and add the matching dead-letter hint.
validate_magic read exactly 4096 bytes and strict-decoded them; a multibyte
character straddling the boundary made perfectly valid .md/.txt files fail
with invalid_format. Only tolerate 'unexpected end of data' when the file
actually continues past the sniff window; genuinely corrupt bytes still fail.
This AList deployment (sales.dobotoa.cn family) only recognizes x-api-token on
the /p/ download route; an Authorization header gets 302'd to login.dingtalk.com.
Probe x-api-token first, fall back to Authorization, then fail-closed.
Annotation in 来源与目录 is now the only import decision surface:
- migration 000033: catalog_import_intents (durable, rescan-proof per-file
intent with locator snapshot + fetch lifecycle), source_items.policy_state,
planned publication state, ui_setting_revisions.ingestion_concurrency
- marking fans a folder decision out to per-file intents, materializes
versioned items, reuses already-verified local bytes (compare, don't pull),
and plans one publication per routed KB; blocked retires planned rows
while live publications stay untouched (需下架 shows in the KB diff)
- artifact.fetch worker lane (scripts/artifact_fetch.py): DingTalk export
tree/live box API, AList /api/fs/get direct download with SSO-redirect
fail-closed, PP ledger via locator hash; content-level dedupe on sha256
- 开始处理 promotes planned->pending inside the claim-time concurrency budget
from system settings; claims enforce it in SQL
- monitor overview rebuilt as knowledge-base diff: planned/needs_removal per
KB + fetch pipeline summary; frontend lanes 待入库/需下架 replace the
deprecated snapshot change-set confirmation
- spool: images (png/jpg/gif/bmp/webp) accepted, ppt/pptx rejected in favour
of PDF twins; DingTalk PPT resolves its converted PDF pair