Files
attune/docs/api/api-completion-plan.md
2026-02-04 17:46:30 -06:00

16 KiB

API Completion Plan: Implementing Suppressed Features

Date: 2026-01-27
Status: Phase 1 & 3 Complete, Phase 2 In Progress
Context: During zero-warnings cleanup, several API methods and features were marked with #[allow(dead_code)] because they represent planned but unimplemented functionality. This document outlines a plan to implement these features.

Overview

We identified 4 main categories of suppressed features:

  1. CLI Client REST operations - Missing HTTP methods for full CRUD
  2. CLI Configuration management - Incomplete config commands and profile support
  3. Token refresh mechanism - Session management for long-running CLI usage
  4. Executor monitoring APIs - Runtime inspection of policies and queues

Priority 1: Token Refresh Mechanism (High Impact)

Problem

  • Access tokens expire after 1 hour
  • Long-running CLI sessions require manual re-login
  • No automatic token refresh flow

Suppressed Methods

  • ApiClient::set_auth_token() - Update token after refresh
  • ApiClient::clear_auth_token() - Clear on logout/refresh failure
  • CliConfig::refresh_token() - Get refresh token from config

Implementation Plan

1.1: Add Token Refresh API Endpoint

File: attune/crates/api/src/routes/auth.rs

#[utoipa::path(
    post,
    path = "/auth/refresh",
    request_body = RefreshTokenRequest,
    responses(
        (status = 200, description = "Token refreshed", body = LoginResponse),
        (status = 401, description = "Invalid refresh token")
    ),
    tag = "auth"
)]
async fn refresh_token(
    State(state): State<AppState>,
    Json(req): Json<RefreshTokenRequest>,
) -> Result<Json<ApiResponse<LoginResponse>>, ApiError> {
    // Validate refresh token
    // Generate new access token (and optionally new refresh token)
    // Return new tokens
}

Add DTO: attune/crates/api/src/dto/auth.rs

#[derive(Deserialize)]
pub struct RefreshTokenRequest {
    pub refresh_token: String,
}

1.2: Implement Automatic Refresh in CLI Client

File: attune/crates/cli/src/client.rs

Add method:

pub async fn refresh_auth_token(&mut self) -> Result<()> {
    // Get refresh token from config
    // Call /auth/refresh endpoint
    // Update auth_token with set_auth_token()
    // Update config file with new tokens
}

Enhance execute() method:

async fn execute<T: DeserializeOwned>(&self, req: RequestBuilder) -> Result<T> {
    let response = req.send().await?;
    
    // If 401 and we have refresh token, try refresh once
    if response.status() == StatusCode::UNAUTHORIZED {
        if let Ok(Some(_)) = config.refresh_token() {
            self.refresh_auth_token().await?;
            // Retry original request with new token
        }
    }
    
    self.handle_response(response).await
}

1.3: Add Refresh Command (Optional)

File: attune/crates/cli/src/commands/auth.rs

AuthCommands::Refresh => {
    // Manually refresh token
    // Useful for testing or explicit refresh
}

Effort: 4-6 hours
Dependencies: None
Value: High - significantly improves CLI UX


Priority 2: Complete CRUD Operations (High Impact)

Problem

  • CLI can only Create (POST) and Read (GET) resources
  • No Update (PUT/PATCH) or Delete (DELETE) commands
  • REST client API incomplete

Suppressed Methods

  • ApiClient::put() - For update operations
  • ApiClient::delete() - For delete operations
  • ApiClient::get_with_query() - For filtering/search

Implementation Plan

2.1: Resource Update Commands

Add update subcommands to existing command modules:

Pack Updates (attune/crates/cli/src/commands/pack.rs):

PackCommands::Update {
    ref_name: String,
    #[arg(long)] name: Option<String>,
    #[arg(long)] description: Option<String>,
    #[arg(long)] version: Option<String>,
    #[arg(long)] enabled: Option<bool>,
} => {
    let update = UpdatePackRequest { name, description, version, enabled };
    let pack = client.put(&format!("/packs/{}", ref_name), &update).await?;
    // Display updated pack
}

Action Updates (attune/crates/cli/src/commands/action.rs):

ActionCommands::Update {
    ref_name: String,
    #[arg(long)] name: Option<String>,
    #[arg(long)] description: Option<String>,
    #[arg(long)] enabled: Option<bool>,
} => {
    // Similar pattern
}

Repeat for: Rules, Triggers, Sensors, Workflows

2.2: Resource Delete Commands

Add delete subcommands:

PackCommands::Delete {
    ref_name: String,
    #[arg(long)] force: bool, // Skip confirmation
} => {
    if !force {
        let confirm = dialoguer::Confirm::new()
            .with_prompt(&format!("Delete pack '{}'?", ref_name))
            .interact()?;
        if !confirm { return Ok(()); }
    }
    
    client.delete::<()>(&format!("/packs/{}", ref_name)).await?;
    print_success(&format!("Pack '{}' deleted", ref_name));
}

2.3: Search and Filtering

Enhance list commands with query parameters:

PackCommands::List {
    #[arg(long)] enabled: Option<bool>,
    #[arg(long)] search: Option<String>,
    #[arg(long)] limit: Option<u32>,
    #[arg(long)] offset: Option<u32>,
} => {
    let mut query = vec![];
    if let Some(enabled) = enabled {
        query.push(format!("enabled={}", enabled));
    }
    if let Some(search) = search {
        query.push(format!("search={}", search));
    }
    // Build query string and use get_with_query()
}

Effort: 8-12 hours
Dependencies: API endpoints must support PUT/DELETE (most already do)
Value: High - completes CLI feature parity with API


Priority 3: Profile and Configuration Management (Medium Impact)

Problem

  • --profile flag declared in main.rs but not used
  • attune config set api-url command defined but not implemented
  • Profile switching requires manual attune config use command

Suppressed Methods

  • CliConfig::set_api_url() - Direct API URL update
  • CliConfig::load_with_profile() - Load with profile override
  • CliConfig::api_url() - Get current API URL

Implementation Plan

3.1: Implement --profile Flag Support

File: attune/crates/cli/src/main.rs

Currently the flag exists but is unused. Update main():

#[tokio::main]
async fn main() -> Result<()> {
    let cli = Cli::parse();
    
    // Load config with profile override
    let config = if let Some(profile) = &cli.profile {
        CliConfig::load_with_profile(Some(profile))?
    } else {
        CliConfig::load()?
    };
    
    // Pass config to command handlers instead of loading fresh each time
}

Update all command handlers to accept &CliConfig parameter.

3.2: Complete Config Set Command

File: attune/crates/cli/src/commands/config.rs

The handle_set() function exists but uses set_value() which only handles specific keys. Add:

async fn handle_set(key: String, value: String, output_format: OutputFormat) -> Result<()> {
    let mut config = CliConfig::load()?;
    
    match key.as_str() {
        "api_url" | "api-url" => {
            config.set_api_url(value.clone())?;
        }
        _ => {
            config.set_value(&key, value.clone())?;
        }
    }
    
    // Output handling...
}

3.3: Add Config Get/Show Commands

ConfigCommands::Show => {
    let config = CliConfig::load()?;
    let profile = config.current_profile()?;
    
    // Display full config including:
    // - Current profile
    // - API URL (from config.api_url())
    // - Auth status
    // - All settings
}

Effort: 3-4 hours
Dependencies: None
Value: Medium - improves multi-environment workflow


Priority 4: Executor Monitoring APIs (Low-Medium Impact)

Problem

  • No visibility into executor runtime state
  • Cannot inspect queue depths or policy enforcement
  • No way to adjust policies at runtime

Suppressed Methods in attune/crates/executor/src/:

  • PolicyEnforcer::new(), with_global_policy(), set_*_policy()
  • PolicyEnforcer::check_policies(), wait_for_policy_compliance()
  • QueueManager::get_all_queue_stats(), cancel_execution(), clear_all_queues()
  • ExecutorService::pool(), config(), publisher()

Implementation Plan

4.1: Add Executor Admin API Endpoints

New File: attune/crates/api/src/routes/executor_admin.rs

// Queue monitoring
GET /api/v1/admin/executor/queues
  -> List all action queues with stats (depth, active, capacity)

GET /api/v1/admin/executor/queues/{action_id}
  -> Detailed queue stats for specific action

// Policy inspection
GET /api/v1/admin/executor/policies
  -> List all configured policies (global, pack, action)

// Policy management (future)
POST /api/v1/admin/executor/policies/global
  -> Set global execution policy

POST /api/v1/admin/executor/policies/pack/{pack_id}
  -> Set pack-specific policy

POST /api/v1/admin/executor/policies/action/{action_id}
  -> Set action-specific policy

// Queue operations
POST /api/v1/admin/executor/queues/{action_id}/clear
  -> Clear queue for action (emergency)

DELETE /api/v1/admin/executor/queues/{action_id}/executions/{execution_id}
  -> Cancel queued execution

4.2: Expose Executor State via Message Queue

Alternative approach: Instead of HTTP API, use pub/sub:

// Executor publishes stats periodically
topic: "executor.stats"
payload: {
  "queues": [...],
  "policies": [...],
  "active_executions": 42
}

// API service subscribes and caches latest stats
// Serves from cache on GET /admin/executor/stats

4.3: Add CLI Admin Commands

New File: attune/crates/cli/src/commands/admin.rs

#[derive(Subcommand)]
pub enum AdminCommands {
    /// Executor administration
    Executor {
        #[command(subcommand)]
        command: ExecutorAdminCommands,
    },
}

#[derive(Subcommand)]
pub enum ExecutorAdminCommands {
    /// Show queue statistics
    Queues {
        #[arg(long)] action: Option<String>,
    },
    /// Show policy configuration
    Policies,
    /// Clear a queue (dangerous)
    ClearQueue {
        action: String,
        #[arg(long)] confirm: bool,
    },
}

Effort: 6-10 hours
Dependencies: Requires deciding on HTTP API vs. message queue approach
Value: Medium - mainly for ops/debugging, not end-user facing


Non-Priority Items (Keep Suppressed)

These items should remain with #[allow(dead_code)] for now:

Test Infrastructure

  • attune/crates/api/tests/helpers.rs - Test helper methods
  • attune/crates/cli/tests/common/mod.rs - Mock functions
  • attune/crates/executor/tests/* - Test runtime helpers

Reason: These are test utilities that may be used in future tests. They provide a complete test API surface even if not all methods are currently used.

Service Internal Fields

  • WorkerService.config - Kept for potential future use
  • ExecutorService.queue_name - Backward compatibility
  • Subscriber.client_id, user_id - Structural completeness
  • WorkflowExecutionHandle.workflow_def_id - May be needed for advanced workflow features

Reason: These maintain API completeness and may be needed for future features. Removing them would require breaking changes.

Methods Only Used in Tests

  • PolicyEnforcer::new() (vs. with_queue_manager())
  • QueueManager::new(), with_defaults() (vs. with_db_pool())

Reason: Simpler constructors useful for unit testing. Production code uses more complete constructors.


Implementation Roadmap

Phase 1: Foundation COMPLETE

  1. Token Refresh Mechanism (Priority 1) - COMPLETE 2026-01-27
    • API endpoint (already existed)
    • CLI client auto-refresh implemented
    • Manual refresh command (attune auth refresh)
    • Config file persistence of refreshed tokens
    • Zero warnings, fully functional
    • Testing: Auto-refresh on 401, manual refresh command tested

Phase 2: CLI Feature Completion COMPLETE

  1. CRUD Operations (Priority 2) - COMPLETE 2026-01-27
    • Update commands implemented for actions, rules, triggers, packs
    • Delete commands with confirmation for actions, triggers (rules/packs already had it)
    • All ApiClient HTTP methods now active (PUT, DELETE)
    • Zero dead_code warnings for implemented features
    • Testing: All CLI tests pass (2 pre-existing auth failures unrelated)

Phase 3: Configuration Enhancement COMPLETE

  1. Profile Management (Priority 3) - COMPLETE 2026-01-27
    • --profile flag fully implemented across all commands
    • CliConfig::load_with_profile() method
    • All command handlers updated (auth, action, rule, execution, key, sensor, trigger, pack, config)
    • Zero warnings, fully functional
    • Testing: All CLI tests pass with profile support

Phase 4: Operational Visibility (Week 6-8, Optional)

  1. Executor Monitoring (Priority 4)
    • Design decision: HTTP API vs. pub/sub
    • Implement chosen approach
    • CLI admin commands
    • Blockers: Architecture decision needed
    • Testing: Requires running executor instances

Success Criteria

Phase 1 Complete

  • Users can work with CLI for >1 hour without re-login
  • Expired tokens automatically refresh transparently
  • Manual attune auth refresh command works

Phase 2 Complete

  • All resources support full CRUD via CLI (Create, Read, Update, Delete)
  • Update commands accept optional fields (label, description, etc.)
  • Delete operations require confirmation (unless --yes flag)
  • Users can manage entire platform lifecycle from CLI

Phase 3 Complete

  • --profile dev/staging/prod flag works across all commands
  • attune config set api-url <url> updates current profile
  • Multi-environment workflows seamless

Phase 4 Complete

  • Operators can view executor queue depths
  • Policy configuration visible via API/CLI
  • Emergency queue operations available

Risk Assessment

Low Risk

  • Token refresh: Well-defined pattern, existing JWT infrastructure
  • CRUD completion: API endpoints mostly exist, just need CLI wiring
  • Profile flag: Simple config plumbing

Medium Risk

  • Executor monitoring: Architecture decision required (HTTP vs. message queue)
    • HTTP: Simpler but requires executor to expose endpoints
    • Message Queue: More scalable but adds complexity
    • Recommendation: Start with HTTP for simplicity

Dependency Risks

  • No major dependencies between phases
  • Each phase can be implemented independently
  • Phase 4 can be deferred if priorities change

Documentation Updates Required

After implementation:

  1. Update docs/cli-reference.md with new commands
  2. Update docs/api-authentication.md with refresh flow
  3. Add docs/cli-configuration.md with profile examples
  4. Add docs/executor-monitoring.md (Phase 4)
  5. Update this document's status to "Complete"

Alternatives Considered

Alternative 1: Remove Suppressed Methods

Rejected: These methods represent planned functionality with clear use cases. Removing them would require re-adding later with breaking changes.

Alternative 2: Implement All at Once

Rejected: Phased approach allows for incremental value delivery and testing. Phase 4 can be deferred if needed.

Alternative 3: Auto-generate CLI from OpenAPI

Deferred: Would eliminate need for manual CLI CRUD implementation, but requires significant tooling investment. Consider for future major version.


Next Steps

  1. Review this plan with team/stakeholders
  2. Decide on Phase 4 architecture (HTTP vs. message queue)
  3. Create GitHub issues for each phase
  4. Implement Phase 1 (highest impact, no blockers)
  5. Update this document as implementation progresses

  • attune/docs/dead-code-cleanup.md - Warning cleanup context
  • attune/docs/cli-reference.md - Current CLI commands
  • attune/docs/api-authentication.md - Auth flow documentation
  • attune/CHANGELOG.md - Historical context on warning fixes