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:
- CLI Client REST operations - Missing HTTP methods for full CRUD
- CLI Configuration management - Incomplete config commands and profile support
- Token refresh mechanism - Session management for long-running CLI usage
- 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 refreshApiClient::clear_auth_token()- Clear on logout/refresh failureCliConfig::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 operationsApiClient::delete()- For delete operationsApiClient::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
--profileflag declared in main.rs but not usedattune config set api-urlcommand defined but not implemented- Profile switching requires manual
attune config usecommand
Suppressed Methods
CliConfig::set_api_url()- Direct API URL updateCliConfig::load_with_profile()- Load with profile overrideCliConfig::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 methodsattune/crates/cli/tests/common/mod.rs- Mock functionsattune/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 useExecutorService.queue_name- Backward compatibilitySubscriber.client_id,user_id- Structural completenessWorkflowExecutionHandle.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
- ✅ 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
- ✅ 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
- ✅ Profile Management (Priority 3) - COMPLETE 2026-01-27
- ✅
--profileflag 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)
- ⏳ 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 refreshcommand 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/prodflag works across all commandsattune 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:
- Update
docs/cli-reference.mdwith new commands - Update
docs/api-authentication.mdwith refresh flow - Add
docs/cli-configuration.mdwith profile examples - Add
docs/executor-monitoring.md(Phase 4) - 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
- Review this plan with team/stakeholders
- Decide on Phase 4 architecture (HTTP vs. message queue)
- Create GitHub issues for each phase
- Implement Phase 1 (highest impact, no blockers)
- Update this document as implementation progresses
Related Documentation
attune/docs/dead-code-cleanup.md- Warning cleanup contextattune/docs/cli-reference.md- Current CLI commandsattune/docs/api-authentication.md- Auth flow documentationattune/CHANGELOG.md- Historical context on warning fixes