9.3 KiB
TODO: Execution-Scoped API Token Generation
Priority: High
Status: Not Started
Related Work: work-summary/2026-02-07-env-var-standardization.md
Blocked By: None
Blocking: Full API access from action executions
Overview
Actions currently receive an empty ATTUNE_API_TOKEN environment variable. This TODO tracks the implementation of execution-scoped JWT token generation to enable actions to authenticate with the Attune API.
Background
As of 2026-02-07, the environment variable standardization work updated the worker to provide standard environment variables to actions, including ATTUNE_API_TOKEN. However, token generation is not yet implemented - the variable is set to an empty string as a placeholder.
Requirements
Functional Requirements
- Token Generation: Generate JWT tokens scoped to specific executions
- Token Claims: Include execution-specific claims and permissions
- Token Lifecycle: Tokens expire with execution or after timeout
- Security: Tokens cannot access other executions or system resources
- Integration: Seamlessly integrate into existing execution flow
Non-Functional Requirements
- Performance: Token generation should not significantly delay execution startup
- Security: Follow JWT best practices and secure token scoping
- Consistency: Match patterns from sensor token generation
- Testability: Unit and integration tests for token generation and validation
Design
Token Claims Structure
{
"sub": "execution:12345",
"identity_id": 42,
"execution_id": 12345,
"scopes": [
"execution:read:self",
"execution:create:child",
"secrets:read:owned"
],
"iat": 1738934400,
"exp": 1738938000,
"nbf": 1738934400
}
Token Scopes
| Scope | Description | Use Case |
|---|---|---|
execution:read:self |
Read own execution data | Query execution status, retrieve parameters |
execution:create:child |
Create child executions | Workflow orchestration, sub-tasks |
secrets:read:owned |
Access secrets owned by execution identity | Retrieve API keys, credentials |
Token Expiration
- Default Expiration: Execution timeout (from action metadata) or 5 minutes (300 seconds)
- Maximum Expiration: 1 hour (configurable)
- Auto-Invalidation: Token marked invalid when execution completes/fails/cancels
Token Generation Flow
- Executor receives execution request from queue
- Executor loads action metadata (includes timeout)
- Executor generates execution-scoped JWT token:
- Subject:
execution:{id} - Claims: execution ID, identity ID, scopes
- Expiration: now + timeout or max lifetime
- Subject:
- Token added to environment variables (
ATTUNE_API_TOKEN) - Action script uses token for API authentication
Implementation Tasks
Phase 1: Token Generation Service
- Create
TokenServiceor add to existing auth service - Implement
generate_execution_token(execution_id, identity_id, timeout)method - Use same JWT signing key as API service
- Add token generation to
ActionExecutor::prepare_execution_context() - Replace empty string with generated token
Files to Modify:
crates/common/src/auth.rs(or create new token module)crates/worker/src/executor.rs(line ~220)
Estimated Effort: 4-6 hours
Phase 2: Token Validation
- Update API auth middleware to recognize execution-scoped tokens
- Validate token scopes against requested resources
- Ensure execution tokens cannot access other executions
- Add scope checking to protected endpoints
Files to Modify:
crates/api/src/auth/middleware.rscrates/api/src/auth/jwt.rs
Estimated Effort: 3-4 hours
Phase 3: Token Lifecycle Management
- Track active execution tokens in memory or cache
- Invalidate tokens when execution completes
- Handle token refresh (if needed for long-running actions)
- Add cleanup for orphaned tokens
Files to Modify:
crates/worker/src/executor.rs- Consider adding token registry/cache
Estimated Effort: 2-3 hours
Phase 4: Testing
- Unit tests for token generation
- Unit tests for token validation and scope checking
- Integration test: action calls API with generated token
- Integration test: verify token cannot access other executions
- Integration test: verify token expires appropriately
- Test child execution creation with token
Files to Create:
crates/worker/tests/token_generation_tests.rscrates/api/tests/execution_token_auth_tests.rs
Estimated Effort: 4-5 hours
Phase 5: Documentation
- Document token generation in worker architecture docs
- Update QUICKREF-execution-environment.md with token details
- Add security considerations to documentation
- Provide examples of actions using API with token
- Document troubleshooting for token-related issues
Files to Update:
docs/QUICKREF-execution-environment.mddocs/architecture/worker-service.mddocs/authentication/authentication.mdpacks/core/actions/README.md(add API usage examples)
Estimated Effort: 2-3 hours
Technical Details
JWT Signing
Use the same JWT secret as the API service:
use jsonwebtoken::{encode, EncodingKey, Header};
let token = encode(
&Header::default(),
&claims,
&EncodingKey::from_secret(jwt_secret.as_bytes()),
)?;
Token Structure Reference
Look at sensor token generation in crates/sensor/src/api_client.rs for patterns:
- Similar claims structure
- Similar expiration handling
- Can reuse token generation utilities
Middleware Integration
Update RequireAuth extractor to handle execution-scoped tokens:
// Pseudo-code
match token_subject_type {
"user" => validate_user_token(token),
"service_account" => validate_service_token(token),
"execution" => validate_execution_token(token, execution_id_from_route),
}
Scope Validation
Add scope checking helper:
fn require_scope(token: &Token, required_scope: &str) -> Result<()> {
if token.scopes.contains(&required_scope.to_string()) {
Ok(())
} else {
Err(Error::Forbidden("Insufficient scope"))
}
}
Security Considerations
Token Scoping
- Execution Isolation: Token must only access its own execution
- No System Access: Cannot modify system configuration
- Limited Secrets: Only secrets owned by execution identity
- Time-Bounded: Expires with execution or timeout
Attack Vectors to Prevent
- Token Reuse: Expired tokens must be rejected
- Cross-Execution Access: Token for execution A cannot access execution B
- Privilege Escalation: Cannot use token to gain admin access
- Token Leakage: Never log full token value
Validation Checklist
- Token signature verified
- Token not expired
- Execution ID matches token claims
- Required scopes present in token
- Identity owns requested resources
Testing Strategy
Unit Tests
#[test]
fn test_generate_execution_token() {
let token = generate_execution_token(12345, 42, 300).unwrap();
let claims = decode_token(&token).unwrap();
assert_eq!(claims.execution_id, 12345);
assert_eq!(claims.identity_id, 42);
assert!(claims.scopes.contains(&"execution:read:self".to_string()));
}
#[test]
fn test_token_cannot_access_other_execution() {
let token = generate_execution_token(12345, 42, 300).unwrap();
// Try to access execution 99999 with token for execution 12345
let result = api_client.get_execution(99999, &token).await;
assert!(result.is_err());
}
Integration Tests
- Happy Path: Action successfully calls API with token
- Scope Enforcement: Action cannot perform unauthorized operations
- Token Expiration: Expired token is rejected
- Child Execution: Action can create child execution with token
Dependencies
Required Access
- JWT secret (same as API service)
- Access to execution data (for claims)
- Access to identity data (for ownership checks)
Configuration
Add to worker config (or use existing values):
security:
jwt_secret: "..." # Shared with API
execution_token_max_lifetime: 3600 # 1 hour
Success Criteria
- ✅ Actions receive valid JWT token in
ATTUNE_API_TOKEN - ✅ Actions can authenticate with API using token
- ✅ Token scopes are enforced correctly
- ✅ Tokens cannot access other executions
- ✅ Tokens expire appropriately
- ✅ All tests pass
- ✅ Documentation is complete and accurate
References
- Environment Variable Standardization - Background and context
- QUICKREF: Execution Environment - Token usage documentation
- Worker Service Architecture - Executor implementation details
- Authentication Documentation - JWT patterns and security
- Sensor Token Generation:
crates/sensor/src/api_client.rs- Reference implementation
Estimated Total Effort
Total: 15-21 hours (approximately 2-3 days of focused work)
Notes
- Consider reusing token generation utilities from API service
- Ensure consistency with sensor token generation patterns
- Document security model clearly for pack developers
- Add examples to core pack showing API usage from actions