From 7997a7e35e747f9069c87ee027da326f9035c468 Mon Sep 17 00:00:00 2001 From: rldyourmnd Date: Thu, 3 Sep 2026 00:12:15 +0500 Subject: [PATCH] fix(telemetry): accept exact SemVer prereleases OpenObserve publishes an immutable latest release whose semantic version carries an rc suffix. Accept bounded SemVer prerelease identities for the store while preserving exact asset name, path, host, and SHA256 validation; malformed and mutable identities remain rejected. --- internal/telemetrymanifest/manifest_test.go | 15 +++++++++++++++ internal/telemetrymanifest/validate.go | 17 +++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/internal/telemetrymanifest/manifest_test.go b/internal/telemetrymanifest/manifest_test.go index 05725ad5..77d75fed 100644 --- a/internal/telemetrymanifest/manifest_test.go +++ b/internal/telemetrymanifest/manifest_test.go @@ -86,6 +86,21 @@ func TestValidationRejectsMutableUnsafeOrSharedInputs(t *testing.T) { } } +func TestStoreAcceptsAnExactPrereleaseIdentity(t *testing.T) { + manifest := mustLoadManifest(t) + manifest.Store.Version = "v1.0.0-rc1" + manifest.Store.Archive.Name = "openobserve-v1.0.0-rc1-linux-amd64.tar.gz" + manifest.Store.Archive.URL = "https://downloads.openobserve.ai/releases/openobserve/v1.0.0-rc1/openobserve-v1.0.0-rc1-linux-amd64.tar.gz" + if err := manifest.Validate(); err != nil { + t.Fatalf("exact prerelease artifact was refused: %v", err) + } + + manifest.Store.Version = "v1.0.0-rc1/latest" + if err := manifest.Validate(); err == nil || !strings.Contains(err.Error(), "store.version") { + t.Fatalf("mutable or malformed prerelease identity was accepted: %v", err) + } +} + func TestDecodeRejectsUnknownAndMultipleDocuments(t *testing.T) { t.Parallel() diff --git a/internal/telemetrymanifest/validate.go b/internal/telemetrymanifest/validate.go index 798aba67..84c20f96 100644 --- a/internal/telemetrymanifest/validate.go +++ b/internal/telemetrymanifest/validate.go @@ -12,11 +12,12 @@ import ( ) var ( - filePattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$`) - shaPattern = regexp.MustCompile(`^[0-9a-f]{64}$`) - streamPattern = regexp.MustCompile(`^[a-z][a-z0-9_]{2,63}$`) - versionPattern = regexp.MustCompile(`^v[0-9]+\.[0-9]+\.[0-9]+$`) - bucketPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{2,62}$`) + filePattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$`) + shaPattern = regexp.MustCompile(`^[0-9a-f]{64}$`) + streamPattern = regexp.MustCompile(`^[a-z][a-z0-9_]{2,63}$`) + versionPattern = regexp.MustCompile(`^v[0-9]+\.[0-9]+\.[0-9]+$`) + releaseVersionPattern = regexp.MustCompile(`^v[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*)?$`) + bucketPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{2,62}$`) ) type Issue struct { @@ -99,13 +100,13 @@ func validateStore(add func(string, string), store Store) { if store.Implementation != "openobserve" { add("store.implementation", "must be openobserve") } - if !versionPattern.MatchString(store.Version) { - add("store.version", "must be an exact vMAJOR.MINOR.PATCH version") + if !releaseVersionPattern.MatchString(store.Version) { + add("store.version", "must be an exact semantic release version") } if store.BinaryPath != "openobserve" { add("store.binary_path", "must be the exact extracted openobserve executable") } - if versionPattern.MatchString(store.Version) { + if releaseVersionPattern.MatchString(store.Version) { name := "openobserve-" + store.Version + "-linux-amd64.tar.gz" validateAsset(add, "store.archive", store.Archive, "downloads.openobserve.ai", "/releases/openobserve/"+store.Version+"/"+name, name)