This is an automated email from the ASF dual-hosted git repository.

FreeOnePlus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-mcp-server.git


The following commit(s) were added to refs/heads/master by this push:
     new bb63ec1  feat: support Doris-lineage distribution version brands (#213)
bb63ec1 is described below

commit bb63ec1821d16b319f96636dd90a8675885bfe87
Author: Yijia Su <[email protected]>
AuthorDate: Thu Aug 13 23:16:35 2026 +0800

    feat: support Doris-lineage distribution version brands (#213)
    
    Recognize explicitly configured distribution brand tokens while preserving 
the project minimum, feature ranges, mixed-component checks, and evidence 
provenance boundaries. Resolve the branch against current master and close the 
remaining parser and certification edge cases identified in review.
    
    Co-authored-by: Jmmt-mingrui <[email protected]>
---
 docs/reference/configuration.md                |   1 +
 docs/reference/configuration.zh-CN.md          |   1 +
 doris_mcp_server/main.py                       |   3 +
 doris_mcp_server/tools/capability_detector.py  |  31 ++-
 doris_mcp_server/tools/doris_feature_matrix.py | 139 ++++++++++++--
 doris_mcp_server/tools/doris_version.py        |  82 ++++++--
 doris_mcp_server/tools/tools_manager.py        |   9 +
 doris_mcp_server/utils/config.py               |  30 +++
 doris_mcp_server/utils/version_brands.py       |  62 ++++++
 test/protocol/test_multiworker_config.py       |  26 +++
 test/tools/test_capability_detector.py         | 173 ++++++++++++++++-
 test/tools/test_doris_feature_matrix.py        | 255 ++++++++++++++++++++++++-
 test/tools/test_doris_version.py               | 106 ++++++++++
 13 files changed, 879 insertions(+), 39 deletions(-)

diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md
index ff1be41..38453bd 100644
--- a/docs/reference/configuration.md
+++ b/docs/reference/configuration.md
@@ -123,6 +123,7 @@ Increasing one variable does not remove the absolute safety 
cap.
 | `CAPABILITY_SNAPSHOT_TTL_SECONDS` | route-private snapshot lifetime |
 | `CAPABILITY_PROBE_TIMEOUT_SECONDS` | bounded probe timeout |
 | `CAPABILITY_STALE_GRACE_SECONDS` | maximum stale fallback window |
+| `CAPABILITY_VERSION_BRAND_ALIASES` | comma-separated extra 
`@@version_comment` brand tokens for Doris-lineage distributions |
 | `MCP_TOOL_PROVIDERS` | comma-separated exact custom provider allowlist |
 
 Governance:
diff --git a/docs/reference/configuration.zh-CN.md 
b/docs/reference/configuration.zh-CN.md
index dd09ea9..8509836 100644
--- a/docs/reference/configuration.zh-CN.md
+++ b/docs/reference/configuration.zh-CN.md
@@ -118,6 +118,7 @@ HTTP 安全:
 | `CAPABILITY_SNAPSHOT_TTL_SECONDS` | 路由私有 Snapshot Lifetime |
 | `CAPABILITY_PROBE_TIMEOUT_SECONDS` | 有界 Probe Timeout |
 | `CAPABILITY_STALE_GRACE_SECONDS` | 最大 Stale Fallback Window |
+| `CAPABILITY_VERSION_BRAND_ALIASES` | 逗号分隔的额外 `@@version_comment` 品牌标识,用于 
Doris 系发行版 |
 | `MCP_TOOL_PROVIDERS` | 逗号分隔的精确 Custom Provider Allowlist |
 
 Governance:
diff --git a/doris_mcp_server/main.py b/doris_mcp_server/main.py
index e0611a7..c996d6a 100644
--- a/doris_mcp_server/main.py
+++ b/doris_mcp_server/main.py
@@ -109,6 +109,9 @@ def _multiworker_environment(
         "CAPABILITY_STALE_GRACE_SECONDS": str(
             config.capability.stale_grace_seconds
         ),
+        "CAPABILITY_VERSION_BRAND_ALIASES": ",".join(
+            config.capability.version_brand_aliases
+        ),
         "GOVERNANCE_MAX_SAMPLE_RATIO": str(
             config.governance.max_sample_ratio
         ),
diff --git a/doris_mcp_server/tools/capability_detector.py 
b/doris_mcp_server/tools/capability_detector.py
index 6d115c4..88c35be 100644
--- a/doris_mcp_server/tools/capability_detector.py
+++ b/doris_mcp_server/tools/capability_detector.py
@@ -611,7 +611,7 @@ class DorisCapabilityDetector:
             frontend_rows,
             fallback=version,
         )
-        backends = _backend_versions(backend_rows)
+        backends = _backend_versions(backend_rows, default_brand=version.brand)
         versions = DorisClusterVersionVector(
             master_fe=master_fe,
             follower_fes=follower_fes,
@@ -2436,13 +2436,22 @@ def _nonnegative_int(value: Any | None) -> int:
     return max(0, parsed)
 
 
-def _component_version(value: Any) -> DorisVersion:
+def _component_version(
+    value: Any,
+    *,
+    default_brand: str | None = None,
+) -> DorisVersion:
     raw = "" if value is None else str(value).strip()
     if not raw:
         return parse_doris_version_comment("")
-    if "doris" not in raw.lower():
-        raw = f"Doris version doris-{raw}"
-    return parse_doris_version_comment(raw)
+    parsed = parse_doris_version_comment(raw)
+    if parsed.is_parsed:
+        return parsed
+    # Brandless component builds (for example "4.0.6" or "4.0.6-abc1234")
+    # carry no brand of their own; inherit the cluster brand observed in
+    # @@version_comment so distribution provenance is not lost.
+    brand = default_brand or "doris"
+    return parse_doris_version_comment(f"{brand} version {brand}-{raw}")
 
 
 def _truthy(value: Any) -> bool:
@@ -2460,7 +2469,10 @@ def _frontend_versions(
     for row in rows:
         if not _component_is_active(row):
             continue
-        version = _component_version(_row_value(row, "Version", "FeVersion"))
+        version = _component_version(
+            _row_value(row, "Version", "FeVersion"),
+            default_brand=fallback.brand,
+        )
         observed.append(
             (
                 version,
@@ -2485,9 +2497,14 @@ def _frontend_versions(
 
 def _backend_versions(
     rows: Sequence[Mapping[str, Any]],
+    *,
+    default_brand: str | None = None,
 ) -> tuple[DorisVersion, ...]:
     return tuple(
-        _component_version(_row_value(row, "Version", "BeVersion"))
+        _component_version(
+            _row_value(row, "Version", "BeVersion"),
+            default_brand=default_brand,
+        )
         for row in rows
         if _component_is_active(row)
     )
diff --git a/doris_mcp_server/tools/doris_feature_matrix.py 
b/doris_mcp_server/tools/doris_feature_matrix.py
index 585dac2..9e93ab4 100644
--- a/doris_mcp_server/tools/doris_feature_matrix.py
+++ b/doris_mcp_server/tools/doris_feature_matrix.py
@@ -28,6 +28,7 @@ from typing import Annotated, Literal, Self
 
 from pydantic import Field, StringConstraints, model_validator
 
+from ..utils.version_brands import normalize_version_brand_aliases
 from .domain_models import (
     CapabilityVariant,
     ChildSupportContract,
@@ -399,10 +400,17 @@ class PatchCertificationCase(ContractModel):
 
 
 class PatchCertificationEvidence(ContractModel):
-    """Committed proof required before one three-part Doris patch is 
certified."""
+    """Committed proof required before one three-part Doris patch is certified.
+
+    ``brand`` identifies which distribution the evidence certifies. The
+    default ``doris`` brand denotes Apache Doris real-cluster evidence; a
+    derived distribution is only certified by evidence recorded under its
+    own brand token.
+    """
 
     certification_id: Identifier
     version: NonEmptyText
+    brand: NonEmptyText = "doris"
     master_fe_version_comment: NonEmptyText
     follower_fe_version_comments: tuple[NonEmptyText, ...] = ()
     backend_version_comments: Annotated[
@@ -443,21 +451,40 @@ class PatchCertificationEvidence(ContractModel):
                 "certification evidence requires a three-part target version"
             )
         target_literal = _version_literal(target)
+        if normalize_version_brand_aliases((self.brand,)) != (self.brand,):
+            raise ValueError(
+                "certification evidence brand must be a canonical lowercase "
+                "brand token"
+            )
         comments = (
             self.master_fe_version_comment,
             *self.follower_fe_version_comments,
             *self.backend_version_comments,
         )
         for comment in comments:
-            observed = parse_doris_version_comment(comment)
-            if (
-                not observed.is_parsed
-                or observed.core != target_literal
-            ):
-                raise ValueError(
-                    "every certified FE and BE must report the Doris core "
-                    f"version {target_literal}"
-                )
+            if self.brand == "doris":
+                observed = parse_doris_version_comment(comment)
+                if (
+                    not observed.is_parsed
+                    or observed.core != target_literal
+                ):
+                    raise ValueError(
+                        "every certified FE and BE must report the Doris core "
+                        f"version {target_literal}"
+                    )
+            else:
+                # Distribution evidence is validated without relying on the
+                # runtime brand registry: the comment must carry the declared
+                # brand token and the certified three-part core version.
+                if not _distribution_comment_matches(
+                    comment,
+                    brand=self.brand,
+                    core=target_literal,
+                ):
+                    raise ValueError(
+                        f"every certified FE and BE must report the 
{self.brand} "
+                        f"core version {target_literal}"
+                    )
 
         expected_cases = {
             ("stdio", "hierarchical"),
@@ -525,12 +552,18 @@ class DorisPatchCertificationMatrix(ContractModel):
                 "certification targets must use three-part versions"
             )
         _require_unique(targets, "patch certification targets")
-        evidence_versions = tuple(record.version for record in self.evidence)
-        _require_unique(evidence_versions, "patch certification evidence 
versions")
+        evidence_keys = tuple(
+            f"{record.brand}:{record.version}" for record in self.evidence
+        )
+        _require_unique(
+            evidence_keys,
+            "patch certification evidence brand/version pairs",
+        )
         _require_unique(
             tuple(record.certification_id for record in self.evidence),
             "patch certification evidence IDs",
         )
+        evidence_versions = tuple(record.version for record in self.evidence)
         if not set(evidence_versions).issubset(targets):
             raise ValueError(
                 "patch certification evidence must reference target versions"
@@ -583,11 +616,19 @@ class DorisPatchCertificationMatrix(ContractModel):
         literal = observed.core
         if literal is None:
             raise AssertionError("parsed Doris version must expose a core 
version")
+        component_brands = {version.brand for version in components}
+        uniform_brand = (
+            component_brands.pop() if len(component_brands) == 1 else None
+        )
         target = literal in self.target_versions
+        # Certification evidence is provenance-aware: Apache Doris evidence
+        # only certifies clusters whose components all carry the doris brand,
+        # and a derived distribution is only certified by evidence recorded
+        # under its own brand token.
         matches = tuple(
             record
             for record in self.evidence
-            if record.version == literal
+            if record.version == literal and record.brand == uniform_brand
         )
         if matches:
             return self._report(
@@ -603,6 +644,21 @@ class DorisPatchCertificationMatrix(ContractModel):
                 ),
             )
         if target:
+            if uniform_brand != "doris":
+                return self._report(
+                    observed_fe,
+                    observed_be,
+                    uniform_version=literal,
+                    status=VersionCertificationStatus.TARGET_UNCERTIFIED,
+                    reason_code="PATCH_CERTIFICATION_DISTRIBUTION_UNVERIFIED",
+                    targeted=True,
+                    limitations=(
+                        "The observed components do not all carry the Apache "
+                        "Doris brand, so Apache Doris patch certification does 
"
+                        "not transfer; a distribution requires its own "
+                        "committed certification evidence.",
+                    ),
+                )
             return self._report(
                 observed_fe,
                 observed_be,
@@ -934,13 +990,59 @@ def _ordered_unique(values: Iterable[object]) -> 
tuple[str, ...]:
     return tuple(dict.fromkeys(str(value) for value in values))
 
 
+def _distribution_comment_matches(
+    comment: str,
+    *,
+    brand: str,
+    core: str,
+) -> bool:
+    """Match one evidence brand and core without the mutable alias registry."""
+    escaped_brand = re.escape(brand)
+    escaped_core = re.escape(core)
+    pattern = re.compile(
+        rf"""
+        (?<![A-Za-z0-9_])
+        {escaped_brand}
+        (?:\s*,?\s*version)?
+        (?:\s+{escaped_brand}-|\s*-\s*|\s+)
+        {escaped_core}
+        (?:-(?:rc\d+|alpha\d*|beta\d*))?
+        (?:-[0-9a-f]{{7,40}})?
+        (?=\s|\(|,|$)
+        """,
+        re.IGNORECASE | re.VERBOSE,
+    )
+    return pattern.search(comment) is not None
+
+
 def _certification_status(
     version: DorisVersion | None,
     matrix: DorisFeatureMatrix,
+    versions: DorisClusterVersionVector | None = None,
 ) -> VersionCertificationStatus:
     if version is None or version.core is None:
         return VersionCertificationStatus.UNKNOWN
     literal = version.core
+    # Apache Doris certification evidence only applies when every observed
+    # component carries the Apache Doris brand; a registered distribution is
+    # at best target-uncertified until its own evidence is committed.
+    provenance_verified = version.brand_verified
+    if provenance_verified and versions is not None:
+        components = (
+            versions.master_fe,
+            *versions.follower_fes,
+            *versions.backends,
+        )
+        provenance_verified = all(
+            component.is_parsed and component.brand_verified
+            for component in components
+        )
+    if not provenance_verified:
+        return (
+            VersionCertificationStatus.TARGET_UNCERTIFIED
+            if literal in matrix.certification_targets
+            else VersionCertificationStatus.OUTSIDE_TARGET
+        )
     if literal in matrix.certified_versions:
         return VersionCertificationStatus.CERTIFIED
     if literal in matrix.certification_targets:
@@ -961,7 +1063,7 @@ def _evaluation(
     matched_variants: tuple[str, ...] = (),
     matched_ranges: tuple[str, ...] = (),
 ) -> FeatureVersionEvaluation:
-    certification_status = _certification_status(effective, matrix)
+    certification_status = _certification_status(effective, matrix, versions)
     return FeatureVersionEvaluation(
         feature_id=feature.feature_id,
         requested_variant=variant_name,
@@ -2190,8 +2292,13 @@ DORIS_PATCH_CERTIFICATION_MATRIX = 
DorisPatchCertificationMatrix(
     evidence=PATCH_CERTIFICATION_EVIDENCE,
 )
 
-CERTIFIED_DORIS_VERSIONS = (
-    DORIS_PATCH_CERTIFICATION_MATRIX.certified_versions
+# Feature-level certification claims Apache Doris real-cluster evidence
+# only; distribution-branded evidence never certifies the Apache feature
+# matrix.
+CERTIFIED_DORIS_VERSIONS = tuple(
+    record.version
+    for record in PATCH_CERTIFICATION_EVIDENCE
+    if record.brand == "doris"
 )
 
 DORIS_FEATURE_MATRIX = DorisFeatureMatrix(
diff --git a/doris_mcp_server/tools/doris_version.py 
b/doris_mcp_server/tools/doris_version.py
index d88d437..fbd192b 100644
--- a/doris_mcp_server/tools/doris_version.py
+++ b/doris_mcp_server/tools/doris_version.py
@@ -20,30 +20,51 @@
 from __future__ import annotations
 
 import re
-from collections.abc import Mapping, Sequence
+from collections.abc import Iterable, Mapping, Sequence
 from dataclasses import dataclass
 from enum import StrEnum
 from typing import Any
 
 from ..utils.db import DorisConnection
+from ..utils.version_brands import (
+    DEFAULT_VERSION_BRAND,
+    normalize_version_brand_aliases,
+)
 
 DORIS_VERSION_COMMENT_QUERY = "SELECT @@version_comment;"
 _VERSION_COMMENT_COLUMN = "@@version_comment"
 _VERSION_COMMENT_MAX_BYTES = 4096
 
-_VERSION_PATTERN = re.compile(
-    r"""
-    (?<![A-Za-z0-9_])
-    (?:apache\s+)?doris
-    (?:\s*,?\s*version)?
-    (?:\s+doris-|\s*-\s*|\s+)
-    (?P<core>\d+\.\d+\.\d+)
-    (?:-(?P<prerelease>rc\d+|alpha\d*|beta\d*))?
-    (?:-(?P<commit>[0-9a-f]{7,40}))?
-    (?=\s|\(|,|$)
-    """,
-    re.IGNORECASE | re.VERBOSE,
-)
+_DEFAULT_BRAND = DEFAULT_VERSION_BRAND
+
+# Brand tokens whose version comments follow the Apache Doris three-part
+# core version scheme. Only ``doris`` is recognized by default; derived
+# distributions that report their own brand token can register it through
+# ``configure_version_brands`` so the comment participates in every numeric
+# version check (minimum version, patch ranges, mixed-component
+# evaluation). Comments without a recognized brand still fail closed.
+_known_brands: tuple[str, ...] = (_DEFAULT_BRAND,)
+
+
+def _compile_version_pattern(brands: tuple[str, ...]) -> re.Pattern[str]:
+    brand_alternatives = "|".join((r"apache\s+doris", *brands))
+    prefix_alternatives = "|".join(brands)
+    return re.compile(
+        rf"""
+        (?<![A-Za-z0-9_])
+        (?P<brand>{brand_alternatives})
+        (?:\s*,?\s*version)?
+        (?:\s+(?:{prefix_alternatives})-|\s*-\s*|\s+)
+        (?P<core>\d+\.\d+\.\d+)
+        (?:-(?P<prerelease>rc\d+|alpha\d*|beta\d*))?
+        (?:-(?P<commit>[0-9a-f]{{7,40}}))?
+        (?=\s|\(|,|$)
+        """,
+        re.IGNORECASE | re.VERBOSE,
+    )
+
+
+_VERSION_PATTERN = _compile_version_pattern(_known_brands)
 _DEPLOYMENT_PATTERNS = (
     ("cloud", re.compile(r"\bcloud\s+mode\b", re.IGNORECASE)),
     ("shared_data", re.compile(r"\bshared[-\s]+data\b", re.IGNORECASE)),
@@ -65,12 +86,18 @@ class DorisVersion:
     prerelease: str | None = None
     commit: str | None = None
     deployment_hint: str | None = None
+    brand: str | None = None
     parse_status: DorisVersionParseStatus = DorisVersionParseStatus.UNKNOWN
 
     @property
     def is_parsed(self) -> bool:
         return self.parse_status is DorisVersionParseStatus.PARSED
 
+    @property
+    def brand_verified(self) -> bool:
+        """Whether the version comment carries the Apache Doris brand."""
+        return self.brand == "doris"
+
     @property
     def core(self) -> str | None:
         if (
@@ -107,6 +134,27 @@ class DorisVersion:
         return (self.major, self.minor, self.patch)
 
 
+def known_version_brands() -> tuple[str, ...]:
+    """Return the currently recognized version-comment brand tokens."""
+    return _known_brands
+
+
+def configure_version_brands(aliases: Iterable[str]) -> tuple[str, ...]:
+    """Register extra version-comment brand tokens and rebuild the pattern.
+
+    The ``doris`` brand is always recognized. Aliases replace any
+    previously configured set, so passing an empty iterable restores the
+    default doris-only behavior. Aliases are normalized and validated with
+    the same contract used by configuration validation.
+    """
+    global _known_brands, _VERSION_PATTERN
+
+    extras = normalize_version_brand_aliases(aliases)
+    _known_brands = tuple(dict.fromkeys((_DEFAULT_BRAND, *extras)))
+    _VERSION_PATTERN = _compile_version_pattern(_known_brands)
+    return _known_brands
+
+
 def parse_doris_version_comment(comment: str) -> DorisVersion:
     deployment_hint = _detect_deployment_hint(comment)
     match = _VERSION_PATTERN.search(comment)
@@ -125,10 +173,16 @@ def parse_doris_version_comment(comment: str) -> 
DorisVersion:
         prerelease=prerelease.lower() if prerelease else None,
         commit=commit.lower() if commit else None,
         deployment_hint=deployment_hint,
+        brand=_normalize_brand(match.group("brand")),
         parse_status=DorisVersionParseStatus.PARSED,
     )
 
 
+def _normalize_brand(value: str) -> str:
+    normalized = " ".join(value.casefold().split())
+    return "doris" if normalized == "apache doris" else normalized
+
+
 def parse_doris_version_rows(
     rows: Sequence[Mapping[str, Any]],
 ) -> DorisVersion:
diff --git a/doris_mcp_server/tools/tools_manager.py 
b/doris_mcp_server/tools/tools_manager.py
index 682ba2e..6a5dda1 100644
--- a/doris_mcp_server/tools/tools_manager.py
+++ b/doris_mcp_server/tools/tools_manager.py
@@ -63,6 +63,7 @@ from .domain_manifest import (
     DomainManifestService,
 )
 from .doris_feature_matrix import DORIS_FEATURE_MATRIX
+from .doris_version import configure_version_brands
 from .governance_handlers import GovernanceToolHandlersMixin
 from .lakehouse_handlers import LakehouseToolHandlersMixin
 from .pipeline_handlers import PipelineToolHandlersMixin
@@ -142,6 +143,14 @@ class DorisToolsManager(
         if domain_availability_provider is None:
             bound_handlers = BoundHandlerAvailabilityProvider(self)
             capability_config = getattr(config, "capability", None)
+            # Register any configured @@version_comment brand aliases before
+            # the first probe parses a cluster version.
+            brand_aliases = getattr(
+                capability_config, "version_brand_aliases", ()
+            )
+            configure_version_brands(
+                brand_aliases if isinstance(brand_aliases, list | tuple) else 
()
+            )
             detector = DorisCapabilityDetector(
                 connection_manager,
                 probe_timeout_seconds=getattr(
diff --git a/doris_mcp_server/utils/config.py b/doris_mcp_server/utils/config.py
index f74cd29..7646365 100644
--- a/doris_mcp_server/utils/config.py
+++ b/doris_mcp_server/utils/config.py
@@ -61,6 +61,7 @@ from .secret_policy import (
     normalize_token_hash_algorithm,
     validate_high_entropy_secret,
 )
+from .version_brands import normalize_version_brand_aliases
 
 
 class AuthConfigError(ValueError):
@@ -891,6 +892,10 @@ class CapabilityConfig:
     snapshot_ttl_seconds: int = 300
     probe_timeout_seconds: int = 5
     stale_grace_seconds: int = 900
+    # Extra @@version_comment brand tokens recognized as Doris-lineage
+    # distributions (for example a vendor distribution brand). Each token
+    # must be a single lowercase alphanumeric word.
+    version_brand_aliases: list[str] = field(default_factory=list)
 
 
 @dataclass
@@ -1665,6 +1670,12 @@ class DorisConfig:
                 config.capability.stale_grace_seconds,
             )
             _mark_source(config, "capability_stale_grace_seconds", "env")
+        if "CAPABILITY_VERSION_BRAND_ALIASES" in os.environ:
+            config.capability.version_brand_aliases = _env_csv(
+                "CAPABILITY_VERSION_BRAND_ALIASES",
+                config.capability.version_brand_aliases,
+            )
+            _mark_source(config, "capability_version_brand_aliases", "env")
         if "GOVERNANCE_MAX_SAMPLE_RATIO" in os.environ:
             config.governance.max_sample_ratio = float(
                 os.getenv(
@@ -1971,6 +1982,9 @@ class DorisConfig:
                 "stale_grace_seconds": (
                     self.capability.stale_grace_seconds
                 ),
+                "version_brand_aliases": list(
+                    self.capability.version_brand_aliases
+                ),
             },
             "governance": {
                 "max_sample_ratio": self.governance.max_sample_ratio,
@@ -2277,6 +2291,19 @@ class DorisConfig:
             errors.append(
                 "Capability stale grace must be in the range 0-86400 seconds"
             )
+        # JSON configuration can smuggle in non-list values despite the
+        # declared field type, so widen to object before the runtime check.
+        aliases: object = self.capability.version_brand_aliases
+        if not isinstance(aliases, list | tuple):
+            errors.append(
+                "Capability version brand aliases must be a list of strings, "
+                f"got: {type(aliases).__name__}"
+            )
+        else:
+            try:
+                normalize_version_brand_aliases(aliases)
+            except (TypeError, ValueError) as exc:
+                errors.append(str(exc))
         if not 0 < self.governance.max_sample_ratio <= 1:
             errors.append(
                 "Governance maximum sample ratio must be in the range (0, 1]"
@@ -2608,6 +2635,9 @@ class DorisConfig:
                 "stale_grace_seconds": (
                     self.capability.stale_grace_seconds
                 ),
+                "version_brand_aliases": list(
+                    self.capability.version_brand_aliases
+                ),
             },
             "semantic": {
                 "enabled": self.semantic.enabled,
diff --git a/doris_mcp_server/utils/version_brands.py 
b/doris_mcp_server/utils/version_brands.py
new file mode 100644
index 0000000..8eb6f1c
--- /dev/null
+++ b/doris_mcp_server/utils/version_brands.py
@@ -0,0 +1,62 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""Canonical validation for Doris version-comment brand aliases.
+
+Both configuration validation and the runtime brand registry share this
+normalization contract so an alias accepted by one is accepted by the
+other.
+"""
+
+from __future__ import annotations
+
+import re
+from collections.abc import Iterable
+
+DEFAULT_VERSION_BRAND = "doris"
+BRAND_TOKEN_PATTERN = re.compile(r"^[a-z][a-z0-9]*$")
+RESERVED_BRAND_TOKENS = frozenset({"apache", "version"})
+
+
+def normalize_version_brand_aliases(aliases: Iterable[object]) -> tuple[str, 
...]:
+    """Normalize and validate configured version-comment brand aliases.
+
+    Each alias must be a string holding a single lowercase alphanumeric
+    word. Reserved tokens (``apache``, ``version``) are rejected. Empty
+    entries are ignored and duplicates collapse while preserving order.
+
+    Raises:
+        TypeError: if an entry is not a string.
+        ValueError: if an entry is not a valid brand token.
+    """
+    normalized: list[str] = []
+    for alias in aliases:
+        if not isinstance(alias, str):
+            raise TypeError(
+                "Doris version brand aliases must be strings, "
+                f"got: {alias!r}"
+            )
+        token = " ".join(alias.casefold().split())
+        if not token:
+            continue
+        if (
+            BRAND_TOKEN_PATTERN.fullmatch(token) is None
+            or token in RESERVED_BRAND_TOKENS
+        ):
+            raise ValueError(f"Invalid Doris version brand alias: {alias!r}")
+        normalized.append(token)
+    return tuple(dict.fromkeys(normalized))
diff --git a/test/protocol/test_multiworker_config.py 
b/test/protocol/test_multiworker_config.py
index bf44588..547f532 100644
--- a/test/protocol/test_multiworker_config.py
+++ b/test/protocol/test_multiworker_config.py
@@ -130,16 +130,22 @@ def 
test_capability_cache_controls_are_explicit_and_validated(
     monkeypatch.setenv("CAPABILITY_SNAPSHOT_TTL_SECONDS", "120")
     monkeypatch.setenv("CAPABILITY_PROBE_TIMEOUT_SECONDS", "7")
     monkeypatch.setenv("CAPABILITY_STALE_GRACE_SECONDS", "480")
+    monkeypatch.setenv("CAPABILITY_VERSION_BRAND_ALIASES", "enterprisedb, 
forkdb")
 
     configured = DorisConfig.from_env()
 
     assert configured.capability.snapshot_ttl_seconds == 120
     assert configured.capability.probe_timeout_seconds == 7
     assert configured.capability.stale_grace_seconds == 480
+    assert configured.capability.version_brand_aliases == [
+        "enterprisedb",
+        "forkdb",
+    ]
     assert configured.to_dict()["capability"] == {
         "snapshot_ttl_seconds": 120,
         "probe_timeout_seconds": 7,
         "stale_grace_seconds": 480,
+        "version_brand_aliases": ["enterprisedb", "forkdb"],
     }
     assert configured.validate() == []
 
@@ -164,10 +170,30 @@ def 
test_capability_cache_controls_are_explicit_and_validated(
     from_file.capability.snapshot_ttl_seconds = 0
     from_file.capability.probe_timeout_seconds = 61
     from_file.capability.stale_grace_seconds = -1
+    from_file.capability.version_brand_aliases = ["bad-token!"]
     errors = from_file.validate()
     assert "Capability snapshot TTL must be in the range 1-86400 seconds" in 
errors
     assert "Capability probe timeout must be in the range 1-60 seconds" in 
errors
     assert "Capability stale grace must be in the range 0-86400 seconds" in 
errors
+    assert "Invalid Doris version brand alias: 'bad-token!'" in errors
+
+    # Reserved tokens and non-list JSON values fail the same contract that
+    # configure_version_brands() enforces at runtime.
+    from_file.capability.snapshot_ttl_seconds = 30
+    from_file.capability.probe_timeout_seconds = 3
+    from_file.capability.stale_grace_seconds = 60
+    from_file.capability.version_brand_aliases = ["version"]
+    assert "Invalid Doris version brand alias: 'version'" in 
from_file.validate()
+    from_file.capability.version_brand_aliases = ["apache"]
+    assert "Invalid Doris version brand alias: 'apache'" in 
from_file.validate()
+    from_file.capability.version_brand_aliases = ["enterprisedb", 42]
+    assert any(
+        "must be strings" in error for error in from_file.validate()
+    )
+    from_file.capability.version_brand_aliases = "enterprisedb"
+    assert any(
+        "must be a list of strings" in error for error in from_file.validate()
+    )
 
 
 def test_governance_runtime_controls_load_serialize_and_validate(
diff --git a/test/tools/test_capability_detector.py 
b/test/tools/test_capability_detector.py
index 8066cd6..f6f9acd 100644
--- a/test/tools/test_capability_detector.py
+++ b/test/tools/test_capability_detector.py
@@ -18,6 +18,7 @@
 
 from __future__ import annotations
 
+from collections.abc import Iterator
 from contextlib import asynccontextmanager
 from types import SimpleNamespace
 from typing import Any
@@ -32,7 +33,12 @@ from doris_mcp_server.tools.capability_detector import (
     DorisCapabilityDetector,
     _classify_profile_api_response,
 )
-from doris_mcp_server.tools.doris_feature_matrix import DORIS_FEATURE_MATRIX
+from doris_mcp_server.tools.doris_feature_matrix import (
+    DORIS_FEATURE_MATRIX,
+    DORIS_PATCH_CERTIFICATION_MATRIX,
+    VersionCertificationStatus,
+)
+from doris_mcp_server.tools.doris_version import configure_version_brands
 from doris_mcp_server.utils.db import DorisRouteIdentity
 from doris_mcp_server.utils.doris_http_client import DorisHTTPResponse
 from doris_mcp_server.utils.security import AuthContext
@@ -56,6 +62,15 @@ _STORAGE_HISTORY_PROBE_SQL = (
 )
 
 
[email protected]
+def enterprise_brand_alias() -> Iterator[str]:
+    configure_version_brands(("enterprisedb",))
+    try:
+        yield "enterprisedb"
+    finally:
+        configure_version_brands(())
+
+
 class _ProbeConnection:
     def __init__(self) -> None:
         self.statements: list[str] = []
@@ -1069,6 +1084,162 @@ async def 
test_detector_uses_fallback_for_unknown_master_and_retains_follower()
     assert evaluation.reason_code == "DORIS_VERSION_UNKNOWN"
 
 
[email protected]
+async def test_detector_propagates_comment_brand_to_brandless_components(
+    enterprise_brand_alias: str,
+) -> None:
+    connection = _ProbeConnection()
+    connection.row_overrides["SELECT @@version_comment;"] = [
+        {"@@version_comment": f"{enterprise_brand_alias} version 4.0.5"}
+    ]
+    connection.row_overrides["SHOW FRONTENDS"] = [
+        {
+            "Name": "fe-1",
+            "IsMaster": "true",
+            "Version": "4.0.5",
+        },
+    ]
+    connection.row_overrides["SHOW BACKENDS"] = [
+        {
+            "BackendId": "1",
+            "Version": "4.0.5-rc01-59de8c4c524",
+        },
+    ]
+    detector = DorisCapabilityDetector(  # type: ignore[arg-type]
+        _ProbeConnectionManager(connection)
+    )
+
+    snapshot = await detector.detect_base(
+        None,
+        capability_generation=1,
+        provider_generation="provider.a",
+    )
+    report = DORIS_PATCH_CERTIFICATION_MATRIX.evaluate(snapshot.version_vector)
+
+    # Brandless component versions inherit the @@version_comment brand, so
+    # Apache Doris patch certification must not transfer to a distribution.
+    assert snapshot.version_vector.master_fe.brand == enterprise_brand_alias
+    assert snapshot.version_vector.master_fe.brand_verified is False
+    assert snapshot.version_vector.backends[0].brand == enterprise_brand_alias
+    assert report.uniform_observed_version == "4.0.5"
+    assert report.status is VersionCertificationStatus.TARGET_UNCERTIFIED
+    assert report.reason_code == "PATCH_CERTIFICATION_DISTRIBUTION_UNVERIFIED"
+    assert report.certified is False
+
+
[email protected]
+async def test_detector_does_not_treat_commit_substrings_as_brand_tokens() -> 
None:
+    configure_version_brands(("db",))
+    try:
+        connection = _ProbeConnection()
+        connection.row_overrides["SHOW FRONTENDS"] = [
+            {
+                "Name": "fe-1",
+                "IsMaster": "true",
+                "Version": "4.0.5-adb1234",
+            },
+        ]
+        detector = DorisCapabilityDetector(  # type: ignore[arg-type]
+            _ProbeConnectionManager(connection)
+        )
+
+        snapshot = await detector.detect_base(
+            None,
+            capability_generation=1,
+            provider_generation="provider.a",
+        )
+
+        assert snapshot.version_vector.master_fe.is_parsed is True
+        assert snapshot.version_vector.master_fe.brand == "doris"
+        assert snapshot.version_vector.master_fe.core == "4.0.5"
+    finally:
+        configure_version_brands(())
+
+
[email protected]
+async def test_detector_defaults_brandless_components_to_doris_brand() -> None:
+    connection = _ProbeConnection()
+    connection.row_overrides["SHOW FRONTENDS"] = [
+        {
+            "Name": "fe-1",
+            "IsMaster": "true",
+            "Version": "4.0.5",
+        },
+    ]
+    connection.row_overrides["SHOW BACKENDS"] = [
+        {
+            "BackendId": "1",
+            "Version": "4.0.5-rc01-59de8c4c524",
+        },
+    ]
+    detector = DorisCapabilityDetector(  # type: ignore[arg-type]
+        _ProbeConnectionManager(connection)
+    )
+
+    snapshot = await detector.detect_base(
+        None,
+        capability_generation=1,
+        provider_generation="provider.a",
+    )
+    report = DORIS_PATCH_CERTIFICATION_MATRIX.evaluate(snapshot.version_vector)
+
+    assert snapshot.version_vector.master_fe.brand == "doris"
+    assert snapshot.version_vector.master_fe.brand_verified is True
+    assert snapshot.version_vector.backends[0].brand == "doris"
+    assert report.status is VersionCertificationStatus.CERTIFIED
+    assert report.certified is True
+
+
[email protected]
+async def test_detector_parses_enterprise_brand_versions(
+    enterprise_brand_alias: str,
+) -> None:
+    connection = _ProbeConnection()
+    connection.row_overrides["SELECT @@version_comment;"] = [
+        {"@@version_comment": f"{enterprise_brand_alias} version 4.0.6"}
+    ]
+    connection.row_overrides["SHOW FRONTENDS"] = [
+        {
+            "Name": "fe-1",
+            "IsMaster": "true",
+            "Version": f"{enterprise_brand_alias}-4.0.6-abc1234",
+        },
+    ]
+    connection.row_overrides["SHOW BACKENDS"] = [
+        {
+            "BackendId": "1",
+            "Version": f"{enterprise_brand_alias}-4.0.6-abc1234",
+        },
+    ]
+    detector = DorisCapabilityDetector(  # type: ignore[arg-type]
+        _ProbeConnectionManager(connection)
+    )
+
+    snapshot = await detector.detect_base(
+        None,
+        capability_generation=1,
+        provider_generation="provider.a",
+    )
+    evaluation = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_catalog",
+        child_name="list_catalogs",
+        versions=snapshot.version_vector,
+    )
+
+    assert snapshot.version_vector.master_fe.is_parsed is True
+    assert snapshot.version_vector.master_fe.core == "4.0.6"
+    assert snapshot.version_vector.master_fe.brand == enterprise_brand_alias
+    assert snapshot.version_vector.master_fe.brand_verified is False
+    assert snapshot.version_vector.backends[0].is_parsed is True
+    assert snapshot.mixed_versions is False
+    assert (
+        snapshot.probes["version_probe_completed"].status
+        is CapabilityProbeStatus.SUPPORTED
+    )
+    assert evaluation.compatible is True
+    assert evaluation.reason_code == "VERSION_RANGE_MATCHED"
+
+
 @pytest.mark.asyncio
 async def test_governance_probes_keep_pre_406_audit_lineage_available() -> 
None:
     connection = _ProbeConnection()
diff --git a/test/tools/test_doris_feature_matrix.py 
b/test/tools/test_doris_feature_matrix.py
index 4316b2e..1f0651c 100644
--- a/test/tools/test_doris_feature_matrix.py
+++ b/test/tools/test_doris_feature_matrix.py
@@ -17,6 +17,7 @@
 from __future__ import annotations
 
 from collections import Counter
+from collections.abc import Iterator
 from typing import Any, cast
 
 import pytest
@@ -43,7 +44,19 @@ from doris_mcp_server.tools.doris_feature_matrix import (
     VersionCertificationStatus,
     matching_version_ranges,
 )
-from doris_mcp_server.tools.doris_version import parse_doris_version_comment
+from doris_mcp_server.tools.doris_version import (
+    configure_version_brands,
+    parse_doris_version_comment,
+)
+
+
[email protected]
+def enterprise_brand_alias() -> Iterator[str]:
+    configure_version_brands(("enterprisedb",))
+    try:
+        yield "enterprisedb"
+    finally:
+        configure_version_brands(())
 
 
 def _vector(
@@ -104,6 +117,26 @@ def _certification_evidence(
     )
 
 
+def _distribution_certification_evidence(
+    brand: str,
+    version: str = "4.0.5",
+) -> PatchCertificationEvidence:
+    return PatchCertificationEvidence(
+        certification_id=f"{brand}_{version.replace('.', '_')}_linux_amd64",
+        version=version,
+        brand=brand,
+        master_fe_version_comment=f"{brand} version {version}",
+        backend_version_comments=(f"{brand}-{version}-abc1234",),
+        platform="linux_amd64",
+        deployment_mode="unknown",
+        cases=_certification_cases(),
+        domain_names=tuple(EXPECTED_DOMAIN_CHILDREN),
+        child_contract_count=55,
+        evidence_sha256="b" * 64,
+        verified_on="2026-08-01",
+    )
+
+
 def test_matrix_contains_exact_8_domain_55_child_contract() -> None:
     assert len(DORIS_FEATURE_MATRIX.features) == 55
     assert tuple(EXPECTED_DOMAIN_CHILDREN) == (
@@ -407,6 +440,133 @@ def 
test_patch_certification_fails_closed_for_unknown_or_mixed_components() -> N
     assert mixed.uniform_observed_version is None
 
 
+def test_distribution_brand_does_not_inherit_apache_certification(
+    enterprise_brand_alias: str,
+) -> None:
+    versions = DorisClusterVersionVector.from_comments(
+        master_fe=f"{enterprise_brand_alias} version 4.0.5",
+        backends=(f"{enterprise_brand_alias}-4.0.5-abc1234",),
+    )
+
+    feature = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_catalog",
+        child_name="list_tables",
+        versions=versions,
+    )
+    assert feature.compatible is True
+    assert feature.reason_code == "VERSION_RANGE_MATCHED"
+    assert feature.certification_status is (
+        VersionCertificationStatus.TARGET_UNCERTIFIED
+    )
+    assert feature.certified is False
+
+    report = DORIS_PATCH_CERTIFICATION_MATRIX.evaluate(versions)
+    assert report.uniform_observed_version == "4.0.5"
+    assert report.status is VersionCertificationStatus.TARGET_UNCERTIFIED
+    assert report.reason_code == "PATCH_CERTIFICATION_DISTRIBUTION_UNVERIFIED"
+    assert report.targeted is True
+    assert report.certified is False
+    assert report.evidence_ids == ()
+
+
+def test_mixed_brand_components_are_not_apache_certified(
+    enterprise_brand_alias: str,
+) -> None:
+    versions = DorisClusterVersionVector.from_comments(
+        master_fe="Doris version doris-4.0.5",
+        backends=(f"{enterprise_brand_alias}-4.0.5-abc1234",),
+    )
+
+    report = DORIS_PATCH_CERTIFICATION_MATRIX.evaluate(versions)
+    assert report.status is VersionCertificationStatus.TARGET_UNCERTIFIED
+    assert report.reason_code == "PATCH_CERTIFICATION_DISTRIBUTION_UNVERIFIED"
+    assert report.certified is False
+
+    # Feature-level certification also checks provenance across the whole
+    # version vector, not just the scope-effective component.
+    feature = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_catalog",
+        child_name="list_tables",
+        versions=versions,
+    )
+    assert feature.certification_status is (
+        VersionCertificationStatus.TARGET_UNCERTIFIED
+    )
+    assert feature.certified is False
+
+
+def test_distribution_evidence_certifies_only_its_own_brand(
+    enterprise_brand_alias: str,
+) -> None:
+    matrix = DorisPatchCertificationMatrix(
+        minimum_supported_version="2.0.0",
+        target_versions=CERTIFICATION_TARGET_VERSIONS,
+        evidence=(
+            _certification_evidence("4.0.5"),
+            _distribution_certification_evidence(enterprise_brand_alias),
+        ),
+    )
+
+    distribution = matrix.evaluate(
+        DorisClusterVersionVector.from_comments(
+            master_fe=f"{enterprise_brand_alias} version 4.0.5",
+            backends=(f"{enterprise_brand_alias}-4.0.5-abc1234",),
+        )
+    )
+    assert distribution.status is VersionCertificationStatus.CERTIFIED
+    assert distribution.certified is True
+    assert distribution.evidence_ids == ("enterprisedb_4_0_5_linux_amd64",)
+
+    apache = matrix.evaluate(_vector("4.0.5"))
+    assert apache.status is VersionCertificationStatus.CERTIFIED
+    assert apache.evidence_ids == ("doris_4_1_2_linux_amd64",)
+
+    apache_only = DorisPatchCertificationMatrix(
+        minimum_supported_version="2.0.0",
+        target_versions=CERTIFICATION_TARGET_VERSIONS,
+        evidence=(_certification_evidence("4.0.5"),),
+    )
+    cross_brand = apache_only.evaluate(
+        DorisClusterVersionVector.from_comments(
+            master_fe=f"{enterprise_brand_alias} version 4.0.5",
+            backends=(f"{enterprise_brand_alias}-4.0.5-abc1234",),
+        )
+    )
+    assert cross_brand.status is VersionCertificationStatus.TARGET_UNCERTIFIED
+    assert cross_brand.certified is False
+
+
+def test_distribution_evidence_validates_comments_without_brand_registry() -> 
None:
+    evidence = _distribution_certification_evidence("enterprisedb")
+    assert evidence.brand == "enterprisedb"
+
+    payload = evidence.model_dump(mode="python")
+    payload["backend_version_comments"] = ("enterprisedb-4.1.1-abc1234",)
+    with pytest.raises(
+        ValidationError,
+        match="enterprisedb core version 4.0.5",
+    ):
+        PatchCertificationEvidence.model_validate(payload)
+
+    payload = evidence.model_dump(mode="python")
+    payload["brand"] = "EnterpriseDB"
+    with pytest.raises(ValidationError, match="canonical lowercase brand 
token"):
+        PatchCertificationEvidence.model_validate(payload)
+
+    for invalid_comment in (
+        "notenterprisedb version 4.0.5",
+        "enterprisedb version 14.0.50",
+        "notenterprisedb-14.0.50-abc1234",
+    ):
+        payload = evidence.model_dump(mode="python")
+        payload["backend_version_comments"] = (invalid_comment,)
+        with pytest.raises(
+            ValidationError,
+            match="enterprisedb core version 4.0.5",
+        ):
+            PatchCertificationEvidence.model_validate(payload)
+
+
 def test_patch_evidence_rejects_incomplete_host_or_component_proof() -> None:
     evidence = _certification_evidence()
     payload = evidence.model_dump(mode="python")
@@ -819,6 +979,21 @@ def test_an_unparseable_component_version_fails_closed() 
-> None:
     )
 
 
+def test_unparseable_observed_component_prevents_feature_certification() -> 
None:
+    result = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_catalog",
+        child_name="list_tables",
+        versions=DorisClusterVersionVector.from_comments(
+            master_fe="Doris version doris-4.0.5",
+            backends=("unknown-build",),
+        ),
+    )
+
+    assert result.compatible is True
+    assert result.certification_status is 
VersionCertificationStatus.TARGET_UNCERTIFIED
+    assert result.certified is False
+
+
 def test_version_below_2_0_0_is_rejected_before_child_evaluation() -> None:
     result = DORIS_FEATURE_MATRIX.evaluate(
         domain="doris_catalog",
@@ -831,6 +1006,84 @@ def 
test_version_below_2_0_0_is_rejected_before_child_evaluation() -> None:
     assert result.minimum_supported_version == "2.0.0"
 
 
+def test_enterprise_brand_versions_flow_through_every_version_gate(
+    enterprise_brand_alias: str,
+) -> None:
+    below_minimum = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_catalog",
+        child_name="list_tables",
+        versions=DorisClusterVersionVector.from_comments(
+            master_fe=f"{enterprise_brand_alias} version 1.2.8",
+        ),
+    )
+    assert below_minimum.compatible is False
+    assert below_minimum.reason_code == "DORIS_VERSION_BELOW_MINIMUM"
+
+    base = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_catalog",
+        child_name="list_tables",
+        versions=DorisClusterVersionVector.from_comments(
+            master_fe=f"{enterprise_brand_alias} version 2.1.5",
+        ),
+    )
+    assert base.compatible is True
+    assert base.reason_code == "VERSION_RANGE_MATCHED"
+
+    # Patch ranges stay enforced on distribution brands: the native lineage
+    # variant requires >=4.0.6, so a 2.1.5 distribution cluster falls back
+    # to the audit variant instead of exposing the native one.
+    native_lineage = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_governance",
+        child_name="trace_column_lineage",
+        versions=DorisClusterVersionVector.from_comments(
+            master_fe=f"{enterprise_brand_alias} version 2.1.5",
+        ),
+        variant_name="native_lineage_events",
+    )
+    assert native_lineage.compatible is False
+    assert native_lineage.reason_code == "VERSION_RANGE_NOT_MATCHED"
+
+    audit_lineage = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_governance",
+        child_name="trace_column_lineage",
+        versions=DorisClusterVersionVector.from_comments(
+            master_fe=f"{enterprise_brand_alias} version 2.1.5",
+        ),
+        variant_name="audit_sql_inference_primary",
+    )
+    assert audit_lineage.compatible is True
+
+    # Mixed-component evaluation uses the same conservative minimum for
+    # distribution brands.
+    mixed = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_cluster",
+        child_name="get_cache_status",
+        versions=DorisClusterVersionVector.from_comments(
+            master_fe=f"{enterprise_brand_alias} version 4.1.3",
+            backends=(f"{enterprise_brand_alias}-4.0.5-abc1234",),
+        ),
+        variant_name="advanced_cache_types",
+    )
+    assert mixed.compatible is False
+    assert mixed.reason_code == "VERSION_RANGE_NOT_MATCHED"
+    assert mixed.effective_version == "4.0.5"
+
+
+def test_unrecognized_distribution_comment_format_still_fails_closed(
+    enterprise_brand_alias: str,
+) -> None:
+    result = DORIS_FEATURE_MATRIX.evaluate(
+        domain="doris_catalog",
+        child_name="list_tables",
+        versions=DorisClusterVersionVector.from_comments(
+            master_fe=f"{enterprise_brand_alias} pro 2.1.5",
+        ),
+    )
+
+    assert result.compatible is False
+    assert result.reason_code == "DORIS_VERSION_UNKNOWN"
+
+
 def test_target_patch_is_distinct_from_certified_patch() -> None:
     result = DORIS_FEATURE_MATRIX.evaluate(
         domain="doris_catalog",
diff --git a/test/tools/test_doris_version.py b/test/tools/test_doris_version.py
index ad1dd1b..41a83d5 100644
--- a/test/tools/test_doris_version.py
+++ b/test/tools/test_doris_version.py
@@ -15,6 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
+from collections.abc import Iterator
 from unittest.mock import AsyncMock, MagicMock
 
 import pytest
@@ -22,6 +23,8 @@ import pytest
 from doris_mcp_server.tools.doris_version import (
     DORIS_VERSION_COMMENT_QUERY,
     DorisVersionParseStatus,
+    configure_version_brands,
+    known_version_brands,
     parse_doris_version_comment,
     parse_doris_version_rows,
     probe_doris_version,
@@ -29,6 +32,15 @@ from doris_mcp_server.tools.doris_version import (
 from doris_mcp_server.utils.db import DorisConnection, QueryResult
 
 
[email protected]
+def enterprise_brand_alias() -> Iterator[str]:
+    configure_version_brands(("enterprisedb",))
+    try:
+        yield "enterprisedb"
+    finally:
+        configure_version_brands(())
+
+
 def test_version_probe_uses_version_comment() -> None:
     assert DORIS_VERSION_COMMENT_QUERY == "SELECT @@version_comment;"
 
@@ -81,11 +93,105 @@ def test_parse_supported_version_comments(
     assert version.raw == comment
 
 
[email protected](
+    "comment",
+    [
+        "enterprisedb version 2.1.5",
+        "enterprisedb-4.0.6-abc1234",
+    ],
+)
+def test_unregistered_brand_comments_fail_closed(comment: str) -> None:
+    version = parse_doris_version_comment(comment)
+
+    assert version.parse_status is DorisVersionParseStatus.UNKNOWN
+    assert version.is_parsed is False
+    assert version.core is None
+
+
[email protected](
+    ("comment", "core"),
+    [
+        ("enterprisedb version 2.1.5", "2.1.5"),
+        ("enterprisedb version enterprisedb-2.1.5-rc04", "2.1.5"),
+        ("enterprisedb-4.0.6-abc1234", "4.0.6"),
+    ],
+)
+def test_registered_brand_alias_comments_parse_three_part_version(
+    comment: str,
+    core: str,
+    enterprise_brand_alias: str,
+) -> None:
+    version = parse_doris_version_comment(comment)
+
+    assert version.parse_status is DorisVersionParseStatus.PARSED
+    assert version.core == core
+    assert version.normalized == core
+    assert version.brand == enterprise_brand_alias
+    assert version.brand_verified is False
+
+
+def test_brand_alias_configuration_replaces_previous_set(
+    enterprise_brand_alias: str,
+) -> None:
+    assert known_version_brands() == ("doris", enterprise_brand_alias)
+
+    configure_version_brands(("forkdb",))
+
+    assert known_version_brands() == ("doris", "forkdb")
+    assert (
+        parse_doris_version_comment("enterprisedb version 2.1.5").is_parsed
+        is False
+    )
+    assert parse_doris_version_comment("forkdb version 2.1.5").brand == 
"forkdb"
+
+
[email protected](
+    "alias",
+    [
+        "version",
+        "apache",
+        "bad-token!",
+        "two words",
+        "1db",
+    ],
+)
+def test_configure_version_brands_rejects_invalid_aliases(alias: str) -> None:
+    with pytest.raises(ValueError, match="Invalid Doris version brand alias"):
+        configure_version_brands((alias,))
+
+
+def test_configure_version_brands_rejects_non_string_aliases() -> None:
+    with pytest.raises(TypeError, match="must be strings"):
+        configure_version_brands(("enterprisedb", 42))
+
+
+def test_configure_version_brands_ignores_empty_aliases() -> None:
+    assert configure_version_brands(("", "  ")) == ("doris",)
+    assert known_version_brands() == ("doris",)
+
+
[email protected](
+    "comment",
+    [
+        "Doris version doris-3.0.3-rc03-43f06a5e26 (Cloud Mode)",
+        "Apache Doris version 4.0.7",
+        "doris-4.1.3-abcdef1234",
+    ],
+)
+def test_apache_doris_comments_carry_verified_brand(comment: str) -> None:
+    version = parse_doris_version_comment(comment)
+
+    assert version.brand == "doris"
+    assert version.brand_verified is True
+
+
 @pytest.mark.parametrize(
     "comment",
     [
         "",
         "MySQL 8.0.36",
+        "8.0.33",
+        "otherdb version 3.2.0",
         "version 4.1.3",
         "Doris version unknown",
         "Doris version 4.1.3-preview1",


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to