Remove pre-1.0 production governance surfaces
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
)
|
||||
|
||||
func ValidatePluginLifecycleInstallation(installation domain.PluginLifecycleInstallation) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "id", installation.ID)
|
||||
violations = appendRequired(violations, "pluginId", installation.PluginID)
|
||||
violations = appendRequired(violations, "serverInstanceId", installation.ServerInstanceID)
|
||||
if !validPluginLifecycleState(installation.DesiredState) {
|
||||
violations = append(violations, "desiredState is invalid")
|
||||
}
|
||||
if !validPluginLifecycleState(installation.CurrentState) {
|
||||
violations = append(violations, "currentState is invalid")
|
||||
}
|
||||
if installation.LastOperation != "" && !validPluginLifecycleOperation(installation.LastOperation) {
|
||||
violations = append(violations, "lastOperation is invalid")
|
||||
}
|
||||
for _, value := range []fieldString{{field: "compatibility", value: installation.Compatibility}, {field: "failureReason", value: installation.FailureReason}} {
|
||||
if len(value.value) > maxProductionMessageLength || unsafeProductionText(value.value) {
|
||||
violations = append(violations, value.field+" is unsafe")
|
||||
}
|
||||
}
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidatePluginLifecycleRequest(request domain.PluginLifecycleRequest) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "pluginId", request.PluginID)
|
||||
violations = appendRequired(violations, "serverInstanceId", request.ServerInstanceID)
|
||||
violations = appendRequired(violations, "idempotencyKey", request.IdempotencyKey)
|
||||
if !validPluginLifecycleOperation(request.Operation) {
|
||||
violations = append(violations, "operation is invalid")
|
||||
}
|
||||
if (request.Operation == domain.PluginLifecycleOperationDisable || request.Operation == domain.PluginLifecycleOperationRollback || request.Operation == domain.PluginLifecycleOperationRetire) && !request.Confirmed {
|
||||
violations = append(violations, "confirmed is required for disruptive plugin lifecycle operation")
|
||||
}
|
||||
for _, value := range []fieldString{{field: "targetVersion", value: request.TargetVersion}, {field: "idempotencyKey", value: request.IdempotencyKey}} {
|
||||
if unsafeProductionText(value.value) {
|
||||
violations = append(violations, value.field+" is unsafe")
|
||||
}
|
||||
}
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidateAIConfigDiffPreview(preview domain.AIConfigDiffPreview) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "id", preview.ID)
|
||||
violations = appendRequired(violations, "requestId", preview.RequestID)
|
||||
violations = appendRequired(violations, "createdBy", preview.CreatedBy)
|
||||
violations = appendRequired(violations, "serverInstanceId", preview.ServerInstanceID)
|
||||
violations = appendRequired(violations, "key", preview.Key)
|
||||
violations = appendRequired(violations, "diffSummary", preview.DiffSummary)
|
||||
if preview.ConfigVersion <= 0 {
|
||||
violations = append(violations, "configVersion must be positive")
|
||||
}
|
||||
if !validAIConfigDiffState(preview.State) {
|
||||
violations = append(violations, "state is invalid")
|
||||
}
|
||||
if !validLogicalFileKey(preview.Key) || !validConfigFileKey(preview.Key) {
|
||||
violations = append(violations, "key is invalid")
|
||||
}
|
||||
if len([]byte(preview.ProposedConfig)) > maxServerConfigContentSize || containsUnsafeRuntimeSecret(preview.ProposedConfig) || looksLikeRawHostPath(preview.ProposedConfig) {
|
||||
violations = append(violations, "proposedConfig is unsafe")
|
||||
}
|
||||
if len(preview.DiffSummary) > maxProductionMessageLength || unsafeProductionText(preview.DiffSummary) {
|
||||
violations = append(violations, "diffSummary is unsafe")
|
||||
}
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func ValidateAIConfigDiffApprovalRequest(request domain.AIConfigDiffApprovalRequest) error {
|
||||
var violations []string
|
||||
violations = appendRequired(violations, "diffId", request.DiffID)
|
||||
violations = appendRequired(violations, "idempotencyKey", request.IdempotencyKey)
|
||||
if unsafeProductionText(request.DiffID) || unsafeProductionText(request.IdempotencyKey) {
|
||||
violations = append(violations, "AI config approval request is unsafe")
|
||||
}
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func validPluginLifecycleState(state domain.PluginLifecycleState) bool {
|
||||
switch state {
|
||||
case domain.PluginLifecycleStatePending, domain.PluginLifecycleStateInstalled, domain.PluginLifecycleStateEnabled, domain.PluginLifecycleStateDisabled, domain.PluginLifecycleStateUpgrading, domain.PluginLifecycleStateRollingBack, domain.PluginLifecycleStateRetired, domain.PluginLifecycleStateFailed:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func validPluginLifecycleOperation(operation domain.PluginLifecycleOperation) bool {
|
||||
switch operation {
|
||||
case domain.PluginLifecycleOperationInstall, domain.PluginLifecycleOperationEnable, domain.PluginLifecycleOperationDisable, domain.PluginLifecycleOperationUpgrade, domain.PluginLifecycleOperationRollback, domain.PluginLifecycleOperationRetire, domain.PluginLifecycleOperationDependencyCheck:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func validAIConfigDiffState(state domain.AIConfigDiffState) bool {
|
||||
switch state {
|
||||
case domain.AIConfigDiffStatePending, domain.AIConfigDiffStateApproved, domain.AIConfigDiffStateCancelled, domain.AIConfigDiffStateExpired:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func unsafeProductionText(value string) bool {
|
||||
lower := strings.ToLower(value)
|
||||
return containsUnsafeRuntimeSecret(value) ||
|
||||
looksLikeRawHostPath(value) ||
|
||||
strings.Contains(lower, "api key") ||
|
||||
strings.Contains(lower, "apikey") ||
|
||||
strings.Contains(lower, "provider base url") ||
|
||||
strings.Contains(lower, "direct run") ||
|
||||
strings.Contains(lower, "rcon password") ||
|
||||
strings.Contains(lower, "dsn=")
|
||||
}
|
||||
Reference in New Issue
Block a user