# Findings & Decisions ## Requirements - Verify the repository against the 9-step implementation plan provided by the user. - Use `/Users/liangxu/Documents/test/geo-rankly/docs/superpowers/specs/2026-03-31-admin-web-backend-core-design.md` as the source of truth for the next development slice. - Continue development immediately after identifying the earliest unfinished step. - For desktop AI monitoring, put scheduling authority on the client, keep scraping silent/background-only, allow stale cross-day tasks to be dropped, and avoid fanning one question to all models at once. ## Research Findings - Current 2026-05-07 publish-management request targets `apps/admin-web`: the user wants a new content-management page showing publish title, account/platform, status, task info, time, and actions for external link, opening the desktop client workbench, and retrying. - Desktop client already has `PublishManagementView.vue` with the desired table shape and action semantics, but it calls Electron IPC (`window.desktopBridge`). Admin-web needs tenant-authenticated HTTP endpoints instead. - Existing backend desktop endpoints are `/api/desktop/publish-tasks` and `/api/desktop/publish-tasks/:id/retry`, but they require desktop client token auth. Tenant API currently exposes publish-job creation only, not publish task list/retry. - `DesktopTaskService.ListPublishTasks` already has the correct pagination/title-search/status ordering behavior, but accepts a desktop client context. A tenant variant should scope by request actor/current workspace and created-by user. - `PublishJobService.RetryByDesktopTask` already contains retry reconstruction logic, but accepts desktop client context. A tenant variant can reuse the same core flow with actor workspace/user ownership checks. - Admin-web content-management nav currently includes media, knowledge, and images under `AppShell.vue`; publish management should join that group as `/publish-management`. - Web "open workbench" cannot call Electron IPC directly. A desktop deep-link URL can be used as a link-style entry; if the desktop app does not register that scheme yet, the link is still a front-end contract for the desktop client to adopt. - Current review scope: determine whether the monitoring data detail path and the daily scheduled generation of question collection tasks are working. - `cmd/scheduler` starts `ScheduleDispatchWorker`, monitoring result recovery, lease recovery, received inspection, and knowledge cleanup; it does not start a worker that generates daily `monitoring_collect_tasks`. - The only production code path found so far that inserts `monitoring_collect_tasks` is `MonitoringService.CollectNow` via `ensureCollectNowTasks`; this writes `trigger_source = 'manual'`. - Current local Monitoring PG data confirms recent task creation is manual: on 2026-04-24 there are 3 desktop/manual/plugin_standard tasks; on 2026-04-23 there are 6 desktop/manual/plugin_standard tasks. The latest `automatic` monitoring collect tasks in this local DB are from 2026-04-17, not today. - Current local business PG has `tenant_monitoring_quotas.collect_frequency = 'daily'` and `task_daily_hard_cap = 36`, but those fields are configuration only in the code paths inspected so far; no scheduler reads them to generate today's monitoring tasks. - The repository already contains core backend scaffolding under `server/`, including `cmd/tenant-api`, `internal/bootstrap`, `shared`, `tenant`, `migrations`, and SQL query files. - `server/Makefile` already defines `dev-init`, `dev-api`, `migrate-up`, `sqlc-generate`, `seed`, `lint`, and `test`. - The bootstrap layer already exposes `/api/health/live` and `/api/health/ready`. - The design doc defines a sequential 9-step delivery plan and expects `sqlc` generated code under `internal/tenant/repository/generated/`, plus repository wrappers around it. - The repository has 19 migration `.up.sql` files, matching the plan's schema count, and `cmd/dev-seed` seeds `admin@geo.local` plus plan/quota/template data. - `internal/tenant/repository/` currently contains only query SQL, `sqlc.yaml`, `tx.go`, and placeholder integration tests; there is no `generated/` directory and no repository wrapper implementations. - `auth_service.go`, `workspace_service.go`, `template_service.go`, `article_service.go`, and `brand_service.go` still issue SQL directly against `pgxpool.Pool`, which contradicts the design doc's Step 4 target. - Running `make sqlc-generate` currently fails because `server/internal/tenant/repository/sqlc.yaml` sets `schema: "../../migrations/"`, which resolves to a non-existent path. The correct repository-relative path should point to `server/migrations`. - After fixing `sqlc.yaml`, `make sqlc-generate` succeeds and produces typed code in `server/internal/tenant/repository/generated/`. - Repository wrappers now exist for auth, workspace, template, article, quota, and audit queries, and the auth/workspace/template services consume them on the main code path. - Refresh token rotation is now atomic in Redis via a Lua script in `session_store.go`, with tests covering successful rotation and hash mismatch rejection. - `make test` and `make lint` both pass locally after cleaning up existing lint violations. - A GitHub Actions workflow now exists at `.github/workflows/backend-ci.yml`; it runs `sqlc` generation, verifies generated code is committed, executes the tenant SQL scope guard, runs tests, and runs `golangci-lint`. - The `server/Makefile` now exposes `tenant-scope-guard`, so the tenant filter check is available both locally and in CI. - The `server/Makefile` no longer depends on a preinstalled `migrate` binary; it now runs `golang-migrate` via `go run -tags postgres`, which allowed `make dev-init` to run successfully on this machine. - `make dev-init` now completes end-to-end: Docker services start, all 19 migrations apply, and seed data creates tenant/user/plan/template records. - Runtime verification succeeded for `/api/health/live`, `/api/health/ready`, `POST /api/auth/login`, `GET /api/auth/me`, `POST /api/auth/refresh`, and `POST /api/auth/logout`. - Negative auth checks also passed at runtime: the old access token returns `40103 token_revoked` after logout, and the old refresh token returns `40121 refresh_session_expired` after rotation. - Workspace runtime verification passed for all four first-screen endpoints: `overview`, `recent-articles`, `quota-summary`, and `template-cards`. - Template generation runtime verification passed end-to-end: creating a generation task produced an article, article detail returned `generate_status=completed`, article versions returned one version, and quota balance decreased from 100 to 99. - Brand runtime verification passed for create keyword/question/competitor flows, question version history returned two versions after update, and soft-deleted brands can be recreated with the same name. - The repository still has no `apps/` or `packages/` directories, so neither `admin-web` nor `ops-admin-web` has been started. - The frontend architecture doc recommends `pnpm workspace + Vue 3 + TypeScript + ant-design-vue + Vite`, with shared packages for UI, shared DTOs, HTTP client, and TS config. - The current backend already exposes enough stable endpoints for a first `admin-web` slice: `POST /api/auth/login`, `GET /api/auth/me`, and the four workspace endpoints under `/api/tenant/workspace/*`. - Backend responses use a consistent envelope: `code`, `message`, `data`, and `request_id`, which makes a shared frontend API client straightforward. - Local toolchain support for the frontend is present on this machine: `node v22.20.0`, `npm 10.9.3`, and `pnpm 10.28.2`. - A new pnpm workspace now exists at the repo root, with `apps/admin-web` plus shared packages under `packages/shared-types`, `packages/http-client`, and `packages/tsconfig`. - `apps/admin-web` is now a working Vue 3 + TypeScript + Vite 8 app with Ant Design Vue, Pinia, Vue Router, and Vue Query wired in. - The frontend implements a persistent auth session store, login flow, route guard, auto-refresh-capable API client, and a tenant-facing application shell. - The workspace page is wired to live backend data through the four dashboard endpoints and renders template cards, stats, quota, and recent articles. - Placeholder routes now exist for template creation, custom generation, optimization, media, brands, tracking, and knowledge so the navigation shell is ready for incremental page delivery. - `pnpm build:admin` passes successfully, producing a production build under `apps/admin-web/dist/`. - Static preview verification passed via `vite preview` and HTTP checks against `http://127.0.0.1:4173/login`, which returned `HTTP/1.1 200 OK` plus the built asset references. - Gemini CLI was tested but then abandoned for this turn: `gemini-3.1-pro-preview` consistently returned `429 MODEL_CAPACITY_EXHAUSTED`, and the user explicitly requested not to use Gemini afterward. - After the user indicated Playwright was fixed, browser-level verification succeeded through the Playwright CLI path rather than the broken MCP path. - Browser testing exposed one real frontend bug: the login CTA rendered correctly but did not submit the form on click until it was explicitly bound to `handleSubmit`. - After the login-button fix, a Playwright end-to-end flow successfully loaded `/login`, signed in with the seeded account, reached `/workspace`, and verified the presence of the workspace heading plus the template and recent-content sections. - The production bundle size improved substantially after switching Ant Design Vue registration from full-plugin mode to per-component registration; the main JS chunk dropped from roughly `1.4 MB` to about `747 kB` before gzip. - The currently exposed tenant-facing backend interfaces fall into four frontend-covered groups: auth, workspace, templates/articles, and brands. - The reference screenshots were re-read using position-aware OCR extraction, which made the layout intent clear beyond the raw text labels. - `docs/refer/工作台.png` places the main content in a left-heavy column with template cards above recent articles, while the right side holds the compact stats cluster; the quota/plan card sits in the left sidebar footer rather than the main canvas. - `docs/refer/模板创作.png` uses a top page hero, a horizontal filter/action strip, an article table below it, and a separate template-selection layer before entering a 3-step generation flow. - `docs/refer/文擎GEO/模版创作-新建模版-创建topx文章-步骤一.png` and `...步骤二.png` show the generation flow as a wizard: step 1 basic info plus brand/keyword/competitor context, step 2 title and structure selection, step 3 generation. - `docs/refer/品牌词库.png` uses a top brand card rail, then a split content area with keyword navigation on the left and question management on the right; the competitor library lives under a sibling tab. - `docs/refer/媒体管理.png` confirms the overall visual system: page hero under the content header, three-step guide card near the top, and white cards on a cool gray background with the same left navigation shell. - The user explicitly asked for i18n and styling discipline during implementation: text should move behind translation keys, and component styles should live in `