package connectorkit import "regexp" type Manifest struct { SchemaVersion string `json:"schemaVersion"` Slug string `json:"slug"` Name string `json:"name"` Version string `json:"version"` AssetType string `json:"assetType"` Category string `json:"category"` Summary string `json:"summary,omitempty"` Description string `json:"description,omitempty"` Publisher map[string]string `json:"publisher"` Repository map[string]string `json:"repository"` Documentation map[string]string `json:"documentation"` Capabilities []string `json:"capabilities"` Evidence map[string]bool `json:"evidence"` Security map[string]bool `json:"security"` SupportedLanguages []string `json:"supportedLanguages,omitempty"` } type Finding struct { Code string Severity string Message string } type ValidationResult struct { OK bool EvidenceScore int Tier string Findings []Finding } var slugPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{2,95}$`) var versionPattern = regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+(?:[-+][a-zA-Z0-9.-]+)?$`) var categories = map[string]bool{ "ai-governance": true, "compliance": true, "crm": true, "devops": true, "erp": true, "iam": true, "security": true, "storage": true, } func ValidateManifest(manifest Manifest) ValidationResult { findings := make([]Finding, 0) if !slugPattern.MatchString(manifest.Slug) { findings = append(findings, Finding{"manifest.invalid_slug", "error", "slug must be lower-kebab-case"}) } if !versionPattern.MatchString(manifest.Version) { findings = append(findings, Finding{"manifest.invalid_version", "error", "version must be semantic versioning"}) } if !categories[manifest.Category] { findings = append(findings, Finding{"manifest.invalid_category", "error", "unsupported category"}) } if len(manifest.Capabilities) == 0 { findings = append(findings, Finding{"capabilities.empty", "error", "at least one capability is required"}) } if manifest.SchemaVersion == "" || manifest.Name == "" || manifest.AssetType == "" { findings = append(findings, Finding{"manifest.missing_field", "error", "schemaVersion, name, and assetType are required"}) } score := 0 if len(findings) == 0 { score = 0 if manifest.Evidence["receipts"] && manifest.Evidence["offlineVerification"] { score += 25 } else { score += 18 } if manifest.Security["secretScan"] && manifest.Security["dependencyScan"] { score += 20 } else { score += 12 } if manifest.Evidence["witnessCompatible"] { score += 15 } else { score += 8 } if manifest.Repository["url"] != "" && manifest.Documentation["url"] != "" { score += 15 } else { score += 10 } if hasCapability(manifest.Capabilities, "proofstream") { score += 15 } else { score += 10 } score += 5 } tier := "hidden" switch { case score >= 95: tier = "platinum" case score >= 85: tier = "gold" case score >= 70: tier = "silver" case score >= 50: tier = "community" } if score < 50 && len(findings) == 0 { findings = append(findings, Finding{"score.hidden", "error", "Evidence Score below 50 cannot be publicly listed"}) } return ValidationResult{OK: len(findings) == 0 && score >= 50, EvidenceScore: score, Tier: tier, Findings: findings} } func hasCapability(values []string, target string) bool { for _, value := range values { if value == target { return true } } return false }