18 KiB
Environment Variable Standardization
Date: 2026-02-07
Status: Code Complete - Docker Build Required for Testing
Related Thread: Attune Secure Action Parameter Migration
Overview
Review of environment variables provided to actions and sensors revealed inconsistencies with the documented standard. This work standardized the environment variables across both execution models, achieving near-complete parity. The only remaining work is implementing execution-scoped API token generation.
Summary of Changes
Actions (Worker)
- ✅ Renamed
ATTUNE_EXECUTION_ID→ATTUNE_EXEC_ID - ✅ Renamed
ATTUNE_ACTION_REF→ATTUNE_ACTION - ✅ Removed
ATTUNE_ACTION_ID(internal DB field not useful to actions) - ✅ Added
ATTUNE_API_URL(from environment or constructed from server config) - ✅ Added
ATTUNE_RULE(fetched from enforcement record when applicable) - ✅ Added
ATTUNE_TRIGGER(fetched from enforcement record when applicable) - ⚠️ Added
ATTUNE_API_TOKENfield (currently empty string - token generation TODO)
Sensors (Sensor Manager)
- ✅ Added
ATTUNE_SENSOR_ID(sensor database ID for parity withATTUNE_EXEC_ID)
Result
- Before: Actions had non-standard variable names, no API access, no execution context
- After: Actions and sensors follow consistent patterns with clear parity
- Remaining: Implement execution-scoped JWT token generation for full API access
Standard Environment Variables (Per Documentation)
According to docs/QUICKREF-execution-environment.md, all executions should receive:
| Variable | Type | Description | Always Present |
|---|---|---|---|
ATTUNE_ACTION |
string | Action ref (e.g., core.http_request) |
✅ Yes |
ATTUNE_EXEC_ID |
integer | Execution database ID | ✅ Yes |
ATTUNE_API_TOKEN |
string | Execution-scoped API token | ✅ Yes |
ATTUNE_RULE |
string | Rule ref that triggered execution | ❌ Only if from rule |
ATTUNE_TRIGGER |
string | Trigger ref that caused enforcement | ❌ Only if from trigger |
Additionally, the API URL should be available:
ATTUNE_API_URL- Base URL for Attune API
Current State Analysis
Action Worker (crates/worker/src/executor.rs)
Currently Setting:
- ❌
ATTUNE_EXECUTION_ID(should beATTUNE_EXEC_ID) - ❌
ATTUNE_ACTION_REF(should beATTUNE_ACTION) - ❌
ATTUNE_ACTION_ID(not in standard, DB internal ID)
Missing:
- ❌
ATTUNE_API_TOKEN- CRITICAL - Actions cannot call API! - ❌
ATTUNE_API_URL- Actions don't know where to call - ❌
ATTUNE_RULE- No context about triggering rule - ❌
ATTUNE_TRIGGER- No context about triggering event
Issues:
- Actions have NO API access (no token or URL)
- Variable names don't match documented standard
- Missing execution context (rule/trigger info)
- Documentation promises features that don't exist
Sensor Manager (crates/sensor/src/sensor_manager.rs)
Currently Setting:
- ✅
ATTUNE_API_URL- Sensor knows where to call API - ✅
ATTUNE_API_TOKEN- Sensor can authenticate - ✅
ATTUNE_SENSOR_REF- Sensor identity (equivalent toATTUNE_ACTION) - ✅
ATTUNE_SENSOR_TRIGGERS- Sensor-specific: trigger instances to monitor - ✅
ATTUNE_MQ_URL- Sensor-specific: message queue connection - ✅
ATTUNE_MQ_EXCHANGE- Sensor-specific: exchange for event publishing - ✅
ATTUNE_LOG_LEVEL- Logging configuration
Missing for Parity:
- ❌
ATTUNE_SENSOR_ID- Sensor database ID (equivalent toATTUNE_EXEC_ID)
Assessment: Sensors are in MUCH better shape than actions! They have:
- Full API access (token + URL)
- Clear identity (sensor ref)
- Sensor-specific context (triggers, MQ config)
Required Fixes
Fix 1: Action Worker - Add Standard Environment Variables
File: attune/crates/worker/src/executor.rs
Function: prepare_execution_context()
Line: ~212-237
Changes Required:
-
Rename existing variables:
// OLD env.insert("ATTUNE_EXECUTION_ID".to_string(), execution.id.to_string()); env.insert("ATTUNE_ACTION_REF".to_string(), execution.action_ref.clone()); // NEW env.insert("ATTUNE_EXEC_ID".to_string(), execution.id.to_string()); env.insert("ATTUNE_ACTION".to_string(), execution.action_ref.clone()); -
Remove non-standard variable:
// REMOVE - internal DB ID not useful to actions env.insert("ATTUNE_ACTION_ID".to_string(), action_id.to_string()); -
Add API access:
// Add API URL from config env.insert("ATTUNE_API_URL".to_string(), self.api_url.clone()); // Generate execution-scoped API token let api_token = self.generate_execution_token(execution.id).await?; env.insert("ATTUNE_API_TOKEN".to_string(), api_token); -
Add execution context (rule/trigger):
// Add rule context if execution was triggered by rule if let Some(ref rule_ref) = execution.rule_ref { env.insert("ATTUNE_RULE".to_string(), rule_ref.clone()); } // Add trigger context if execution was triggered by event if let Some(ref trigger_ref) = execution.trigger_ref { env.insert("ATTUNE_TRIGGER".to_string(), trigger_ref.clone()); }
Prerequisites:
- ActionExecutor needs access to API URL (from config)
- Need to implement
generate_execution_token()method (similar to sensor token generation) - Execution model may need
rule_refandtrigger_reffields (check if exists)
Fix 2: Sensor Manager - Add Sensor ID
File: attune/crates/sensor/src/sensor_manager.rs
Function: start_standalone_sensor()
Line: ~248-257
Changes Required:
.env("ATTUNE_SENSOR_ID", &sensor.id.to_string()) // Add sensor DB ID
This provides parity with ATTUNE_EXEC_ID for actions.
Fix 3: Update Documentation Examples
All documentation examples that reference environment variables need to be verified for consistency:
docs/QUICKREF-execution-environment.md- Already correct (this is the spec)packs/core/actions/README.md- Check for outdated variable namesdocs/architecture/worker-service.md- Update implementation details- Any pack action scripts using old names
Implementation Plan
Phase 1: Database Schema Check
- Verify
executiontable hasrule_refandtrigger_refcolumns - If missing, create migration to add them
- Ensure these fields are populated by executor when creating executions
Phase 2: Token Generation for Actions
- Create
generate_execution_token()method in ActionExecutor - Similar to sensor token generation but scoped to execution
- Token should grant:
- Read access to own execution
- Create child executions
- Access secrets owned by execution identity
- Limited validity (expires with execution)
Phase 3: Update ActionExecutor
- Add API URL to ActionExecutor config/initialization
- Implement token generation
- Update
prepare_execution_context()with all standard variables - Remove
ATTUNE_ACTION_ID(internal ID)
Phase 4: Update SensorManager
- Add
ATTUNE_SENSOR_IDenvironment variable
Phase 5: Testing
- Test action execution with API calls using new token
- Verify all environment variables are present and correct
- Test rule/trigger context propagation
- Update integration tests
Phase 6: Documentation Update
- Update any code examples using old variable names
- Add migration guide for pack developers
- Update troubleshooting docs
Migration Impact
Breaking Changes
✅ Acceptable - Project is pre-production with no external users
Pack Compatibility
- Core pack actions may need updates if they reference old variable names
- Most actions read from stdin (parameters), not environment
- Environment variables are for context/API access, not primary data flow
Worker Compatibility
- Old workers will continue to work (new variables are additive)
- Renaming variables is breaking but acceptable in pre-production
- Can be done as a coordinated release (all services updated together)
Benefits
- Consistency: Actions and sensors follow same patterns
- Documentation Accuracy: Code matches documented interface
- API Access for Actions: Actions can call API as documented
- Better Debugging: Standard variable names across platform
- Workflow Support: Actions can create child executions
- Context Awareness: Actions know their triggering rule/event
Risks
Low Risk
- Variable renaming (compile-time checked)
- Adding new variables (backward compatible)
Medium Risk
- Token generation (security-sensitive, must be scoped correctly)
- API URL configuration (must be available to worker)
Mitigation
- Review token scoping carefully
- Test API access thoroughly
- Add integration tests for token-based API calls
- Document token limitations
Implementation Status
Completed ✅
- ✅ Document findings (this file)
- ✅ Check execution table schema - Confirmed
enforcementfield links to enforcement withrule_refandtrigger_ref - ✅ Update ActionExecutor environment variables:
- Renamed
ATTUNE_EXECUTION_ID→ATTUNE_EXEC_ID - Renamed
ATTUNE_ACTION_REF→ATTUNE_ACTION - Removed
ATTUNE_ACTION_ID(internal DB field) - Added
ATTUNE_API_URL(from env var or constructed from server config) - Added
ATTUNE_RULE(fetched from enforcement if present) - Added
ATTUNE_TRIGGER(fetched from enforcement if present) - Added
ATTUNE_API_TOKENfield (placeholder empty string for now)
- Renamed
- ✅ Update SensorManager - Added
ATTUNE_SENSOR_IDenvironment variable - ✅ Verify compilation - Both worker and sensor binaries compile successfully
- ✅ Create test rules - Three test rules created and verified via API
- ✅ Docker testing attempt - Identified schema mismatch issue requiring full rebuild
Blocked (Awaiting Docker Rebuild)
- 🔄 Docker image rebuild - REQUIRED before testing
- Docker images contain binaries compiled before
env_varsfield was added - Schema mismatch: database has
env_varscolumn but binaries don't - Full no-cache rebuild needed:
docker compose build --no-cache --parallel - Estimated time: 20-30 minutes (Rust compilation)
- See:
work-summary/2026-02-07-docker-testing-summary.md
- Docker images contain binaries compiled before
Pending (After Docker Rebuild)
-
⏳ Test end-to-end with Docker stack:
- Verify executions complete (not stuck in "requested" status)
- Verify all environment variables are present and correct
- Test rule/trigger context propagation
- Monitor worker logs for
ATTUNE_EXEC_ID,ATTUNE_ACTION,ATTUNE_API_URL,ATTUNE_RULE,ATTUNE_TRIGGER - Verify sensor has
ATTUNE_SENSOR_ID
-
⏳ Implement execution token generation - Critical TODO
- Need to create execution-scoped JWT tokens
- Similar to sensor token generation in
sensor/src/api_client.rs - Token should grant limited permissions:
- Read own execution data
- Create child executions
- Access secrets owned by execution identity
- Limited validity (expires with execution or after timeout)
- Update
ActionExecutor::prepare_execution_context()to generate real token instead of empty string - See:
docs/TODO-execution-token-generation.md
-
⏳ Update documentation and examples:
- Verify all docs reference correct variable names
- Update pack action scripts if needed
- Add migration notes
Implementation Details
Files Modified
-
attune/crates/worker/src/executor.rs:- Added
api_url: Stringfield toActionExecutorstruct - Updated constructor to accept
api_urlparameter - Modified
prepare_execution_context()to set standard environment variables - Added enforcement lookup to populate
ATTUNE_RULEandATTUNE_TRIGGER - TODO: Replace empty
ATTUNE_API_TOKENwith actual token generation
- Added
-
attune/crates/worker/src/service.rs:- Added API URL construction from
ATTUNE_API_URLenv var or server config - Passed
api_urltoActionExecutor::new()
- Added API URL construction from
-
attune/crates/sensor/src/sensor_manager.rs:- Added
.env("ATTUNE_SENSOR_ID", &sensor.id.to_string())to sensor process
- Added
API URL Resolution
The worker service now resolves the API URL using:
let api_url = std::env::var("ATTUNE_API_URL")
.unwrap_or_else(|_| format!("http://{}:{}", config.server.host, config.server.port));
This matches the pattern used by the sensor service and allows override via environment variable.
Enforcement Context Lookup
When an execution has an enforcement field populated, the executor fetches the enforcement record to extract rule_ref and trigger_ref:
if let Some(enforcement_id) = execution.enforcement {
if let Ok(Some(enforcement)) = sqlx::query_as::<_, Enforcement>(
"SELECT * FROM enforcement WHERE id = $1"
)
.bind(enforcement_id)
.fetch_optional(&self.pool)
.await
{
env.insert("ATTUNE_RULE".to_string(), enforcement.rule_ref);
env.insert("ATTUNE_TRIGGER".to_string(), enforcement.trigger_ref);
}
}
Token Generation TODO
The most critical remaining work is implementing execution-scoped API token generation. This requires:
- Create token generation service (similar to sensor token generation)
- Token Claims:
sub: execution IDidentity_id: execution owner/identityscope: ["execution:read:self", "execution:create:child", "secrets:read:owned"]exp: execution timeout or max lifetime
- Token Security:
- Scoped to specific execution (cannot access other executions)
- Limited validity period
- Automatically invalidated when execution completes
- Integration Point:
ActionExecutor::prepare_execution_context()line ~220
Next Steps
Critical: Execution Token Generation
The most important remaining work is implementing execution-scoped API token generation:
Requirements:
- Create token generation service/method in worker
- Generate JWT with execution-scoped claims:
- Subject: execution ID
- Identity: execution owner/identity
- Scopes: read own execution, create children, access owned secrets
- Expiration: execution timeout or max lifetime
- Replace empty string in
ActionExecutor::prepare_execution_context()line ~220 - Test API access from actions using generated token
Security Considerations:
- Token must be scoped to single execution (cannot access other executions)
- Limited lifetime tied to execution duration
- Auto-invalidated on execution completion
- Follow pattern from sensor token generation
Optional Follow-Up
Testing:
- Fix existing test compilation errors (unrelated to this work)
- Add integration test verifying environment variable presence
- Test action API calls with generated token
- Verify rule/trigger context propagation in test scenarios
Documentation:
- ✅ Created
QUICKREF-sensor-action-env-parity.mdcomparing sensor and action variables - ✅ Updated sensor interface documentation with
ATTUNE_SENSOR_ID - Review core pack action scripts for old variable names (if any exist)
- Document token generation and security model once implemented
Migration for Existing Actions
If any existing actions reference old variable names:
# Search for deprecated variables
grep -r "ATTUNE_EXECUTION_ID\|ATTUNE_ACTION_REF\|ATTUNE_ACTION_ID" packs/
# Replace with new names
sed -i 's/ATTUNE_EXECUTION_ID/ATTUNE_EXEC_ID/g' <files>
sed -i 's/ATTUNE_ACTION_REF/ATTUNE_ACTION/g' <files>
# Remove references to ATTUNE_ACTION_ID (use ATTUNE_EXEC_ID instead)
Note: Most actions should not be affected since parameters come from stdin, not environment variables.
Docker Testing Results
Attempted: Full stack rebuild and end-to-end testing with three test rules (echo every 1s, sleep every 5s, HTTP POST every 10s).
Outcome: Schema mismatch prevents execution - binaries were compiled before env_vars field was added.
Evidence:
- ✅ 147+ executions created in database (all in "requested" status)
- ✅ Sensor generating events correctly every 1, 5, and 10 seconds
- ✅ Executor creating enforcements and executions from events
- ❌ Executor fails to update execution status: "no column found for name: env_vars"
- ❌ API fails to query executions: same error
- ❌ Workers cannot process executions (likely same issue)
Root Cause: Docker build cache - images contain pre-env_vars binaries, database has post-env_vars schema.
Resolution Required: Full no-cache Docker rebuild (~20-30 minutes).
Details: See work-summary/2026-02-07-docker-testing-summary.md
Conclusion
This work successfully standardized environment variables across the Attune platform in code, achieving parity between actions and sensors. Both execution models now follow consistent patterns for identity, API access, and execution context.
Code Changes Complete:
- ✅ ActionExecutor sets standard environment variables
- ✅ SensorManager sets standard environment variables
- ✅ Enforcement lookup provides rule/trigger context
- ✅ API URL configuration working
- ✅ Compiles successfully
Remaining Work:
- Docker rebuild (20-30 min) - to deploy code changes
- End-to-end testing - verify environment variables in running system
- Token generation - implement execution-scoped JWT tokens (see TODO doc)
The changes are backward-compatible in practice since:
- Most actions read parameters from stdin, not environment variables
- Environment variables are primarily for context and API access
- The project is pre-production with no external users
Architecture validated: During testing, the core event-driven flow (sensor→event→rule→enforcement→execution) worked perfectly, creating 147+ executions. Once Docker images are rebuilt, the system will be ready for full validation.
References
- QUICKREF: Execution Environment Variables - Standard for actions
- QUICKREF: Sensor vs Action Environment Parity - Side-by-side comparison (NEW)
- Sensor Interface Specification - Updated with ATTUNE_SENSOR_ID
- Worker Service Architecture
- Core Pack Actions README
- Implementation:
crates/worker/src/executor.rs,crates/worker/src/service.rs,crates/sensor/src/sensor_manager.rs