kt-template-online-api/docs/superpowers/plans/2026-06-15-api-admin-full-refactor-v3.md

1589 lines
71 KiB
Markdown

# API/Admin Full Refactor V3 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Complete the third-phase API/Admin full-module refactor from the approved design: rebuild schema, migrate all API modules, rebuild the QQBot plugin platform, finish NapCat device/login flow, sync Admin, and close locally before one unified push and online smoke.
**Architecture:** Execute as a batch-gated migration. API owns schema, domain contracts, runtime state, plugin execution, and deployment smoke; Admin follows API contracts in the same batch or the next immediate task. Each batch starts with RED checks, ends with local verification, KT review, Superpowers review, and separate API/Admin commits.
**Tech Stack:** NestJS 11, TypeORM 0.3, MySQL, pnpm 9 API workspace, Vben Admin 5 / Vue 3 / TSX / Ant Design Vue, pnpm 10 Admin workspace, Jest, Playwright, ktWorkflow MCP, Jenkins/K8s/NapCat runtime.
---
## Scope Check
The approved spec spans several independent subsystems: database rebuild, API module migration, Admin contract sync, plugin runtime, existing plugin rewrite, NapCat runtime, and online release. Keep one master plan so the third-phase goal stays intact, but execute it as batch-gated work. Do not merge two batches into one commit window.
Every batch must leave the product in a locally verifiable state. Batch 8 is the only push/deploy batch.
## Current State Evidence
- API repo: `D:\MyFiles\KT\Node\kt-template-online-api`, implementation branch `dev-api-full-refactor-v3`, package manager `pnpm@9.15.9`, no `.node-version`, no `engines`.
- Admin repo: `D:\MyFiles\KT\Vue\kt-template-admin`, implementation branch `dev-admin-full-refactor-v3`, package manager `pnpm@10.28.2`, `.node-version=22.22.0`, `engines.node >=20.19.0`, `engines.pnpm >=10.0.0`.
- Admin repo has three old dirty files authorized by the user to discard during implementation preparation:
- `README.md`
- `apps/web-antdv-next/src/api/qqbot/index.ts`
- `apps/web-antdv-next/src/views/qqbot/account/list.tsx`
- API existing top-level source roots: `src/admin`, `src/blog`, `src/common`, `src/middleware`, `src/minio`, `src/qqbot`, `src/runtime`, `src/wordpress`.
- API existing SQL roots: `sql/vben-admin-init.sql`, `sql/blog-init.sql`, `sql/blog-menu.sql`, `sql/qqbot-init.sql`, plus migration/fix scripts.
- Admin existing app root: `apps/web-antdv-next/src`, with `api`, `views`, `router`, `components`, `store`, `locales`.
## Execution Rules
- Use `apply_patch` for manual file edits.
- Do not push before Batch 8.
- Do not run destructive DB commands until Batch 8 and user confirms the action window.
- Do not treat Jenkins/K8s success as functional success.
- For API interface changes, run a real local request or a bounded smoke script.
- For Admin page changes, run a route/page smoke with browser evidence.
- If a local Node/Vite service is started, clean the process before ending the work turn.
- If a recurring blocker appears twice, record the stable solution before a third raw attempt.
## File Structure Map
### API Files To Create
| Path | Responsibility |
| ----------------------------------------------- | ---------------------------------------------------------------------------------- |
| `docs/refactor-v3/schema-map.md` | Batch 0 full schema ownership map. |
| `docs/refactor-v3/api-admin-contract-matrix.md` | API route, DTO, SSE, and Admin caller/page matrix. |
| `docs/refactor-v3/breaking-changes.md` | Approved route, DTO, schema, seed, and Admin contract breaks. |
| `docs/refactor-v3/rebuild-runbook.md` | Local dry run, online backup, schema rebuild, smoke, and rollback runbook. |
| `sql/refactor-v3/00-full-schema.sql` | Full new schema, no historical patch accumulation. |
| `sql/refactor-v3/01-seed-core.sql` | Initial seed for Admin, menus, platform settings, QQBot core, and plugin metadata. |
| `sql/refactor-v3/99-verify.sql` | SQL checks that prove required tables, seed rows, and indexes exist. |
| `scripts/refactor-v3/db-dry-run.ps1` | Local empty DB rebuild smoke wrapper. |
| `scripts/refactor-v3/db-backup-online.ps1` | Online backup command wrapper without secrets. |
| `scripts/refactor-v3/db-restore-online.ps1` | Online rollback wrapper without secrets. |
| `scripts/refactor-v3/local-smoke.ps1` | Bounded local smoke entry for API contract checks. |
| `src/modules/admin/**` | New Admin/Auth/Platform Config module. |
| `src/modules/blog/**` | New Blog content module. |
| `src/modules/wordpress/**` | New WordPress mirror/sync module. |
| `src/modules/asset/**` | New Asset/MinIO ownership module. |
| `src/modules/qqbot/core/**` | New QQBot account, command, message, permission, send queue core. |
| `src/modules/qqbot/plugin-platform/**` | Manifest, registry, CLI, worker runtime, RPC, installation lifecycle. |
| `src/modules/qqbot/plugins/**` | Rewritten BangDream, FF14 Market, FFLogs, Repeater plugin packages. |
| `src/modules/qqbot/napcat/**` | NapCat container, device identity, login session, challenge, cleanup runtime. |
| `test/refactor-v3/**` | Cross-batch schema, contract, smoke, and release guard tests. |
| `test/modules/**` | New module-scoped tests matching `src/modules/**`. |
### API Files To Modify
| Path | Responsibility |
| ------------------- | ----------------------------------------------------------------------------------------- |
| `src/app.module.ts` | Replace legacy module imports with new `src/modules/**` modules when each batch is ready. |
| `src/runtime/**` | Keep `/health/runtime` stable, add runtime clients/adapters needed by modules. |
| `src/common/**` | Keep only shared response, error, time, Snowflake, logger, decorator helpers. |
| `src/admin/**` | Legacy module removed after Batch 2 compatibility tests pass. |
| `src/blog/**` | Legacy module removed after Batch 3 compatibility tests pass. |
| `src/wordpress/**` | Legacy module removed after Batch 3 compatibility tests pass. |
| `src/minio/**` | Replaced by `src/modules/asset/**` after Batch 3. |
| `src/qqbot/**` | Legacy core/plugin/NapCat modules removed after Batches 4-7. |
| `API.md` | API contract changes and breaking changes summary. |
| `README.md` | Refactor/development command entry updates. |
### Admin Files To Create Or Modify
| Path | Responsibility |
| --------------------------------------------------------- | ------------------------------------------------------------------------ |
| `apps/web-antdv-next/src/api/system/*.ts` | Sync Admin/Auth/Platform Config API contracts. |
| `apps/web-antdv-next/src/api/blog/*.ts` | Sync Blog/WordPress/Asset API contracts. |
| `apps/web-antdv-next/src/api/qqbot/index.ts` | Replace old QQBot API types and callers. |
| `apps/web-antdv-next/src/api/qqbot/plugin.ts` | Plugin platform API caller. |
| `apps/web-antdv-next/src/api/qqbot/napcat.ts` | NapCat login/device/SSE caller. |
| `apps/web-antdv-next/src/views/system/**` | Identity, menu, role, dept, dict, setting, notice pages. |
| `apps/web-antdv-next/src/views/blog/**` | Blog, WordPress, Asset management pages. |
| `apps/web-antdv-next/src/views/qqbot/**` | QQBot account, command, rule, message, send queue, plugin, NapCat pages. |
| `apps/web-antdv-next/src/router/routes/modules/system.ts` | Menu route sync if frontend routes change. |
| `apps/web-antdv-next/src/router/routes/modules/blog.ts` | Blog route sync. |
| `apps/web-antdv-next/src/router/routes/modules/qqbot.ts` | QQBot/plugin/NapCat route sync. |
| `apps/web-antdv-next/src/locales/langs/zh-CN/system.json` | Visible Chinese labels for new states and pages. |
## Batch 0: Workspace And Migration Preparation
### Task 0.1: Prepare API branch
**Files:**
- No file edits in this task.
- [x] **Step 1: Verify API worktree is clean**
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api status --short --branch
```
Expected:
```text
## main...origin/main [ahead 3]
```
- [x] **Step 2: Create API implementation branch**
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api switch -c dev-api-full-refactor-v3
```
Expected:
```text
Switched to a new branch 'dev-api-full-refactor-v3'
```
- [x] **Step 3: Confirm branch**
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api branch --show-current
```
Expected:
```text
dev-api-full-refactor-v3
```
Actual note: `dev/api-full-refactor-v3` could not be created because the API repository already has a local `dev` branch, so Git cannot create a nested ref under `refs/heads/dev`. The implementation branch is `dev-api-full-refactor-v3` to preserve the existing `dev` branch.
### Task 0.2: Clean authorized Admin old artifacts and prepare branch
**Files:**
- Restore only:
- `D:\MyFiles\KT\Vue\kt-template-admin\README.md`
- `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\qqbot\index.ts`
- `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\account\list.tsx`
- [x] **Step 1: Verify Admin dirty set is exactly authorized**
Run:
```powershell
git -C D:\MyFiles\KT\Vue\kt-template-admin status --short
```
Expected:
```text
M README.md
M apps/web-antdv-next/src/api/qqbot/index.ts
M apps/web-antdv-next/src/views/qqbot/account/list.tsx
```
- [x] **Step 2: Stop if any extra path appears**
If the output contains another path, stop and ask the user before cleanup.
- [x] **Step 3: Restore authorized old files**
Run:
```powershell
git -C D:\MyFiles\KT\Vue\kt-template-admin restore -- README.md apps/web-antdv-next/src/api/qqbot/index.ts apps/web-antdv-next/src/views/qqbot/account/list.tsx
```
Expected: command exits `0`.
- [x] **Step 4: Confirm Admin worktree is clean**
Run:
```powershell
git -C D:\MyFiles\KT\Vue\kt-template-admin status --short --branch
```
Expected:
```text
## main...origin/main
```
- [x] **Step 5: Create Admin implementation branch**
Run:
```powershell
git -C D:\MyFiles\KT\Vue\kt-template-admin switch -c dev-admin-full-refactor-v3
```
Expected:
```text
Switched to a new branch 'dev-admin-full-refactor-v3'
```
### Task 0.3: Create migration control documents
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\schema-map.md`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\api-admin-contract-matrix.md`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\breaking-changes.md`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\rebuild-runbook.md`
- [x] **Step 1: Add `schema-map.md`**
Use this content:
```markdown
# Refactor V3 Schema Map
## Global Rules
- Primary keys are Snowflake `BIGINT`; API/Admin boundary treats IDs as strings.
- Table names use lower snake case.
- Queryable values are structured columns, not JSON-only fields.
- Event/log tables are append-only and have retention strategy.
- New schema is full initialization SQL, not historical `ALTER TABLE` patches.
## Domains
| Domain | Tables | Owner Batch | Notes |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------------------------------------------------------------- |
| Admin Identity | `admin_user`, `admin_role`, `admin_permission`, `admin_menu`, `admin_department`, `admin_user_role`, `admin_role_permission`, `admin_role_menu` | Batch 2 | Login, menu, role, permission, department. |
| Platform Config | `platform_dict_group`, `platform_dict_item`, `platform_component_template`, `platform_setting` | Batch 2 | Dict and component template split from legacy Admin misc. |
| Blog Content | `blog_post`, `blog_taxonomy`, `blog_term`, `blog_post_term`, `blog_theme_profile`, `blog_import_job` | Batch 3 | Categories and tags use relation table. |
| WordPress Mirror | `wordpress_site`, `wordpress_auth_session`, `wordpress_remote_post`, `wordpress_remote_term`, `wordpress_sync_job`, `wordpress_sync_mapping` | Batch 3 | Remote state separate from local Blog content. |
| Asset | `asset_bucket`, `asset_object`, `asset_reference`, `asset_access_grant` | Batch 3 | MinIO object ownership and access grant. |
| System Event | `system_notice`, `system_event`, `system_event_dedupe`, `system_event_delivery` | Batch 2 | MySQL stores actionable events; Loki remains log query source. |
| Runtime Evidence | `runtime_evidence_index` | Batch 1 | Safe index only, no large logs or secrets. |
| QQBot Core | `qqbot_account`, `qqbot_connection_session`, `qqbot_capability_binding`, `qqbot_permission_policy`, `qqbot_command`, `qqbot_command_alias`, `qqbot_rule`, `qqbot_conversation`, `qqbot_message`, `qqbot_send_task`, `qqbot_send_log`, `qqbot_dedupe_event` | Batch 4 | Account, connection, permission, command, message, send queue. |
| NapCat Runtime | `napcat_container`, `napcat_device_identity`, `napcat_account_binding`, `napcat_login_session`, `napcat_login_challenge`, `napcat_runtime_cleanup` | Batch 7 | Device identity and login challenge state. |
| QQBot Plugin Platform | `qqbot_plugin`, `qqbot_plugin_version`, `qqbot_plugin_installation`, `qqbot_plugin_operation`, `qqbot_plugin_event_handler`, `qqbot_plugin_account_binding`, `qqbot_plugin_config`, `qqbot_plugin_asset`, `qqbot_plugin_runtime_event` | Batch 5 | Manifest, install lifecycle, runtime health, bindings. |
| Plugin-Owned Data | plugin namespace tables | Batch 6 | Table names start with registered plugin namespace. |
```
- [x] **Step 2: Add `api-admin-contract-matrix.md`**
Use this content:
```markdown
# API/Admin Contract Matrix
| Batch | API Contract | Admin Surface | Smoke Evidence |
| ----- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------- |
| 1 | `GET /health/runtime` plain JSON, runtime adapter internals | Runtime status remains available | `curl http://localhost:<port>/health/runtime` |
| 2 | `/auth/*`, `/admin/user/*`, `/admin/menu/*`, `/admin/role/*`, `/admin/dept/*`, `/admin/dict/*`, `/admin/notice/*` | Login, menu, system pages | Login request, menu load, route render |
| 3 | `/blog/*`, `/wordpress/*`, `/asset/*` | Blog, WordPress, Asset pages | Public blog request, Admin list request, asset upload smoke |
| 4 | `/qqbot/account/*`, `/qqbot/command/*`, `/qqbot/rule/*`, `/qqbot/message/*`, `/qqbot/send/*` | QQBot core pages | `/qqbot/command/test` local request |
| 5 | `/qqbot/plugin-platform/*` | Plugin upload/install/enable/config/health pages | local test plugin install and enable |
| 6 | plugin operations exposed through QQBot command/event routing | Existing plugin pages and operation views | BangDream, FF14, FFLogs, Repeater smoke |
| 7 | `/qqbot/napcat/*`, login SSE events | NapCat device/login progress pages | simulated captcha and new-device session |
| 8 | public deployed URLs | deployed Admin | online smoke bundle |
```
- [x] **Step 3: Add `breaking-changes.md`**
Use this content:
```markdown
# Refactor V3 Breaking Changes
## Approved
| Area | Change | Reason | First Batch |
| --------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------- | ----------- |
| Database | Rebuild all API-owned tables from new full schema | Current data is not important and old schema blocks clean module ownership | Batch 0 |
| SQL init | Replace historical patch scripts with `sql/refactor-v3/*` | Avoid accumulated `ALTER TABLE` history | Batch 0 |
| Admin QQBot API types | Replace old QQBot caller types with new contract | New QQBot Core, Plugin Platform, and NapCat state model | Batch 4 |
## Protected Behavior
- Admin login succeeds.
- Admin menu loads.
- Vben success/error wrappers remain stable for Admin APIs.
- `/health/runtime` remains plain JSON.
- Blog public list/detail remain available.
- QQBot command test remains available.
- QQBot status keeps OneBot, container, WebUI, and QQ login state separate.
- NapCat cleanup failure blocks success.
```
- [x] **Step 4: Add `rebuild-runbook.md`**
Use this content:
```markdown
# Refactor V3 Rebuild Runbook
## Local Dry Run
1. Create an empty local database dedicated to refactor V3.
2. Apply `sql/refactor-v3/00-full-schema.sql`.
3. Apply `sql/refactor-v3/01-seed-core.sql`.
4. Run `sql/refactor-v3/99-verify.sql`.
5. Start API against the dry-run database.
6. Run `scripts/refactor-v3/local-smoke.ps1`.
## Online Backup
1. Confirm the exact API image tag and current database name.
2. Run `scripts/refactor-v3/db-backup-online.ps1`.
3. Record backup path, timestamp, source database, and restore command.
## Online Rebuild
1. Stop or limit API write traffic.
2. Apply full schema and seed scripts.
3. Run verify SQL.
4. Deploy API/Admin image versions bound to this schema.
5. Run online smoke bundle.
## Rollback
1. Stop write traffic.
2. Restore the recorded backup or previous schema bundle.
3. Roll back API/Admin images.
4. Re-run smoke for the restored version.
```
- [x] **Step 5: Verify docs exist**
Run:
```powershell
Test-Path D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\schema-map.md
Test-Path D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\api-admin-contract-matrix.md
Test-Path D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\breaking-changes.md
Test-Path D:\MyFiles\KT\Node\kt-template-online-api\docs\refactor-v3\rebuild-runbook.md
```
Expected:
```text
True
True
True
True
```
### Task 0.4: Add schema skeleton and RED schema test
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\sql\refactor-v3\00-full-schema.sql`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\sql\refactor-v3\01-seed-core.sql`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\sql\refactor-v3\99-verify.sql`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\test\refactor-v3\schema-map.spec.ts`
- [x] **Step 1: Write failing schema test**
Create `test/refactor-v3/schema-map.spec.ts`:
```ts
import { readFileSync } from 'fs';
import { join } from 'path';
const root = join(__dirname, '..', '..');
const requiredTables = [
'admin_user',
'admin_role',
'admin_permission',
'admin_menu',
'admin_department',
'platform_dict_group',
'platform_dict_item',
'blog_post',
'blog_taxonomy',
'blog_term',
'wordpress_site',
'asset_object',
'system_notice',
'runtime_evidence_index',
'qqbot_account',
'qqbot_command',
'qqbot_send_task',
'qqbot_plugin',
'qqbot_plugin_installation',
'qqbot_plugin_runtime_event',
'napcat_device_identity',
'napcat_login_session',
'napcat_login_challenge',
];
describe('refactor v3 schema skeleton', () => {
it('declares every required table in the full schema file', () => {
const sql = readFileSync(
join(root, 'sql/refactor-v3/00-full-schema.sql'),
'utf8',
);
for (const table of requiredTables) {
expect(sql).toContain(`CREATE TABLE IF NOT EXISTS ${table}`);
}
});
it('declares core seed and verification scripts', () => {
const seed = readFileSync(
join(root, 'sql/refactor-v3/01-seed-core.sql'),
'utf8',
);
const verify = readFileSync(
join(root, 'sql/refactor-v3/99-verify.sql'),
'utf8',
);
expect(seed).toContain('INSERT INTO admin_user');
expect(seed).toContain('INSERT INTO qqbot_command');
expect(seed).toContain('INSERT INTO qqbot_plugin');
expect(verify).toContain('admin_user');
expect(verify).toContain('qqbot_command');
expect(verify).toContain('qqbot_plugin');
expect(verify).toContain('napcat_device_identity');
});
});
```
- [x] **Step 2: Run RED check**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/refactor-v3/schema-map.spec.ts
```
Expected: FAIL because `sql/refactor-v3/00-full-schema.sql` does not exist.
- [x] **Step 3: Add minimal SQL skeleton**
Create the three SQL files with table declarations, seed markers, and verify markers. Use full table definitions before ending Batch 0; the initial minimal version only makes the RED check meaningful.
- [x] **Step 4: Run GREEN check**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/refactor-v3/schema-map.spec.ts
```
Expected: PASS.
### Task 0.5: Add DB dry-run wrappers
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-dry-run.ps1`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-backup-online.ps1`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-restore-online.ps1`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\local-smoke.ps1`
- [x] **Step 1: Add dry-run script**
Create `db-dry-run.ps1`:
```powershell
param(
[Parameter(Mandatory=$true)][string]$Database,
[string]$HostName = "127.0.0.1",
[int]$Port = 3306,
[string]$User = "root"
)
$ErrorActionPreference = "Stop"
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
throw "Database must match ^[A-Za-z0-9_]+$"
}
$root = Resolve-Path (Join-Path $PSScriptRoot "..\..")
$schema = Join-Path $root "sql\refactor-v3\00-full-schema.sql"
$seed = Join-Path $root "sql\refactor-v3\01-seed-core.sql"
$verify = Join-Path $root "sql\refactor-v3\99-verify.sql"
function Invoke-MysqlSource {
param(
[Parameter(Mandatory = $true)][string]$Path
)
$sourcePath = (Resolve-Path -LiteralPath $Path).Path.Replace("\", "/")
mysql -h $HostName -P $Port -u $User $Database --execute="source $sourcePath"
}
mysql -h $HostName -P $Port -u $User -e "DROP DATABASE IF EXISTS ``$Database``; CREATE DATABASE ``$Database`` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
Invoke-MysqlSource -Path $schema
Invoke-MysqlSource -Path $seed
Invoke-MysqlSource -Path $verify
```
- [x] **Step 2: Add online backup script**
Create `db-backup-online.ps1`:
```powershell
param(
[Parameter(Mandatory=$true)][string]$Database,
[Parameter(Mandatory=$true)][string]$OutputDirectory
)
$ErrorActionPreference = "Stop"
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
throw "Database must match ^[A-Za-z0-9_]+$"
}
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
$target = Join-Path $OutputDirectory "$Database-refactor-v3-$stamp.sql"
mysqldump --set-gtid-purged=OFF --single-transaction --routines --triggers --default-character-set=utf8mb4 "--result-file=$target" $Database
Write-Output $target
```
- [x] **Step 3: Add restore script**
Create `db-restore-online.ps1`:
```powershell
param(
[Parameter(Mandatory=$true)][string]$Database,
[Parameter(Mandatory=$true)][string]$BackupFile
)
$ErrorActionPreference = "Stop"
if ($Database -notmatch '^[A-Za-z0-9_]+$') {
throw "Database must match ^[A-Za-z0-9_]+$"
}
if (-not (Test-Path -LiteralPath $BackupFile -PathType Leaf)) {
throw "BackupFile does not exist"
}
$sourcePath = (Resolve-Path -LiteralPath $BackupFile).Path.Replace("\", "/")
mysql -e "DROP DATABASE IF EXISTS ``$Database``; CREATE DATABASE ``$Database`` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql --default-character-set=utf8mb4 $Database --execute="source $sourcePath"
```
- [x] **Step 4: Add local smoke script**
Create `local-smoke.ps1`:
```powershell
param(
[string]$BaseUrl = "http://127.0.0.1:5320"
)
$ErrorActionPreference = "Stop"
$runtime = Invoke-RestMethod -Method Get -Uri "$BaseUrl/health/runtime" -TimeoutSec 10
if (-not $runtime.service) {
throw "Runtime health response did not include service"
}
Write-Output "runtime.service=$($runtime.service)"
```
- [x] **Step 5: Validate scripts parse**
Run:
```powershell
powershell -NoProfile -Command '$null = [scriptblock]::Create((Get-Content -Raw -LiteralPath "D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-dry-run.ps1")); "ok"'
powershell -NoProfile -Command '$null = [scriptblock]::Create((Get-Content -Raw -LiteralPath "D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\local-smoke.ps1")); "ok"'
powershell -NoProfile -Command '$null = [scriptblock]::Create((Get-Content -Raw -LiteralPath "D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-backup-online.ps1")); "ok"'
powershell -NoProfile -Command '$null = [scriptblock]::Create((Get-Content -Raw -LiteralPath "D:\MyFiles\KT\Node\kt-template-online-api\scripts\refactor-v3\db-restore-online.ps1")); "ok"'
```
Expected:
```text
ok
ok
ok
ok
```
### Task 0.6: Batch 0 verification and commits
**Files:**
- Modify: `D:\MyFiles\KT\TASKS.md`
- API commit includes only Batch 0 API files.
- Root commit includes only `TASKS.md`.
- [ ] **Step 1: Run API Batch 0 checks**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/refactor-v3/schema-map.spec.ts
git -C D:\MyFiles\KT\Node\kt-template-online-api diff --check
```
Expected: Jest PASS and diff check exits `0`.
- [ ] **Step 2: Run doc sync**
Run MCP tool:
```text
kt_change_doc_sync(project=api, taskType=docs)
```
Expected: all required docs are updated or explicitly reported as not needed.
- [ ] **Step 3: Run KT global review**
Run MCP tool:
```text
kt_global_code_review(projects=["api","root"], contentScanMode="changed", includeContentScan=true)
```
Expected: `findings=[]`.
- [ ] **Step 4: Commit API Batch 0**
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add docs/refactor-v3 sql/refactor-v3 scripts/refactor-v3 test/refactor-v3
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "chore: 准备第三期迁移脚手架"
```
- [ ] **Step 5: Commit TASKS record**
Run:
```powershell
git -C D:\MyFiles\KT add TASKS.md
git -C D:\MyFiles\KT commit -m "docs: 记录第三期迁移准备"
```
## Batch 1: Runtime/Common Foundation
### Task 1.1: Add runtime adapter contracts
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\runtime\client\runtime-http-client.types.ts`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\runtime\client\runtime-process-client.types.ts`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\runtime\client\runtime-docker-client.types.ts`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\test\runtime\runtime-client-contract.spec.ts`
- [x] **Step 1: Write RED contract test**
Test expectations:
```ts
describe('runtime client contracts', () => {
it('uses explicit timeout and redaction fields for external calls', () => {
const request = {
url: 'https://example.invalid',
method: 'GET' as const,
timeoutMs: 1000,
redactHeaders: ['authorization'],
};
expect(request.timeoutMs).toBeGreaterThan(0);
expect(request.redactHeaders).toContain('authorization');
});
});
```
- [x] **Step 2: Create type files**
Define request/response types for HTTP, process, and Docker calls. Each request type includes `timeoutMs`, `correlationId`, and `safeSummary`.
- [x] **Step 3: Export contracts**
Modify `src/runtime/index.ts` to export the new client contract types.
- [x] **Step 4: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/runtime/runtime-client-contract.spec.ts test/runtime/runtime-health.service.spec.ts test/runtime/runtime-health.controller.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
```
Expected: PASS.
### Task 1.2: Keep common narrow and stable
**Files:**
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\src\common\index.ts`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\src\common\common.module.ts`
- Test: existing `test/common/*.spec.ts`
- [x] **Step 1: List exported common symbols**
Run:
```powershell
Get-Content D:\MyFiles\KT\Node\kt-template-online-api\src\common\index.ts
```
- [x] **Step 2: Remove only exports made obsolete by new runtime contracts**
Keep response wrappers, filters, interceptors, time decorators, Snowflake, logger config, and generic tools.
Actual note: no runtime client or now-obsolete export was present in `src/common/index.ts` or `src/common/common.module.ts`, so Common stayed unchanged to avoid artificial churn.
- [x] **Step 3: Verify common tests**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/common/tool.service.spec.ts test/common/swagger-response.spec.ts test/common/kt-date-time.decorator.spec.ts test/common/api-request-log.interceptor.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
```
Expected: PASS.
### Task 1.3: Commit Batch 1
**Files:**
- Modify: `D:\MyFiles\KT\TASKS.md`
- API and root commits.
- [x] **Step 1: Run Batch 1 review gates**
Run MCP tools:
```text
kt_change_doc_sync(project=api, taskType=refactor)
kt_global_code_review(projects=["api","root"], contentScanMode="changed", includeContentScan=true)
```
Expected: required docs resolved and `findings=[]`.
- [x] **Step 2: Commit**
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add src/runtime src/common test/runtime test/common docs/refactor-v3
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 重整运行时与通用基础层"
git -C D:\MyFiles\KT add TASKS.md
git -C D:\MyFiles\KT commit -m "docs: 记录第三期基础层迁移"
```
## Batch 2: Admin/Auth/Platform Config
Reusable guardrail for later module batches: route contract tests must prove both
decorator route compatibility and module graph reachability. If a route remains
available through an imported legacy module, assert the importing module metadata
and assert that the imported controller is not also registered directly.
### Task 2.1: Build new Admin module boundary
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\admin\admin.module.ts`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\admin\identity\**`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\admin\platform-config\**`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\src\app.module.ts`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\admin\admin-contract.spec.ts`
- [x] **Step 1: Write RED route compatibility test**
Create assertions for login, menu, user, role, dept, dict, notice controller paths using `test/helpers/controller-route.helper.ts`.
- [x] **Step 2: Create module shell**
Create `src/modules/admin/admin.module.ts` with controllers and providers grouped by `identity` and `platform-config`.
- [x] **Step 3: Move one domain at a time**
Move identity first, then menu/permission, then dict/component/notice. After each move, run the related Jest file.
Actual: Batch 2 kept legacy `src/admin/**` files in place and created the new shell boundary by grouping identity and platform-config controllers/providers. Dict and notice remain reachable through imported legacy modules to avoid duplicate controller registration.
- [x] **Step 4: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/admin/auth/admin-password-crypto.service.spec.ts test/admin/admin-menu.service.spec.ts test/admin/dict/dict.service.spec.ts test/admin/notice/admin-notice.service.spec.ts test/modules/admin/admin-contract.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
```
Expected: PASS.
### Task 2.2: Sync Admin frontend system callers and pages
**Files:**
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\core\auth.ts`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\core\menu.ts`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\system\*.ts`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\system\**`
- [x] **Step 1: Update API types to string IDs**
All ID fields crossing the API boundary use `string`.
Actual: no Admin frontend edit was needed. The targeted `core` and `system` API wrappers already use string IDs for user, role, menu, dept, dict, and notice contracts; the only `id: number` scan hit is the local `SystemKtTableDemo` demo row type, not a backend contract.
- [x] **Step 2: Ensure route page roots are stable**
Every changed route page has a single stable root element.
Actual: targeted system pages already use a single `Page` root, with modal/drawer children inside the page root.
- [x] **Step 3: Verify Admin typecheck**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck
```
Expected: PASS.
- [x] **Step 4: Run local login/menu smoke**
Start API and Admin only for this smoke. Save evidence under `.kt-workspace/test-artifacts/admin-system/<date>/`.
Actual: because Admin frontend had no code diff in this batch, full dev-server login was not started. The interface smoke used a local Nest TestingModule HTTP server with real Admin boundary controllers from `ADMIN_IDENTITY_CONTROLLERS` and `ADMIN_PLATFORM_CONFIG_CONTROLLERS`, then called `GET /auth/password-public-key`, `GET /menu/all`, `GET /dict/codes`, and `GET /system/notice/list` successfully.
### Task 2.3: Commit Batch 2
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/admin src/app.module.ts test/modules/admin sql/refactor-v3 docs/refactor-v3
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 迁移后台身份权限与平台配置"
git -C D:\MyFiles\KT\Vue\kt-template-admin add apps/web-antdv-next/src/api/core apps/web-antdv-next/src/api/system apps/web-antdv-next/src/views/system apps/web-antdv-next/src/router
git -C D:\MyFiles\KT\Vue\kt-template-admin commit -m "refactor: 同步后台系统管理契约"
git -C D:\MyFiles\KT add TASKS.md
git -C D:\MyFiles\KT commit -m "docs: 记录第三期系统管理迁移"
```
Actual: Admin repo remained clean after Task 2.2 verification, so Batch 2 creates no Admin commit.
## Batch 3: Blog/WordPress/Asset
### Task 3.1: Build Blog, WordPress, and Asset modules
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\blog\**`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\wordpress\**`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\asset\**`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\src\app.module.ts`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\blog\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\wordpress\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\asset\**`
- [x] **Step 1: Write RED tests for public Blog behavior**
Cover article list, article detail, term relation, and theme profile.
- [x] **Step 2: Write RED tests for WordPress mapping**
Cover remote ID to local post/term mapping and sync job state.
- [x] **Step 3: Write RED tests for Asset ownership**
Cover object owner module, MIME metadata, reference, and access grant.
- [x] **Step 4: Implement modules**
Keep route compatibility for public Blog endpoints and Admin-facing endpoints. Move MinIO ownership out of legacy `src/minio` into `src/modules/asset`.
- [x] **Step 5: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/blog/blog-article.service.spec.ts test/blog/blog-term.service.spec.ts test/wordpress/wordpress.service.spec.ts test/modules/blog test/modules/wordpress test/modules/asset
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
```
Expected: PASS.
Actual note: Batch 3 moved API ownership to transitional `BlogContentModule`, `WordpressMirrorModule`, and `AssetModule` boundaries while retaining legacy business internals behind imported modules for compatibility. Contract tests now parse `sql/refactor-v3/00-full-schema.sql` through `test/helpers/sql-schema.helper.ts` so domain expectations catch SQL schema drift instead of only repeating local constants. Route compatibility and duplicate-controller safety are covered by module graph tests, with `QqbotModule` mocked in metadata-only specs to avoid unrelated BangDream/NapCat side effects.
### Task 3.2: Sync Admin Blog/WordPress/Asset pages
**Files:**
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\blog\index.ts`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\blog\wordpress.ts`
- Create: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\blog\asset.ts`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\blog\**`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\router\routes\modules\blog.ts`
- [x] **Step 1: Update callers**
Use string IDs and explicit response types.
- [x] **Step 2: Keep pages work-focused**
Use KtTable or existing forms; avoid landing-page or card-heavy redesign.
- [x] **Step 3: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck
```
Expected: PASS.
Actual note: Admin Blog/WordPress ID-facing types were aligned to string IDs, `api/blog/asset.ts` was added against the existing `/minio/*` compatibility routes, and the Blog router/page layout was left unchanged because Batch 3 did not introduce a new visible page structure.
### Task 3.3: Commit Batch 3
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/blog src/modules/wordpress src/modules/asset src/app.module.ts test/modules sql/refactor-v3 docs/refactor-v3 API.md README.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 迁移博客镜像与资产模块"
git -C D:\MyFiles\KT\Vue\kt-template-admin add apps/web-antdv-next/src/api/blog apps/web-antdv-next/src/views/blog apps/web-antdv-next/src/router/routes/modules/blog.ts
git -C D:\MyFiles\KT\Vue\kt-template-admin commit -m "refactor: 同步博客与资产管理页面"
```
## Batch 4: QQBot Core
### Task 4.1: Build QQBot core module
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\core\**`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\src\app.module.ts`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\core\**`
- [x] **Step 1: Write RED status-separation tests**
Cover OneBot connection, container status, WebUI status, and QQ login status as separate fields.
- [x] **Step 2: Write RED command tests**
Cover operation key lookup, command ID usage, aliases, cooldown, permission policy, and parser validation.
- [x] **Step 3: Write RED send queue tests**
Cover queue reservation, rate limit, send log, and dedupe event behavior.
- [x] **Step 4: Implement core**
Move account, connection, command, rule, message, permission, send, dedupe, and dashboard logic into `src/modules/qqbot/core`.
- [x] **Step 5: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/qqbot/command/qqbot-command-parser.service.spec.ts test/qqbot/send/qqbot-send.service.spec.ts test/qqbot/send/qqbot-rate-limit.service.spec.ts test/qqbot/event/qqbot-event.service.spec.ts test/modules/qqbot/core
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
```
Expected: PASS.
Actual note: `QqbotCoreModule` now owns the QQBot Nest boundary directly with Config/AdminAuthGuard/Dict/TypeORM imports, full controller/provider/entity/export lists, and `src/qqbot/qqbot.module.ts` kept only as a compatibility shim. The RED contract tests failed first on missing `QQBOT_CORE_ENTITIES` / `QQBOT_CORE_EXPORTS` and missing `qqbot-core.contract`; after implementation, Turing review found that registered legacy TypeORM entities were not fully represented in `sql/refactor-v3/00-full-schema.sql`. The follow-up RED/GREEN guard now checks every registered QQBot Core entity table/column against the real v3 SQL, checks nullable entity columns, and rejects SQL-only required insert columns. The schema map and full SQL include transitional compatibility tables/columns for currently registered legacy QQBot, plugin-adjacent, and NapCat-adjacent entities; Batches 5-7 will replace those internals rather than treating this as the final plugin/NapCat design.
### Task 4.2: Sync Admin QQBot core pages
**Files:**
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\qqbot\index.ts`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\account\**`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\command\list.tsx`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\rule\list.tsx`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\message\list.tsx`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\sendLog\list.tsx`
- [x] **Step 1: Split status fields in the API types**
Define `oneBotStatus`, `containerStatus`, `webuiStatus`, and `qqLoginStatus` separately.
- [x] **Step 2: Keep account page single-root**
If modal/drawer components are siblings, wrap the route in one root container.
- [x] **Step 3: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck
```
Expected: PASS.
Actual note: QQBot account API types now expose `oneBotStatus`, `containerStatus`, `webuiStatus`, and `qqLoginStatus` as top-level split fields while preserving nested `napcat` fallbacks. The account page keeps its existing single route root and derives display/actions from the split status helpers, including disabling disconnect by OneBot status instead of the old collapsed connection status. Command/rule/message/sendLog pages did not need visible changes in this slice because their contracts did not consume the status fields. Admin typecheck passed.
### Task 4.3: Run local QQBot command smoke
Run API locally, query enabled command by `operationKey`, pass `commandId`, and include full command text.
Expected evidence:
- request URL
- command ID
- operation key
- response status
- sanitized response summary without `replyText`
Actual evidence: local Nest TestingModule HTTP smoke calls `GET /qqbot/command/list?operationKey=bangdream.song.search&enabled=true&pageNo=1&pageSize=10`, obtains command ID `cmd-bangdream-song-search`, then calls `POST /qqbot/command/test` with `commandId` and full text `/查歌 FIRE BIRD`. Response status is 200 and the asserted summary strips `replyText` while proving real `QqbotCommandService.page`, `QqbotCommandEngineService.preview`, parser, reply template, and plugin execution boundaries were exercised with mocked repository/plugin edges. Main-thread verification passed `pnpm exec jest --runInBand --runTestsByPath test/refactor-v3/schema-map.spec.ts ... test/modules/qqbot/core/qqbot-core-command-smoke.spec.ts` with 13 suites / 28 tests, API `pnpm run typecheck`, and Admin `pnpm -F @vben/web-antdv-next run typecheck`.
### Task 4.4: Commit Batch 4
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/qqbot/core src/app.module.ts test/modules/qqbot/core sql/refactor-v3 docs/refactor-v3 API.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 迁移QQBot核心模块"
git -C D:\MyFiles\KT\Vue\kt-template-admin add apps/web-antdv-next/src/api/qqbot apps/web-antdv-next/src/views/qqbot apps/web-antdv-next/src/router/routes/modules/qqbot.ts
git -C D:\MyFiles\KT\Vue\kt-template-admin commit -m "refactor: 同步QQBot核心管理页"
```
## Batch 5: QQBot Plugin Platform
### Task 5.1: Build plugin platform schema and manifest contracts
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugin-platform\manifest\**`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugin-platform\persistence\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugin-platform\manifest.spec.ts`
- [x] **Step 1: Write RED manifest validation tests**
Cover plugin key, semantic version, SDK version, operations, events, config schema, assets, migrations, permissions, and runtime limits.
- [x] **Step 2: Implement manifest parser**
Reject unknown permissions, duplicate operation keys, duplicate event keys, missing runtime budgets, and package paths outside plugin root.
- [x] **Step 3: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/qqbot/plugin-platform/manifest.spec.ts
```
Expected: PASS.
Actual note: Manifest RED first failed with missing `src/modules/qqbot/plugin-platform/manifest`. The parser now normalizes complete manifests and rejects unknown permissions, duplicate operation/event keys, missing runtime budgets, missing operation timeout, and paths outside the plugin root. Batch 5 persistence RED first failed with missing `persistence`; TypeORM entities now map all 9 plugin-platform v3 tables and are checked against real `sql/refactor-v3/00-full-schema.sql`.
### Task 5.2: Build plugin CLI
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\qqbot-plugin\cli.ts`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\qqbot-plugin\templates\basic\plugin.json`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\scripts\qqbot-plugin\templates\basic\src\index.ts`
- Modify: `D:\MyFiles\KT\Node\kt-template-online-api\package.json`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugin-platform\cli.spec.ts`
- [x] **Step 1: Add package script**
Add:
```json
{
"scripts": {
"qqbot-plugin": "ts-node -r tsconfig-paths/register scripts/qqbot-plugin/cli.ts"
}
}
```
Keep existing scripts.
- [x] **Step 2: Implement commands**
Commands:
```text
create <pluginKey>
validate <path>
pack <path>
install-local <package>
```
- [x] **Step 3: Verify CLI**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api qqbot-plugin create demo-plugin
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api qqbot-plugin validate .\plugins\demo-plugin
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api qqbot-plugin pack .\plugins\demo-plugin
```
Expected: commands exit `0`, package includes content hash.
Actual note: Added `pnpm qqbot-plugin` backed by `scripts/qqbot-plugin/cli.ts`, with `create`, `validate`, `pack`, and `install-local`. CLI tests caught a package hash mismatch caused by `undefined` fields in stable serialization; stable stringify now skips `undefined` so `pack` and `install-local` verify the same content hash. Real CLI smoke created `plugins/demo-plugin`, validated it, packed `demo-plugin-0.1.0-acc880b89e70.qqbot-plugin.json`, installed it locally, and then removed the temporary directory.
### Task 5.3: Build worker runtime and lifecycle
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugin-platform\runtime\**`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugin-platform\sdk\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugin-platform\worker-runtime.spec.ts`
- [x] **Step 1: Write RED RPC tests**
Cover `load`, `activate`, `executeOperation`, `handleEvent`, `health`, `deactivate`, `dispose`, timeout, and crash isolation.
- [x] **Step 2: Implement host-side runtime**
Worker messages include correlation ID, timeout budget, operation ID, safe input summary, and structured output.
- [x] **Step 3: Implement SDK**
Expose only send queue, plugin config, plugin storage, runtime HTTP client, plugin asset loader, operation context, and event context.
- [x] **Step 4: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/qqbot/plugin-platform/worker-runtime.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
```
Expected: PASS.
Actual note: Worker runtime RED first failed on missing `runtime` and `sdk`. `QqbotPluginWorkerRuntime` now sends lifecycle/execution RPC messages with correlation ID, timeout budget, operation ID/event key, and safe input summary without raw secret values. Worker crash and timeout become plugin-scoped runtime events and set the installation runtime status boundary to failed. `createQqbotPluginSdk` exposes only host-controlled send queue, config, storage, runtime HTTP, asset, operation context, event context, and runtime-event capabilities.
### Task 5.4: Sync Admin plugin platform page
**Files:**
- Create: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\qqbot\plugin.ts`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\plugin\list.tsx`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\router\routes\modules\qqbot.ts`
- [x] **Step 1: Add plugin caller**
Caller methods: upload, validate, install, enable, disable, upgrade, uninstall, update config, list runtime events, list account bindings.
- [x] **Step 2: Build management page**
Use tables, status tags, drawers/modals for upload/config/events, and Chinese operation labels.
- [x] **Step 3: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck
```
Expected: PASS.
Actual note: Added `/qqbot/plugin-platform/*` API controller/service/module before wiring Admin so the caller methods target real routes. Admin now has `src/api/qqbot/plugin.ts` with upload, validate, install, install-local, enable, disable, upgrade, uninstall, config update, runtime events, and account bindings. The existing plugin page remains a single `Page` root, keeps the operation table, and adds Chinese platform actions plus modal/drawer flows for Manifest JSON, installation records, runtime events, and account bindings. Admin route title changed from "插件能力" to "插件平台".
### Task 5.5: Commit Batch 5
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/qqbot/plugin-platform scripts/qqbot-plugin test/modules/qqbot/plugin-platform package.json sql/refactor-v3 docs/refactor-v3 API.md README.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "feat: 建立QQBot插件平台"
git -C D:\MyFiles\KT\Vue\kt-template-admin add apps/web-antdv-next/src/api/qqbot apps/web-antdv-next/src/views/qqbot/plugin apps/web-antdv-next/src/router/routes/modules/qqbot.ts
git -C D:\MyFiles\KT\Vue\kt-template-admin commit -m "feat: 增加QQBot插件管理页"
```
## Batch 6: Existing Plugin Rewrite
### Task 6.1: Rewrite BangDream as platform plugin
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugins\bangdream\plugin.json`
- Create/modify: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugins\bangdream\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugins\bangdream\**`
- [x] **Step 1: Preserve business directories**
Keep business capabilities in `domain/song`, `domain/card`, `domain/character`, `domain/event`, `domain/gacha`, `domain/player`, `domain/cutoff`, and `domain/catalog`; keep orchestration in `application`, operations in `operations`, external APIs in `infrastructure/integration`, cache/static patch adapters in `infrastructure/storage`, dictionary/static config in `config`, and visual helpers in `theme`.
- [x] **Step 2: Convert operation registry to manifest metadata**
Keep operation keys and aliases stable. `handlerName` becomes worker-internal.
- [x] **Step 3: Verify BangDream**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/qqbot/plugins/bangdream/manifest/operation-manifest.spec.ts test/qqbot/plugins/bangdream/manifest/command-sql.spec.ts test/modules/qqbot/plugins/bangdream-rewrite/bangdream-operation-parity.spec.ts
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
```
Expected: PASS. Event stage smoke keeps `imageCount=5`.
Actual note: BangDream moved to `src/modules/qqbot/plugins/bangdream/src` with third-phase plugin ownership: business code in `domain/*`, orchestration in `application`, operations in `operations`, external APIs in `infrastructure/integration`, cache/static patch adapters in `infrastructure/storage`, dictionary/static config in `config`, and visual helpers in `theme`. Added `plugin.json` with platform key `bangdream`; manifest operations are the single metadata source for stable operation keys, aliases, names, and worker-internal `handlerName`. Runtime registry now uses platform key `bangdream` as primary while resolving legacy `bangDream`; `/qqbot/plugin/*` local HTTP smoke now proves the controller returns platform keys and resolves legacy `bangDream` to `bangdream`. Verification passed via focused manifest/command SQL Jest, plugin migration contract, QQBot core module contract path guard, plugin controller HTTP smoke, `pnpm run typecheck`, and `scripts/bangdream-render-smoke.ps1 -OperationKey bangdream.event.stage -Text 310`, which produced `imageCount=5`.
### Task 6.2: Rewrite FF14 Market, FFLogs, and Repeater
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugins\ff14-market\**`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugins\fflogs\**`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\plugins\repeater\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugins\ff14-market\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugins\fflogs\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\plugins\repeater\**`
- [x] **Step 1: FF14 Market**
Use host runtime HTTP SDK for external requests. No direct axios client in plugin code.
- [x] **Step 2: FFLogs**
Use plugin config for credential references. No real secret in manifest, tests, docs, or commits.
- [x] **Step 3: Repeater**
Use host send queue and account binding. Do not bypass rate limit.
- [x] **Step 4: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/qqbot/plugins/ff14-market/qqbot-ff14-worlds.spec.ts test/qqbot/plugins/fflogs/qqbot-fflogs-client.service.spec.ts test/qqbot/plugins/repeater/qqbot-repeater.plugin.spec.ts test/modules/qqbot/plugins/ff14-market test/modules/qqbot/plugins/fflogs test/modules/qqbot/plugins/repeater
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
```
Expected: PASS.
Actual note: FF14 Market, FFLogs, and Repeater moved to `src/modules/qqbot/plugins/*` and each now has a platform `plugin.json` plus real third-phase package structure. FF14 Market splits operation binding into `operations`, use cases into `application`, world/market types into `domain`, external clients into `infrastructure/integration`, and config into `config`; FFLogs splits character-summary operation, application use case, GraphQL/OAuth client, config, and token cache; Repeater splits event handler, repeat policy/domain state, runtime config, application state, and host integration. Verification passed via focused plugin Jest, migration direct-HTTP scan for FF14/FFLogs, `/qqbot/plugin/list` and `/qqbot/plugin/operation/list` local HTTP smoke, and `pnpm run typecheck`; final focused Jest covered 9 suites / 27 tests.
### Task 6.3: Commit Batch 6
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/qqbot/plugins test/modules/qqbot/plugins sql/refactor-v3 docs/refactor-v3 API.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "refactor: 重写现有QQBot插件"
```
## Batch 7: NapCat Runtime
### Task 7.1: Build NapCat device persistence model
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\napcat\device\**`
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\napcat\container\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\napcat\device-identity.spec.ts`
- [ ] **Step 1: Write RED persistence test**
Assert that rebuilding a container for the same account reuses data directory, hostname, machine-id path, and MAC address from `napcat_device_identity`.
- [ ] **Step 2: Implement device identity service**
Device identity owns container name, data dir, hostname, machine ID path, MAC, account binding, verification status, and last login evidence.
- [ ] **Step 3: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/qqbot/napcat/device-identity.spec.ts
```
Expected: PASS.
### Task 7.2: Build NapCat login state machine
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\napcat\login\**`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\napcat\login-state-machine.spec.ts`
- [ ] **Step 1: Write RED state tests**
Cover this order:
```text
quick-login -> password-login -> captcha -> new-device -> manual-qr -> success/failure
```
Also cover cleanup failure blocking success.
- [ ] **Step 2: Implement login session and challenge states**
Keep captcha and new-device challenge state pending until explicitly resolved, expired, or failed.
- [ ] **Step 3: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/qqbot/napcat/login-state-machine.spec.ts
```
Expected: PASS.
### Task 7.3: Implement new-device NapCat API flow
**Files:**
- Create: `D:\MyFiles\KT\Node\kt-template-online-api\src\modules\qqbot\napcat\integration\napcat-login-api.client.ts`
- Test: `D:\MyFiles\KT\Node\kt-template-online-api\test\modules\qqbot\napcat\new-device-flow.spec.ts`
- [ ] **Step 1: Write RED new-device flow test**
Test sequence:
```text
GetNewDeviceQRCode -> PollNewDeviceQR -> NewDeviceLogin
```
Expected state mapping:
```text
qr-pending -> scanned -> confirming -> verified
```
- [ ] **Step 2: Implement client methods**
Methods:
```ts
getNewDeviceQRCode(sessionId: string): Promise<NewDeviceQrCode>
pollNewDeviceQR(sessionId: string): Promise<NewDeviceQrStatus>
newDeviceLogin(sessionId: string): Promise<NewDeviceLoginResult>
```
- [ ] **Step 3: Verify**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand --runTestsByPath test/modules/qqbot/napcat/new-device-flow.spec.ts
```
Expected: PASS.
### Task 7.4: Sync Admin NapCat login page and SSE Chinese progress
**Files:**
- Create: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\api\qqbot\napcat.ts`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\account\**`
- Create: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\views\qqbot\napcat\**`
- Modify: `D:\MyFiles\KT\Vue\kt-template-admin\apps\web-antdv-next\src\router\routes\modules\qqbot.ts`
- [ ] **Step 1: Add Chinese progress labels**
Labels include:
```text
正在快速登录
快速登录失败,进入密码登录
正在密码登录
需要验证码
验证码已提交,等待确认
需要新设备验证二维码
新设备二维码待扫码
新设备二维码已扫码
新设备确认中
新设备验证成功,继续登录
正在生成手动二维码
登录成功
登录失败
运行态清理失败
```
- [ ] **Step 2: Render captcha and new-device states separately**
Do not display new-device QR as captcha. Do not clear captcha state only because a subsequent poll omits URL.
- [ ] **Step 3: Verify Admin typecheck**
Run:
```powershell
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck
```
Expected: PASS.
### Task 7.5: Run local NapCat simulated smoke
Use mocked NapCat responses or a local controlled container. Evidence must show:
- device identity reused after container rebuild
- captcha challenge remains pending
- new-device QR generated through `GetNewDeviceQRCode`
- poll transitions to scanned/confirming
- `NewDeviceLogin` completes
- cleanup failure blocks success
### Task 7.6: Commit Batch 7
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api add src/modules/qqbot/napcat test/modules/qqbot/napcat sql/refactor-v3 docs/refactor-v3 API.md
git -C D:\MyFiles\KT\Node\kt-template-online-api commit -m "feat: 重建NapCat设备与登录运行时"
git -C D:\MyFiles\KT\Vue\kt-template-admin add apps/web-antdv-next/src/api/qqbot apps/web-antdv-next/src/views/qqbot apps/web-antdv-next/src/router/routes/modules/qqbot.ts
git -C D:\MyFiles\KT\Vue\kt-template-admin commit -m "feat: 完成NapCat登录进度管理页"
```
## Batch 8: Unified Local Closure, Push, Deploy, Online Smoke
### Task 8.1: Final local verification
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api status --short --branch
git -C D:\MyFiles\KT\Vue\kt-template-admin status --short --branch
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api run typecheck
pnpm --dir D:\MyFiles\KT\Node\kt-template-online-api exec jest --runInBand
pnpm --dir D:\MyFiles\KT\Vue\kt-template-admin -F @vben/web-antdv-next run typecheck
git -C D:\MyFiles\KT\Node\kt-template-online-api diff --check
git -C D:\MyFiles\KT\Vue\kt-template-admin diff --check
```
Expected: all commands exit `0`.
### Task 8.2: Run local full smoke
Required smoke evidence:
- `/health/runtime`
- Admin login
- Admin menu
- Blog public list/detail
- Asset upload/read
- QQBot command test
- Plugin install/enable/health
- Rewritten plugin operation
- NapCat simulated login flow
### Task 8.3: Ask user for push and DB rebuild window
Do not push or run online DB rebuild until the user explicitly confirms.
### Task 8.4: Push and observe deployment
After confirmation, push both repos.
Run:
```powershell
git -C D:\MyFiles\KT\Node\kt-template-online-api push -u origin dev-api-full-refactor-v3
git -C D:\MyFiles\KT\Vue\kt-template-admin push -u origin dev-admin-full-refactor-v3
```
Then collect Jenkins/K8s evidence:
- build number
- commit hash
- image tag
- Deployment generation and observedGeneration
- desired/updated/ready counts
- selected Pod image
- restart count
- Pod logs/events if failing
### Task 8.5: Online DB rebuild
Before writes:
- state source database
- state target database
- state backup path
- state restore command
- state SQL scripts to apply
Run online backup first. Apply schema only after backup succeeds.
### Task 8.6: Online full smoke
Required online evidence:
- `/health/runtime` returns service and status
- Admin login succeeds
- Admin menu loads
- Blog public pages work
- plugin package install/enable/health succeeds
- `/qqbot/command/test` uses operationKey-derived command ID and full command text
- NapCat real account login completes through the actual required path for that account
- if new-device appears, evidence includes `GetNewDeviceQRCode -> PollNewDeviceQR -> NewDeviceLogin`
- response summaries strip `replyText`
### Task 8.7: Final closeout
Run MCP tools:
```text
kt_change_doc_sync(project=api, taskType=deploy)
kt_change_doc_sync(project=admin, taskType=deploy)
kt_global_code_review(projects=["api","admin","root"], contentScanMode="changed", includeContentScan=true)
kt_cleanup_history(dryRun=true)
kt_workflow_loop_audit(stage="finish", requireCompletion=true)
```
Expected: required docs resolved, review findings resolved, cleanup final deleted count is `0`, and closeout can report complete.
## Cross-Batch Review Gates
Run these before every batch commit:
```text
kt_change_doc_sync(...)
kt_global_code_review(...)
```
Run Superpowers review before claiming a batch is finished:
```text
superpowers:requesting-code-review
```
If review finds a real Important issue, fix it and re-review before commit.
## Plan Self-Review
### Spec Coverage
| Spec Requirement | Plan Coverage |
| ------------------------------------------------------------------------- | ------------------------------------------------ |
| API/Admin dual-repo refactor | Tasks 0.1, 0.2, 2.2, 3.2, 4.2, 5.4, 7.4, 8.1-8.7 |
| Clean Admin authorized old artifacts during implementation preparation | Task 0.2 |
| Full database redesign and destructive rebuild with rollback | Tasks 0.3-0.5, 8.5 |
| Batch 0-8 local-first rhythm | Batch sections 0-8 and Cross-Batch Review Gates |
| Runtime/Common migration | Batch 1 |
| Admin/Auth/Platform Config migration | Batch 2 |
| Blog/WordPress/Asset migration | Batch 3 |
| QQBot Core migration | Batch 4 |
| QQBot Plugin Platform | Batch 5 |
| Existing plugin rewrite | Batch 6 |
| NapCat device persistence and login state machine | Batch 7 |
| New-device flow `GetNewDeviceQRCode -> PollNewDeviceQR -> NewDeviceLogin` | Task 7.3 |
| SSE/Admin Chinese progress | Task 7.4 |
| Unified push, Jenkins/K8s, DB rebuild, online smoke | Batch 8 |
### Type And Path Consistency
- API plan paths use `D:\MyFiles\KT\Node\kt-template-online-api`.
- Admin plan paths use `D:\MyFiles\KT\Vue\kt-template-admin`.
- New API implementation root is consistently `src/modules/**`.
- Legacy API roots are removed only after matching batch compatibility checks pass.
- Admin IDs crossing the API boundary are consistently planned as `string`.
## Final Completion Criteria
The third phase is complete only when all of these are true:
- API branch contains Batch 0-8 commits.
- Admin branch contains every Admin contract sync commit.
- API/Admin local verification passes.
- Online backup and rollback path are recorded.
- New schema is applied online.
- Jenkins/K8s observation matches pushed commits.
- Online functional smoke passes.
- NapCat real account flow completes, including device persistence and new-device flow when triggered.
- TASKS and required docs are updated.
- KT global review and Superpowers review are clean.
- No Node/Vite validation process started by the run remains alive.