docs: 设计API运行时基础重构
This commit is contained in:
parent
835c8abdcb
commit
f387088709
@ -0,0 +1,494 @@
|
||||
# API Runtime Foundation Design
|
||||
|
||||
## Background
|
||||
|
||||
The API project has grown into several runtime-heavy domains: Admin, Blog,
|
||||
WordPress, QQBot, MinIO, Loki logging, Jenkins/K8s deployment, and NAS-hosted
|
||||
NapCat containers. The current module layout works, but reliability behavior is
|
||||
spread across large services and scripts.
|
||||
|
||||
The most visible pressure points are:
|
||||
|
||||
- `src/qqbot/account/qqbot-napcat-login.service.ts` mixes session state, SSE
|
||||
events, quick login, password login, captcha, QR code fallback, cleanup, and
|
||||
NapCat WebUI calls.
|
||||
- `src/qqbot/napcat/qqbot-napcat-container.service.ts` mixes database container
|
||||
state, SSH process execution, Docker script generation, runtime status checks,
|
||||
and NapCat WebUI requests.
|
||||
- `src/wordpress/wordpress.service.ts` mixes WordPress auth, request transport,
|
||||
data normalization, markdown conversion, public article reads, and theme
|
||||
integration.
|
||||
- Runtime configuration is read directly through `ConfigService.get(...)` in
|
||||
many services, with required keys, defaults, timeouts, and secret masking
|
||||
handled locally.
|
||||
- Jenkins/K8s deployment already builds and rolls out the API, but post-rollout
|
||||
evidence still depends on manual observation and task-specific smoke commands.
|
||||
|
||||
The user selected the API-wide refactor priority as:
|
||||
|
||||
1. Runtime reliability.
|
||||
2. Module boundaries.
|
||||
3. Contract stability.
|
||||
4. Testability.
|
||||
|
||||
The user also selected a combined path: first implement the API runtime
|
||||
foundation, then extend that line into ktWorkflow/Jenkins/K8s automated
|
||||
observation.
|
||||
|
||||
## Goal
|
||||
|
||||
Build an API Runtime Foundation that centralizes configuration, external
|
||||
runtime calls, health reporting, cleanup semantics, and verification evidence,
|
||||
then use NapCat and Jenkins/K8s as the first end-to-end reliability samples.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not rewrite every API business module in the first phase.
|
||||
- Do not migrate all Admin, Blog, WordPress, MinIO, QQBot, and common contracts
|
||||
at once.
|
||||
- Do not replace existing Vben response wrappers or public API shapes during the
|
||||
runtime foundation phase unless a sample integration requires a narrow
|
||||
compatibility change.
|
||||
- Do not bypass QQ or Tencent security checks. Captcha and new-device
|
||||
verification stay user-driven.
|
||||
- Do not commit real secrets, backend `.env.development`, backend
|
||||
`.env.production`, database passwords, SSH keys, tokens, or production
|
||||
Kubernetes Secrets.
|
||||
|
||||
## Scope
|
||||
|
||||
This spec covers the first API-wide subproject:
|
||||
|
||||
- Add a runtime foundation inside the API project.
|
||||
- Connect that foundation to two sample runtime paths:
|
||||
- API deployment observation through Jenkins/K8s and ktWorkflow.
|
||||
- QQBot NapCat runtime and login reliability.
|
||||
- Create guardrails so future refactors move from runtime reliability into
|
||||
module boundaries, contract stability, and testability without large,
|
||||
unrelated rewrites.
|
||||
|
||||
Future subprojects should receive their own Superpowers specs:
|
||||
|
||||
- API module boundary refactor.
|
||||
- API contract and DTO stability.
|
||||
- API testability and large-service decomposition.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Runtime Foundation Layer
|
||||
|
||||
Create a focused runtime layer rather than expanding `common` into a larger
|
||||
utility bucket. The layer owns operational concerns, while business modules keep
|
||||
domain state and user-facing behavior.
|
||||
|
||||
Proposed package boundary:
|
||||
|
||||
```text
|
||||
src/runtime/
|
||||
runtime.module.ts
|
||||
config/
|
||||
client/
|
||||
health/
|
||||
evidence/
|
||||
cleanup/
|
||||
errors/
|
||||
```
|
||||
|
||||
The exact file split can change during implementation, but each unit must have
|
||||
one responsibility and a clear consumer:
|
||||
|
||||
- Runtime config is consumed by API modules and adapters.
|
||||
- Runtime clients are consumed by integration adapters, not controllers.
|
||||
- Runtime health is consumed by health controllers and deployment smoke.
|
||||
- Runtime evidence is consumed by scripts, ktWorkflow, and final task records.
|
||||
- Runtime cleanup is consumed by integration adapters that create temporary
|
||||
runtime state.
|
||||
|
||||
### RuntimeConfigModule
|
||||
|
||||
`RuntimeConfigModule` provides typed config profiles for the runtime paths that
|
||||
matter first:
|
||||
|
||||
- app and HTTP server settings.
|
||||
- database connection metadata needed for health checks.
|
||||
- Loki logging and query settings.
|
||||
- WordPress integration settings.
|
||||
- MinIO integration settings.
|
||||
- QQBot and NapCat runtime settings.
|
||||
- Jenkins/K8s smoke observation settings where they are needed by scripts.
|
||||
|
||||
Each profile must provide:
|
||||
|
||||
- typed values with normalized number and boolean parsing.
|
||||
- required key validation.
|
||||
- safe defaults where the current project already has stable defaults.
|
||||
- secret masking for logs, health output, evidence files, and review output.
|
||||
- a safe snapshot method that never returns raw passwords, tokens, private keys,
|
||||
or secret values.
|
||||
|
||||
`ConfigService.get(...)` may remain in untouched legacy code during migration,
|
||||
but new runtime code should consume typed config profiles.
|
||||
|
||||
### RuntimeHttpClient and RuntimeProcessClient
|
||||
|
||||
External calls should flow through runtime clients instead of ad hoc
|
||||
`fetch`, `http.request`, `https.request`, or `spawn` logic.
|
||||
|
||||
`RuntimeHttpClient` handles:
|
||||
|
||||
- request timeout.
|
||||
- operation name.
|
||||
- safe target summary.
|
||||
- duration.
|
||||
- status code.
|
||||
- response parsing failures.
|
||||
- classified errors.
|
||||
|
||||
`RuntimeProcessClient` handles:
|
||||
|
||||
- bounded process execution.
|
||||
- command family and safe argument summaries.
|
||||
- stdin script support for NAS SSH here-string workflows.
|
||||
- duration and exit code.
|
||||
- timeout classification.
|
||||
- stdout/stderr truncation for safe evidence.
|
||||
|
||||
These clients do not know domain rules. They return transport-level results that
|
||||
adapters translate into domain state.
|
||||
|
||||
### RuntimeHealthService
|
||||
|
||||
Add a machine-readable runtime health endpoint such as:
|
||||
|
||||
```text
|
||||
GET /health/runtime
|
||||
```
|
||||
|
||||
The endpoint should support at least these states:
|
||||
|
||||
- `live`: the process is running and can answer HTTP requests.
|
||||
- `ready`: critical dependencies and required config are available.
|
||||
- `degraded`: optional dependencies are unavailable, but core API behavior can
|
||||
continue.
|
||||
- `blocked`: required config is missing or a critical dependency is unavailable.
|
||||
|
||||
Initial probes should be lightweight. They should not perform destructive work
|
||||
or expensive business operations. The first implementation can keep the existing
|
||||
K8s TCP readiness probe and let Jenkins/ktWorkflow call `/health/runtime`.
|
||||
Switching the Kubernetes readiness probe to HTTP should happen only after the
|
||||
endpoint proves stable online.
|
||||
|
||||
### RuntimeEvidenceService
|
||||
|
||||
Runtime evidence should be emitted as structured JSON under
|
||||
`.kt-workspace/test-artifacts/...` and summarized in final reports.
|
||||
|
||||
Evidence records should include:
|
||||
|
||||
- title and task type.
|
||||
- target project and environment.
|
||||
- command or endpoint name.
|
||||
- safe target summary.
|
||||
- start time, end time, and duration.
|
||||
- result status.
|
||||
- classified error when present.
|
||||
- validation assertions.
|
||||
- cleanup result.
|
||||
|
||||
Evidence must not include full logs, raw tokens, raw passwords, SSH keys, full
|
||||
base64 image payloads, or production Secret values.
|
||||
|
||||
### RuntimeCleanup Semantics
|
||||
|
||||
Cleanup must be explicit and reportable. Runtime operations that create
|
||||
temporary state must return cleanup results instead of burying cleanup failure in
|
||||
logs.
|
||||
|
||||
For NapCat, cleanup failure includes:
|
||||
|
||||
- failing to remove runtime login password environment variables.
|
||||
- failing to clean temporary SSH scripts or runtime artifacts started by this
|
||||
task.
|
||||
- failing to preserve or verify required persistent device state.
|
||||
|
||||
Cleanup failure must not be overwritten by ordinary offline or login-failed
|
||||
messages.
|
||||
|
||||
### NapCatRuntimeAdapter
|
||||
|
||||
NapCat becomes the first domain adapter for the runtime foundation.
|
||||
|
||||
It should own runtime concerns that currently sit inside large QQBot services:
|
||||
|
||||
- SSH/Docker script execution through `RuntimeProcessClient`.
|
||||
- Docker device identity persistence.
|
||||
- NapCat WebUI calls through `RuntimeHttpClient`.
|
||||
- timeout and retry classification.
|
||||
- safe runtime evidence for container rebuilds, captcha, new-device verification,
|
||||
and cleanup.
|
||||
|
||||
The QQBot account/login services should keep domain state:
|
||||
|
||||
- account binding.
|
||||
- login session lifecycle.
|
||||
- SSE progress.
|
||||
- expected selfId checks.
|
||||
- success and failure messages.
|
||||
|
||||
The adapter must support the confirmed NapCat upstream new-device flow:
|
||||
|
||||
1. `PasswordLogin` or `CaptchaLogin` returns `needNewDevice`, `jumpUrl`, and
|
||||
`newDevicePullQrCodeSig`.
|
||||
2. API calls `GetNewDeviceQRCode` with `uin` and `jumpUrl`.
|
||||
3. API keeps the same scan session pending and exposes a user-facing new-device
|
||||
QR state through SSE/Admin.
|
||||
4. API polls `PollNewDeviceQR` using `bytesToken`.
|
||||
5. When the user confirms the QR, API calls `NewDeviceLogin` with `uin`,
|
||||
`passwordMd5`, and `newDevicePullQrCodeSig`.
|
||||
6. API checks login state, cleans runtime password state, binds the account, and
|
||||
records evidence.
|
||||
|
||||
### DeployObservationAdapter
|
||||
|
||||
Deployment observation starts from ktWorkflow and can reuse API evidence
|
||||
formats. It should collect:
|
||||
|
||||
- Jenkins job and build number.
|
||||
- commit hash.
|
||||
- image tag.
|
||||
- Kubernetes Deployment generation and observedGeneration.
|
||||
- updated and ready replica counts.
|
||||
- running Pod selected by image tag.
|
||||
- restart count.
|
||||
- recent Pod logs or events when failing.
|
||||
- `/health/runtime` response.
|
||||
- task-specific smoke result.
|
||||
|
||||
Rollout success alone is deployment evidence, not functional success.
|
||||
|
||||
## Data Flow
|
||||
|
||||
The target flow is:
|
||||
|
||||
```text
|
||||
Controller or script
|
||||
-> business service
|
||||
-> domain adapter
|
||||
-> runtime config/client/cleanup/health/evidence
|
||||
-> external system
|
||||
```
|
||||
|
||||
External results flow back as:
|
||||
|
||||
```text
|
||||
external system result
|
||||
-> runtime client classification
|
||||
-> domain adapter translation
|
||||
-> business service state update
|
||||
-> controller/SSE/API response
|
||||
-> runtime evidence summary
|
||||
```
|
||||
|
||||
For NapCat login, that means:
|
||||
|
||||
```text
|
||||
Admin refresh login
|
||||
-> QqbotNapcatLoginService session state
|
||||
-> NapCatRuntimeAdapter
|
||||
-> RuntimeProcessClient for Docker/SSH
|
||||
-> RuntimeHttpClient for NapCat WebUI
|
||||
-> classified status
|
||||
-> SSE Chinese progress and scan/status response
|
||||
-> runtime evidence
|
||||
```
|
||||
|
||||
For deployment observation, that means:
|
||||
|
||||
```text
|
||||
push/commit
|
||||
-> Jenkins build and K8s rollout
|
||||
-> ktWorkflow DeployObservationAdapter
|
||||
-> Kubernetes and health checks
|
||||
-> task smoke
|
||||
-> runtime evidence
|
||||
-> closeout decision
|
||||
```
|
||||
|
||||
## Error Model
|
||||
|
||||
Runtime errors should be classified before business code decides the user-facing
|
||||
message.
|
||||
|
||||
### `config_error`
|
||||
|
||||
Required configuration is missing, dangerous, or unreadable.
|
||||
|
||||
Examples:
|
||||
|
||||
- missing database host.
|
||||
- missing explicit QQBot account secret.
|
||||
- missing NapCat SSH target.
|
||||
- unreadable SSH key path.
|
||||
|
||||
Result: blocked. Do not claim deploy or runtime success.
|
||||
|
||||
### `dependency_unavailable`
|
||||
|
||||
The external dependency is unreachable or not authorized.
|
||||
|
||||
Examples:
|
||||
|
||||
- WordPress timeout.
|
||||
- Loki query timeout.
|
||||
- NapCat WebUI unavailable.
|
||||
- SSH command timeout.
|
||||
|
||||
Result: degraded or blocked, depending on dependency criticality.
|
||||
|
||||
### `operation_failed`
|
||||
|
||||
The dependency is reachable but the business operation did not complete.
|
||||
|
||||
Examples:
|
||||
|
||||
- NapCat requires captcha.
|
||||
- NapCat requires new-device verification.
|
||||
- QQ account mismatch.
|
||||
- WordPress returns an upstream validation error.
|
||||
|
||||
Result: domain service keeps pending, returns a business error, or falls back
|
||||
according to its state machine.
|
||||
|
||||
### `cleanup_failed`
|
||||
|
||||
Primary work may have completed or partially completed, but cleanup failed.
|
||||
|
||||
Examples:
|
||||
|
||||
- `NAPCAT_QUICK_PASSWORD` could not be removed.
|
||||
- temporary runtime evidence could not be cleaned.
|
||||
- a remote temporary file created by this run remains.
|
||||
|
||||
Result: block success reporting until the cleanup failure is handled or reported
|
||||
as a stable blocker.
|
||||
|
||||
## Phased Delivery
|
||||
|
||||
### Phase 1: Runtime Foundation Skeleton
|
||||
|
||||
Create the runtime module, typed config profiles, health types, evidence types,
|
||||
and lightweight `/health/runtime` endpoint.
|
||||
|
||||
Initial validation:
|
||||
|
||||
- targeted Jest for config parsing, masking, health state aggregation, and
|
||||
evidence serialization.
|
||||
- `pnpm run typecheck`.
|
||||
- one real local or reused-service request to `/health/runtime` when the
|
||||
endpoint exists.
|
||||
|
||||
### Phase 2: Deployment Observation Foundation
|
||||
|
||||
Add ktWorkflow/Jenkins/K8s observation support that can use the new health and
|
||||
evidence format.
|
||||
|
||||
Initial validation:
|
||||
|
||||
- ktWorkflow typecheck and self-test.
|
||||
- dry-run or read-only deploy observation against the current API deployment.
|
||||
- evidence written under `.kt-workspace/test-artifacts`.
|
||||
|
||||
### Phase 3: NapCat Runtime Adapter Sample
|
||||
|
||||
Refactor the NapCat runtime boundary around device persistence, WebUI calls,
|
||||
new-device QR flow, runtime password cleanup, and SSH/Docker evidence.
|
||||
|
||||
Required behavior:
|
||||
|
||||
- Docker container rebuild preserves device identity files:
|
||||
- `$DATA_DIR/QQ` mounted to `/app/.config/QQ`.
|
||||
- `$DATA_DIR/device.env` stores stable MAC and hostname.
|
||||
- `$DATA_DIR/machine-id` mounts to `/etc/machine-id:ro`.
|
||||
- Docker run uses `--mac-address` and `--hostname`.
|
||||
- Reset login state must not delete `device.env` or `machine-id`.
|
||||
- Captcha and new-device verification keep the same scan session pending.
|
||||
- New-device verification follows `GetNewDeviceQRCode -> PollNewDeviceQR ->
|
||||
NewDeviceLogin`.
|
||||
- SSE/Admin progress remains Chinese and user-facing:
|
||||
- quick login.
|
||||
- password login.
|
||||
- captcha required.
|
||||
- new-device QR generated.
|
||||
- scanned.
|
||||
- confirming.
|
||||
- success or failure.
|
||||
- Runtime login password cleanup failure blocks success.
|
||||
|
||||
Initial validation:
|
||||
|
||||
- targeted Jest around NapCat device persistence and new-device login flow.
|
||||
- API typecheck.
|
||||
- local or reused service request for changed login endpoints.
|
||||
- online account smoke after push and rollout.
|
||||
|
||||
### Phase 4: Boundary Ratchet
|
||||
|
||||
Add guardrails so future runtime work uses the foundation.
|
||||
|
||||
Guardrails:
|
||||
|
||||
- new external integration code should not directly scatter
|
||||
`ConfigService.get(...)` without a typed runtime profile.
|
||||
- new runtime calls should use runtime clients or justify why not.
|
||||
- new deployment completion claims should include rollout, health, and smoke
|
||||
evidence.
|
||||
- new cleanup-sensitive flows should return cleanup evidence.
|
||||
|
||||
Validation:
|
||||
|
||||
- ktWorkflow global review rule updates.
|
||||
- ktWorkflow self-test.
|
||||
- documentation sync for README/API/docs/TASKS/Obsidian entries as required.
|
||||
|
||||
## Verification Strategy
|
||||
|
||||
Verification scales with risk:
|
||||
|
||||
- docs-only spec commit: self-review, `git diff --check`, and scoped review.
|
||||
- runtime foundation code: targeted Jest and typecheck.
|
||||
- interface changes: real local or reused-service request.
|
||||
- deployment automation: read-only observation or dry run first, then online
|
||||
observation after push.
|
||||
- NapCat runtime changes: targeted Jest, real API request, Jenkins/K8s rollout,
|
||||
and online account smoke.
|
||||
|
||||
Completion of the full workstream requires:
|
||||
|
||||
- KT documentation sync.
|
||||
- cleanup-history final `deleted=[]` evidence when artifacts are produced.
|
||||
- KT global review with no blocking findings.
|
||||
- Superpowers code review evidence.
|
||||
- ktWorkflow closeout evidence.
|
||||
|
||||
## Worktree Cleanliness
|
||||
|
||||
The earlier NapCat half-implementation draft was explicitly abandoned before
|
||||
this spec was committed. Future implementation work should start from a clean
|
||||
API worktree, apart from committed design and planning documents. If new local
|
||||
changes appear before implementation starts, inspect and classify them before
|
||||
editing.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
The first implementation plan is ready when it can produce these outcomes in
|
||||
order:
|
||||
|
||||
1. API has a runtime foundation skeleton with typed config, health, evidence,
|
||||
and classified error primitives.
|
||||
2. Jenkins/K8s/ktWorkflow can observe a deployment using the shared evidence
|
||||
shape.
|
||||
3. NapCat login and container runtime become the first real adapter sample.
|
||||
4. Online verification proves rollout, health, and at least one real runtime
|
||||
smoke path.
|
||||
5. The next API refactor phase can start from module boundaries rather than
|
||||
re-solving runtime reliability.
|
||||
Loading…
Reference in New Issue
Block a user