first commit

This commit is contained in:
npc0-hue
2026-07-11 14:56:10 +08:00
commit 7e05d0a4e7
660 changed files with 78119 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
package domain
type AIInvocationRequest struct {
RequestID string
PluginID string
RouteKey string
ServerInstanceID string
Purpose string
ProviderID string
Model string
Prompt string
CurrentConfig string
ContextRefs map[string]string
}
type AIInvocationUsage struct {
ProviderID string
Model string
InputTokens int
OutputTokens int
Mocked bool
}
type AIConfigRecommendation struct {
Key string
SuggestedConfig string
DiffSummary string
}
type AIInvocationSafeError struct {
Code string
Message string
Details []string
}
type AIInvocationResponse struct {
RequestID string
Purpose string
ProviderID string
Model string
Status string
Recommendation string
ConfigRecommendation *AIConfigRecommendation
Usage AIInvocationUsage
Error *AIInvocationSafeError
}
type AIProviderInvocationResult struct {
Recommendation string
SuggestedConfig string
Usage AIInvocationUsage
Error *AIInvocationSafeError
}
func CopyAIInvocationRequest(request AIInvocationRequest) AIInvocationRequest {
request.ContextRefs = CopyStringMap(request.ContextRefs)
return request
}
func CopyAIInvocationResponse(response AIInvocationResponse) AIInvocationResponse {
if response.ConfigRecommendation != nil {
recommendation := *response.ConfigRecommendation
response.ConfigRecommendation = &recommendation
}
if response.Error != nil {
errorCopy := *response.Error
errorCopy.Details = CopyStringSlice(errorCopy.Details)
response.Error = &errorCopy
}
return response
}
+84
View File
@@ -0,0 +1,84 @@
package domain
import "time"
type ArtifactDownloadReferenceRequest struct {
ArtifactID string
}
type ArtifactDownloadReference struct {
ArtifactID string
OwnerKind ArtifactOwnerKind
OwnerID string
Filename string
ContentType string
SizeBytes int64
Checksum string
State ArtifactState
DownloadURL string
ExpiresAt time.Time
RangeSupported bool
ChunkSizeBytes int
StorageBehavior string
}
type ArtifactContentRequest struct {
ArtifactID string
Offset int64
Limit int
}
type ArtifactContent struct {
ArtifactID string
Filename string
ContentType string
Offset int64
SizeBytes int64
TotalSizeBytes int64
Checksum string
ContentChecksum string
Partial bool
RangeSupported bool
Payload []byte
StorageBehavior string
ServedAt time.Time
}
type ArtifactTransferProgress struct {
ArtifactID string
BytesRead int64
TotalSizeBytes int64
Complete bool
}
type ArtifactDownloadSafeError struct {
Code string
Message string
Details []string
}
func CopyArtifactDownloadReferenceRequest(request ArtifactDownloadReferenceRequest) ArtifactDownloadReferenceRequest {
return request
}
func CopyArtifactDownloadReference(reference ArtifactDownloadReference) ArtifactDownloadReference {
return reference
}
func CopyArtifactContentRequest(request ArtifactContentRequest) ArtifactContentRequest {
return request
}
func CopyArtifactContent(content ArtifactContent) ArtifactContent {
content.Payload = CopyBytes(content.Payload)
return content
}
func CopyArtifactTransferProgress(progress ArtifactTransferProgress) ArtifactTransferProgress {
return progress
}
func CopyArtifactDownloadSafeError(safeError ArtifactDownloadSafeError) ArtifactDownloadSafeError {
safeError.Details = CopyStringSlice(safeError.Details)
return safeError
}
+187
View File
@@ -0,0 +1,187 @@
package domain
import "time"
type ArtifactTransferDirection string
const (
ArtifactTransferDirectionUpload ArtifactTransferDirection = "upload"
)
type ArtifactTransferOpen struct {
RunEndpointID string
SessionToken string
ArtifactID string
Direction ArtifactTransferDirection
OwnerKind ArtifactOwnerKind
OwnerID string
SizeBytes int64
ChunkSizeBytes int
Checksum string
IdempotencyKey string
}
type ArtifactTransferOpenResult struct {
Accepted bool
TransferID string
Direction ArtifactTransferDirection
Artifact Artifact
TotalChunks int
ChunkSizeBytes int
ReceivedChunkIndexes []int
NextMissingChunkIndex int
Completed bool
Duplicate bool
ServerTime time.Time
}
type ArtifactChunkUpload struct {
RunEndpointID string
SessionToken string
TransferID string
ArtifactID string
ChunkIndex int
Offset int64
SizeBytes int
Checksum string
Payload []byte
}
type ArtifactChunkUploadResult struct {
Accepted bool
TransferID string
ArtifactID string
ChunkIndex int
ReceivedChunkIndexes []int
NextMissingChunkIndex int
Duplicate bool
ServerTime time.Time
}
type ArtifactTransferStatusQuery struct {
RunEndpointID string
SessionToken string
TransferID string
ArtifactID string
}
type ArtifactTransferStatusResult struct {
Accepted bool
TransferID string
ArtifactID string
Direction ArtifactTransferDirection
TotalChunks int
ChunkSizeBytes int
ReceivedChunkIndexes []int
NextMissingChunkIndex int
Completed bool
ServerTime time.Time
}
type ArtifactTransferComplete struct {
RunEndpointID string
SessionToken string
TransferID string
ArtifactID string
Checksum string
SizeBytes int64
}
type ArtifactTransferCompleteResult struct {
Accepted bool
TransferID string
Artifact Artifact
Completed bool
ServerTime time.Time
}
type ArtifactChunkRecord struct {
ChunkIndex int
Offset int64
SizeBytes int
Checksum string
Payload []byte
ReceivedAt time.Time
}
type ArtifactTransferSession struct {
TransferID string
RunEndpointID string
ArtifactID string
Direction ArtifactTransferDirection
OwnerKind ArtifactOwnerKind
OwnerID string
SizeBytes int64
ChunkSizeBytes int
Checksum string
IdempotencyKey string
TotalChunks int
ReceivedChunks map[int]ArtifactChunkRecord
Completed bool
CreatedAt time.Time
UpdatedAt time.Time
}
func CopyArtifactTransferOpen(open ArtifactTransferOpen) ArtifactTransferOpen {
return open
}
func CopyArtifactChunkUpload(chunk ArtifactChunkUpload) ArtifactChunkUpload {
chunk.Payload = CopyBytes(chunk.Payload)
return chunk
}
func CopyArtifactTransferOpenResult(result ArtifactTransferOpenResult) ArtifactTransferOpenResult {
result.Artifact = CopyArtifact(result.Artifact)
result.ReceivedChunkIndexes = CopyIntSlice(result.ReceivedChunkIndexes)
return result
}
func CopyArtifactChunkUploadResult(result ArtifactChunkUploadResult) ArtifactChunkUploadResult {
result.ReceivedChunkIndexes = CopyIntSlice(result.ReceivedChunkIndexes)
return result
}
func CopyArtifactTransferStatusResult(result ArtifactTransferStatusResult) ArtifactTransferStatusResult {
result.ReceivedChunkIndexes = CopyIntSlice(result.ReceivedChunkIndexes)
return result
}
func CopyArtifactTransferCompleteResult(result ArtifactTransferCompleteResult) ArtifactTransferCompleteResult {
result.Artifact = CopyArtifact(result.Artifact)
return result
}
func CopyArtifactChunkRecord(record ArtifactChunkRecord) ArtifactChunkRecord {
record.Payload = CopyBytes(record.Payload)
return record
}
func CopyArtifactTransferSession(session ArtifactTransferSession) ArtifactTransferSession {
if session.ReceivedChunks != nil {
chunks := make(map[int]ArtifactChunkRecord, len(session.ReceivedChunks))
for index, record := range session.ReceivedChunks {
chunks[index] = CopyArtifactChunkRecord(record)
}
session.ReceivedChunks = chunks
}
return session
}
func CopyBytes(values []byte) []byte {
if values == nil {
return nil
}
out := make([]byte, len(values))
copy(out, values)
return out
}
func CopyIntSlice(values []int) []int {
if values == nil {
return nil
}
out := make([]int, len(values))
copy(out, values)
return out
}
+81
View File
@@ -0,0 +1,81 @@
package domain
import "time"
type RunCapabilityReport struct {
Capabilities []string
Fingerprint string
}
type RunControlHello struct {
RegistrationToken string
RunEndpointID string
DisplayName string
Version string
Status RunEndpointStatus
Platform string
CapabilityReport RunCapabilityReport
Capacity RunCapacity
}
type RunControlHelloResult struct {
Accepted bool
RunEndpointID string
SessionToken string
ServerTime time.Time
HeartbeatIntervalSeconds int
FeatureFlags []string
}
type RunControlHeartbeat struct {
RunEndpointID string
SessionToken string
Version string
Status RunEndpointStatus
CapabilityFingerprint string
Capacity RunCapacity
}
type RunControlHeartbeatResult struct {
Accepted bool
RunEndpointID string
NextHeartbeatSeconds int
RefreshCapabilities bool
ServerTime time.Time
}
type RunControlSession struct {
RunEndpointID string
SessionToken string
CapabilityFingerprint string
HeartbeatIntervalSeconds int
CreatedAt time.Time
UpdatedAt time.Time
}
func CopyRunCapabilityReport(report RunCapabilityReport) RunCapabilityReport {
report.Capabilities = CopyStringSlice(report.Capabilities)
return report
}
func CopyRunControlHello(hello RunControlHello) RunControlHello {
hello.CapabilityReport = CopyRunCapabilityReport(hello.CapabilityReport)
return hello
}
func CopyRunControlHelloResult(result RunControlHelloResult) RunControlHelloResult {
result.FeatureFlags = CopyStringSlice(result.FeatureFlags)
return result
}
func CopyRunControlHeartbeat(heartbeat RunControlHeartbeat) RunControlHeartbeat {
return heartbeat
}
func CopyRunControlHeartbeatResult(result RunControlHeartbeatResult) RunControlHeartbeatResult {
return result
}
func CopyRunControlSession(session RunControlSession) RunControlSession {
return session
}
+193
View File
@@ -0,0 +1,193 @@
package domain
import "time"
type RunJobProgressReport struct {
Percent int
Message string
}
type RunJobAssignment struct {
JobID string
ServerInstanceID string
RunEndpointID string
Capability string
TargetKey string
InputRef string
IdempotencyKey string
State JobState
Progress RunJobProgressReport
ResultRef string
LeaseToken string
Attempt int
CreatedAt time.Time
UpdatedAt time.Time
}
type RunJobClaim struct {
RunEndpointID string
SessionToken string
Capabilities []string
Capacity RunCapacity
}
type RunJobClaimResult struct {
Accepted bool
RunEndpointID string
HasJob bool
Job *RunJobAssignment
NextPollSeconds int
ServerTime time.Time
}
type RunJobAck struct {
RunEndpointID string
SessionToken string
JobID string
LeaseToken string
Attempt int
Message string
}
type RunJobAckResult struct {
Accepted bool
Job RunJobAssignment
ServerTime time.Time
}
type RunJobProgress struct {
RunEndpointID string
SessionToken string
JobID string
LeaseToken string
Attempt int
Progress RunJobProgressReport
Sequence uint64
}
type RunJobProgressResult struct {
Accepted bool
Job RunJobAssignment
ServerTime time.Time
}
type RunJobResult struct {
RunEndpointID string
SessionToken string
JobID string
LeaseToken string
Attempt int
State JobState
Progress RunJobProgressReport
ResultRef string
Message string
ErrorCode string
}
type RunJobResultResult struct {
Accepted bool
Job RunJobAssignment
ServerTime time.Time
}
type RunJobCancelRequest struct {
JobID string
Reason string
}
type RunJobCancelRequestResult struct {
Accepted bool
JobID string
Reason string
RequestedAt time.Time
}
type RunJobCancelPoll struct {
RunEndpointID string
SessionToken string
JobID string
LeaseToken string
}
type RunJobCancelPollResult struct {
Accepted bool
RunEndpointID string
HasCancel bool
JobID string
Reason string
RequestedAt time.Time
ServerTime time.Time
}
type RunJobReconcile struct {
RunEndpointID string
SessionToken string
ActiveJobIDs []string
}
type RunJobReconcileResult struct {
Accepted bool
RunEndpointID string
ActiveJobs []RunJobAssignment
UnknownJobIDs []string
ServerTime time.Time
}
type RunJobLease struct {
JobID string
RunEndpointID string
SessionToken string
LeaseToken string
Attempt int
CancelReason string
CancelRequestedAt time.Time
TerminalFingerprint string
CreatedAt time.Time
UpdatedAt time.Time
}
func CopyRunJobAssignment(assignment RunJobAssignment) RunJobAssignment {
return assignment
}
func CopyRunJobAssignmentPtr(assignment *RunJobAssignment) *RunJobAssignment {
if assignment == nil {
return nil
}
copy := CopyRunJobAssignment(*assignment)
return &copy
}
func CopyRunJobClaim(claim RunJobClaim) RunJobClaim {
claim.Capabilities = CopyStringSlice(claim.Capabilities)
return claim
}
func CopyRunJobClaimResult(result RunJobClaimResult) RunJobClaimResult {
result.Job = CopyRunJobAssignmentPtr(result.Job)
return result
}
func CopyRunJobReconcile(reconcile RunJobReconcile) RunJobReconcile {
reconcile.ActiveJobIDs = CopyStringSlice(reconcile.ActiveJobIDs)
return reconcile
}
func CopyRunJobReconcileResult(result RunJobReconcileResult) RunJobReconcileResult {
result.ActiveJobs = CopyRunJobAssignments(result.ActiveJobs)
result.UnknownJobIDs = CopyStringSlice(result.UnknownJobIDs)
return result
}
func CopyRunJobAssignments(assignments []RunJobAssignment) []RunJobAssignment {
if assignments == nil {
return nil
}
out := make([]RunJobAssignment, len(assignments))
copy(out, assignments)
return out
}
func CopyRunJobLease(lease RunJobLease) RunJobLease {
return lease
}
+93
View File
@@ -0,0 +1,93 @@
package domain
import "time"
type LogEntry struct {
Seq uint64
Timestamp time.Time
Level string
Line string
Fields map[string]string
Redacted bool
}
type LogBatchIngest struct {
RunEndpointID string
SessionToken string
LogStreamID string
ServerInstanceID string
StreamKey string
Source LogStreamSource
FirstSeq uint64
LastSeq uint64
Compression string
Checksum string
Entries []LogEntry
}
type LogBatchIngestResult struct {
Accepted bool
LogStreamID string
AcceptedFrom uint64
AcceptedTo uint64
LatestSeq uint64
Duplicate bool
ServerTime time.Time
}
type LogStreamCursorQuery struct {
LogStreamID string
AfterSeq uint64
Limit int
}
type LogStreamCursorResult struct {
LogStreamID string
Entries []LogEntry
NextSeq uint64
LatestSeq uint64
}
type LogBatchRecord struct {
Checksum string
FirstSeq uint64
LastSeq uint64
Entries []LogEntry
}
func CopyLogEntry(entry LogEntry) LogEntry {
if entry.Fields != nil {
fields := make(map[string]string, len(entry.Fields))
for key, value := range entry.Fields {
fields[key] = value
}
entry.Fields = fields
}
return entry
}
func CopyLogEntries(entries []LogEntry) []LogEntry {
if entries == nil {
return nil
}
out := make([]LogEntry, len(entries))
for i, entry := range entries {
out[i] = CopyLogEntry(entry)
}
return out
}
func CopyLogBatchIngest(batch LogBatchIngest) LogBatchIngest {
batch.Entries = CopyLogEntries(batch.Entries)
return batch
}
func CopyLogStreamCursorResult(result LogStreamCursorResult) LogStreamCursorResult {
result.Entries = CopyLogEntries(result.Entries)
return result
}
func CopyLogBatchRecord(record LogBatchRecord) LogBatchRecord {
record.Entries = CopyLogEntries(record.Entries)
return record
}
+816
View File
@@ -0,0 +1,816 @@
package domain
import "time"
type UserStatus string
const (
UserStatusActive UserStatus = "active"
UserStatusDisabled UserStatus = "disabled"
UserStatusPending UserStatus = "pending"
)
type AIProviderKind string
const (
AIProviderKindOpenAICompatible AIProviderKind = "openai-compatible"
AIProviderKindOpenAI AIProviderKind = "openai"
AIProviderKindClaude AIProviderKind = "claude"
AIProviderKindGemini AIProviderKind = "gemini"
AIProviderKindOllama AIProviderKind = "ollama"
AIProviderKindCustom AIProviderKind = "custom"
)
type AIRelayMode string
const (
AIRelayModeDirect AIRelayMode = "direct"
AIRelayModeRelay AIRelayMode = "relay"
AIRelayModeLocal AIRelayMode = "local"
)
type AIProviderStatus string
const (
AIProviderStatusActive AIProviderStatus = "active"
AIProviderStatusDisabled AIProviderStatus = "disabled"
AIProviderStatusError AIProviderStatus = "error"
)
type GamePluginStatus string
const (
GamePluginStatusInstalled GamePluginStatus = "installed"
GamePluginStatusDisabled GamePluginStatus = "disabled"
GamePluginStatusInvalid GamePluginStatus = "invalid"
GamePluginStatusUpdating GamePluginStatus = "updating"
)
type PluginMarketplaceStateAction string
const (
PluginMarketplaceStateActionInstall PluginMarketplaceStateAction = "install"
PluginMarketplaceStateActionEnable PluginMarketplaceStateAction = "enable"
PluginMarketplaceStateActionDisable PluginMarketplaceStateAction = "disable"
)
type ServerInstanceState string
const (
ServerInstanceStateDraft ServerInstanceState = "draft"
ServerInstanceStateInstalling ServerInstanceState = "installing"
ServerInstanceStateReady ServerInstanceState = "ready"
ServerInstanceStateRunning ServerInstanceState = "running"
ServerInstanceStateStopped ServerInstanceState = "stopped"
ServerInstanceStateFailed ServerInstanceState = "failed"
ServerInstanceStateDeleted ServerInstanceState = "deleted"
)
type RunEndpointStatus string
const (
RunEndpointStatusOnline RunEndpointStatus = "online"
RunEndpointStatusOffline RunEndpointStatus = "offline"
RunEndpointStatusDegraded RunEndpointStatus = "degraded"
RunEndpointStatusDisabled RunEndpointStatus = "disabled"
)
type JobState string
const (
JobStateQueued JobState = "queued"
JobStateAccepted JobState = "accepted"
JobStateRunning JobState = "running"
JobStateSucceeded JobState = "succeeded"
JobStateFailed JobState = "failed"
JobStateCancelled JobState = "cancelled"
)
type ArtifactOwnerKind string
const (
ArtifactOwnerKindPlatform ArtifactOwnerKind = "platform"
ArtifactOwnerKindPlugin ArtifactOwnerKind = "plugin"
ArtifactOwnerKindServerInstance ArtifactOwnerKind = "server-instance"
ArtifactOwnerKindJob ArtifactOwnerKind = "job"
)
type ArtifactState string
const (
ArtifactStateUploading ArtifactState = "uploading"
ArtifactStateAvailable ArtifactState = "available"
ArtifactStateExpired ArtifactState = "expired"
ArtifactStateFailed ArtifactState = "failed"
)
type LogStreamSource string
const (
LogStreamSourceProcess LogStreamSource = "process"
LogStreamSourceFile LogStreamSource = "file"
LogStreamSourcePlugin LogStreamSource = "plugin"
)
type LogStorageBackend string
const (
LogStorageBackendLocalSegments LogStorageBackend = "local-segments"
LogStorageBackendLoki LogStorageBackend = "loki"
LogStorageBackendClickHouse LogStorageBackend = "clickhouse"
LogStorageBackendOpenSearch LogStorageBackend = "opensearch"
LogStorageBackendElasticsearch LogStorageBackend = "elasticsearch"
)
type AuditResult string
const (
AuditResultSuccess AuditResult = "success"
AuditResultDenied AuditResult = "denied"
AuditResultFailed AuditResult = "failed"
AuditResultQueued AuditResult = "queued"
)
type User struct {
ID string
DisplayName string
Email string
Status UserStatus
Roles []string
PasswordHash string
Profile UserProfile
Theme UserThemePreference
CreatedAt time.Time
UpdatedAt time.Time
}
type UserProfile struct {
AvatarURL string
Phone string
QQ string
ContactNote string
}
type UserThemePreference struct {
UserID string
PaletteID string
BackgroundPresetID string
BackgroundImage string
Persistence string
UpdatedAt time.Time
}
type UserRegistration struct {
DisplayName string
Email string
Password string
Profile UserProfile
}
type UserLogin struct {
Account string
Password string
}
type AuthSession struct {
SessionID string
User User
Status string
Message string
}
type AIProvider struct {
ID string
Name string
Kind AIProviderKind
BaseURL string
APIKeyRef string
Models []string
DefaultModel string
RelayMode AIRelayMode
TimeoutMS int
Status AIProviderStatus
RedactionPolicy string
}
type AIProviderTestResult struct {
ProviderID string
Mode string
Success bool
Message string
Violations []string
}
type AIProviderModels struct {
ProviderID string
DefaultModel string
Models []string
}
type PluginPermissions struct {
AI bool
Logs bool
Files bool
Jobs bool
Artifacts bool
}
type PluginLifecycleActions struct {
Install string
Start string
Stop string
Restart string
Status string
}
type GamePluginPage struct {
Key string
Title string
Path string
Permissions []string
BridgeActions []string
}
type GamePluginBridge struct {
Actions []string
}
type GamePluginManifestServer struct {
Type string
DisplayName string
SupportedOS []string
CreateFormSchema string
}
type GamePluginManifestAI struct {
Purposes []string
}
type GamePluginManifest struct {
ID string
Name string
Description string
Version string
Kind string
Tags []string
Server GamePluginManifestServer
Bridge GamePluginBridge
Capabilities []string
Permissions []string
Actions PluginLifecycleActions
Pages []GamePluginPage
AI GamePluginManifestAI
}
type GamePluginManifestRegistration struct {
ManifestRef string
Manifest GamePluginManifest
}
type GamePlugin struct {
ID string
Name string
Description string
Version string
ServerType string
ServerDisplayName string
SupportedOS []string
ManifestRef string
CreateFormSchemaRef string
RequiredRunCapabilities []string
DeclaredPermissions []string
Permissions PluginPermissions
LifecycleActions PluginLifecycleActions
BridgeActions []string
Pages []GamePluginPage
Tags []string
AIPurposes []string
ValidationViolations []string
Status GamePluginStatus
}
type PluginMarketplacePlugin struct {
ID string
Name string
Description string
Version string
ServerType string
ServerDisplayName string
SupportedOS []string
ManifestRef string
CreateFormSchemaRef string
Capabilities []string
DeclaredPermissions []string
Permissions PluginPermissions
LifecycleActions PluginLifecycleActions
BridgeActions []string
Pages []GamePluginPage
Tags []string
AIPurposes []string
ValidationViolations []string
Status GamePluginStatus
Source string
}
type PluginBridgeAction string
const (
PluginBridgeActionServerInstancesRead PluginBridgeAction = "server.instances.read"
PluginBridgeActionJobsDispatch PluginBridgeAction = "jobs.dispatch"
PluginBridgeActionLogsQuery PluginBridgeAction = "logs.query"
PluginBridgeActionArtifactsOpen PluginBridgeAction = "artifacts.open"
PluginBridgeActionFilesRequest PluginBridgeAction = "files.request"
PluginBridgeActionAIInvoke PluginBridgeAction = "ai.invoke"
)
type PluginBridgeAuthorizeRequest struct {
PluginID string
RouteKey string
ServerInstanceID string
Action PluginBridgeAction
AIPurpose string
}
type PluginBridgeAuthorization struct {
PluginID string
RouteKey string
ServerInstanceID string
Action PluginBridgeAction
Allowed bool
RequiredPermissions []string
EffectivePermissions []string
Reason string
}
type PluginBridgeExecuteRequest struct {
RequestID string
PluginID string
RouteKey string
ServerInstanceID string
Action PluginBridgeAction
AIPurpose string
Payload map[string]string
}
type PluginBridgeSafeError struct {
Code string
Message string
Details []string
}
type PluginBridgeExecuteResponse struct {
RequestID string
PluginID string
RouteKey string
ServerInstanceID string
Action PluginBridgeAction
Status string
Result map[string]string
Error *PluginBridgeSafeError
}
type ServerInstance struct {
ID string
PluginID string
PluginVersion string
RunEndpointID string
Name string
OwnerUserID string
AdminUserIDs []string
State ServerInstanceState
ConfigVersion int
CreatedAt time.Time
UpdatedAt time.Time
}
type PlatformResourceUsage struct {
CPUPercent float64
MemoryPercent float64
DiskPercent float64
Source string
CollectedAt time.Time
}
type ServerMetrics struct {
ServerInstanceID string
Online bool
PlayerCount *int
MaxPlayers *int
TPS *float64
LatencyMS *float64
CPUPercent *float64
MemoryPercent *float64
DiskPercent *float64
Source string
CollectedAt time.Time
}
type ServerConfig struct {
ServerInstanceID string
ConfigVersion int
Format string
Key string
Content string
Source string
UpdatedAt time.Time
}
type ConfigDiffLine struct {
Kind string
OldNumber int
NewNumber int
Content string
}
type ServerConfigDiffRequest struct {
ServerInstanceID string
ExpectedConfigVersion int
Key string
ProposedContent string
ProposedContentInputRef string
}
type ServerConfigDiffPreview struct {
ServerInstanceID string
ConfigVersion int
Key string
CurrentContent string
ProposedContent string
ProposedContentInputRef string
Diff []ConfigDiffLine
HasChanges bool
Source string
ReviewedAt time.Time
}
type ServerConfigWriteApproval struct {
ServerInstanceID string
ExpectedConfigVersion int
Key string
ProposedContent string
ProposedContentInputRef string
IdempotencyKey string
}
type ServerConfigWriteDispatch struct {
Preview ServerConfigDiffPreview
Job Job
Status string
}
type FileOperationKind string
const (
FileOperationRead FileOperationKind = "read"
FileOperationWrite FileOperationKind = "write"
)
type FileOperationDispatchRequest struct {
ServerInstanceID string
PluginID string
Operation FileOperationKind
Key string
InputRef string
ExpectedConfigVersion int
IdempotencyKey string
}
type FileOperationDispatchResult struct {
ServerInstanceID string
PluginID string
Operation FileOperationKind
Key string
InputRef string
Job Job
Status string
}
type RunCapacity struct {
MaxJobs int
RunningJobs int
QueuedJobs int
Summary string
}
const (
JobCapabilityConfigWrite = "config.write"
JobCapabilityFilesRead = "files.read"
JobCapabilityFilesWrite = "files.write"
)
type RunEndpoint struct {
ID string
DisplayName string
Version string
Status RunEndpointStatus
Capabilities []string
Capacity RunCapacity
LastHeartbeatAt time.Time
}
type JobProgress struct {
Percent int
Message string
}
type Job struct {
ID string
ServerInstanceID string
RunEndpointID string
Capability string
TargetKey string
InputRef string
IdempotencyKey string
State JobState
Progress JobProgress
ResultRef string
CreatedAt time.Time
UpdatedAt time.Time
}
type Artifact struct {
ID string
OwnerKind ArtifactOwnerKind
OwnerID string
SizeBytes int64
Checksum string
State ArtifactState
CreatedAt time.Time
UpdatedAt time.Time
}
type LogStream struct {
ID string
ServerInstanceID string
Source LogStreamSource
StreamKey string
LatestSeq uint64
StorageBackend LogStorageBackend
RetentionPolicy string
CreatedAt time.Time
UpdatedAt time.Time
}
type AuditEvent struct {
ID string
ActorID string
Action string
ResourceKind string
ResourceID string
Result AuditResult
Summary string
CreatedAt time.Time
}
type UserFilter struct {
Status UserStatus
}
type AIProviderFilter struct {
Kind AIProviderKind
Status AIProviderStatus
}
type GamePluginFilter struct {
ServerType string
Status GamePluginStatus
}
type PluginMarketplaceFilter struct {
ServerType string
Status GamePluginStatus
Capability string
Keyword string
}
type ServerInstanceFilter struct {
PluginID string
RunEndpointID string
State ServerInstanceState
VisibleToUserID string
}
type RunEndpointFilter struct {
Status RunEndpointStatus
}
type JobFilter struct {
ServerInstanceID string
RunEndpointID string
State JobState
}
type ArtifactFilter struct {
OwnerKind ArtifactOwnerKind
OwnerID string
State ArtifactState
}
type LogStreamFilter struct {
ServerInstanceID string
StreamKey string
}
type AuditEventFilter struct {
ActorID string
ResourceKind string
ResourceID string
Result AuditResult
}
func CopyStringSlice(values []string) []string {
if values == nil {
return nil
}
out := make([]string, len(values))
copy(out, values)
return out
}
func CopyStringMap(values map[string]string) map[string]string {
if values == nil {
return nil
}
out := make(map[string]string, len(values))
for key, value := range values {
out[key] = value
}
return out
}
func CopyUser(user User) User {
user.Roles = CopyStringSlice(user.Roles)
return user
}
func CopyAIProvider(provider AIProvider) AIProvider {
provider.Models = CopyStringSlice(provider.Models)
return provider
}
func CopyAIProviderTestResult(result AIProviderTestResult) AIProviderTestResult {
result.Violations = CopyStringSlice(result.Violations)
return result
}
func CopyAIProviderModels(models AIProviderModels) AIProviderModels {
models.Models = CopyStringSlice(models.Models)
return models
}
func CopyGamePlugin(plugin GamePlugin) GamePlugin {
plugin.RequiredRunCapabilities = CopyStringSlice(plugin.RequiredRunCapabilities)
plugin.DeclaredPermissions = CopyStringSlice(plugin.DeclaredPermissions)
plugin.SupportedOS = CopyStringSlice(plugin.SupportedOS)
plugin.BridgeActions = CopyStringSlice(plugin.BridgeActions)
plugin.Pages = CopyGamePluginPageSlice(plugin.Pages)
plugin.Tags = CopyStringSlice(plugin.Tags)
plugin.AIPurposes = CopyStringSlice(plugin.AIPurposes)
plugin.ValidationViolations = CopyStringSlice(plugin.ValidationViolations)
return plugin
}
func CopyPluginMarketplacePlugin(plugin PluginMarketplacePlugin) PluginMarketplacePlugin {
plugin.SupportedOS = CopyStringSlice(plugin.SupportedOS)
plugin.Capabilities = CopyStringSlice(plugin.Capabilities)
plugin.DeclaredPermissions = CopyStringSlice(plugin.DeclaredPermissions)
plugin.BridgeActions = CopyStringSlice(plugin.BridgeActions)
plugin.Pages = CopyGamePluginPageSlice(plugin.Pages)
plugin.Tags = CopyStringSlice(plugin.Tags)
plugin.AIPurposes = CopyStringSlice(plugin.AIPurposes)
plugin.ValidationViolations = CopyStringSlice(plugin.ValidationViolations)
return plugin
}
func CopyPluginMarketplacePluginSlice(plugins []PluginMarketplacePlugin) []PluginMarketplacePlugin {
if plugins == nil {
return nil
}
out := make([]PluginMarketplacePlugin, len(plugins))
for i, plugin := range plugins {
out[i] = CopyPluginMarketplacePlugin(plugin)
}
return out
}
func CopyGamePluginManifestRegistration(registration GamePluginManifestRegistration) GamePluginManifestRegistration {
registration.Manifest = CopyGamePluginManifest(registration.Manifest)
return registration
}
func CopyGamePluginManifest(manifest GamePluginManifest) GamePluginManifest {
manifest.Tags = CopyStringSlice(manifest.Tags)
manifest.Server.SupportedOS = CopyStringSlice(manifest.Server.SupportedOS)
manifest.Bridge.Actions = CopyStringSlice(manifest.Bridge.Actions)
manifest.Capabilities = CopyStringSlice(manifest.Capabilities)
manifest.Permissions = CopyStringSlice(manifest.Permissions)
manifest.Pages = CopyGamePluginPageSlice(manifest.Pages)
manifest.AI.Purposes = CopyStringSlice(manifest.AI.Purposes)
return manifest
}
func CopyGamePluginPageSlice(pages []GamePluginPage) []GamePluginPage {
if pages == nil {
return nil
}
out := make([]GamePluginPage, len(pages))
for i, page := range pages {
out[i] = page
out[i].Permissions = CopyStringSlice(page.Permissions)
out[i].BridgeActions = CopyStringSlice(page.BridgeActions)
}
return out
}
func CopyPluginBridgeAuthorization(result PluginBridgeAuthorization) PluginBridgeAuthorization {
result.RequiredPermissions = CopyStringSlice(result.RequiredPermissions)
result.EffectivePermissions = CopyStringSlice(result.EffectivePermissions)
return result
}
func CopyPluginBridgeExecuteRequest(request PluginBridgeExecuteRequest) PluginBridgeExecuteRequest {
request.Payload = CopyStringMap(request.Payload)
return request
}
func CopyPluginBridgeExecuteResponse(response PluginBridgeExecuteResponse) PluginBridgeExecuteResponse {
response.Result = CopyStringMap(response.Result)
if response.Error != nil {
errorCopy := *response.Error
errorCopy.Details = CopyStringSlice(errorCopy.Details)
response.Error = &errorCopy
}
return response
}
func CopyServerInstance(instance ServerInstance) ServerInstance {
instance.AdminUserIDs = CopyStringSlice(instance.AdminUserIDs)
return instance
}
func CopyPlatformResourceUsage(usage PlatformResourceUsage) PlatformResourceUsage {
return usage
}
func CopyServerMetrics(metrics ServerMetrics) ServerMetrics {
return metrics
}
func CopyServerMetricsSlice(items []ServerMetrics) []ServerMetrics {
if items == nil {
return nil
}
out := make([]ServerMetrics, len(items))
copy(out, items)
return out
}
func CopyServerConfig(config ServerConfig) ServerConfig {
return config
}
func CopyConfigDiffLines(lines []ConfigDiffLine) []ConfigDiffLine {
if lines == nil {
return nil
}
out := make([]ConfigDiffLine, len(lines))
copy(out, lines)
return out
}
func CopyServerConfigDiffPreview(preview ServerConfigDiffPreview) ServerConfigDiffPreview {
preview.Diff = CopyConfigDiffLines(preview.Diff)
return preview
}
func CopyServerConfigWriteDispatch(dispatch ServerConfigWriteDispatch) ServerConfigWriteDispatch {
dispatch.Preview = CopyServerConfigDiffPreview(dispatch.Preview)
dispatch.Job = CopyJob(dispatch.Job)
return dispatch
}
func CopyFileOperationDispatchResult(result FileOperationDispatchResult) FileOperationDispatchResult {
result.Job = CopyJob(result.Job)
return result
}
func CopyRunEndpoint(endpoint RunEndpoint) RunEndpoint {
endpoint.Capabilities = CopyStringSlice(endpoint.Capabilities)
return endpoint
}
func CopyJob(job Job) Job {
return job
}
func CopyArtifact(artifact Artifact) Artifact {
return artifact
}
func CopyLogStream(stream LogStream) LogStream {
return stream
}
func CopyAuditEvent(event AuditEvent) AuditEvent {
return event
}
+130
View File
@@ -0,0 +1,130 @@
# Platform Domain Resources
This file defines the first platform resource contracts. Concrete Go domain structs are implemented in `platform/domain/resources.go`; API DTO projections live in `platform/dto/resources.go`; database model projections live in `platform/model/resources.go`. Do not define these resource shapes inside handlers or service functions.
## Implemented Boundaries
- Domain constants centralize allowed status, state, provider kind, relay mode, artifact owner, storage backend, and audit result values.
- DTO responses expose `apiKeyRef` for AI providers but never raw key material.
- Model structs include JSON/database tags and explicit `TableName()` mappings for future persistence work.
- `platform/repo.NewFileStore` provides durable local metadata snapshots for platform startup, while `platform/repo.NewMemoryStore` provides deterministic in-memory repository behavior for unit tests and disposable local runs.
- Log stream metadata records the selected body backend. The current durable local body backend uses `local-segments`; future production adapters should target log-optimized stores such as `clickhouse`, `loki`, `opensearch`, or `elasticsearch` rather than row-per-line relational tables.
- `platform/service.Core` enforces create/list/get workflows and cross-resource invariants before resources are persisted.
## User
- `id`: stable user ID.
- `displayName`: visible user name.
- `email`: optional login email.
- `status`: `active`, `disabled`, or `pending`.
- `roles`: role keys assigned to the user.
- `createdAt`: creation time.
- `updatedAt`: last update time.
## AIProvider
- `id`: stable provider ID.
- `name`: display name.
- `kind`: `openai-compatible`, `openai`, `claude`, `gemini`, `ollama`, or `custom`.
- `baseUrl`: provider or relay base URL.
- `apiKeyRef`: secret reference, never the raw key.
- `models`: allowed model IDs.
- `defaultModel`: optional default model.
- `relayMode`: `direct`, `relay`, or `local`.
- `timeoutMs`: request timeout.
- `status`: `active`, `disabled`, or `error`.
- `redactionPolicy`: policy key for prompt/input/output redaction.
## GamePlugin
- `id`: plugin ID such as `game.example`.
- `name`: display name.
- `description`: bounded marketplace/registry summary.
- `version`: installed version.
- `serverType`: game/server type key.
- `serverDisplayName`: visible server type name.
- `supportedOs`: operating systems declared by the plugin manifest.
- `manifestRef`: immutable manifest artifact reference.
- `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.
- `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.
- `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.
## ServerInstance
- `id`: server instance ID.
- `pluginId`: installed game management plugin ID.
- `pluginVersion`: plugin version used to create or last reconcile the instance.
- `runEndpointId`: selected run endpoint.
- `name`: server display name.
- `state`: `draft`, `installing`, `ready`, `running`, `stopped`, `failed`, or `deleted`.
- `configVersion`: optimistic concurrency version for platform-managed config.
- `createdAt`: creation time.
- `updatedAt`: last update time.
## RunEndpoint
- `id`: run endpoint ID.
- `displayName`: visible executor name.
- `version`: run binary version.
- `status`: `online`, `offline`, `degraded`, or `disabled`.
- `capabilities`: current capability keys.
- `capacity`: current queue and resource summary.
- `lastHeartbeatAt`: last control heartbeat time.
## Job
- `id`: job ID.
- `serverInstanceId`: optional target server.
- `runEndpointId`: target run endpoint.
- `capability`: requested capability key.
- `idempotencyKey`: duplicate detection key.
- `state`: `queued`, `accepted`, `running`, `succeeded`, `failed`, or `cancelled`.
- `progress`: bounded progress summary.
- `resultRef`: optional terminal result reference.
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`.
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.
## Artifact
- `id`: artifact ID.
- `ownerKind`: `platform`, `plugin`, `server-instance`, or `job`.
- `ownerId`: owning resource ID.
- `sizeBytes`: expected or final size.
- `checksum`: final checksum.
- `state`: `uploading`, `available`, `expired`, or `failed`.
## LogStream
- `id`: log stream ID.
- `serverInstanceId`: target server.
- `source`: `process`, `file`, `plugin`, or custom source.
- `streamKey`: stable stream key.
- `latestSeq`: latest accepted sequence.
- `storageBackend`: `local-segments`, `loki`, `clickhouse`, `opensearch`, or `elasticsearch`.
- `retentionPolicy`: retention key.
## AuditEvent
- `id`: audit event ID.
- `actorId`: user or system actor.
- `action`: stable action key.
- `resourceKind`: resource kind.
- `resourceId`: resource ID.
- `result`: `success`, `denied`, `failed`, or `queued`.
- `summary`: bounded redacted summary.
- `createdAt`: event time.
+36
View File
@@ -0,0 +1,36 @@
package domain
import "testing"
func TestCopyHelpersIsolateSlices(t *testing.T) {
plugin := GamePlugin{
ID: "server.scum",
RequiredRunCapabilities: []string{"process.start", "logs.read"},
DeclaredPermissions: []string{"server.logs.read"},
Pages: []GamePluginPage{
{Key: "logs", Permissions: []string{"server.logs.read"}},
},
AIPurposes: []string{"logs.diagnose"},
}
copy := CopyGamePlugin(plugin)
copy.RequiredRunCapabilities[0] = "files.read"
copy.DeclaredPermissions[0] = "ai.invoke"
copy.Pages[0].Permissions[0] = "ai.invoke"
copy.AIPurposes[0] = "config.suggest"
if plugin.RequiredRunCapabilities[0] != "process.start" {
t.Fatalf("expected copied plugin slice mutation not to affect original: %+v", plugin.RequiredRunCapabilities)
}
if plugin.DeclaredPermissions[0] != "server.logs.read" || plugin.Pages[0].Permissions[0] != "server.logs.read" || plugin.AIPurposes[0] != "logs.diagnose" {
t.Fatalf("expected copied plugin registry metadata mutation not to affect original: %+v", plugin)
}
provider := AIProvider{ID: "ai.openai", Models: []string{"gpt-4.1"}}
providerCopy := CopyAIProvider(provider)
providerCopy.Models[0] = "gpt-4.1-mini"
if provider.Models[0] != "gpt-4.1" {
t.Fatalf("expected copied provider slice mutation not to affect original: %+v", provider.Models)
}
}
+64
View File
@@ -0,0 +1,64 @@
package domain
type ServerLifecycleAction string
const (
ServerLifecycleActionCreate ServerLifecycleAction = "create"
ServerLifecycleActionStart ServerLifecycleAction = "start"
ServerLifecycleActionStop ServerLifecycleAction = "stop"
)
const (
LifecycleCapabilityInstall = "process.install"
LifecycleCapabilityStart = "process.start"
LifecycleCapabilityStop = "process.stop"
)
type ServerLifecycleCreate struct {
ID string
PluginID string
RunEndpointID string
Name string
OwnerUserID string
IdempotencyKey string
}
type ServerLifecycleCommand struct {
ServerInstanceID string
ExpectedConfigVersion int
IdempotencyKey string
}
type ServerLifecycleResult struct {
Accepted bool
Action ServerLifecycleAction
Instance ServerInstance
Job Job
}
func LifecycleCapabilityForAction(action ServerLifecycleAction) string {
switch action {
case ServerLifecycleActionCreate:
return LifecycleCapabilityInstall
case ServerLifecycleActionStart:
return LifecycleCapabilityStart
case ServerLifecycleActionStop:
return LifecycleCapabilityStop
default:
return ""
}
}
func CopyServerLifecycleCreate(create ServerLifecycleCreate) ServerLifecycleCreate {
return create
}
func CopyServerLifecycleCommand(command ServerLifecycleCommand) ServerLifecycleCommand {
return command
}
func CopyServerLifecycleResult(result ServerLifecycleResult) ServerLifecycleResult {
result.Instance = CopyServerInstance(result.Instance)
result.Job = CopyJob(result.Job)
return result
}