luigidemasi commented on code in PR #27656:
URL: https://github.com/apache/camel/pull/27656#discussion_r4237544152
##########
components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/SemanticAuditService.java:
##########
@@ -64,6 +66,7 @@ public final class SemanticAuditService extends
ServiceSupport {
private final AtomicLong observerErrors = new AtomicLong();
private final Map<String, AtomicLong> sinkErrors = new LinkedHashMap<>();
private final Map<String, SemanticAuditSink> sinks = new LinkedHashMap<>();
+ private final Map<String, SemanticAuditInputRedactor> redactors = new
LinkedHashMap<>();
Review Comment:
Fixed in
[ef9a87d2da22](https://github.com/apache/camel/commit/ef9a87d2da22cdff41c87cc4cb1d491c41451c8b).
Redactors are now resolved into a local map and published together as an
immutable snapshot through a volatile field after initialization succeeds.
Stopping clears the published bindings, which also prevents capture between
stop and restart from applying a previous redactor after configuration changes.
The regressions hold startup halfway through resolving two bindings and
exercise a changed redactor across stop/start; both failed before the fix and
pass now.
_AI-generated by OpenAI Codex on behalf of @luigidemasi._
##########
components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/SemanticAuditInputSnapshot.java:
##########
@@ -0,0 +1,88 @@
+/*
+ * 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.camel.semantic.internal;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Bounded JSON values only: never converts arbitrary objects or consumes
streams. */
+public final class SemanticAuditInputSnapshot {
+ private int remaining;
+ private int nodes = 1000;
+
+ private SemanticAuditInputSnapshot(int maxChars) {
+ remaining = maxChars;
+ }
+
+ public static Object copy(Object input, int maxChars) {
+ return new SemanticAuditInputSnapshot(maxChars).value(input, 0);
+ }
+
+ private Object value(Object value, int depth) {
+ if (--nodes < 0 || depth > 8) {
+ throw new IllegalArgumentException("Input snapshot limit");
+ }
+ if (value == null || value instanceof Boolean) {
+ text(String.valueOf(value));
+ return value;
+ }
+ if (value instanceof String text) {
+ return text(text);
+ }
+ if (value instanceof Byte || value instanceof Short || value
instanceof Integer || value instanceof Long
+ || value instanceof Float || value instanceof Double || value
instanceof BigDecimal
+ || value instanceof BigInteger) {
+ if (value instanceof Double d && !Double.isFinite(d) || value
instanceof Float f && !Float.isFinite(f)
+ || value instanceof BigInteger integer &&
integer.bitLength() > remaining * 4
+ || value instanceof BigDecimal decimal &&
decimal.precision() > remaining) {
+ throw new IllegalArgumentException("Input snapshot limit");
+ }
+ text(value.toString());
+ return value;
+ }
+ if (value instanceof List<?> list && list.size() <= nodes) {
Review Comment:
Added the explanatory comment and a nested boundary test in
[ef9a87d2da22](https://github.com/apache/camel/commit/ef9a87d2da22cdff41c87cc4cb1d491c41451c8b).
Collection-size checks reject obvious overflows early; every recursive value
still decrements the same node counter, and exceeding it throws without
returning a partial snapshot. The test accepts exactly 1,000 nested nodes and
rejects the next node. The existing bound is therefore retained; callers cannot
receive an oversized snapshot.
_AI-generated by OpenAI Codex on behalf of @luigidemasi._
##########
components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/SemanticAuditService.java:
##########
@@ -361,10 +381,50 @@ public final class Invocation {
private final List<SemanticObserver.Observation> handles = new
ArrayList<>();
// Confined to the invocation thread; cancellation emits a separate
request record.
private boolean completed;
+ private final Map<String, Object> inputFields = new LinkedHashMap<>();
private Invocation(Map<String, Object> fields, boolean enabled) {
this.fields = fields;
this.enabled = enabled;
+ if (enabled && configuration.getInput((String)
fields.get("expert")).isEnabled()) {
+ inputFields.put("inputOmitted", "unavailable");
+ }
+ }
+
+ /** Snapshot the effective selected state before a provider can mutate
it. Observers never receive this data. */
+ public void captureInput(Object input) {
+ if (fields == null || completed || inputFields.isEmpty()) {
Review Comment:
Fixed in
[ef9a87d2da22](https://github.com/apache/camel/commit/ef9a87d2da22cdff41c87cc4cb1d491c41451c8b)
with a separate inputCaptured flag set before snapshot/redaction. Repeated
calls now preserve the first attempt, including omitted or failed redaction.
completed remains reserved for evaluation completion: setting it during capture
would suppress both observer completion and audit publication. Parameterized
regressions verify one redactor call, preservation of the first input/omission,
and successful publication of the final record.
_AI-generated by OpenAI Codex on behalf of @luigidemasi._
##########
components/camel-ai/camel-semantic/src/main/java/org/apache/camel/semantic/internal/SemanticAuditService.java:
##########
@@ -361,10 +381,50 @@ public final class Invocation {
private final List<SemanticObserver.Observation> handles = new
ArrayList<>();
// Confined to the invocation thread; cancellation emits a separate
request record.
private boolean completed;
+ private final Map<String, Object> inputFields = new LinkedHashMap<>();
private Invocation(Map<String, Object> fields, boolean enabled) {
this.fields = fields;
this.enabled = enabled;
+ if (enabled && configuration.getInput((String)
fields.get("expert")).isEnabled()) {
+ inputFields.put("inputOmitted", "unavailable");
+ }
+ }
+
+ /** Snapshot the effective selected state before a provider can mutate
it. Observers never receive this data. */
+ public void captureInput(Object input) {
+ if (fields == null || completed || inputFields.isEmpty()) {
+ return;
+ }
+ SemanticAuditInputConfiguration policy =
configuration.getInput((String) fields.get("expert"));
+ SemanticAuditInputRedactor redactor =
redactors.get(fields.get("expert"));
+ inputFields.clear();
+ if (policy.getRedactor() != null && redactor == null) {
+ inputFields.put("inputOmitted", "redaction_failed");
+ return;
+ }
+ Object snapshot;
+ try {
+ snapshot = SemanticAuditInputSnapshot.copy(input,
policy.getMaxChars());
+ } catch (Exception | AssertionError | LinkageError failure) {
Review Comment:
Clarified the rationale in
[ef9a87d2da22](https://github.com/apache/camel/commit/ef9a87d2da22cdff41c87cc4cb1d491c41451c8b):
snapshot failures are isolated from the expert evaluation and produce an
omission reason. Snapshot traversal can execute methods on supplied collection
implementations, so the AssertionError and LinkageError cases are deliberate.
New tests exercise both from collection access and verify that evaluation still
succeeds with input omitted. Fatal VM errors remain outside the catch.
_AI-generated by OpenAI Codex on behalf of @luigidemasi._
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]