This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-7215-436b37e9b62e6be2ef8ea911ec30387dd7e80415 in repository https://gitbox.apache.org/repos/asf/texera.git
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" + } }
