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]

Reply via email to