From ac00e2bd5de28bd8a2acebf47522c971d11b404a Mon Sep 17 00:00:00 2001
From: aecsocket <43144841+aecsocket@users.noreply.github.com>
Date: Thu, 13 Aug 2026 18:12:46 +0000
Subject: [PATCH] allow returning strings from CEL as shorthand
---
.../src/pages/moderation/technical-review/rules.vue | 6 +++---
apps/labrinth/fixtures/delphi-trace-rules.sql | 6 +++---
.../routes/internal/moderation/tech_review/rules.rs | 7 +++++++
.../internal/moderation/tech_review/rules_scan.rs | 12 +++++++++---
4 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/apps/frontend/src/pages/moderation/technical-review/rules.vue b/apps/frontend/src/pages/moderation/technical-review/rules.vue
index bf106a13ef..325e29cc44 100644
--- a/apps/frontend/src/pages/moderation/technical-review/rules.vue
+++ b/apps/frontend/src/pages/moderation/technical-review/rules.vue
@@ -46,8 +46,8 @@
- Return null when the rule does not match, or a map containing
- severity when it does.
+ Return null when the rule does not match, or return a severity string such as
+ "low". A map containing severity is also supported.
@@ -433,7 +433,7 @@ import type { Component } from 'vue'
import IssueDetailPath from '~/components/ui/moderation/IssueDetailPath.vue'
const DEFAULT_RULE = `trace.issue_type == "OBFUSCATED_NAMES"
- ? {"severity": "low"}
+ ? "low"
: null`
const RULE_EDITOR_OPTIONS: Partial = {
useWorker: false,
diff --git a/apps/labrinth/fixtures/delphi-trace-rules.sql b/apps/labrinth/fixtures/delphi-trace-rules.sql
index 03d7ab790d..4e9baa13cb 100644
--- a/apps/labrinth/fixtures/delphi-trace-rules.sql
+++ b/apps/labrinth/fixtures/delphi-trace-rules.sql
@@ -216,7 +216,7 @@ INSERT INTO delphi_rules (name, rule, priority, revision)
VALUES
(
'[DEV trace-rule fixture] Escalate known malware host',
- 'trace.issue_type == "SUSPICIOUS_NETWORK_ACCESS" && trace.data.host == "evil.example" ? {"severity": "malware"} : null',
+ 'trace.issue_type == "SUSPICIOUS_NETWORK_ACCESS" && trace.data.host == "evil.example" ? "malware" : null',
1000,
(SELECT revision FROM delphi_rule_revisions LIMIT 1)
),
@@ -234,7 +234,7 @@ VALUES
),
(
'[DEV trace-rule fixture] Hide known-safe obfuscation',
- 'trace.issue_type == "OBFUSCATED_NAMES" && trace.data.confidence >= 0.95 ? {"severity": "hidden"} : null',
+ 'trace.issue_type == "OBFUSCATED_NAMES" && trace.data.confidence >= 0.95 ? "hidden" : null',
700,
(SELECT revision FROM delphi_rule_revisions LIMIT 1)
),
@@ -252,7 +252,7 @@ VALUES
),
(
'[DEV trace-rule fixture] Downgrade bundled libraries',
- 'trace.issue_type == "BUNDLED_LIBRARY" ? {"severity": "low"} : null',
+ 'trace.issue_type == "BUNDLED_LIBRARY" ? "low" : null',
400,
(SELECT revision FROM delphi_rule_revisions LIMIT 1)
),
diff --git a/apps/labrinth/src/routes/internal/moderation/tech_review/rules.rs b/apps/labrinth/src/routes/internal/moderation/tech_review/rules.rs
index 58b4aebeba..ff5ec950d3 100644
--- a/apps/labrinth/src/routes/internal/moderation/tech_review/rules.rs
+++ b/apps/labrinth/src/routes/internal/moderation/tech_review/rules.rs
@@ -97,6 +97,13 @@ pub struct DelphiRuleEffect {
pub severity: DelphiSeverity,
}
+#[derive(Serialize, utoipa::ToSchema)]
+#[serde(untagged)]
+pub enum DelphiRuleOutput {
+ Severity(DelphiSeverity),
+ Effect(DelphiRuleEffect),
+}
+
struct ValidatedRule {
name: String,
rule: String,
diff --git a/apps/labrinth/src/routes/internal/moderation/tech_review/rules_scan.rs b/apps/labrinth/src/routes/internal/moderation/tech_review/rules_scan.rs
index 4cd7f6d6ba..b8ad0d999c 100644
--- a/apps/labrinth/src/routes/internal/moderation/tech_review/rules_scan.rs
+++ b/apps/labrinth/src/routes/internal/moderation/tech_review/rules_scan.rs
@@ -12,7 +12,7 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
use utoipa::{PartialSchema, ToSchema};
use xredis::RedisPool;
-use super::rules::DelphiRuleEffect;
+use super::rules::{DelphiRuleEffect, DelphiRuleOutput};
use crate::routes::internal::delphi::tech_review_queue::{
self, TechReviewRemovalReason,
};
@@ -156,12 +156,12 @@ pub async fn get_rule_schema(
let mut schemas = Vec::new();
::schemas(&mut schemas);
- as ToSchema>::schemas(&mut schemas);
+ as ToSchema>::schemas(&mut schemas);
Ok(web::Json(DelphiRuleSchemaResponse {
input: schema_to_value(::schema())?,
output: schema_to_value(
- as PartialSchema>::schema(),
+ as PartialSchema>::schema(),
)?,
components: schemas
.into_iter()
@@ -972,6 +972,12 @@ fn evaluate_rule_inner(
match value {
serde_json::Value::Null => Ok(None),
+ serde_json::Value::String(severity) => {
+ let severity =
+ serde_json::from_value(serde_json::Value::String(severity))
+ .wrap_err("cel expression returned an invalid severity")?;
+ Ok(Some(DelphiRuleEffect { severity }))
+ }
value => serde_json::from_value(value)
.map(Some)
.wrap_err("cel expression returned an invalid rule effect"),