- filter rules gain mode ('exclude'|'allow'); nearest allow rule governs a
directory subtree, extensions outside it are filtered before fetch
- filename_extension() now requires a well-formed suffix, so dated names like
'CRA_V3.1手册_2024-07-31_en' no longer fake an extension; extensionless
files are never filtered
- API accepts {mode, extensions}; UI editor becomes grouped format chips with
keep/exclude modes (keep-list default: docs/text/scripts/images)
- migration 000036 + integration tests for allow, nesting and restore
Address two gaps in the first DingTalk-session UI:
- add an explicit admin-only '+ 新增钉钉知识库' action on the data-source
panel; it accepts an alidocs space URL, resolves the live name/root through
the authenticated sidecar, writes the inventory root atomically, upserts a
deterministic source connection, and enqueues its first catalog refresh
- read DingTalk's real QR canvas pixels rather than taking a DOM screenshot;
select by dark-pixel content, composite onto a white quiet zone, and render
at 320x320 so the dialog contains a large complete code, not a page thumbnail
The live refresh path resolves registered roots from the connection locator,
while existing name-based DingTalk sources remain compatible.
DingTalk source scanning depends on a shared browser session whose capture
file had to be replaced by hand whenever it expired (every scan 401s).
- services/dingtalk-login: admin-triggered Playwright sidecar that opens the
space page in a persistent headless Chromium, publishes the QR through
session polling, verifies the first authenticated XHR against the box API,
then writes the capture in place (same inode keeps the worker's ro bind
mount current); tokens never leave the sidecar
- api: POST/GET/DELETE /api/v1/dingtalk-session authenticated relay; QR is a
login artifact, so the whole prefix is admin-only in classifyRole; OpenAPI
contract and proxy/503/hostile-ID tests included
- web: 系统设置 → 数据源配置 钉钉卡片新增扫码刷新会话(仅管理员可见),
QR 弹窗 + 1.5s 轮询 + 成功/过期/失败状态
- compose: sidecar service owns the ONLY rw mount of secrets/; worker keeps ro
Routing targets move from env-only to a UI-managed binding (migration
000034 routing_kb_bindings, single active row):
- GET/PUT /api/v1/routing-bindings + /options: env defaults act as the
bootstrap fallback; a UI binding wins and takes effect immediately
(per-request resolution, no restart), and clearing falls back to env
- PUT validates against the connected WeKnora instance (real knowledge
base list via the scoped API key) and rejects same-KB bindings;
saves require the admin role
- route/catalog capabilities now resolve through the binding so both
annotation paths share one source of truth
- system settings > 服务配置 gains a 知识库绑定 panel: dropdown picker
(or raw ID when WeKnora is unreachable) showing bound name, origin
(UI vs env default) and last author
- contract tests: OpenAPI, handler matrix (fallback, validation,
same-KB rejection, capability resolution), frontend fetch/save layer
validProcessingState predated policy-driven ingestion and rejected
processing_state=planned with a 400, so the 待入库 lane silently fetched
an empty plan list while annotation, fetch and planning had all succeeded.
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