package model import ( "time" "gorm.io/gorm" ) // Device status constants const ( DeviceStatusOnline = "online" DeviceStatusOffline = "offline" DeviceStatusUpgrading = "upgrading" ) // Deployment status constants const ( DeploymentStatusDraft = "draft" DeploymentStatusActive = "active" DeploymentStatusPaused = "paused" DeploymentStatusCompleted = "completed" DeploymentStatusCancelled = "cancelled" ) // Deployment device status constants const ( DeployDeviceStatusPending = "pending" DeployDeviceStatusDownloading = "downloading" DeployDeviceStatusDownloaded = "downloaded" DeployDeviceStatusVerifying = "verifying" DeployDeviceStatusInstalling = "installing" DeployDeviceStatusCompleted = "completed" DeployDeviceStatusFailed = "failed" DeployDeviceStatusRolledBack = "rolled_back" ) // Rollout strategy constants const ( RolloutImmediate = "immediate" RolloutStaged = "staged" ) // Target type constants const ( TargetAll = "all" TargetDevice = "device" TargetGroup = "group" ) // Device represents a connected daemon instance. type Device struct { ID int64 `json:"id" gorm:"primaryKey;autoIncrement"` DeviceID string `json:"deviceId" gorm:"uniqueIndex;size:256;not null"` IPAddress string `json:"ipAddress" gorm:"size:64;default:''"` Hostname string `json:"hostname" gorm:"size:256;default:''"` OS string `json:"os" gorm:"size:64;default:''"` CurrentVersion string `json:"currentVersion" gorm:"size:128;default:'0.0.0'"` Status string `json:"status" gorm:"size:32;default:'online';index"` GroupName string `json:"groupName" gorm:"size:128;default:'default';index"` LastHeartbeat time.Time `json:"lastHeartbeat"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } // Artefact represents an uploaded update package (JAR or patch). type Artefact struct { ID int64 `json:"id" gorm:"primaryKey;autoIncrement"` Version string `json:"version" gorm:"size:128;not null;index"` FileName string `json:"fileName" gorm:"size:512;not null"` FilePath string `json:"-" gorm:"size:1024;not null"` FileSize int64 `json:"fileSize"` SHA256Hash string `json:"sha256Hash" gorm:"size:128"` DeltaRef string `json:"deltaRef" gorm:"size:128;default:''"` IsDelta bool `json:"isDelta"` Metadata string `json:"metadata" gorm:"type:text;default:'{}'"` CreatedAt time.Time `json:"createdAt"` } // Deployment defines an update rollout campaign. type Deployment struct { ID int64 `json:"id" gorm:"primaryKey;autoIncrement"` ArtefactID int64 `json:"artefactId" gorm:"not null;index"` Artefact *Artefact `json:"artefact,omitempty" gorm:"foreignKey:ArtefactID"` Name string `json:"name" gorm:"size:256;not null"` Description string `json:"description" gorm:"type:text;default:''"` TargetType string `json:"targetType" gorm:"size:32;default:'all'"` TargetSpec string `json:"targetSpec" gorm:"type:text;default:'{}'"` RolloutStrategy string `json:"rolloutStrategy" gorm:"size:32;default:'immediate'"` MaxConcurrent int `json:"maxConcurrent" gorm:"default:50"` Status string `json:"status" gorm:"size:32;default:'draft';index"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } // DeploymentDevice tracks an individual device's progress through a deployment. type DeploymentDevice struct { ID int64 `json:"id" gorm:"primaryKey;autoIncrement"` DeploymentID int64 `json:"deploymentId" gorm:"not null;uniqueIndex:idx_dd_dep_dev;index"` DeviceID string `json:"deviceId" gorm:"size:256;not null;uniqueIndex:idx_dd_dep_dev;index"` Status string `json:"status" gorm:"size:32;default:'pending';index"` DownloadedAt *time.Time `json:"downloadedAt"` CompletedAt *time.Time `json:"completedAt"` Error string `json:"error" gorm:"type:text;default:''"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` } // AdminUser represents an operator account. type AdminUser struct { ID int64 `json:"id" gorm:"primaryKey;autoIncrement"` Username string `json:"username" gorm:"uniqueIndex;size:128;not null"` PasswordHash string `json:"-" gorm:"size:256;not null"` Role string `json:"role" gorm:"size:32;default:'admin'"` CreatedAt time.Time `json:"createdAt"` } // -- Request/Response DTOs -- type LoginRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } type LoginResponse struct { Token string `json:"token"` ExpiresAt int64 `json:"expiresAt"` } type RegisterDeviceRequest struct { DeviceID string `json:"deviceId" binding:"required"` IPAddress string `json:"ipAddress"` Hostname string `json:"hostname"` OS string `json:"os"` CurrentVersion string `json:"currentVersion"` GroupName string `json:"groupName"` } type HeartbeatRequest struct { DeviceID string `json:"deviceId" binding:"required"` CurrentVersion string `json:"currentVersion"` Status string `json:"status"` } type CheckUpdateResponse struct { HasUpdate bool `json:"hasUpdate"` ArtefactID int64 `json:"artefactId,omitempty"` Version string `json:"version,omitempty"` FileSize int64 `json:"fileSize,omitempty"` SHA256Hash string `json:"sha256Hash,omitempty"` DownloadURL string `json:"downloadUrl,omitempty"` } type CreateDeploymentRequest struct { ArtefactID int64 `json:"artefactId" binding:"required"` Name string `json:"name" binding:"required"` Description string `json:"description"` TargetType string `json:"targetType" binding:"required"` TargetSpec string `json:"targetSpec"` RolloutStrategy string `json:"rolloutStrategy"` MaxConcurrent int `json:"maxConcurrent"` } type PaginatedResponse struct { Data interface{} `json:"data"` Total int64 `json:"total"` Page int `json:"page"` PageSize int `json:"pageSize"` } // -- Hooks -- func (d *Device) BeforeCreate(tx *gorm.DB) error { now := time.Now() if d.LastHeartbeat.IsZero() { d.LastHeartbeat = now } if d.CreatedAt.IsZero() { d.CreatedAt = now } if d.UpdatedAt.IsZero() { d.UpdatedAt = now } return nil }