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

zqr10159 pushed a commit to branch 2.0.0
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git

commit 967ce7f574104b2cf8700c4716eca24b7cc0681d
Author: Logic <[email protected]>
AuthorDate: Sun Oct 11 17:37:58 2026 +0800

    fix(security): restore reviewed label and config role fallbacks
---
 .../GeneralConfigRouteAuthorizationConfigTest.java | 58 +++++++++++---
 .../config/LabelRouteAuthorizationConfigTest.java  | 32 +++++++-
 .../manager/config/SurenessPolicyTestSupport.java  | 92 ++++++++++++++++++++++
 hertzbeat-startup/src/main/resources/sureness.yml  |  8 ++
 .../hertzbeat-mysql-iotdb/conf/sureness.yml        |  8 ++
 .../hertzbeat-mysql-tdengine/conf/sureness.yml     |  8 ++
 .../conf/sureness.yml                              |  8 ++
 .../conf/sureness.yml                              |  8 ++
 .../conf/sureness.yml                              |  8 ++
 script/sureness.yml                                |  8 ++
 10 files changed, 224 insertions(+), 14 deletions(-)

diff --git 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/GeneralConfigRouteAuthorizationConfigTest.java
 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/GeneralConfigRouteAuthorizationConfigTest.java
index 4eec7a12b5..8871941d0c 100644
--- 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/GeneralConfigRouteAuthorizationConfigTest.java
+++ 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/GeneralConfigRouteAuthorizationConfigTest.java
@@ -19,7 +19,6 @@ package org.apache.hertzbeat.manager.config;
 
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
 
 import java.io.IOException;
 import java.nio.file.Files;
@@ -29,10 +28,14 @@ import java.util.EnumMap;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
 import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
 import org.apache.hertzbeat.manager.controller.GeneralConfigController;
 import org.apache.hertzbeat.manager.pojo.dto.TemplateConfig;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
@@ -78,7 +81,7 @@ class GeneralConfigRouteAuthorizationConfigTest {
     }
 
     @Test
-    void shippedConfigsGiveEverySupportedTypeExactRolesAndStayInSync() throws 
IOException {
+    void 
shippedConfigsKeepEffectiveTypeRolesInSyncAndPreserveReleaseFallbacks() throws 
IOException {
         List<String> referenceRules = 
generalConfigRules(SURENESS_CONFIGS.get(0));
         for (String config : SURENESS_CONFIGS) {
             List<String> lines = 
Files.readAllLines(repoRoot().resolve(config));
@@ -88,26 +91,57 @@ class GeneralConfigRouteAuthorizationConfigTest {
                 String path = policy.getKey() == 
GeneralConfigTypeEnum.public_access
                         ? "/api/config/public-access"
                         : "/api/config/" + policy.getKey().name();
-                assertExactRule(config, lines, path, "get", 
policy.getValue().getRoles());
-                assertExactRule(config, lines, path, "post", 
policy.getValue().postRoles());
+                assertOnlyExpectedRoles(config, lines, path, "get", 
policy.getValue().getRoles());
+                assertOnlyExpectedRoles(config, lines, path, "post", 
policy.getValue().postRoles());
             }
-            assertExactRule(config, lines, "/api/config/template/*", "put", 
ADMIN_ROLE);
-            assertFalse(lines.stream().anyMatch(line -> line.startsWith("  - 
/api/config/**===")),
-                    () -> config + " must not use a broad general config 
wildcard");
+            assertOnlyExpectedRoles(config, lines, "/api/config/template/*", 
"put", ADMIN_ROLE);
+            List<String> fallbacks = lines.stream().filter(line -> 
line.startsWith("  - /api/config/**==="))
+                    .sorted().toList();
+            List<String> expectedFallbacks = 
SurenessPolicyTestSupport.releaseProfile(config) ? List.of(
+                    "  - /api/config/**===delete===[admin]", "  - 
/api/config/**===get===[admin,user,guest]",
+                    "  - /api/config/**===post===[admin]", "  - 
/api/config/**===put===[admin]") : List.of();
+            assertEquals(expectedFallbacks, fallbacks, () -> config + " must 
preserve its fallback profile");
         }
     }
 
-    private static void assertExactRule(
+    private static void assertOnlyExpectedRoles(
             String config, List<String> lines, String path, String method, 
String roles) {
         String expected = "  - " + path + "===" + method + "===" + roles;
-        long count = lines.stream().filter(expected::equals).count();
-        assertEquals(1, count, () -> config + " must contain exactly one " + 
expected);
+        Set<String> matchingRules = lines.stream().filter(line -> 
line.startsWith("  - " + path + "===" + method + "==="))
+                .collect(java.util.stream.Collectors.toSet());
+        // Identical duplicates have the same effective role policy; 
conflicting or missing rules do not.
+        assertEquals(Set.of(expected), matchingRules, () -> config + " must 
require only " + expected);
     }
 
     private static List<String> generalConfigRules(String config) throws 
IOException {
         return Files.readAllLines(repoRoot().resolve(config)).stream()
-                .filter(line -> line.startsWith("  - /api/config/"))
-                .toList();
+                .filter(line -> line.startsWith("  - /api/config/") && 
!line.startsWith("  - /api/config/**==="))
+                .distinct().sorted().toList();
+    }
+
+    @ParameterizedTest
+    @MethodSource("configurations")
+    void 
realMatcherEnforcesExactTypeRolesBeforeFallbackAndKeepsUnmatchedSemantics(String
 config) throws Exception {
+        var matcher = SurenessPolicyTestSupport.matcher(config);
+        for (Map.Entry<GeneralConfigTypeEnum, RolePolicy> policy : 
ROLE_POLICIES.entrySet()) {
+            String path = policy.getKey() == 
GeneralConfigTypeEnum.public_access
+                    ? "/api/config/public-access" : "/api/config/" + 
policy.getKey().name();
+            SurenessPolicyTestSupport.assertPolicy(matcher, config, path, 
"get", policy.getValue().getRoles());
+            SurenessPolicyTestSupport.assertPolicy(matcher, config, path, 
"post", policy.getValue().postRoles());
+        }
+        SurenessPolicyTestSupport.assertPolicy(matcher, config, 
"/api/config/template/linux", "put", ADMIN_ROLE);
+        SurenessPolicyTestSupport.assertPolicy(matcher, config, 
"/api/config/timezones", "get", ALL_ROLES);
+        boolean release = SurenessPolicyTestSupport.releaseProfile(config);
+        SurenessPolicyTestSupport.assertPolicy(matcher, config, 
"/api/config/unlisted", "get", release ? ALL_ROLES : null);
+        for (String method : List.of("post", "put", "delete")) {
+            SurenessPolicyTestSupport.assertPolicy(matcher, config, 
"/api/config/unlisted", method, release ? ADMIN_ROLE : null);
+        }
+        // Null means no role requirement, not deny-all; retain this warning 
for genuinely unmatched paths.
+        SurenessPolicyTestSupport.assertPolicy(matcher, config, 
"/audit/unmatched", "post", null);
+    }
+
+    private static Stream<String> configurations() {
+        return SURENESS_CONFIGS.stream();
     }
 
     private static Map<GeneralConfigTypeEnum, RolePolicy> rolePolicies() {
diff --git 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/LabelRouteAuthorizationConfigTest.java
 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/LabelRouteAuthorizationConfigTest.java
index 0fed84be03..2be5d38662 100644
--- 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/LabelRouteAuthorizationConfigTest.java
+++ 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/LabelRouteAuthorizationConfigTest.java
@@ -26,7 +26,10 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Stream;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.jupiter.api.function.Executable;
 
 /**
@@ -63,8 +66,33 @@ class LabelRouteAuthorizationConfigTest {
         List<String> actualRules = 
Files.readAllLines(repoRoot().resolve(config)).stream()
                 .filter(line -> line.startsWith("  - /api/label") || 
line.startsWith("  - /api/tag/"))
                 .toList();
-        assertEquals(LABEL_RULES, actualRules,
-                () -> config + " must contain only the reviewed Label route 
policy");
+        List<String> expected = new ArrayList<>(LABEL_RULES);
+        if (SurenessPolicyTestSupport.releaseProfile(config)) {
+            expected.addAll(List.of("  - 
/api/label/**===get===[admin,user,guest]",
+                    "  - /api/label/**===post===[admin,user]", "  - 
/api/label/**===put===[admin,user]",
+                    "  - /api/label/**===delete===[admin]"));
+        }
+        assertEquals(expected, actualRules, () -> config + " must preserve 
exact roots and its fallback profile");
+    }
+
+    @ParameterizedTest
+    @MethodSource("configurations")
+    void realMatcherKeepsRootRolesAndAuthenticatedChildFallback(String config) 
throws Exception {
+        var matcher = SurenessPolicyTestSupport.matcher(config);
+        for (String method : List.of("get", "post", "put", "delete")) {
+            String roles = switch (method) {
+                case "get" -> "[admin,user,guest]";
+                case "post", "put" -> "[admin,user]";
+                default -> "[admin]";
+            };
+            SurenessPolicyTestSupport.assertPolicy(matcher, config, 
"/api/label", method, roles);
+            SurenessPolicyTestSupport.assertPolicy(matcher, config, 
"/api/label/child", method,
+                    SurenessPolicyTestSupport.releaseProfile(config) ? roles : 
null);
+        }
+    }
+
+    private static Stream<String> configurations() {
+        return SURENESS_CONFIGS.stream();
     }
 
     private static Path repoRoot() {
diff --git 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/SurenessPolicyTestSupport.java
 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/SurenessPolicyTestSupport.java
new file mode 100644
index 0000000000..73fca342d3
--- /dev/null
+++ 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/config/SurenessPolicyTestSupport.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+package org.apache.hertzbeat.manager.config;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.usthe.sureness.matcher.DefaultPathRoleMatcher;
+import com.usthe.sureness.matcher.PathTreeProvider;
+import com.usthe.sureness.processor.exception.UnauthorizedException;
+import com.usthe.sureness.processor.support.PasswordProcessor;
+import com.usthe.sureness.subject.support.PasswordSubject;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.yaml.snakeyaml.Yaml;
+
+/** Real policy matching and authorization only; subjects assume 
authentication with no credentials. */
+final class SurenessPolicyTestSupport {
+    private SurenessPolicyTestSupport() {
+    }
+
+    static boolean releaseProfile(String config) {
+        return config.startsWith("script/") || 
config.equals("hertzbeat-startup/src/main/resources/sureness.yml");
+    }
+
+    @SuppressWarnings("unchecked")
+    static DefaultPathRoleMatcher matcher(String config) throws Exception {
+        Path root = Path.of("").toAbsolutePath();
+        while (root != null && !Files.isRegularFile(root.resolve("mvnw"))) {
+            root = root.getParent();
+        }
+        if (root == null) {
+            throw new IllegalStateException("Cannot locate repository root");
+        }
+        Map<String, Object> policy = new 
Yaml().load(Files.readString(root.resolve(config)));
+        DefaultPathRoleMatcher matcher = new DefaultPathRoleMatcher();
+        matcher.setPathTreeProvider(new PathTreeProvider() {
+            @Override
+            public Set<String> providePathData() {
+                return Set.copyOf((List<String>) policy.get("resourceRole"));
+            }
+
+            @Override
+            public Set<String> provideExcludedResource() {
+                return Set.copyOf((List<String>) 
policy.get("excludedResource"));
+            }
+        });
+        matcher.buildTree();
+        return matcher;
+    }
+
+    static void assertPolicy(DefaultPathRoleMatcher matcher, String config,
+            String path, String method, String expectedRoles) {
+        List<String> expected = expectedRoles == null ? null
+                : Arrays.asList(expectedRoles.substring(1, 
expectedRoles.length() - 1).split(","));
+        String resource = path + "===" + method;
+        for (String role : List.of("admin", "user", "guest", "unrecognized")) {
+            PasswordSubject subject = 
PasswordSubject.builder("already-authenticated-fixture", null)
+                    
.setTargetResource(resource).setOwnRoles(List.of(role)).build();
+            String context = config + " " + resource + " role=" + role;
+            assertFalse(matcher.isExcludedResource(subject), context);
+            matcher.matchRole(subject);
+            assertEquals(expected, subject.getSupportRoles(), context);
+            if (expected == null || expected.contains(role)) {
+                assertDoesNotThrow(() -> new 
PasswordProcessor().authorized(subject), context);
+            } else {
+                assertThrows(UnauthorizedException.class, () -> new 
PasswordProcessor().authorized(subject), context);
+            }
+        }
+    }
+}
diff --git a/hertzbeat-startup/src/main/resources/sureness.yml 
b/hertzbeat-startup/src/main/resources/sureness.yml
index ca3953169a..023cf7fcc0 100644
--- a/hertzbeat-startup/src/main/resources/sureness.yml
+++ b/hertzbeat-startup/src/main/resources/sureness.yml
@@ -137,12 +137,20 @@ resourceRole:
   - /api/plugin/**===post===[admin]
   - /api/plugin/**===put===[admin]
   - /api/plugin/**===delete===[admin]
+  - /api/config/**===get===[admin,user,guest]
+  - /api/config/**===post===[admin]
+  - /api/config/**===put===[admin]
+  - /api/config/**===delete===[admin]
   # queue depth of the hertzbeat process itself, operational data
   - /api/metrics===get===[admin]
   # per account metric favourites rendered on the monitor pages
   - /api/metrics/**===get===[admin,user,guest]
   - /api/metrics/**===post===[admin,user,guest]
   - /api/metrics/**===delete===[admin,user,guest]
+  - /api/label/**===get===[admin,user,guest]
+  - /api/label/**===post===[admin,user]
+  - /api/label/**===put===[admin,user]
+  - /api/label/**===delete===[admin]
   # the storage availability probe is read by every monitor page, while the 
query
   # route forwards a raw promql expression straight to the time series database
   - /api/warehouse/**===get===[admin,user,guest]
diff --git a/script/docker-compose/hertzbeat-mysql-iotdb/conf/sureness.yml 
b/script/docker-compose/hertzbeat-mysql-iotdb/conf/sureness.yml
index ca3953169a..023cf7fcc0 100644
--- a/script/docker-compose/hertzbeat-mysql-iotdb/conf/sureness.yml
+++ b/script/docker-compose/hertzbeat-mysql-iotdb/conf/sureness.yml
@@ -137,12 +137,20 @@ resourceRole:
   - /api/plugin/**===post===[admin]
   - /api/plugin/**===put===[admin]
   - /api/plugin/**===delete===[admin]
+  - /api/config/**===get===[admin,user,guest]
+  - /api/config/**===post===[admin]
+  - /api/config/**===put===[admin]
+  - /api/config/**===delete===[admin]
   # queue depth of the hertzbeat process itself, operational data
   - /api/metrics===get===[admin]
   # per account metric favourites rendered on the monitor pages
   - /api/metrics/**===get===[admin,user,guest]
   - /api/metrics/**===post===[admin,user,guest]
   - /api/metrics/**===delete===[admin,user,guest]
+  - /api/label/**===get===[admin,user,guest]
+  - /api/label/**===post===[admin,user]
+  - /api/label/**===put===[admin,user]
+  - /api/label/**===delete===[admin]
   # the storage availability probe is read by every monitor page, while the 
query
   # route forwards a raw promql expression straight to the time series database
   - /api/warehouse/**===get===[admin,user,guest]
diff --git a/script/docker-compose/hertzbeat-mysql-tdengine/conf/sureness.yml 
b/script/docker-compose/hertzbeat-mysql-tdengine/conf/sureness.yml
index ca3953169a..023cf7fcc0 100644
--- a/script/docker-compose/hertzbeat-mysql-tdengine/conf/sureness.yml
+++ b/script/docker-compose/hertzbeat-mysql-tdengine/conf/sureness.yml
@@ -137,12 +137,20 @@ resourceRole:
   - /api/plugin/**===post===[admin]
   - /api/plugin/**===put===[admin]
   - /api/plugin/**===delete===[admin]
+  - /api/config/**===get===[admin,user,guest]
+  - /api/config/**===post===[admin]
+  - /api/config/**===put===[admin]
+  - /api/config/**===delete===[admin]
   # queue depth of the hertzbeat process itself, operational data
   - /api/metrics===get===[admin]
   # per account metric favourites rendered on the monitor pages
   - /api/metrics/**===get===[admin,user,guest]
   - /api/metrics/**===post===[admin,user,guest]
   - /api/metrics/**===delete===[admin,user,guest]
+  - /api/label/**===get===[admin,user,guest]
+  - /api/label/**===post===[admin,user]
+  - /api/label/**===put===[admin,user]
+  - /api/label/**===delete===[admin]
   # the storage availability probe is read by every monitor page, while the 
query
   # route forwards a raw promql expression straight to the time series database
   - /api/warehouse/**===get===[admin,user,guest]
diff --git 
a/script/docker-compose/hertzbeat-mysql-victoria-metrics/conf/sureness.yml 
b/script/docker-compose/hertzbeat-mysql-victoria-metrics/conf/sureness.yml
index ca3953169a..023cf7fcc0 100644
--- a/script/docker-compose/hertzbeat-mysql-victoria-metrics/conf/sureness.yml
+++ b/script/docker-compose/hertzbeat-mysql-victoria-metrics/conf/sureness.yml
@@ -137,12 +137,20 @@ resourceRole:
   - /api/plugin/**===post===[admin]
   - /api/plugin/**===put===[admin]
   - /api/plugin/**===delete===[admin]
+  - /api/config/**===get===[admin,user,guest]
+  - /api/config/**===post===[admin]
+  - /api/config/**===put===[admin]
+  - /api/config/**===delete===[admin]
   # queue depth of the hertzbeat process itself, operational data
   - /api/metrics===get===[admin]
   # per account metric favourites rendered on the monitor pages
   - /api/metrics/**===get===[admin,user,guest]
   - /api/metrics/**===post===[admin,user,guest]
   - /api/metrics/**===delete===[admin,user,guest]
+  - /api/label/**===get===[admin,user,guest]
+  - /api/label/**===post===[admin,user]
+  - /api/label/**===put===[admin,user]
+  - /api/label/**===delete===[admin]
   # the storage availability probe is read by every monitor page, while the 
query
   # route forwards a raw promql expression straight to the time series database
   - /api/warehouse/**===get===[admin,user,guest]
diff --git 
a/script/docker-compose/hertzbeat-postgresql-greptimedb/conf/sureness.yml 
b/script/docker-compose/hertzbeat-postgresql-greptimedb/conf/sureness.yml
index ca3953169a..023cf7fcc0 100644
--- a/script/docker-compose/hertzbeat-postgresql-greptimedb/conf/sureness.yml
+++ b/script/docker-compose/hertzbeat-postgresql-greptimedb/conf/sureness.yml
@@ -137,12 +137,20 @@ resourceRole:
   - /api/plugin/**===post===[admin]
   - /api/plugin/**===put===[admin]
   - /api/plugin/**===delete===[admin]
+  - /api/config/**===get===[admin,user,guest]
+  - /api/config/**===post===[admin]
+  - /api/config/**===put===[admin]
+  - /api/config/**===delete===[admin]
   # queue depth of the hertzbeat process itself, operational data
   - /api/metrics===get===[admin]
   # per account metric favourites rendered on the monitor pages
   - /api/metrics/**===get===[admin,user,guest]
   - /api/metrics/**===post===[admin,user,guest]
   - /api/metrics/**===delete===[admin,user,guest]
+  - /api/label/**===get===[admin,user,guest]
+  - /api/label/**===post===[admin,user]
+  - /api/label/**===put===[admin,user]
+  - /api/label/**===delete===[admin]
   # the storage availability probe is read by every monitor page, while the 
query
   # route forwards a raw promql expression straight to the time series database
   - /api/warehouse/**===get===[admin,user,guest]
diff --git 
a/script/docker-compose/hertzbeat-postgresql-victoria-metrics/conf/sureness.yml 
b/script/docker-compose/hertzbeat-postgresql-victoria-metrics/conf/sureness.yml
index ca3953169a..023cf7fcc0 100644
--- 
a/script/docker-compose/hertzbeat-postgresql-victoria-metrics/conf/sureness.yml
+++ 
b/script/docker-compose/hertzbeat-postgresql-victoria-metrics/conf/sureness.yml
@@ -137,12 +137,20 @@ resourceRole:
   - /api/plugin/**===post===[admin]
   - /api/plugin/**===put===[admin]
   - /api/plugin/**===delete===[admin]
+  - /api/config/**===get===[admin,user,guest]
+  - /api/config/**===post===[admin]
+  - /api/config/**===put===[admin]
+  - /api/config/**===delete===[admin]
   # queue depth of the hertzbeat process itself, operational data
   - /api/metrics===get===[admin]
   # per account metric favourites rendered on the monitor pages
   - /api/metrics/**===get===[admin,user,guest]
   - /api/metrics/**===post===[admin,user,guest]
   - /api/metrics/**===delete===[admin,user,guest]
+  - /api/label/**===get===[admin,user,guest]
+  - /api/label/**===post===[admin,user]
+  - /api/label/**===put===[admin,user]
+  - /api/label/**===delete===[admin]
   # the storage availability probe is read by every monitor page, while the 
query
   # route forwards a raw promql expression straight to the time series database
   - /api/warehouse/**===get===[admin,user,guest]
diff --git a/script/sureness.yml b/script/sureness.yml
index ca3953169a..023cf7fcc0 100644
--- a/script/sureness.yml
+++ b/script/sureness.yml
@@ -137,12 +137,20 @@ resourceRole:
   - /api/plugin/**===post===[admin]
   - /api/plugin/**===put===[admin]
   - /api/plugin/**===delete===[admin]
+  - /api/config/**===get===[admin,user,guest]
+  - /api/config/**===post===[admin]
+  - /api/config/**===put===[admin]
+  - /api/config/**===delete===[admin]
   # queue depth of the hertzbeat process itself, operational data
   - /api/metrics===get===[admin]
   # per account metric favourites rendered on the monitor pages
   - /api/metrics/**===get===[admin,user,guest]
   - /api/metrics/**===post===[admin,user,guest]
   - /api/metrics/**===delete===[admin,user,guest]
+  - /api/label/**===get===[admin,user,guest]
+  - /api/label/**===post===[admin,user]
+  - /api/label/**===put===[admin,user]
+  - /api/label/**===delete===[admin]
   # the storage availability probe is read by every monitor page, while the 
query
   # route forwards a raw promql expression straight to the time series database
   - /api/warehouse/**===get===[admin,user,guest]


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

Reply via email to