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

github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/main by this push:
     new 3dcd82b8e1 fix(workflow-operator): mask the HF API token field as a 
password widget (#7215)
3dcd82b8e1 is described below

commit 3dcd82b8e1602e3fa44b5121f09c9cb2c8d3b86b
Author: Prateek Ganigi <[email protected]>
AuthorDate: Sun Aug 2 16:59:13 2026 -0700

    fix(workflow-operator): mask the HF API token field as a password widget 
(#7215)
    
    ### What changes were proposed in this PR?
    
    The HuggingFace inference operator's `hfApiToken` field was a plain text
    input, the token was visible in the property panel and stored verbatim
    in the workflow JSON. This adds `@JsonSchemaInject(json =
    UIWidget.UIWidgetPassword)` to the field so it renders as a masked
    password input, following the same convention the SQL source operators
    (`SQLSourceOpDesc`) already use for their password field.
    
    ### Any related issues, documentation, discussions?
    
    Closes #7193.
    
    ### How was this PR tested?
    
    `sbt "WorkflowOperator/testOnly
    org.apache.texera.amber.operator.huggingFace.*
    org.apache.texera.amber.operator.metadata.*"`: the Hugging Face suite
    and the operator-metadata specs pass (146 tests). This includes a new
    test asserting the generated JSON schema marks `hfApiToken` as a
    password widget (`widget.formlyConfig.templateOptions.type ==
    "password"`), and the `metadata.*` specs confirm operator-schema
    generation still succeeds. scalafmt clean.
    
    The password widget is a schema-only change reusing an existing, shipped
    mechanism (`UIWidget.UIWidgetPassword`, already used by the SQL source
    operators), so no UI change was needed.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Yes, this PR was co-authored with Claude Opus 4.8 in compliance with
    ASF.
---
 .../operator/huggingFace/HuggingFaceInferenceOpDesc.scala  |  5 +++--
 .../huggingFace/HuggingFaceInferenceOpDescSpec.scala       | 14 ++++++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git 
a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDesc.scala
 
b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDesc.scala
index c08084135b..6599625ddf 100644
--- 
a/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDesc.scala
+++ 
b/common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDesc.scala
@@ -20,7 +20,7 @@
 package org.apache.texera.amber.operator.huggingFace
 
 import com.fasterxml.jackson.annotation.{JsonProperty, JsonPropertyDescription}
-import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaTitle
+import com.kjetland.jackson.jsonSchema.annotations.{JsonSchemaInject, 
JsonSchemaTitle}
 import org.apache.texera.amber.core.tuple.{AttributeType, Schema}
 import org.apache.texera.amber.core.workflow.{InputPort, OutputPort, 
PortIdentity}
 import org.apache.texera.amber.operator.PythonOperatorDescriptor
@@ -34,7 +34,7 @@ import org.apache.texera.amber.operator.huggingFace.codegen.{
   TaskCodegen,
   TextGenCodegen
 }
-import 
org.apache.texera.amber.operator.metadata.annotations.AutofillAttributeName
+import 
org.apache.texera.amber.operator.metadata.annotations.{AutofillAttributeName, 
UIWidget}
 import org.apache.texera.amber.operator.metadata.{OperatorGroupConstants, 
OperatorInfo}
 import org.apache.texera.amber.pybuilder.PyStringTypes.EncodableString
 
@@ -65,6 +65,7 @@ class HuggingFaceInferenceOpDesc extends 
PythonOperatorDescriptor {
   @JsonPropertyDescription(
     "Your Hugging Face API token (from https://huggingface.co/settings/tokens)"
   )
+  @JsonSchemaInject(json = UIWidget.UIWidgetPassword)
   var hfApiToken: EncodableString = ""
 
   @JsonProperty(value = "task", required = true, defaultValue = 
"text-generation")
diff --git 
a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDescSpec.scala
 
b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDescSpec.scala
index 7fcfe541bf..99eb14ed6f 100644
--- 
a/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDescSpec.scala
+++ 
b/common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/HuggingFaceInferenceOpDescSpec.scala
@@ -32,6 +32,7 @@ import 
org.apache.texera.amber.operator.metadata.OperatorGroupConstants
 import org.apache.texera.amber.pybuilder.PyStringTypes.EncodableString
 import org.scalatest.flatspec.AnyFlatSpec
 import org.scalatest.matchers.should.Matchers
+import org.apache.texera.amber.operator.metadata.OperatorMetadataGenerator
 
 class HuggingFaceInferenceOpDescSpec extends AnyFlatSpec with Matchers {
 
@@ -647,4 +648,17 @@ class HuggingFaceInferenceOpDescSpec extends AnyFlatSpec 
with Matchers {
     val outSchema = out(desc.operatorInfo.outputPorts.head.id)
     outSchema.getAttributeNames.contains("hf_response") shouldBe true
   }
+
+  it should "mask the API token field as a password widget in the generated 
schema" in {
+    val tokenProp = OperatorMetadataGenerator
+      .generateOperatorJsonSchema(classOf[HuggingFaceInferenceOpDesc])
+      .path("properties")
+      .path("hfApiToken")
+    tokenProp
+      .path("widget")
+      .path("formlyConfig")
+      .path("templateOptions")
+      .path("type")
+      .asText() shouldBe "password"
+  }
 }

Reply via email to