Complete platform management workflows

This commit is contained in:
npc0-hue
2026-07-14 16:39:37 +08:00
parent 7e05d0a4e7
commit 4f33f761a3
106 changed files with 11313 additions and 460 deletions
@@ -0,0 +1,103 @@
## Context
The platform already has control, job, log, and artifact channels, plus plugin-declared remote access capabilities for FTP, rsync, run-mediated files, SQL, logs, and RCON. The missing layer is operational delivery: operators need to generate a per-server run executable, download it for a selected OS/architecture, authenticate it with the server's current database-backed run key, update it after it is online, and let plugins declare how run finds and controls the actual game server.
The old SCUM stack has useful patterns: a run-side process controller, a separate client/robot manager for cases where server control requires a game client or custom automation, Git-based source updates, Go toolchain checks, FTP log polling, SQLite reads, and command forwarding. This design generalizes those patterns without making SCUM special in platform core.
## Goals / Non-Goals
**Goals:**
- Let server owners generate and download a server-scoped run package from the server list or server action menu.
- Store one current run key and one current client-manager key per server/component in the database, encrypted at rest, with redacted secret references in APIs and logs.
- Let online run endpoints self-update through a platform job that stages, verifies, swaps, and reports rollback-safe status.
- Let plugins declare runtime profiles that explain how to find a server, start/stop it, check dependencies, install missing dependencies, collect live and historical logs, and expose files, FTP/rsync, SQL, and RCON.
- Let plugins declare optional client-manager build profiles for cases like SCUM where a separate executable must be compiled from an open repository with a distinct authentication key.
- Keep all browser and plugin operations platform-mediated and preserve channel isolation for control, jobs, logs, files, and artifacts.
**Non-Goals:**
- No billing, cloud host sales, server rental marketplace, or cloud-provider provisioning workflow.
- No raw run keys, client-manager keys, FTP passwords, database DSNs, RCON passwords, direct sockets, or host paths in plugin pages or platform_web responses.
- No arbitrary plugin shell scripts for dependency installation or build execution.
- No requirement that every game use run; FTP-only, FTP+RCON, and custom-client modes remain valid when declared by the plugin.
- No production package-signing infrastructure beyond local checksums/signature hooks in the first implementation.
## Decisions
### Decision 1: Distribution artifacts are secret-bearing platform records
Platform stores generated run and client-manager packages as artifacts with a distribution record containing kind, server instance, plugin ID, target OS/architecture, source revision, checksum, status, component kind, and key generation. The package config contains the current active key for that server/component because the remote executable must authenticate with it. API responses, logs, job payloads, plugin SDK payloads, and UI state expose only artifact IDs, key generation, and redacted secret refs.
Alternative considered: ship one global run binary and ask users to hand-edit config files. Rejected because it causes copy/paste key exposure, weak auditability, and poor operator experience.
### Decision 2: Run and client-manager credentials are separate singleton keys
Each server/component has exactly one active run key and, when needed, exactly one active client-manager key. Run and client-manager keys remain different secrets, but platform does not keep multiple simultaneously valid keys for the same component. Resetting a key replaces the encrypted database value, increments the key generation, invalidates every older run or client package for that component, and requires regenerating and redeploying the affected package.
Alternative considered: reuse the run key for plugin client managers. Rejected because client managers may have broader game-specific control surfaces and need independent reset, revocation, and audit.
Alternative considered: issue temporary enrollment tokens and exchange them for runtime keys. Rejected because the desired operator model is a single database-backed current key per server/component, with explicit reset when trust must be revoked.
### Decision 3: Plugins declare runtime profiles, not raw local paths
Plugins define runtime profiles with logical server discovery probes, lifecycle actions, dependency probes, dependency install plans, log sources, transport profiles, and optional client-manager profiles. Operators bind those logical keys to a server instance at setup time. Run resolves bindings locally and returns logical status, not raw host paths.
Alternative considered: hardcode Minecraft and SCUM discovery rules into platform. Rejected because the platform should remain a game server management core, while game-specific control knowledge belongs in plugins.
### Decision 4: Dependency install is typed and reviewable
Dependency checks are read-only probes such as command version, service existence, port availability, file presence under scoped roots, Steam app presence, Java version, Docker availability, or Windows package presence. Install plans are typed steps with approved package managers or verified downloads. Platform shows the plan and queues it only after operator approval.
Alternative considered: let plugins provide arbitrary install shell scripts. Rejected because it creates an unrestricted execution path and conflicts with run security rules.
### Decision 5: Client-manager builds are source-pinned build jobs
Plugin client-manager profiles declare a repository URL, branch/tag or pinned revision policy, supported targets, build system, config template keys, dependency hints, and produced artifact paths. Platform creates a build job in an isolated workspace or future build worker, redacts secrets from logs, writes generated config from secret refs, and publishes a downloadable artifact.
Alternative considered: require plugin authors to upload prebuilt binaries only. Rejected because SCUM-style managers need reproducible platform-side injection of per-server config and keys.
### Decision 6: Run owns local execution and transport adapters
Run is the multi-platform server launcher and transport agent. It starts/stops third-party programs through plugin lifecycle profiles, tails stdout/stderr and declared log files, transfers files through the artifact channel, and performs declared FTP/rsync, SQL, and RCON operations through scoped adapters. Long transfers must not block heartbeat, job ack/result, or log ingest.
Alternative considered: let platform_web or plugin pages connect directly to FTP/RCON/SQL. Rejected because that exposes credentials and bypasses platform authorization, audit, and channel isolation.
### Decision 7: Live and historical logs share durable sequence semantics
Run streams live process output and file tails through the log channel with source IDs and monotonically increasing sequences. Historical logs are fetched through backfill jobs that use checkpoints, file fingerprints, FTP polling cursors, or database cursors to avoid duplicates. Platform_web displays live tail and history through platform APIs only.
Alternative considered: return log bodies inside job results. Rejected because logs can be large and must not compete with control and job metadata.
### Decision 8: Self-update is staged and rollback-safe
When run is online and supports the update capability, platform queues an update job with an artifact ref and checksum. Run downloads via the artifact channel, verifies checksum/signature metadata, stages the new binary, drains or rejects new local work, swaps atomically where supported, restarts, and reports success or rollback failure. Offline endpoints keep the latest downloadable package for manual replacement.
Alternative considered: send a raw command to pull the latest repository. Rejected because it is platform-specific, hard to verify, and unsafe to audit.
## Risks / Trade-offs
- [Risk] Build jobs can execute untrusted repository code. Mitigation: require plugin-declared build profiles, pinned refs, isolated workspaces, bounded logs, and a later sandboxed build worker before public plugin builds.
- [Risk] Self-update can leave a remote run offline. Mitigation: stage artifacts, verify checksums, retain previous binary, report last-known version, and keep manual download available.
- [Risk] Dependency install plans differ across Windows, Linux, and macOS. Mitigation: model probes and install steps per target platform, and show unsupported targets before dispatch.
- [Risk] Historical log backfill can duplicate records. Mitigation: persist per-source checkpoints with file fingerprints, offsets, sequence acknowledgements, and cursor metadata.
- [Risk] Resetting a key immediately breaks deployed run or client-manager binaries. Mitigation: make reset confirmations explicit, mark old packages revoked, show that regeneration is required, and keep online update/manual download paths visible.
- [Risk] Operators may expect plugin profiles to work without binding server-specific values. Mitigation: require server setup validation before showing actions that depend on missing bindings.
## Migration Plan
1. Extend plugin manifest schema and examples with runtime profiles, dependency probes, log sources, transport profiles, and client-manager build profiles.
2. Add platform domain, model, DTO, validator, and service support for distribution records, encrypted database key storage, key reset, key generation checks, build jobs, dependency status, runtime bindings, and update jobs.
3. Add run package config loading, registration authentication against the current database key generation, dependency probes, discovery probes, log source checkpoints, transport adapter envelopes, and self-update executor.
4. Add platform_web server-list and server-detail action menus for generate/download/update run, generate/download client manager, dependency checks, live logs, and historical logs.
5. Add tests and docs across plugins, platform, run, and platform_web; validate with OpenSpec, structure checks, backend tests, plugin validation, run tests, frontend tests, and browser walkthroughs for touched UI.
Rollback removes the new distribution/client-manager routes and UI actions, leaves existing run endpoints and plugin-declared remote access behavior intact, and preserves already-created artifacts as inert downloadable records until manually cleaned.
## Open Questions
- Which envelope-key source should protect the encrypted key columns stored in the platform database?
- Should platform-side builds run in the platform process for the first version, or require a separate build worker from day one?
- What default retention should apply to historical logs and generated binaries?
- Which target packaging formats should be first-class first: zip/tar.gz only, or Windows service installer, systemd unit bundle, and launchd plist bundles?
- Should plugin client-manager profiles support private repositories later, and if so how should source credentials be stored and audited?