Files
attune/work-summary/2026-02-09-dotenv-parameter-flattening.md
David Culbreth 87d830f952
Some checks failed
CI / Rustfmt (push) Successful in 23s
CI / Cargo Audit & Deny (push) Successful in 30s
CI / Web Blocking Checks (push) Successful in 48s
CI / Security Blocking Checks (push) Successful in 8s
CI / Clippy (push) Failing after 1m55s
CI / Web Advisory Checks (push) Successful in 35s
CI / Security Advisory Checks (push) Successful in 37s
CI / Tests (push) Successful in 8m5s
[wip] cli capability parity
2026-03-06 16:58:50 -06:00

6.3 KiB

DOTENV Parameter Flattening Fix

Date: 2026-02-09 Status: Complete Impact: Bug Fix - Critical

Problem

The core.http_request action was failing when executed, even though the HTTP request succeeded (returned 200 status). Investigation revealed that the action was receiving incorrect parameter values - specifically, the url parameter received "200" instead of the actual URL like "https://example.com".

Root Cause

The issue was in how nested JSON objects were being converted to DOTENV format for stdin parameter delivery:

  1. The action YAML specified parameter_format: dotenv for shell-friendly parameter passing
  2. When execution parameters contained nested objects (like headers: {}, query_params: {}), the format_dotenv() function was serializing them as JSON strings
  3. The shell script expected flattened dotted notation (e.g., headers.Content-Type=application/json)
  4. This mismatch caused parameter parsing to fail in the shell script

Example of the bug:

// Input parameters
{
  "url": "https://example.com",
  "headers": {"Content-Type": "application/json"},
  "query_params": {"page": "1"}
}

Incorrect output (before fix):

url='https://example.com'
headers='{"Content-Type":"application/json"}'
query_params='{"page":"1"}'

The shell script couldn't parse headers='{...}' and expected:

headers.Content-Type='application/json'
query_params.page='1'

Solution

Modified crates/worker/src/runtime/parameter_passing.rs to flatten nested JSON objects before formatting as DOTENV:

Key Changes

  1. Added flatten_parameters() function: Recursively flattens nested objects using dot notation
  2. Modified format_dotenv(): Now calls flatten_parameters() before formatting
  3. Empty object handling: Empty objects ({}) are omitted entirely from output
  4. Array handling: Arrays are still serialized as JSON strings (expected behavior)
  5. Sorted output: Lines are sorted alphabetically for consistency

Implementation Details

fn flatten_parameters(
    params: &HashMap<String, JsonValue>,
    prefix: &str,
) -> HashMap<String, String> {
    let mut flattened = HashMap::new();

    for (key, value) in params {
        let full_key = if prefix.is_empty() {
            key.clone()
        } else {
            format!("{}.{}", prefix, key)
        };

        match value {
            JsonValue::Object(map) => {
                // Recursively flatten nested objects
                let nested = /* ... */;
                flattened.extend(nested);
            }
            // ... handle other types
        }
    }

    flattened
}

Correct output (after fix):

headers.Content-Type='application/json'
query_params.page='1'
url='https://example.com'

Testing

Unit Tests Added

  1. test_format_dotenv_nested_objects: Verifies nested object flattening
  2. test_format_dotenv_empty_objects: Verifies empty objects are omitted

All tests pass:

running 9 tests
test runtime::parameter_passing::tests::test_format_dotenv ... ok
test runtime::parameter_passing::tests::test_format_dotenv_empty_objects ... ok
test runtime::parameter_passing::tests::test_format_dotenv_escaping ... ok
test runtime::parameter_passing::tests::test_format_dotenv_nested_objects ... ok
test runtime::parameter_passing::tests::test_format_json ... ok
test runtime::parameter_passing::tests::test_format_yaml ... ok
test runtime::parameter_passing::tests::test_create_parameter_file ... ok
test runtime::parameter_passing::tests::test_prepare_parameters_stdin ... ok
test runtime::parameter_passing::tests::test_prepare_parameters_file ... ok

test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured

Code Cleanup

  • Removed unused value_to_string() function
  • Removed unused OutputFormat import from local.rs
  • Zero compiler warnings after fix

Files Modified

  1. crates/worker/src/runtime/parameter_passing.rs

    • Added flatten_parameters() function
    • Modified format_dotenv() to use flattening
    • Removed unused value_to_string() function
    • Added unit tests
  2. crates/worker/src/runtime/local.rs

    • Removed unused OutputFormat import

Documentation Created

  1. docs/parameters/dotenv-parameter-format.md - Comprehensive guide covering:
    • DOTENV format specification
    • Nested object flattening rules
    • Shell script parsing examples
    • Security considerations
    • Troubleshooting guide
    • Best practices

Deployment

  1. Rebuilt worker-shell Docker image with fix
  2. Restarted worker-shell service
  3. Fix is now live and ready for testing

Impact

Before Fix

  • core.http_request action: FAILED with incorrect parameters
  • Any action using parameter_format: dotenv with nested objects: BROKEN

After Fix

  • core.http_request action: Should work correctly with nested headers/query_params
  • All dotenv-format actions: Properly receive flattened nested parameters
  • Shell scripts: Can parse parameters without external dependencies (no jq needed)

Verification Steps

To verify the fix works:

  1. Execute core.http_request with nested parameters:
attune action execute core.http_request \
  --param url=https://example.com \
  --param method=GET \
  --param 'headers={"Content-Type":"application/json"}' \
  --param 'query_params={"page":"1"}'
  1. Check execution logs - should see flattened parameters in stdin:
headers.Content-Type='application/json'
query_params.page='1'
url='https://example.com'
  1. Verify execution succeeds with correct HTTP request/response

This fix resolves parameter passing for all shell actions using:

  • parameter_delivery: stdin
  • parameter_format: dotenv
  • Nested object parameters

Notes

  • DOTENV format is recommended for shell actions due to security (no process list exposure) and simplicity (no external dependencies)
  • JSON and YAML formats still work as before (no changes needed)
  • This is a backward-compatible fix - existing actions continue to work
  • The core.http_request action specifically benefits as it uses nested headers and query_params objects

Next Steps

  1. Test core.http_request action with various parameter combinations
  2. Update any other core pack actions to use parameter_format: dotenv where appropriate
  3. Consider adding integration tests for parameter passing formats