21 KiB
API Full Module Architecture, Schema, and Plugin Platform Design
Background
The API project has grown from a compact NestJS service into a multi-domain
backend for Admin, Blog, WordPress, MinIO, QQBot, NapCat, Loki-backed runtime
events, and online deployment observation. The first runtime foundation phase
added the shared /health/runtime endpoint, typed runtime checks, and evidence
patterns needed to observe future refactors safely.
The next phase is not another QQBot-only repair. It is an API-wide architecture planning phase that prepares a full module refactor and a database redesign from scratch. Existing production data is considered unimportant for this phase, so the target design may rename tables, drop obsolete columns, split or merge tables, and rebuild initialization SQL. Even with that freedom, the implementation phase must keep backups, rollback commands, and smoke checks so online deployment remains auditable.
Scope Decision
This document covers the planning-only phase selected by the user:
- Define the API target module architecture.
- Redesign the database schema from scratch across all API domains.
- Design a first-class QQBot plugin platform with worker isolation, online installation, hot-plug enable/disable, and CLI scaffolding.
- Define the migration matrix and the future implementation order.
This document does not implement code, SQL, Admin UI, or runtime behavior. After this planning phase is reviewed, the full migration implementation must start a new Superpowers brainstorming loop before touching code.
Goals
- Make module ownership explicit enough that every controller, use case, entity, repository, external integration, and test has a clear home.
- Replace the current patch-based table history with a clean target schema.
- Keep external API compatibility by default, while listing deliberate breaking changes before implementation.
- Turn QQBot plugins into a unified platform instead of a set of hard-coded Nest providers.
- Make plugin creation repeatable through a CLI scaffold.
- Allow online plugin installation, validation, enable/disable, upgrade, and uninstall without restarting the entire API process.
- Plan existing plugin rewrites for BangDream, FF14 Market, FFLogs, and Repeater under the same plugin contract.
- Preserve the runtime reliability work from Phase 1 as the foundation for future module and deployment verification.
Non-Goals
- Do not write implementation code in this planning phase.
- Do not preserve the old database structure merely for migration convenience.
- Do not treat Jenkins/K8s rollout success as functional success.
- Do not move Admin frontend code in this phase. Admin changes are planned here and implemented after a separate brainstorming loop.
- Do not bypass QQ or Tencent security checks. NapCat captcha and new-device verification stay user-driven.
- Do not let installed plugin code access raw backend secrets, raw TypeORM repositories, or arbitrary Nest dependency injection.
Target Architecture
The target source layout separates platform foundation, shared primitives, and business modules:
src/
runtime/
common/
modules/
admin/
blog/
wordpress/
asset/
qqbot/
runtime owns operational primitives:
- typed runtime config profiles.
- HTTP and process clients with timeouts, safe summaries, and classified errors.
- health probes and
/health/runtime. - runtime evidence records.
- cleanup semantics.
common owns stable shared primitives:
- Vben response and error helpers.
- exception filters and interceptors.
- date/time decorators and serialization helpers.
- Snowflake ID generation.
- low-level text and object utilities.
- logging primitives that are not domain-specific.
Business modules own user-facing behavior. Each module follows the same internal shape:
module/
contract/
application/
domain/
infrastructure/
persistence/
integration/
schema/
tests/
Layer Responsibilities
contract contains controllers, request DTOs, response DTOs, Swagger metadata,
and compatibility adapters for existing routes.
application contains use cases, transaction boundaries, authorization checks,
and state orchestration. It may depend on domain services, repositories, and
integration ports. It must not hand-build external HTTP requests, Docker
scripts, or ad hoc SQL strings.
domain contains pure business rules, state machines, policy objects, and
value objects. Domain code should be testable without Nest, TypeORM, Docker,
HTTP, or external credentials.
infrastructure/persistence contains TypeORM entities, repository
implementations, query models, and schema-specific mappers.
infrastructure/integration contains external adapters such as WordPress HTTP,
MinIO SDK, Loki query, OneBot WebSocket, NapCat WebUI, plugin worker RPC, and
runtime process calls.
schema contains table design notes, initialization SQL ownership, migration
or rebuild scripts, and validation SQL for the module.
tests contains module-level unit, contract, repository, and integration
smoke tests. Cross-module smoke tests may stay under the root test/ folder
when they verify a user workflow instead of a single module.
Compatibility Rules
- Existing route paths remain stable unless the implementation plan lists a breaking change.
- Admin-facing responses keep the current Vben success/error wrapper unless an endpoint is explicitly documented as stream, file, WebSocket, or plain JSON.
- Public runtime health remains plain JSON.
- Snowflake IDs stay
BIGINTin MySQL and string-like values at JavaScript/API boundaries. - Runtime time fields use
KtDateTime extends Datethrough the existing KT date-time decorators. - Existing SQL filenames may be replaced by new full-build files during the implementation phase, but this planning phase does not modify them.
Data Architecture Redesign
The implementation phase may rebuild the schema from scratch. Because current data is not important, the target schema should be optimized for clean domain ownership rather than old compatibility. The implementation phase must still capture a backup before destructive online database work and must provide a rollback or restore command.
Global Schema Conventions
- Primary keys use Snowflake
BIGINT. - Foreign key columns use
*_idand are indexed. - Stable relation tables use composite unique keys.
- High-write log and event tables avoid hard database foreign keys when they would make retention or cleanup difficult.
- Business config tables use soft delete only when restore is valuable.
- Append-only runtime events, command logs, message logs, and plugin runtime events use retention instead of soft delete.
- Common timestamps are
create_time,update_time, and optionaldelete_time. - Status columns use explicit string enums documented in schema notes.
- JSON columns are reserved for raw external payload snapshots, plugin metadata, low-frequency config, or evidence details. Queryable fields must be first-class columns.
- Text fields with known UI or storage limits must document the truncation rule.
- New initialization SQL should be generated as a clean full schema, not as an
accumulated stack of historical
ALTER TABLEpatches.
Domain Table Plan
| Domain | Target Tables | Notes |
|---|---|---|
| Admin Identity | admin_user, admin_role, admin_permission, admin_menu, admin_department, admin_user_role, admin_role_permission, admin_role_menu |
Keep Admin route behavior stable while separating route menus from permission atoms. Department is hierarchical. User avatar, timezone, and home path remain user profile fields. |
| Platform Config | platform_dict_group, platform_dict_item, platform_component_template, platform_setting |
Move dictionary and component-template ownership out of miscellaneous Admin services. Dict group/item replace overloaded flat dict rows. |
| Blog Content | blog_post, blog_taxonomy, blog_term, blog_post_term, blog_theme_profile, blog_import_job |
Replace comma/text category and tag storage with relation tables. Theme config becomes a named profile. |
| WordPress Mirror | wordpress_site, wordpress_auth_session, wordpress_remote_post, wordpress_remote_term, wordpress_sync_job, wordpress_sync_mapping |
Separate remote WordPress state from local Blog content. Mapping table connects remote IDs to local posts or terms. |
| Asset/MinIO | asset_bucket, asset_object, asset_reference, asset_access_grant |
Track object ownership, source module, MIME/type metadata, and temporary access grants without scattering MinIO URLs across business tables. |
| System Event | system_notice, system_event, system_event_dedupe, system_event_delivery |
Keep Loki as the log query source. Store only actionable notices, dedupe state, and notification delivery state in MySQL. |
| Runtime Evidence | runtime_evidence_index |
Store safe index metadata for important runtime evidence files, not full logs or secrets. Large JSON evidence remains under .kt-workspace/test-artifacts or deployment artifact storage. |
| 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 |
Split account identity, connection state, permissions, routing, conversation state, message history, and send queue/history. |
| NapCat Runtime | napcat_container, napcat_device_identity, napcat_account_binding, napcat_login_session, napcat_login_challenge, napcat_runtime_cleanup |
Device identity is a first-class table for MAC, hostname, machine-id path, data dir, and verification state. Login challenges cover captcha and new-device flows. Cleanup records block false success. |
| 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 |
Installed plugin metadata, versions, operations, events, account bindings, config, assets, and runtime events belong to the platform, not to individual plugin code. |
| Plugin-Owned Data | qqbot_plugin_data_* or module-specific plugin tables |
Plugin migrations may create namespaced tables. Names must start with the plugin key or a registered namespace to avoid collisions. |
Destructive Rebuild Strategy
The implementation phase may use this rebuild flow:
- Capture a timestamped online database backup.
- Stop or gate write traffic for the API during destructive schema work.
- Drop or rename old API tables according to the approved rebuild script.
- Apply the new full initialization SQL.
- Seed required Admin user, roles, menus, platform settings, dictionaries, core QQBot plugin metadata, and default online commands.
- Start the API against the new schema.
- Run local or online smoke checks for Admin login, menu loading, Blog public
reads, MinIO check, QQBot command registry, plugin registry, NapCat account
status, and
/health/runtime. - If a critical smoke fails, restore the backup or reapply the previous schema bundle and redeploy the previous API image.
QQBot Plugin Platform
QQBot plugins become a platform capability instead of hard-coded Nest service registrations. Command plugins, event plugins, renderers, external-query plugins, and automation plugins use one contract.
Plugin Package Structure
plugins/<pluginKey>/
plugin.json
src/
index.ts
operations/
events/
config/
migrations/
assets/
tests/
plugin.json is the source of truth for:
- plugin key, name, description, version, author, license, and homepage.
- minimum API plugin SDK version.
- permissions requested from the host.
- operations and event handlers.
- config schema and defaults.
- asset declarations.
- migration declarations.
- runtime requirements such as timeout, memory limit, and worker type.
Worker-Isolated Runtime
The approved runtime model is process isolation:
- API main process installs packages, validates manifests, owns the registry, and routes commands/events.
- Plugin code runs in a dedicated worker or child process.
- A plugin crash marks the plugin instance
degradedorofflinewithout crashing the API process. - Enable, disable, upgrade, and uninstall operations start or stop workers and refresh the registry at runtime.
- Workers communicate with the API through a narrow RPC protocol.
The RPC protocol must support these commands:
load: load manifest and compiled entry.activate: initialize runtime state.deactivate: stop accepting work.executeOperation: execute a command or query operation.handleEvent: handle message or account events.health: return plugin health.dispose: release resources before shutdown.
RPC messages carry operation IDs, correlation IDs, timeout budgets, sanitized input, and structured output. The host owns timeout enforcement.
Plugin SDK Boundary
Plugin code cannot access Nest dependency injection, raw TypeORM repositories, raw backend environment variables, or arbitrary filesystem paths. It receives a controlled SDK with explicit capabilities:
- send QQBot messages through the host send queue.
- read and write plugin config through the plugin config service.
- read and write plugin-owned storage.
- emit plugin runtime events.
- request host-provided runtime HTTP calls with configured timeout and safe evidence.
- load declared static assets from the plugin asset root.
- inspect the current operation or event context.
Plugins must declare permissions before installation. The host rejects packages whose manifest requests unsupported permissions or whose code package does not match the validated hash.
CLI Scaffold
The repository should add a CLI for plugin authors:
pnpm qqbot-plugin create <pluginKey>
pnpm qqbot-plugin validate <path>
pnpm qqbot-plugin pack <path>
pnpm qqbot-plugin install-local <package>
create generates:
plugin.json.src/index.tswithcreatePlugin().- one operation handler template.
- one event handler template.
- config schema and defaults.
- migration/schema template.
- contract tests.
- package metadata.
- README/API draft fragments.
validate checks manifest shape, operation keys, event keys, permissions,
schema files, migrations, package size, disallowed paths, and basic test
presence.
pack produces a versioned plugin package with a content hash.
install-local installs a package into the local development plugin root using
the same validation path as online installation.
Online Installation and Hot-Plug State Machine
Plugin installation state moves through:
uploaded -> validated -> installed -> enabled
enabled -> disabled
installed -> uninstalled
enabled -> upgrading -> enabled
enabled -> failed
Admin uploads a plugin package. The API validates manifest, package hash,
version compatibility, permissions, migrations, and declared assets. The package
is stored under a controlled runtime plugin directory, never under src/.
Enabling a plugin starts its worker, registers operations and event handlers, and records the runtime status. Disabling a plugin stops the worker and removes its active operations/events from routing without deleting data. Uninstalling a plugin stops workers, removes registry entries, unbinds commands/events, and then follows the selected data policy: preserve plugin data by default, delete only when the admin explicitly chooses cleanup.
Existing Plugin Rewrite Plan
BangDream becomes the large reference plugin. Its current business capability split can stay inside the plugin package:
bangDream/
operations/
song/
card/
character/
event/
gacha/
player/
cutoff/
provider/
renderer/
theme/
assets/
The existing BangDream operation registry becomes manifest-backed operation metadata. Handler names remain implementation details inside the plugin worker. The current image rendering smoke expectations, including event stage split output behavior, remain acceptance tests.
FF14 Market becomes an external-query plugin using the host runtime HTTP SDK for XIVAPI and Universalis calls.
FFLogs becomes an external-query plugin using the host runtime HTTP SDK for GraphQL/token calls and plugin config for client credentials references.
Repeater becomes an event plugin with host-managed account binding and plugin-owned transient state. It must not bypass the host send queue.
Module Migration Matrix
The future implementation phase should be split into auditable batches:
| Batch | Scope | Outcome |
|---|---|---|
| 0 | Migration preparation | New schema map, full initialization SQL plan, destructive rebuild script plan, backup/restore commands, validation SQL, module template, and breaking-change list. |
| 1 | Runtime/Common | Keep runtime foundation stable, add missing runtime client/evidence primitives needed by module adapters, and shrink common to stable shared primitives. |
| 2 | Admin/Auth/Platform Config | Rebuild identity, menu, permission, dictionary, component template, and system notice models. Admin login and menu loading must pass first. |
| 3 | Blog/WordPress/Asset | Rebuild Blog content relations, WordPress mirror/sync, and MinIO asset ownership. Public Blog reads and Admin Blog management must pass. |
| 4 | QQBot Core | Rebuild account, connection, permission, command, rule, conversation, message, and send queue models. Command matching and send queue tests must pass. |
| 5 | QQBot Plugin Platform | Add plugin manifest validation, database registry, CLI scaffold, worker runtime, RPC, online install, hot-plug state, and Admin/API management contracts. |
| 6 | Existing Plugin Rewrite | Rewrite BangDream, FF14 Market, FFLogs, and Repeater as isolated plugin packages. Existing command smoke behavior must remain available. |
| 7 | NapCat Runtime | Implement container device persistence, login session state machine, captcha/new-device flow, and cleanup evidence on the new QQBot/NapCat model. |
| 8 | Online Closure | Deploy, observe Jenkins/K8s, run /health/runtime, Admin smoke, Blog smoke, plugin install/enable smoke, QQBot command smoke, and real NapCat account login smoke. |
NapCat is intentionally after QQBot Core and Plugin Platform. It depends on the new account model and shares runtime verification with command/event routing, but it is not itself a plugin.
Contract and Breaking-Change Policy
External API compatibility is the default. Any implementation task that changes route paths, request fields, response fields, status semantics, SSE event names, Admin API wrappers, or SQL seed identifiers must add the change to a breaking-change table before coding.
Allowed planned breakages:
- Database table names, columns, indexes, and initialization SQL may change freely because the schema is redesigned from scratch.
- Admin pages may need API-wrapper updates during the implementation phase.
- Plugin management endpoints are new and can use new route shapes.
Protected behavior:
- Admin login and menu loading.
- Vben response wrapper for business APIs.
/health/runtimeplain JSON.- Blog public article list/detail behavior.
- QQBot command test flow.
- QQBot account status distinction between OneBot connection, container, WebUI, and QQ login state.
- NapCat login safety checks, captcha handoff, new-device verification, and runtime password cleanup blocking semantics.
Verification Strategy
Planning-only verification for this spec:
- spec self-review for missing markers, contradictions, and ambiguous scope.
git diff --check.- KT documentation sync check.
- KT global review on changed files.
Future implementation verification must include:
- targeted unit tests for domain policies and state machines.
- repository/schema tests for new SQL and TypeORM mappings.
- plugin contract tests generated by the CLI scaffold.
- worker runtime tests for load, activate, execute, health, deactivate, and crash isolation.
- local API requests for changed endpoints.
- Admin UI smoke when Admin callers change.
- database rebuild dry run against a local database before online destructive work.
- online backup, rebuild, restore path, Jenkins/K8s observation, and functional smoke after deploy.
Acceptance Criteria for This Planning Phase
This planning phase is complete when:
- The design document is written under
docs/superpowers/specs/. - The design document is committed.
- The user reviews the committed document.
- The next step is a Superpowers writing-plans phase for the planning output, not code implementation.
- The subsequent full migration starts a fresh Superpowers brainstorming loop before implementation begins.
Handoff to the Next Phase
After user review, the writing-plans phase should produce a plan document for the planning deliverable. That plan should describe how to turn this design into implementation-ready work packages, schema documents, plugin platform tasks, and validation checklists.
The subsequent full implementation must start from a new brainstorming loop because it will involve destructive schema work, Admin/API contract decisions, runtime plugin security boundaries, and online closure.