Files
attune/docs/TODO-execution-token-generation.md

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

  1. Token Generation: Generate JWT tokens scoped to specific executions
  2. Token Claims: Include execution-specific claims and permissions
  3. Token Lifecycle: Tokens expire with execution or after timeout
  4. Security: Tokens cannot access other executions or system resources
  5. Integration: Seamlessly integrate into existing execution flow

Non-Functional Requirements

  1. Performance: Token generation should not significantly delay execution startup
  2. Security: Follow JWT best practices and secure token scoping
  3. Consistency: Match patterns from sensor token generation
  4. 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

  1. Executor receives execution request from queue
  2. Executor loads action metadata (includes timeout)
  3. Executor generates execution-scoped JWT token:
    • Subject: execution:{id}
    • Claims: execution ID, identity ID, scopes
    • Expiration: now + timeout or max lifetime
  4. Token added to environment variables (ATTUNE_API_TOKEN)
  5. Action script uses token for API authentication

Implementation Tasks

Phase 1: Token Generation Service

  • Create TokenService or 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.rs
  • crates/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.rs
  • crates/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.md
  • docs/architecture/worker-service.md
  • docs/authentication/authentication.md
  • packs/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

  1. Execution Isolation: Token must only access its own execution
  2. No System Access: Cannot modify system configuration
  3. Limited Secrets: Only secrets owned by execution identity
  4. Time-Bounded: Expires with execution or timeout

Attack Vectors to Prevent

  1. Token Reuse: Expired tokens must be rejected
  2. Cross-Execution Access: Token for execution A cannot access execution B
  3. Privilege Escalation: Cannot use token to gain admin access
  4. 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

  1. Happy Path: Action successfully calls API with token
  2. Scope Enforcement: Action cannot perform unauthorized operations
  3. Token Expiration: Expired token is rejected
  4. 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

  1. Actions receive valid JWT token in ATTUNE_API_TOKEN
  2. Actions can authenticate with API using token
  3. Token scopes are enforced correctly
  4. Tokens cannot access other executions
  5. Tokens expire appropriately
  6. All tests pass
  7. Documentation is complete and accurate

References

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