Commit Graph

40 Commits

Author SHA1 Message Date
root 8ea4a2ffff fix(publish): require submit marker before platform write
Desktop Client Build / Resolve Build Metadata (push) Successful in 20s
Frontend CI / Frontend (push) Successful in 2m57s
Desktop Client Build / Build Desktop Client (push) Successful in 25m11s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 34s
Backend CI / Backend (push) Successful in 50m56s
2026-05-30 22:29:28 +08:00
root fa51a3455f fix(publish): prevent stuck publish queue and duplicate posting
Desktop Client Build / Resolve Build Metadata (push) Successful in 41s
Backend CI / Backend (push) Failing after 7m14s
Desktop Client Build / Build Desktop Client (push) Successful in 23m46s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 56s
The desktop publish queue could stall for a long time and end users assumed
the software was broken. Root cause: a hung adapter held its execution slot
with no wall-clock timeout while auto-renewing its lease forever, so the
server never reclaimed it and every queued task behind it stayed 等待发布.
Auto-recovery also risked silently re-posting a non-idempotent article.

Client (Electron):
- per-task wall-clock deadline + abort; progress-gated lease renewal that
  stops and aborts a stalled task instead of renewing it forever
- decouple the concurrency cap from CDP-induced CPU/memory pressure
  (admission gate instead of self-throttling collapse); 15s watchdog pump
- all adapter network I/O now has fetch timeouts and honors context.signal;
  bounded image-upload concurrency with per-image timeout
- surface live adapter progress, elapsed time, queue position and a
  working-vs-queued distinction in the publish view

Server (tenant-api):
- publish lease-recovery worker (every 3m) + supporting index: reclaim
  expired in_progress publish leases, requeue (<3 attempts) or terminal-fail
- 3-minute lease TTL with client-presence-gated extension; max 3 attempts

Idempotency (production-grade core):
- durable publish_submit_started_at marker, set before the irreversible
  platform submit POST; recovery and abort route a maybe-submitted task to
  unknown (manual reconcile, kept in the dedup set) instead of re-posting
- desktop UI requires explicit confirmation before retrying a possibly-
  already-published task

Verified: go build/vet/test (incl. resolvePublishRecoveryOutcome), vue-tsc,
vitest 141/141, gofmt all clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 19:52:17 +08:00
root 5f6e9f11da feat(desktop): add client release updater
Desktop Client Build / Resolve Build Metadata (push) Successful in 19s
Frontend CI / Frontend (push) Successful in 3m20s
Backend CI / Backend (push) Successful in 16m48s
Desktop Client Build / Build Desktop Client (push) Successful in 24m46s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 37s
2026-05-25 19:23:49 +08:00
root 28633cf570 feat(monitoring): fail same-client queued tasks on desktop authorization failure
Desktop Client Build / Resolve Build Metadata (push) Successful in 44s
Backend CI / Backend (push) Successful in 17m5s
Desktop Client Build / Build Desktop Client (push) Successful in 25m13s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 42s
When a desktop monitoring task fails with a non-retryable authorization failure
(login expired, challenge required, risk control), all pending same-client/same-platform
tasks for the same business day are immediately bulk-failed as non-retryable, avoiding
wasted execution attempts. Adds preflight authorization checks before task execution,
enriches failure payloads with disposition metadata (code, category, retryable flags),
and triggers account health reports on auth state degradation.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 23:50:50 +08:00
root 0823e47d46 feat: tighten desktop presence loop and refine admin-web UX
Desktop Client Build / Resolve Build Metadata (push) Successful in 43s
Frontend CI / Frontend (push) Successful in 3m46s
Backend CI / Backend (push) Failing after 7m52s
Desktop Client Build / Build Desktop Client (push) Successful in 27m13s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 59s
- Shrink desktop presence TTL to 30s and heartbeat to 15s so unexpected
  client exits surface within one TTL even if the explicit offline call
  is missed; keep migration default aligned.
- Trust a known presence miss in resolveDesktopClientOnline instead of
  falling back to the recent-heartbeat heuristic, so a still-cached
  LastSeenAt cannot mask an offline client.
- Release the runtime session before clearing renderer desktop sessions
  on shutdown to avoid leaving stale leases behind.
- Auto-refresh the MediaView account list every 5s and revamp card
  layout (inline platform badge, status tags, UID row, meta box).
- Let the brand-question AI wizard accept multiple seed topics via a
  tag-style input; candidates from each topic are merged and deduped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 19:36:24 +08:00
root 94c6b5d5a5 fix(desktop): stop forcing login window on business API 401
Desktop Client Build / Resolve Build Metadata (push) Successful in 29s
Frontend CI / Frontend (push) Successful in 4m48s
Desktop Client Build / Build Desktop Client (push) Successful in 26m5s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 42s
Business calls (heartbeat, account sync, lease/pull/resume tasks,
preempt monitoring lease) used to short-circuit any 401 into
handleAuthExpired, which tore down the runtime and switched the
window to login. That stole the screen on transient or per-request
auth glitches and conflicted with the renderer-side proactive token
renewal.

Now business 401s fall through to the existing warn/danger activity
log paths and runtime keeps running. The login redirect is owned
solely by the renderer's renewAuthenticatedSession → on refresh /
rotate failure → forceLogoutAfterRenewFailure path. Server-side
revocation via error code 40991 is unaffected.

Removed the now-orphan plumbing: handleAuthExpired,
isApiClientError helper, emitRuntimeAuthExpired /
onRuntimeAuthExpired events, and forceLoginWindowForAuthExpired
listener registration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:55:10 +08:00
Xu Liang f38930b0ac feat(desktop): implement client token rotation and session management enhancements
Desktop Client Build / Resolve Build Metadata (push) Successful in 27s
Desktop Client Build / Build Desktop Client (push) Successful in 22m14s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 26s
2026-05-08 11:43:25 +08:00
root df467b63b4 feat(desktop): refresh publish tasks instantly on lease activation
Emit a 'publish-task-lease' runtime invalidation event whenever the
scheduler activates a publish task, and have PublishManagementView
listen for it to trigger an immediate refresh. The view also switches
to a 5s active-task poll only while a task is in_progress, replacing
the unconditional 20s timer.
2026-05-06 21:34:13 +08:00
root 47681ab1f5 feat(desktop): report current user online clients 2026-05-06 18:25:05 +08:00
root f3487bcacf fix(desktop): isolate AI account auth probes 2026-05-06 18:20:10 +08:00
Xu Liang a99d7a4971 refactor(desktop): tighten account dedup, probe scheduling, and session cleanup
- Dedup AI platform accounts by platform ID rather than identity key, preferring higher health rank then newer verified_at
- Clean up session data and health records when duplicate or replaced accounts are removed
- Remove reconcileTrackedAccountRemoteState — no longer optimistically trust remote health state
- Spread initial probes over a random window (5s–3min) to avoid thundering-herd on startup
- Stop scheduling a next probe after an account is marked expired
- Update AI platforms stats strip to show authorized/pending instead of configured/authorized

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 15:38:53 +08:00
root 13464c7788 fix(desktop): normalize API base URL across renderer and main
Replace ad-hoc trim/fallback logic with a shared normalizer that strips
trailing slashes and accidental /api suffixes, rejects non-http schemes,
and rewrites Vite dev origins (517x) back to localhost:8080 so the
desktop client never points its API client at the renderer dev server.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 12:56:47 +08:00
Xu Liang 680adf7b93 fix(desktop): scope account access to owning client and extend identity verification
Backend CI / Backend (push) Successful in 14m18s
Restrict account tracking, probing, and health reporting to accounts owned
by the current client (client_id match). Extend identity-match verification
to bilibili, juejin, and smzdm so session validity is confirmed locally
rather than deferred to remote health state. Server-side account view now
uses stored client_id as authoritative owner instead of presence data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 22:09:10 +08:00
root 162abdc97c chore(frontend): introduce prettier + eslint and prune unused code
Backend CI / Backend (push) Has been cancelled
Frontend CI / Frontend (push) Failing after 1m39s
- Add Prettier 3 with prettier-plugin-organize-imports (sorts/removes unused imports)
- Add ESLint 10 flat config with typescript-eslint + eslint-plugin-vue + eslint-config-prettier
- Add root scripts: format, format:check, lint, lint:fix
- Reformat 257 files across admin-web, ops-web, desktop-client, packages
- Remove unused locals/exports flagged by --noUnusedLocals/--noUnusedParameters
- Fix duplicate localTabLabel key, surrogate-pair regex u-flag, NBSP literal in regex
- Skip server/ (Go) and apps/browser-extension/ (deprecated per ADR)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 20:39:09 +08:00
root c87842347e feat(account-health): reconcile remote bind state and ignore stale runtime reports
Track an authRevision per local record so a fresh bind cancels in-flight
probes, sync server-confirmed health back into the desktop cache via
reconcileTrackedAccountRemoteState, include verified_at in the upsert
signature, and drop runtime health reports older than the stored
verified_at on the server side.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 18:15:39 +08:00
root 426e94dd6b feat(desktop/account-health): mark freshly bound accounts as live
Bind callbacks now stamp the runtime account as health=live with a fresh
verified_at and seed the health record via markTrackedAccountBound, so the
UI doesn't show a just-bound account as 尚未校验 while waiting for the next
probe. Also let force probes bypass the cached-result short-circuit so the
manual 重新校验 button always re-runs the probe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 17:11:50 +08:00
root 59ad14ef2c feat(desktop/account-health): treat active/expiring_soon probes as live and dedupe in-flight checks
Why: avoid showing accounts as not-live during stale-window probes; keep publish gating consistent with runtime view.

- collapse FIRST_PROBE window so initial probe runs immediately
- skip due-probe selection when a probe is already queued/in-flight
- mirror auth-state→health projection on both client report and tenant ingest paths

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 15:58:25 +08:00
root a6b17bae62 fix(monitoring): reject succeeded results missing answers or citation sources
Server callback now rejects succeeded submissions without a non-empty answer,
or whose answer contains [citation:N] markers without any sources. Desktop
adapters mirror this client-side: kimi returns unknown when sources arrive
without a final answer, and yuanbao returns unknown when the answer has
unresolved citation markers. Yuanbao also unwraps redirect URLs, harvests
citations from more DOM attributes and document URL fields, drops links
pointing back at yuanbao itself, and dedupes overlapping streaming
fragments. Runtime controller forwards only an explicit "succeeded" status
as success; anything else becomes failed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 22:07:21 +08:00
root c3feb7477a feat(desktop-client): queue account probes and report health to server
Replace serial probe-on-lock with a bounded probe queue (concurrency 3) that
adds a "queued" probe state, manual cooldown, and retry backoff. After each
probe the runtime debounces a batched POST to the new
/desktop/accounts/health-reports endpoint so the server learns about live,
expired, and risk transitions without waiting for a re-bind. Adds an
account-scoped IPC (probeRuntimeAccount + runtimeAccountSnapshot) so the
renderer can refresh a single row instead of replaying the full snapshot,
and exposes the resulting "重新校验" action in AccountsView/AiPlatformsView.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:33:55 +08:00
root 290da7cd50 feat(publish): add seven publish adapters for new media platforms
Wire sohuhao, wangyihao, juejin, smzdm, weixin-gzh, zol, and dongchedi
into the publish runtime: each ships its own publish protocol and
auth-failure classifier (login/token/challenge codes) plus registry
entries in selectPublishAdapter and the auth adapter map. Smzdm bind
detection now triple-falls-back across page-context fetch, session
fetch, cookie fetch, and a final cookie-derived account so the
nickname-less guest profile still resolves to a stable platform UID.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 00:57:37 +08:00
root 53bebb46be perf(bind): speed up account bind detection and runtime sync
Replace the 1.8s polling interval with a 650ms tick plus a debounced
navigation-driven detect, listen for page-title-updated to catch SPA
transitions, and flush the session asynchronously. The bind handler
now optimistically seeds the runtime account list via
noteRuntimeAccountBound and fires the full server refresh in the
background, so the UI reflects the new binding without waiting on a
round-trip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 21:57:26 +08:00
root 0ce3f51f62 feat(publish): add bilibili and qiehao desktop adapters
Wire bilibili and qiehao (om.qq.com) into the publish adapter registry
and auth-failure classifier. Bilibili bind uses WBI-signed space-info
fallback to retrieve the avatar when nav lacks a face URL, and the
account list image renders with a no-referrer policy so bilibili CDN
serves the avatar cross-origin.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 21:57:04 +08:00
root 87e329207c feat(publish): add baijiahao and jianshu desktop adapters
Wires up Baijiahao (百家号) and Jianshu (简书) as first-class desktop
publish targets, with risk-control prompts surfaced in the runtime
controller and a normalized error message in publish records. Adds
external-link buttons in the publish management table, an asset
format conversion endpoint for cover image compatibility, and
reorders publish-status display priority so failures take precedence
over partial successes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:47:35 +08:00
root 58207f7f03 feat(desktop): add foreground publish admission scheduler
Publish is now treated as the runtime foreground channel and AI
monitoring as background. A new in-memory publish-scheduler owns queue
selection, per-platform active locks, and 3-6s post-completion platform
cooldowns.

The runtime controller tracks lease-in-flight per kind so a monitor
lease no longer blocks a publish lease, derives total concurrency from
hardware class, current process health, and an optional
GEO_DESKTOP_MAX_TOTAL_CONCURRENCY override, and reserves a publish slot
when budgeting monitor capacity. Monitor admission returns zero whenever
publish has backlog or an in-flight lease, so a cooldown-blocked publish
queue still prevents monitor from consuming the foreground reserve.
Runtime diagnostics expose publishScheduler alongside monitorScheduler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:44:08 +08:00
root f6e553dcc3 feat(monitoring): add DeepSeek monitoring end-to-end
- desktop: new DeepSeek page adapter and monitor registry
- desktop: extract generic AI auth helpers into shared module and
  skip binding when challenge signals are present
- admin-web: render DeepSeek HTML answers with inline citation anchors
  and surface reference-number badges on source cards
- server: fall back to inline_links/source_panel_links and read
  text/siteName fields when extracting DeepSeek citations

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 22:54:56 +08:00
root ca40657c5a feat(desktop): add Wenxin monitoring adapter and surface platform risk control
Introduces the Wenxin (文心一言) monitoring adapter and registers it in
the runtime controller and adapter index. Adds a new risk_control
failure classification with custom classifiers for Doubao and Wenxin
that recognize rate-limit, 频控 and 访问环境异常 signals, and propagates
this state through account-health, runtime activity alerts, and the
renderer views so users see "触发风控" instead of a generic challenge
message on the Home, Accounts, and AI Platforms screens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 15:26:24 +08:00
root ce028c56bf feat(desktop): auto-recover in-progress desktop tasks on client lifecycle events
- reset stale in_progress tasks owned by a client on startup, offline, and lease expiry
- monitor tasks re-queue for another pick; publish tasks move to unknown for manual reconcile
- send startup=true flag on first heartbeat so the server can trigger recovery
- finalize the linked desktop task when a phase2 monitor callback arrives via desktop_tasks path
- short-circuit the desktop monitor attempt write after the callback already finalized it

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 09:11:23 +08:00
root f91d2645d3 feat(desktop): add Kimi and Yuanbao monitoring adapters
- implement kimi/yuanbao monitor adapters with dedicated citation panel detection
- detect Kimi session via kimi-auth cookie during account binding
- harden hidden Playwright and bound windows with skipTaskbar/focusable/hiddenInMissionControl to stop stealing focus
- tag hidden bootstrap windows with a unique token so CDP retention resolves the correct page
- enable yuanbao/kimi/wenxin platforms in dev-seed and default monitoring quota
- update kimi loginUrl to www.kimi.com

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 09:09:20 +08:00
root 4142c53fa6 feat(monitoring): dispatch monitoring tasks to desktop via AMQP outbox
Replace SSE /desktop/events with priority AMQP dispatch for monitoring
runs, and add phase1/phase2 infrastructure so desktop workers can lease,
resume, report, skip, and cancel monitoring tasks over the existing
dispatch WebSocket.

- Add monitoring collect outbox worker and phase2 desktop task fields
- Add /desktop/monitoring/tasks/{lease,resume,result,skip,cancel} routes
- Introduce execution-devtools and network-observer on desktop runtime
- Refactor runtime-controller, LoginView, and doubao adapter for the new flow
- Add channelName column to tracking views

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 00:24:21 +08:00
root 9fa091c150 feat(desktop): push publish tasks via AMQP topic dispatch WebSocket
Introduce a desktop.task.dispatch topic exchange with per-client routing
keys. Tenant-api publishes a task_available frame keyed by target client
ID when a publish job is created; every instance binds its own transient
queue and forwards to the matching WebSocket (/api/desktop/dispatch) it
owns. Desktop-client now prefers this push channel and only falls back
to HTTP /lease polling when the socket is down. Also drop admin-web
monitoring-plugin remnants and scope the publish modal account list to
publish platforms.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 19:46:59 +08:00
root 7abac1e9c4 feat: Implement Qwen adapter and enhance AI platform detection
- Added a new Qwen adapter to facilitate monitoring through Playwright, leveraging internal text/chat managers.
- Updated account detection logic to recognize Qwen sessions based on persisted cookies, improving binding reliability.
- Relaxed authentication requirements for monitor tasks, allowing anonymous execution for certain AI platforms.
- Enhanced the generic AI platform detection to include Qwen-specific logic, ensuring accurate session identification.
- Modified the monitoring dashboard to include runtime state indicating if the current user's desktop client is online.
- Updated various files including `account-binder.ts`, `runtime-controller.ts`, and `monitoring_service.go` to support new features and improvements.
2026-04-20 19:10:35 +08:00
root 55e1c2e74b feat(desktop): add monitor scheduler, Playwright CDP layer, and account health
Move monitor-task scheduling authority onto the client with a durable
file-backed queue that survives restart, drops stale cross-day tasks,
enforces per-platform serialism, and adapts global concurrency from
Electron process metrics. Publish tasks keep their existing FIFO.

Add a hidden Playwright CDP manager that attaches to Electron Chromium
on account session partitions, lets adapters opt into `executionMode:
"playwright"`, and leaves the existing hidden WebContentsView path in
place for current adapters.

Introduce an account-health subsystem with silent probes, projected
health/auth states, and IPC invalidation events so the renderer can
show accurate auth/probe status and verification timestamps.

Server-side, derive and forward title/business_date/scheduler_group_key/
question_text metadata on desktop task events so the local scheduler
can defer same-question fan-out before leasing.
2026-04-20 17:16:15 +08:00
root 09295d11a1 feat(monitoring): decouple AI platforms from media_platforms and expand catalog to 6
Add ai_platforms table + shared catalog (yuanbao/kimi/wenxin/deepseek/doubao/qwen),
drop FKs from platform_accounts and desktop_tasks to media_platforms, and wire
target_account_id + platform into DesktopTaskEvent so the desktop runtime no
longer has to infer them from local state. Desktop client gains generic AI page
detection for binding, drops stale-business-date monitor tasks at the edge, and
refactors AccountsView/AiPlatformsView around the shared catalog. Admin tracking
view surfaces per-platform sampling status cards.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 15:40:18 +08:00
root 25dad49ed3 i18n(desktop): localize runtime activity titles and details to Chinese
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 14:17:56 +08:00
root 9bfe0fab48 fix(desktop): report real hostname/platform/arch in heartbeat
Renderer was registering clients with navigator.platform ("MacIntel") and
a hardcoded "renderer-preview" cpu_arch. Source device info from the main
process (os.hostname + process.platform/arch) via a new device-info IPC,
and let heartbeats always send the authoritative runtime values so stale
registrations self-heal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 11:59:35 +08:00
root 4d0c4510ef feat(desktop): add zhihu publish adapter
Ship a Zhihu publish adapter that reuses the shared session fetch and
image pipeline: converts markdown to HTML via marked, uploads cover
and inline images through Zhihu's image token flow, creates a draft,
and publishes it, returning external article URLs. Wire it into the
adapter barrel and runtime-controller's publish adapter selector so
Zhihu publish tasks stop falling through to the scaffold result.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 11:45:08 +08:00
root dc68ad044c refactor(publish): collapse pending_review/unknown task states into failed
Treat ambiguous terminal states as failures end-to-end: server
normalizes unknown desktop task completions and views to failed, drops
the pending_review aggregate branch, and remaps pending_review to
failed in publish record conversion. admin-web removes the
pending_review status option from article list filters, pushes
pending_review through the failed tone, and folds lingering
publishing/pending entries under the publishing bucket. desktop-client
relabels unknown as 发送失败 in PublishManagement/TasksView, rewrites
the scaffold adapter result to a proper failed error envelope, and
sanitises legacy scaffold-only error messages to a user-friendly note.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 11:44:47 +08:00
root ef868f81a1 feat(desktop): add hot view retain/release lifecycle and process metrics
Replace single-shot acquireHotView with retainHotView/releaseHotView
plus a minute-level reaper that closes views idle beyond 5 minutes and
never evicts a view while it still has live retainers. Wrap adapter
calls in try/finally so a failing publish/query still releases the
view. Sample process metrics every minute and expose hot-view policy
and process snapshot via the runtime snapshot for diagnostics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 11:07:58 +08:00
root a617d39a4a feat(desktop): drop parked review flow, add publish management
SaaS 侧人工审核后才创建 publish job,desktop 不再做二次审核:移除
manual/waiting_user/parked/from_parked 状态机与 LeaseFromParked 查询,
desktop client 只执行发布并新增"发布管理"页(待发布队列 / 历史 / 再次
发送)。同时抽离 @geo/publisher-platforms 共享适配器包、新增 Redis-based
desktop_presence 与 publish_record_support,刷新 admin-web 发布弹窗与
媒体库;plan A / spec 文档同步口径。
2026-04-20 09:52:48 +08:00
root b16e9f0bd1 feat(desktop): implement workspace foundation + desktop-client skeleton
Plan 0 (workspaces): add workspaces + workspace_memberships schema, extend
JWT/Actor/claims with primary_workspace_id, seed default workspace per tenant,
thread workspace_id through tenant monitoring quota.

Plan A (desktop skeleton): new Electron app (apps/desktop-client) with main/
preload/renderer, shared Vue component package (packages/ui-shared), and server
surface — desktop client registration + token rotation + heartbeat, SSE task
event stream, desktop accounts/tasks/content handlers, publish job endpoint,
and supporting repositories, services, sqlc queries, and migrations.

Hard cutover per plan: remove browser-extension monitoring callback endpoints,
stub legacy media API in admin-web, and delete monitoring_callback_handler.go.
2026-04-19 14:18:20 +08:00