Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions crates/context_aware_config/src/api/functions/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ async fn create_handler(
let handle = rustyscript::tokio::runtime::Handle::current();
let function = req.function.clone();
handle
.spawn_blocking(move || compile_fn(&function))
.spawn_blocking(move || compile_fn(&function, &req.function_type))
.await
.map_err(|e| {
log::error!("Function compilation task failed: {:?}", e);
Expand Down Expand Up @@ -148,13 +148,14 @@ async fn update_handler(
let DbConnection(mut conn) = db_conn;
let req = request.into_inner();
let f_name: String = params.into_inner().into();
let function = fetch_function(&f_name, &mut conn, &workspace_context.schema_name)?;

// Function Linter Check
if let Some(fc) = &req.draft_code {
let handle = rustyscript::tokio::runtime::Handle::current();
let function = fc.clone();
let function_code = fc.clone();
handle
.spawn_blocking(move || compile_fn(&function))
.spawn_blocking(move || compile_fn(&function_code, &function.function_type))
.await
.map_err(|err| bad_argument!("Invalid function code: {}", err))??;
}
Expand Down
97 changes: 74 additions & 23 deletions crates/context_aware_config/src/validation_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ use superposition_macros::{bad_argument, validation_error};
use service_utils::service::types::{EncryptionKey, WorkspaceContext};
use superposition_types::{
DBConnection,
api::functions::{FunctionExecutionRequest, FunctionExecutionResponse},
database::models::cac::{FunctionCode, FunctionRuntimeVersion, FunctionType},
api::functions::{
ContextValidationTrigger, FunctionEnvironment, FunctionExecutionRequest,
FunctionExecutionResponse, KeyType,
},
database::models::{
ChangeReason,
cac::{FunctionCode, FunctionRuntimeVersion, FunctionType},
},
result as superposition,
};

Expand Down Expand Up @@ -73,11 +79,12 @@ pub fn run_js_function(
args: FunctionExecutionRequest,
runtime_version: FunctionRuntimeVersion,
) -> Result<FunctionExecutionResponse, (String, Option<String>)> {
let wrapped_code = generate_wrapped_code(&code.0);
let wrapped_code = generate_wrapped_code(&code);
let module = Module::new("function.js", &wrapped_code);

let runtime_options = RuntimeOptions {
timeout: Duration::from_millis(1500),
// import_provider: Some(Box::new(DenyFileImportProvider::default())),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove this comment ?

..Default::default()
};

Expand Down Expand Up @@ -147,19 +154,14 @@ pub fn execute_fn(
run_js_function(code, args.clone(), runtime_version)
}

pub fn compile_fn(code_str: &FunctionCode) -> superposition::Result<()> {
let type_check_code = format!(
r#"
{}

export function typeCheck() {{
if (typeof execute === "undefined") {{
throw new Error("execute function is not defined");
}}
}}
"#,
code_str
);
pub fn compile_fn(
code_str: &FunctionCode,
fn_type: &FunctionType,
) -> superposition::Result<()> {
// syntax validation, so we do not need the actual secrets and vars
let stubs = "const SECRETS = {};\nconst VARS = {};\n";
let stubbed_code = FunctionCode(format!("{}\n{}", stubs, code_str));
let type_check_code = generate_wrapped_code(&stubbed_code);

rustyscript::validate(&type_check_code).map_err(|err| {
log::error!("Invalid function syntax: {:?}", err);
Expand All @@ -185,13 +187,62 @@ pub fn compile_fn(code_str: &FunctionCode) -> superposition::Result<()> {
let tokio_runtime = runtime.tokio_runtime();
tokio_runtime
.block_on(async {
runtime
.call_function_async::<()>(
Some(&module_handle),
"typeCheck",
json_args!(),
)
.await
let environment = FunctionEnvironment {
context: serde_json::Map::new(),
overrides: serde_json::Map::new(),
};
match fn_type {
FunctionType::ValueCompute => {
let payload = FunctionExecutionRequest::ValueComputeFunctionRequest {
name: String::new(),
prefix: String::new(),
r#type: superposition_types::api::functions::KeyType::ConfigKey,
environment,
};
let serde_json::Value::Array(_) = runtime
.call_function_async::<serde_json::Value>(
Some(&module_handle),
"execute",
json_args!(payload),
)
.await? else {
return Err(rustyscript::Error::Runtime("The value compute function did not return an array".to_string()));
};
Ok(())
}
other => {
let payload = match other {
FunctionType::ValueValidation => FunctionExecutionRequest::ValueValidationFunctionRequest {
key: String::new(),
value: serde_json::Value::String(String::new()),
r#type:
KeyType::ConfigKey,
environment,
},
FunctionType::ContextValidation => FunctionExecutionRequest::ContextValidationFunctionRequest {
environment,
trigger_reason: ContextValidationTrigger::Context,
},
FunctionType::ChangeReasonValidation => FunctionExecutionRequest::ChangeReasonValidationFunctionRequest {
change_reason: ChangeReason::default(),
},
_ => {
return Err(rustyscript::Error::Runtime("An invalid situation occurred in the runtime".to_string()))
}
};
let serde_json::Value::Bool(_) = runtime
.call_function_async::<serde_json::Value>(
Some(&module_handle),
"execute",
json_args!(payload),
)
.await? else {
return Err(rustyscript::Error::Runtime("The function did not return a boolean".to_string()))
};
Ok(())
}

}
Comment on lines +190 to +245

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify rustyscript Error::Runtime variant and call_function_async signature
rg -nP 'enum Error|Runtime\s*\(|fn call_function_async' $(fd -HI -t d 'rustyscript*' ~/.cargo 2>/dev/null) 2>/dev/null
cargo doc -p rustyscript --no-deps 2>/dev/null | head -n 5 || echo "inspect rustyscript version in Cargo.lock"
rg -nP 'name = "rustyscript"' -A2 Cargo.lock

Repository: juspay/superposition

Length of output: 158


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the validation code and nearby context
sed -n '1,320p' crates/context_aware_config/src/validation_functions.rs | cat -n

# Find related usages/tests/docs in the repo
rg -n "validation_functions|FunctionType::ValueCompute|ContextValidation|ChangeReasonValidation|validate.*function|execute" crates/context_aware_config -S

# Locate rustyscript version and any cached source/docs in the local cargo registry
rg -n 'name = "rustyscript"' Cargo.lock
fd -HI -t d 'rustyscript-*' ~/.cargo/registry/src ~/.cargo/registry/cache 2>/dev/null | head -n 20

Repository: juspay/superposition

Length of output: 20912


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect call sites and validation semantics
sed -n '1,260p' crates/context_aware_config/src/api/functions/handlers.rs | cat -n
sed -n '1,260p' crates/context_aware_config/src/api/dimension/validations.rs | cat -n
sed -n '1,260p' crates/context_aware_config/src/api/default_config/handlers.rs | cat -n

# Search for tests or docs that describe what compile_fn accepts
rg -n "compile_fn|validation_error!|ValueCompute|ContextValidation|ChangeReasonValidation|dummy|empty/default|return type" crates/context_aware_config -S

# Locate rustyscript source in the local cargo registry and inspect the API
fd -HI -t d 'rustyscript-*' ~/.cargo/registry/src ~/.cargo/registry/cache 2>/dev/null | head -n 20

Repository: juspay/superposition

Length of output: 39607


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Get rustyscript version from Cargo.lock and locate the corresponding source
version=$(awk '
  $0 == '\"'\"'name = \"rustyscript\"'\"'\"' {found=1}
  found && $0 ~ /^version = / {gsub(/"/,""); print $3; exit}
' Cargo.lock)

echo "rustyscript version: ${version:-unknown}"

root=$(fd -HI -t d "rustyscript-${version}" ~/.cargo/registry/src ~/.cargo/registry/cache 2>/dev/null | head -n 1)
echo "rustyscript root: $root"

if [ -n "${root:-}" ]; then
  rg -n "enum Error|Runtime\\(|call_function_async" "$root" -S
fi

Repository: juspay/superposition

Length of output: 242


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect runtime validation semantics for context validation functions
sed -n '280,360p' crates/context_aware_config/src/api/context/helpers.rs | cat -n

# Safely extract the rustyscript version from Cargo.lock
python3 - <<'PY'
import re, pathlib
text = pathlib.Path("Cargo.lock").read_text()
m = re.search(r'name = "rustyscript"\nversion = "([^"]+)"', text)
print(m.group(1) if m else "not found")
PY

Repository: juspay/superposition

Length of output: 3623


Avoid validating with empty/default inputs
compile_fn executes execute with an empty FunctionEnvironment and blank fields, so any function that legitimately needs a key, value, or context entry can be rejected at create/update time even if it works during normal execution. Use contract-appropriate fixture data or skip hard-failing on runtime exceptions here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/context_aware_config/src/validation_functions.rs` around lines 187 -
242, The compile_fn validation currently calls validation functions through
validation_functions::compile_fn using an empty FunctionEnvironment and
blank/default request fields, which can falsely fail functions that require real
key/value/context data. Update the execute smoke test payloads for
FunctionType::ValueCompute, FunctionType::ValueValidation, and
FunctionType::ContextValidation to use contract-appropriate fixture inputs, or
relax this path so runtime exceptions from missing data do not hard-fail
create/update validation.

})
.map_err(|e| {
let err_str = e.to_string();
Expand Down
Loading