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
+5
View File
@@ -10,6 +10,11 @@ type RunCapabilityReport struct {
type RunControlHello struct {
RegistrationToken string
RunEndpointID string
ServerInstanceID string
PluginID string
ComponentKind DistributionComponentKind
ComponentKey string
KeyGeneration int
DisplayName string
Version string
Status RunEndpointStatus
+421 -8
View File
@@ -104,6 +104,56 @@ const (
ArtifactStateFailed ArtifactState = "failed"
)
type DistributionComponentKind string
const (
DistributionComponentRun DistributionComponentKind = "run"
DistributionComponentClientManager DistributionComponentKind = "client-manager"
)
type ComponentKeyStatus string
const (
ComponentKeyStatusActive ComponentKeyStatus = "active"
ComponentKeyStatusRevoked ComponentKeyStatus = "revoked"
)
type DistributionStatus string
const (
DistributionStatusAvailable DistributionStatus = "available"
DistributionStatusRevoked DistributionStatus = "revoked"
DistributionStatusBuilding DistributionStatus = "building"
DistributionStatusFailed DistributionStatus = "failed"
)
type RuntimeBindingStatus string
const (
RuntimeBindingStatusComplete RuntimeBindingStatus = "complete"
RuntimeBindingStatusIncomplete RuntimeBindingStatus = "incomplete"
)
type DependencyState string
const (
DependencyStateUnknown DependencyState = "unknown"
DependencyStatePresent DependencyState = "present"
DependencyStateMissing DependencyState = "missing"
DependencyStateInstalling DependencyState = "installing"
DependencyStateFailed DependencyState = "failed"
)
type DistributionJobStatus string
const (
DistributionJobStatusQueued DistributionJobStatus = "queued"
DistributionJobStatusRunning DistributionJobStatus = "running"
DistributionJobStatusSucceeded DistributionJobStatus = "succeeded"
DistributionJobStatusFailed DistributionJobStatus = "failed"
DistributionJobStatusDenied DistributionJobStatus = "denied"
)
type LogStreamSource string
const (
@@ -208,11 +258,12 @@ type AIProviderModels struct {
}
type PluginPermissions struct {
AI bool
Logs bool
Files bool
Jobs bool
Artifacts bool
AI bool
Logs bool
Files bool
Jobs bool
Artifacts bool
RemoteAccess bool
}
type PluginLifecycleActions struct {
@@ -246,6 +297,14 @@ type GamePluginManifestAI struct {
Purposes []string
}
type GamePluginRemoteAccess struct {
Methods []string
RunCapabilities []string
DatabaseEngines []string
RCON bool
LogTransfer bool
}
type GamePluginManifest struct {
ID string
Name string
@@ -260,6 +319,7 @@ type GamePluginManifest struct {
Actions PluginLifecycleActions
Pages []GamePluginPage
AI GamePluginManifestAI
RemoteAccess GamePluginRemoteAccess
}
type GamePluginManifestRegistration struct {
@@ -285,6 +345,7 @@ type GamePlugin struct {
Pages []GamePluginPage
Tags []string
AIPurposes []string
RemoteAccess GamePluginRemoteAccess
ValidationViolations []string
Status GamePluginStatus
}
@@ -307,6 +368,7 @@ type PluginMarketplacePlugin struct {
Pages []GamePluginPage
Tags []string
AIPurposes []string
RemoteAccess GamePluginRemoteAccess
ValidationViolations []string
Status GamePluginStatus
Source string
@@ -320,6 +382,11 @@ const (
PluginBridgeActionLogsQuery PluginBridgeAction = "logs.query"
PluginBridgeActionArtifactsOpen PluginBridgeAction = "artifacts.open"
PluginBridgeActionFilesRequest PluginBridgeAction = "files.request"
PluginBridgeActionRemoteAccessRequest PluginBridgeAction = "remote.access.request"
PluginBridgeActionRunDistribution PluginBridgeAction = "run.distribution.request"
PluginBridgeActionDependenciesRequest PluginBridgeAction = "dependencies.request"
PluginBridgeActionLogsBackfillRequest PluginBridgeAction = "logs.backfill.request"
PluginBridgeActionClientManager PluginBridgeAction = "client-manager.request"
PluginBridgeActionAIInvoke PluginBridgeAction = "ai.invoke"
)
@@ -383,6 +450,10 @@ type ServerInstance struct {
UpdatedAt time.Time
}
type ServerInstanceUpdate struct {
Name *string
}
type PlatformResourceUsage struct {
CPUPercent float64
MemoryPercent float64
@@ -493,9 +564,25 @@ type RunCapacity struct {
}
const (
JobCapabilityConfigWrite = "config.write"
JobCapabilityFilesRead = "files.read"
JobCapabilityFilesWrite = "files.write"
JobCapabilityConfigWrite = "config.write"
JobCapabilityFilesRead = "files.read"
JobCapabilityFilesWrite = "files.write"
JobCapabilityRemoteFTPRead = "remote.ftp.read"
JobCapabilityRemoteFTPWrite = "remote.ftp.write"
JobCapabilityRemoteRsyncRead = "remote.rsync.read"
JobCapabilityRemoteRsyncWrite = "remote.rsync.write"
JobCapabilityRemoteRunFilesRead = "remote.run.files.read"
JobCapabilityRemoteRunFilesWrite = "remote.run.files.write"
JobCapabilityRemoteRunProcessStart = "remote.run.process.start"
JobCapabilityRemoteRunProcessStop = "remote.run.process.stop"
JobCapabilityRemoteRunDBMySQLQuery = "remote.run.db.mysql.query"
JobCapabilityRemoteRunDBSQLiteQuery = "remote.run.db.sqlite.query"
JobCapabilityRemoteRunLogsTransfer = "remote.run.logs.transfer"
JobCapabilityRemoteRunRCONCommand = "remote.run.rcon.command"
JobCapabilityRunSelfUpdate = "run.self-update"
JobCapabilityDependenciesCheck = "dependencies.check"
JobCapabilityDependenciesInstall = "dependencies.install"
JobCapabilityLogsBackfill = "logs.backfill"
)
type RunEndpoint struct {
@@ -539,6 +626,197 @@ type Artifact struct {
UpdatedAt time.Time
}
type RuntimeBinding struct {
ID string
ServerInstanceID string
PluginID string
ProfileKey string
Mode string
Bindings map[string]string
MissingKeys []string
Status RuntimeBindingStatus
CreatedAt time.Time
UpdatedAt time.Time
}
type EncryptedComponentKey struct {
ID string
ServerInstanceID string
ComponentKind DistributionComponentKind
ComponentKey string
EncryptedKey string
KeyHash string
Fingerprint string
SecretRef string
Generation int
Status ComponentKeyStatus
CreatedAt time.Time
UpdatedAt time.Time
ResetAt time.Time
}
type RunDistribution struct {
ID string
ServerInstanceID string
PluginID string
RunEndpointID string
TargetOS string
TargetArch string
PackageFormat string
ArtifactID string
Checksum string
KeyGeneration int
SecretRef string
Status DistributionStatus
CreatedAt time.Time
UpdatedAt time.Time
}
type ClientManagerDistribution struct {
ID string
ServerInstanceID string
PluginID string
ProfileKey string
TargetOS string
TargetArch string
RepositoryURL string
SourceRevision string
BuildJobID string
ArtifactID string
Checksum string
KeyGeneration int
SecretRef string
Status DistributionStatus
CreatedAt time.Time
UpdatedAt time.Time
}
type DependencyStatus struct {
ID string
ServerInstanceID string
PluginID string
ProbeKey string
TargetOS string
TargetArch string
State DependencyState
Required bool
InstallPlanKey string
Message string
CheckedAt time.Time
UpdatedAt time.Time
}
type ClientManagerBuildJob struct {
ID string
ServerInstanceID string
PluginID string
ProfileKey string
TargetOS string
TargetArch string
RepositoryURL string
SourceRevision string
ArtifactID string
Checksum string
KeyGeneration int
LogsRef string
Status DistributionJobStatus
CreatedAt time.Time
UpdatedAt time.Time
}
type RunUpdateJob struct {
ID string
ServerInstanceID string
RunEndpointID string
ArtifactID string
Checksum string
JobID string
IdempotencyKey string
Status DistributionJobStatus
CreatedAt time.Time
UpdatedAt time.Time
}
type RunDistributionGenerateRequest struct {
ServerInstanceID string
TargetOS string
TargetArch string
IdempotencyKey string
}
type ClientManagerBuildRequest struct {
ServerInstanceID string
ProfileKey string
TargetOS string
TargetArch string
RepositoryURL string
SourceRevision string
IdempotencyKey string
}
type ComponentKeyResetRequest struct {
ServerInstanceID string
ComponentKind DistributionComponentKind
ComponentKey string
}
type ComponentAuthenticationRequest struct {
ServerInstanceID string
ComponentKind DistributionComponentKind
ComponentKey string
Generation int
Key string
}
type ComponentAuthenticationResult struct {
ServerInstanceID string
ComponentKind DistributionComponentKind
ComponentKey string
Generation int
Allowed bool
Reason string
}
type ServerRuntimeAction struct {
Key string
Label string
Available bool
Reason string
}
type ServerRuntimeActions struct {
ServerInstanceID string
PluginID string
RunEndpointID string
RunStatus RunEndpointStatus
Actions []ServerRuntimeAction
}
type RunUpdateRequest struct {
ServerInstanceID string
ArtifactID string
Checksum string
IdempotencyKey string
}
type DependencyJobRequest struct {
ServerInstanceID string
ProbeKey string
InstallPlanKey string
TargetOS string
TargetArch string
IdempotencyKey string
Install bool
}
type LogBackfillRequest struct {
ServerInstanceID string
SourceKey string
CheckpointRef string
IdempotencyKey string
Limit int
}
type LogStream struct {
ID string
ServerInstanceID string
@@ -606,6 +884,51 @@ type ArtifactFilter struct {
State ArtifactState
}
type RuntimeBindingFilter struct {
ServerInstanceID string
ProfileKey string
Status RuntimeBindingStatus
}
type EncryptedComponentKeyFilter struct {
ServerInstanceID string
ComponentKind DistributionComponentKind
ComponentKey string
Status ComponentKeyStatus
}
type RunDistributionFilter struct {
ServerInstanceID string
TargetOS string
TargetArch string
Status DistributionStatus
}
type ClientManagerDistributionFilter struct {
ServerInstanceID string
ProfileKey string
TargetOS string
TargetArch string
Status DistributionStatus
}
type DependencyStatusFilter struct {
ServerInstanceID string
ProbeKey string
State DependencyState
}
type ClientManagerBuildJobFilter struct {
ServerInstanceID string
ProfileKey string
Status DistributionJobStatus
}
type RunUpdateJobFilter struct {
ServerInstanceID string
Status DistributionJobStatus
}
type LogStreamFilter struct {
ServerInstanceID string
StreamKey string
@@ -666,6 +989,7 @@ func CopyGamePlugin(plugin GamePlugin) GamePlugin {
plugin.Pages = CopyGamePluginPageSlice(plugin.Pages)
plugin.Tags = CopyStringSlice(plugin.Tags)
plugin.AIPurposes = CopyStringSlice(plugin.AIPurposes)
plugin.RemoteAccess = CopyGamePluginRemoteAccess(plugin.RemoteAccess)
plugin.ValidationViolations = CopyStringSlice(plugin.ValidationViolations)
return plugin
}
@@ -678,6 +1002,7 @@ func CopyPluginMarketplacePlugin(plugin PluginMarketplacePlugin) PluginMarketpla
plugin.Pages = CopyGamePluginPageSlice(plugin.Pages)
plugin.Tags = CopyStringSlice(plugin.Tags)
plugin.AIPurposes = CopyStringSlice(plugin.AIPurposes)
plugin.RemoteAccess = CopyGamePluginRemoteAccess(plugin.RemoteAccess)
plugin.ValidationViolations = CopyStringSlice(plugin.ValidationViolations)
return plugin
}
@@ -706,9 +1031,17 @@ func CopyGamePluginManifest(manifest GamePluginManifest) GamePluginManifest {
manifest.Permissions = CopyStringSlice(manifest.Permissions)
manifest.Pages = CopyGamePluginPageSlice(manifest.Pages)
manifest.AI.Purposes = CopyStringSlice(manifest.AI.Purposes)
manifest.RemoteAccess = CopyGamePluginRemoteAccess(manifest.RemoteAccess)
return manifest
}
func CopyGamePluginRemoteAccess(remote GamePluginRemoteAccess) GamePluginRemoteAccess {
remote.Methods = CopyStringSlice(remote.Methods)
remote.RunCapabilities = CopyStringSlice(remote.RunCapabilities)
remote.DatabaseEngines = CopyStringSlice(remote.DatabaseEngines)
return remote
}
func CopyGamePluginPageSlice(pages []GamePluginPage) []GamePluginPage {
if pages == nil {
return nil
@@ -807,6 +1140,86 @@ func CopyArtifact(artifact Artifact) Artifact {
return artifact
}
func CopyRuntimeBinding(binding RuntimeBinding) RuntimeBinding {
binding.Bindings = CopyStringMap(binding.Bindings)
binding.MissingKeys = CopyStringSlice(binding.MissingKeys)
return binding
}
func CopyEncryptedComponentKey(key EncryptedComponentKey) EncryptedComponentKey {
return key
}
func CopyRunDistribution(distribution RunDistribution) RunDistribution {
return distribution
}
func CopyClientManagerDistribution(distribution ClientManagerDistribution) ClientManagerDistribution {
return distribution
}
func CopyDependencyStatus(status DependencyStatus) DependencyStatus {
return status
}
func CopyClientManagerBuildJob(job ClientManagerBuildJob) ClientManagerBuildJob {
return job
}
func CopyRunUpdateJob(job RunUpdateJob) RunUpdateJob {
return job
}
func CopyRunDistributionGenerateRequest(request RunDistributionGenerateRequest) RunDistributionGenerateRequest {
return request
}
func CopyClientManagerBuildRequest(request ClientManagerBuildRequest) ClientManagerBuildRequest {
return request
}
func CopyComponentKeyResetRequest(request ComponentKeyResetRequest) ComponentKeyResetRequest {
return request
}
func CopyComponentAuthenticationRequest(request ComponentAuthenticationRequest) ComponentAuthenticationRequest {
return request
}
func CopyComponentAuthenticationResult(result ComponentAuthenticationResult) ComponentAuthenticationResult {
return result
}
func CopyServerRuntimeAction(action ServerRuntimeAction) ServerRuntimeAction {
return action
}
func CopyServerRuntimeActions(actions ServerRuntimeActions) ServerRuntimeActions {
actions.Actions = CopyServerRuntimeActionSlice(actions.Actions)
return actions
}
func CopyServerRuntimeActionSlice(actions []ServerRuntimeAction) []ServerRuntimeAction {
if actions == nil {
return nil
}
out := make([]ServerRuntimeAction, len(actions))
copy(out, actions)
return out
}
func CopyRunUpdateRequest(request RunUpdateRequest) RunUpdateRequest {
return request
}
func CopyDependencyJobRequest(request DependencyJobRequest) DependencyJobRequest {
return request
}
func CopyLogBackfillRequest(request LogBackfillRequest) LogBackfillRequest {
return request
}
func CopyLogStream(stream LogStream) LogStream {
return stream
}
+50 -1
View File
@@ -48,16 +48,21 @@ This file defines the first platform resource contracts. Concrete Go domain stru
- `createFormSchemaRef`: create form schema reference.
- `requiredRunCapabilities`: run capabilities required by this plugin.
- `declaredPermissions`: scoped manifest permission keys used by plugin bridge and marketplace views.
- `permissions`: aggregate platform ability declarations for AI, logs, files, jobs, and artifacts.
- `permissions`: aggregate platform ability declarations for AI, logs, files, jobs, artifacts, and remote access.
- `lifecycleActions`: manifest action contract references for install/start/stop and optional restart/status.
- `pages`: plugin-local page metadata with scoped permission requirements.
- `tags`: bounded catalog tags.
- `aiPurposes`: platform-mediated AI purposes such as config suggestions or log diagnosis.
- `remoteAccess`: plugin-declared remote access methods (`ftp`, `rsync`, `run`), run capabilities, database engines, RCON, and log transfer flags.
- `validationViolations`: safe validation findings for invalid plugin records.
- `status`: `installed`, `disabled`, `invalid`, or `updating`.
Manifest registration uses `GamePluginManifestRegistrationRequest` at `POST /api/v1/game-plugins/register-manifest`. Platform validation repeats plugin workspace safety checks and rejects raw host paths, direct run sockets, raw credentials, and raw AI/provider keys before metadata reaches the registry.
Remote access jobs are enabled only when both the selected run endpoint reports the capability and the server instance's installed plugin declares it. Plugin pages must use `remote.access.request` with `server.remote.access`; platform rejects undeclared database, RCON, log transfer, or remote file capabilities before creating jobs.
Runtime profile and distribution permissions are declared by plugins, then gated again by platform routes and services. `server.run.distribution` enables run package generation/download/reset/update operations, `server.dependencies.manage` enables dependency check/install jobs, and `server.client-manager.manage` enables plugin-declared companion client-manager generation/download/reset operations. Plugin metadata stores only declarations and safe refs; raw run/client-manager keys and transport credentials are stored through platform secret resources, never in plugin records.
## ServerInstance
- `id`: server instance ID.
@@ -80,6 +85,46 @@ Manifest registration uses `GamePluginManifestRegistrationRequest` at `POST /api
- `capacity`: current queue and resource summary.
- `lastHeartbeatAt`: last control heartbeat time.
Run control hello can include server/component identity from a generated package config. When `serverInstanceId`, `pluginId`, `componentKind`, `componentKey`, and `keyGeneration` are present, platform authenticates the provided key against the current encrypted component key before issuing a session token. Stale generations after reset are rejected without returning raw key material.
## RuntimeBinding
- `id`: runtime binding ID.
- `serverInstanceId`: server instance using the binding.
- `pluginId`: installed plugin that declared the logical runtime profile.
- `profileKey`: declared lifecycle/runtime profile key.
- `mode`: runtime mode such as `local-process`, `hosted-ftp-rcon`, `ftp-only`, or `custom-client`.
- `bindings`: logical binding keys to operator-provided settings.
- `missingKeys`: logical keys that must be completed before dependent actions are available.
- `status`: `complete`, `incomplete`, or `invalid`.
Bindings are used for action gating and run-side profile resolution. API responses and logs must use logical keys and safe reasons only; they must not expose raw host paths, direct sockets, FTP/RCON passwords, SQL DSNs, or component auth keys.
## Runtime Component Keys And Distributions
- `EncryptedComponentKey`: stores exactly one active encrypted key per server/component plus hash, fingerprint, redacted secret ref, generation, status, and reset time.
- `RunDistribution`: records a generated run package for one server, target OS/architecture, package format, artifact ID, checksum, key generation, secret ref, and status.
- `ClientManagerDistribution`: records a generated plugin-declared client-manager package with profile key, repository/source revision metadata, build job ID, artifact ID, checksum, key generation, secret ref, and status.
- `ClientManagerBuildJob`: records source checkout/build status, target platform, artifact ID, checksum, redacted build log ref, key generation, and status.
- `RunUpdateJob`: records platform-created run self-update orchestration with server, run endpoint, artifact ID, checksum, job ID, idempotency key, and status.
Run and client-manager keys are isolated singleton credentials. Reset replaces the encrypted database value, increments generation, marks older distributions revoked, and requires regenerating and redeploying that component. API DTOs may expose key generation, fingerprint, status, artifact ID, checksum, job ID, and `secret://runtime-keys/.../current` refs, but never the raw key.
## DependencyStatus
- `id`: dependency status ID.
- `serverInstanceId`: server instance checked by run.
- `pluginId`: plugin that declared the probe.
- `probeKey`: logical dependency probe key.
- `targetOs`, `targetArch`: target platform metadata.
- `state`: dependency state such as present, missing, failed, or unknown.
- `required`: whether the probe is required for the runtime profile.
- `installPlanKey`: optional typed install plan key.
- `message`: bounded safe status.
- `checkedAt`, `updatedAt`: observation times.
Dependency checks and installs are queued as run jobs with logical `dependencies/...` or `dependencies/install/...` target keys. Install jobs must use typed plugin-declared plans and must not carry arbitrary shell snippets.
## Job
- `id`: job ID.
@@ -96,6 +141,10 @@ Lifecycle workflow jobs use fixed capabilities:
- `process.install`: dispatched by server create workflow and projects successful terminal results to `ready`.
- `process.start`: dispatched by server start workflow and projects successful terminal results to `running`.
- `process.stop`: dispatched by server stop workflow and projects successful terminal results to `stopped`.
- `run.self-update`: dispatched by runtime distribution APIs with an approved artifact ref and checksum.
- `dependencies.check`: dispatched by dependency check APIs for a declared probe key.
- `dependencies.install`: dispatched by dependency install APIs for a declared typed install plan.
- `logs.backfill`: dispatched by historical log APIs for a declared source key and checkpoint ref.
Failed or cancelled lifecycle jobs project the server instance to `failed`. Active start/stop jobs are visible through job metadata; this change does not add separate `starting` or `stopping` server states.