kt-template-online-api/docs/superpowers/specs/2026-06-13-api-runtime-foundation-design.md

15 KiB

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:

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:

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:

Controller or script
  -> business service
  -> domain adapter
  -> runtime config/client/cleanup/health/evidence
  -> external system

External results flow back as:

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:

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:

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.