- The attention lane was derived from page 1 of the queue (limit 50, newest
by updated_at), so failures ranked past 50 silently disappeared from
"needs attention" as the completed backlog grew.
- Fetch attention items with a dedicated request: the API now accepts a
comma-separated processing_state list (failed,stalled) and the view prefers
that result set over the paged queue.
- Batch retry/cancel targets are computed from the same failure set instead of
the visible page, so actions reach every failing item.
- 全部任务 shows 已显示 N / 共 M plus 加载更多 so rows past 50 are reachable.
- Fix pre-existing ui_settings integration test: strict JSON decoding rejects
the legacy updated_by field (actor comes from the session).
- Tests: view regression (attention item outside the page, load-more
affordance) + handler multi-state filter + isolated-DB set filter.
- Parse-monitor: the batch-retry button rendered red-on-red because
weknoraMonitor.css overrode the global .danger style with text color
only; make .danger a filled red button with proper hover/disabled states.
- Add operator cancel: 批量取消所选 / per-task 不再处理 buttons move
failed/stalled publications to a new 'cancelled' state in one audited
batch operation (POST /api/v1/test-publications/cancel-batch, idempotent,
migration 000041 widens the CHECK constraints). Queued upload jobs are
cancelled, open dead letters abandoned; source records and spool files
stay intact so re-marking in the catalog can retry later.
- Queue status filter and labels learn 已取消; OpenAPI contract updated.
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