# DOTENV Parameter Format

## Overview

The DOTENV parameter format is used to pass action parameters securely via stdin in a shell-compatible format. This format is particularly useful for shell scripts that need to parse parameters without relying on external tools like `jq`.

## Format Specification

### Basic Format

Parameters are formatted as `key='value'` pairs, one per line:

```bash
url='https://example.com'
method='GET'
timeout='30'
verify_ssl='true'
```

### Nested Object Flattening

Nested JSON objects are automatically flattened using dot notation. This allows shell scripts to easily parse complex parameter structures.

**Input JSON:**
```json
{
  "url": "https://example.com",
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Bearer token123"
  },
  "query_params": {
    "page": "1",
    "size": "10"
  }
}
```

**Output DOTENV:**
```bash
headers.Authorization='Bearer token123'
headers.Content-Type='application/json'
query_params.page='1'
query_params.size='10'
url='https://example.com'
```

### Empty Objects

Empty objects (`{}`) are omitted from the output entirely. They do not produce any dotenv entries.

**Input:**
```json
{
  "url": "https://example.com",
  "headers": {},
  "query_params": {}
}
```

**Output:**
```bash
url='https://example.com'
```

### Arrays

Arrays are serialized as JSON strings:

**Input:**
```json
{
  "tags": ["web", "api", "production"]
}
```

**Output:**
```bash
tags='["web","api","production"]'
```

### Special Characters

Single quotes in values are escaped using the shell-safe `'\''` pattern:

**Input:**
```json
{
  "message": "It's working!"
}
```

**Output:**
```bash
message='It'\''s working!'
```

## Shell Script Parsing

### Basic Parameter Parsing

```bash
#!/bin/sh

# Read DOTENV-formatted parameters from stdin
while IFS= read -r line; do
    case "$line" in
        *"---ATTUNE_PARAMS_END---"*) break ;;
    esac
    [ -z "$line" ] && continue

    key="${line%%=*}"
    value="${line#*=}"

    # Remove quotes
    case "$value" in
        \"*\") value="${value#\"}"; value="${value%\"}" ;;
        \'*\') value="${value#\'}"; value="${value%\'}" ;;
    esac

    # Process parameters
    case "$key" in
        url) url="$value" ;;
        method) method="$value" ;;
        timeout) timeout="$value" ;;
    esac
done
```

### Parsing Nested Objects

For flattened nested objects, use pattern matching on the key prefix:

```bash
# Create temporary files for nested data
headers_file=$(mktemp)
query_params_file=$(mktemp)

while IFS= read -r line; do
    case "$line" in
        *"---ATTUNE_PARAMS_END---"*) break ;;
    esac
    [ -z "$line" ] && continue

    key="${line%%=*}"
    value="${line#*=}"

    # Remove quotes
    case "$value" in
        \'*\') value="${value#\'}"; value="${value%\'}" ;;
    esac

    # Process parameters
    case "$key" in
        url) url="$value" ;;
        method) method="$value" ;;
        headers.*)
            # Extract nested key (e.g., "Content-Type" from "headers.Content-Type")
            nested_key="${key#headers.}"
            printf '%s: %s\n' "$nested_key" "$value" >> "$headers_file"
            ;;
        query_params.*)
            nested_key="${key#query_params.}"
            printf '%s=%s\n' "$nested_key" "$value" >> "$query_params_file"
            ;;
    esac
done

# Use the parsed data
if [ -s "$headers_file" ]; then
    while IFS= read -r header; do
        curl_args="$curl_args -H '$header'"
    done < "$headers_file"
fi
```

## Configuration

### Action YAML Configuration

Specify DOTENV format in your action YAML:

```yaml
ref: mypack.myaction
entry_point: myaction.sh
parameter_delivery: stdin
parameter_format: dotenv  # Use dotenv format
output_format: json
```

### Supported Formats

- `dotenv` - Shell-friendly key='value' format with nested object flattening
- `json` - Standard JSON format
- `yaml` - YAML format

### Supported Delivery Methods

- `stdin` - Parameters passed via stdin (recommended for security)
- `file` - Parameters written to a temporary file

## Security Considerations

### Why DOTENV + STDIN?

This combination provides several security benefits:

1. **No process list exposure**: Parameters don't appear in `ps aux` output
2. **No shell escaping issues**: Values are properly quoted
3. **Secret protection**: Sensitive values passed via stdin, not environment variables
4. **No external dependencies**: Pure POSIX shell parsing without `jq` or other tools

### Secret Handling

Secrets are passed separately via stdin after parameters. They are never included in environment variables or parameter files.

```bash
# Parameters are sent first
url='https://api.example.com'
---ATTUNE_PARAMS_END---
# Then secrets (as JSON)
{"api_key":"secret123","password":"hunter2"}
```

## Examples

### Example 1: HTTP Request Action

**Action Configuration:**
```yaml
ref: core.http_request
parameter_delivery: stdin
parameter_format: dotenv
```

**Execution Parameters:**
```json
{
  "url": "https://api.example.com/users",
  "method": "POST",
  "headers": {
    "Content-Type": "application/json",
    "User-Agent": "Attune/1.0"
  },
  "query_params": {
    "page": "1",
    "limit": "10"
  }
}
```

**Stdin Input:**
```bash
headers.Content-Type='application/json'
headers.User-Agent='Attune/1.0'
method='POST'
query_params.limit='10'
query_params.page='1'
url='https://api.example.com/users'
---ATTUNE_PARAMS_END---
```

### Example 2: Simple Shell Action

**Action Configuration:**
```yaml
ref: mypack.greet
parameter_delivery: stdin
parameter_format: dotenv
```

**Execution Parameters:**
```json
{
  "name": "Alice",
  "greeting": "Hello"
}
```

**Stdin Input:**
```bash
greeting='Hello'
name='Alice'
---ATTUNE_PARAMS_END---
```

## Troubleshooting

### Issue: Parameters Not Received

**Symptom:** Action receives empty or incorrect parameter values.

**Solution:** Ensure you're reading until the `---ATTUNE_PARAMS_END---` delimiter:

```bash
while IFS= read -r line; do
    case "$line" in
        *"---ATTUNE_PARAMS_END---"*) break ;;  # Important!
    esac
    # ... parse line
done
```

### Issue: Nested Objects Not Parsed

**Symptom:** Headers or query params not being set correctly.

**Solution:** Use pattern matching to detect dotted keys:

```bash
case "$key" in
    headers.*)
        nested_key="${key#headers.}"
        # Process nested key
        ;;
esac
```

### Issue: Special Characters Corrupted

**Symptom:** Values with single quotes are malformed.

**Solution:** The worker automatically escapes single quotes using `'\''`. Make sure to remove quotes correctly:

```bash
# Remove quotes (handles escaped quotes correctly)
case "$value" in
    \'*\') value="${value#\'}"; value="${value%\'}" ;;
esac
```

## Best Practices

1. **Always read until delimiter**: Don't stop reading stdin early
2. **Handle empty objects**: Check if files are empty before processing
3. **Use temporary files**: For nested objects, write to temp files for easier processing
4. **Validate required parameters**: Check that required values are present
5. **Clean up temp files**: Use `trap` to ensure cleanup on exit

```bash
#!/bin/sh
set -e

# Setup cleanup
headers_file=$(mktemp)
trap "rm -f $headers_file" EXIT

# Parse parameters...
```

## Implementation Details

The parameter flattening is implemented in `crates/worker/src/runtime/parameter_passing.rs`:

- Nested objects are recursively flattened with dot notation
- Empty objects produce no output entries
- Arrays are JSON-serialized as strings
- Output is sorted alphabetically for consistency
- Single quotes are escaped using shell-safe `'\''` pattern

## See Also

- [Action Parameter Schema](../packs/pack-structure.md#parameters)
- [Secrets Management](../authentication/secrets-management.md)
- [Shell Runtime](../architecture/worker-service.md#shell-runtime)