# Mithril Architecture Document

## Overview

Mithril is a minimal Infrastructure-as-a-Service (IaaS) CLI for the Foundation Compute Platform (FCP). It provides direct access to spot compute instances without unnecessary abstractions, following Unix philosophy principles.

## Design Principles

### 1. Simplicity First
- Direct mapping between user commands and API operations
- No hidden state or complex workflows
- Transparent error propagation

### 2. Composability
- Standard Unix tool integration (ssh, scp, pipes)
- Machine-readable output formats
- Exit codes follow conventions

### 3. Minimal Dependencies
- Python standard library + requests
- Optional Flow SDK integration for catalog
- No build process or transpilation

## System Architecture

```
┌─────────────────┐
│   CLI Layer     │
│  (__main__.py)  │
└────────┬────────┘
         │
┌────────▼────────┐
│  Client Layer   │
│  (client.py)    │
└────────┬────────┘
         │
┌────────▼────────┐     ┌──────────────┐
│   FCP API v2    │◄────┤ Catalog      │
│                 │     │ (catalog.py) │
└─────────────────┘     └──────────────┘
```

### Component Responsibilities

#### CLI Layer (`__main__.py`)
- Command parsing and validation
- Output formatting for human consumption
- Environment variable handling
- Process lifecycle management

#### Client Layer (`client.py`)
- HTTP request construction and execution
- Response parsing and error mapping
- Retry logic for transient failures
- SSH key management

#### Catalog Component (`catalog.py`)
- Instance type ID to name resolution
- Caching for performance
- Graceful fallback when Flow SDK unavailable

#### SSH Utilities (`ssh.py`)
- SSH connection establishment
- Key file handling
- Connection parameter configuration

## API Integration

### Endpoint Mapping

| Operation | HTTP Method | Endpoint | Purpose |
|-----------|-------------|----------|---------|
| List Available | GET | `/v2/spot/availability` | Query spot market |
| Create Instance | POST | `/v2/spot/bids` | Submit spot bid |
| Get Status | GET | `/v2/spot/bids/{id}` | Check bid/instance status |
| Delete Instance | DELETE | `/v2/spot/bids/{id}` | Cancel bid and terminate |
| List Instances | GET | `/v2/spot/bids?project={id}` | List active bids |
| Manage SSH Keys | GET/POST | `/v2/ssh-keys` | Key registration |

### Request Flow

1. **Authentication**: Bearer token via `FCP_API_KEY`
2. **Project Scoping**: Via `FCP_PROJECT` environment variable
3. **Retry Strategy**: Exponential backoff for 502-504 errors
4. **Error Handling**: Preserve API error messages

## Data Flow

### Instance Creation Sequence

```
User Input → Validate Environment → Load SSH Key → Query Availability
    ↓
Match Instance Type → Select Region → Calculate Price → Submit Bid
    ↓
Return Bid ID → User Polls Status → Instance Ready → SSH Connect
```

### Key Design Decisions

1. **Stateless Operation**: No local state files or caches beyond runtime
2. **Lazy SSH Key Registration**: Keys uploaded on first use
3. **Price Display**: Show "--" when price unavailable (safety)
4. **Instance Resolution**: Use Flow SDK when available, fallback to raw IDs

## Error Handling

### Error Hierarchy

```
MithrilError (Base)
├── APIError (HTTP 4xx/5xx)
├── ConfigError (Missing env vars)
└── SSHError (Connection failures)
```

### Error Philosophy
- Preserve original error messages
- Add context without obscuring root cause
- Exit codes: 1 for general errors, 0 for success

## Security Considerations

1. **API Key Management**: Environment variable only
2. **SSH Key Handling**: Read from filesystem, never logged
3. **Host Key Verification**: Disabled for ephemeral instances
4. **No Credential Storage**: All auth via environment

## Performance Characteristics

### Latency Sources
1. API round trips (~100-300ms per request)
2. SSH key registration (one-time, ~500ms)
3. Instance type resolution (cached after first lookup)

### Optimization Strategies
- Connection pooling via requests.Session
- Minimal API calls (no polling loops)
- Lazy loading of optional dependencies

## Extension Points

### Adding New Commands
1. Define command in `__main__.py`
2. Implement business logic in `client.py`
3. Add error handling specific to operation

### Provider Support
Currently FCP-specific. Multi-provider support would require:
- Abstract base client class
- Provider-specific implementations
- Unified instance type naming

## Testing Strategy

### Unit Tests
- Mock API responses for client methods
- Test error handling paths
- Verify command parsing

### Integration Tests
- Real API calls with test project
- SSH connectivity verification
- End-to-end workflows

### Performance Tests
- Measure API call latency
- Verify retry behavior
- Cache effectiveness

## Deployment

### Package Structure
```
mithril/
├── __init__.py      # Package metadata
├── __main__.py      # CLI entry point
├── client.py        # API client
├── catalog.py       # Type resolution
├── errors.py        # Exception types
└── ssh.py          # SSH utilities
```

### Distribution
- PyPI package: `fcp-mithril`
- Direct installation: `pip install -e .`
- No compilation or build steps

## Future Considerations

### Potential Enhancements
1. **Batch Operations**: Create/delete multiple instances
2. **Price Alerts**: Notify when spot prices drop
3. **Session Management**: Persistent SSH connections
4. **Metadata Service**: Instance self-discovery

### Architectural Constraints
- Maintain single-file deployability
- Preserve CLI/API parity
- No daemon processes
- No local databases

## Appendix: Design Rationale

### Why Not Use Flow SDK Entirely?
- Reduces dependencies for simple operations
- Allows mithril to work standalone
- Clearer separation of concerns

### Why Disable SSH Host Checking?
- Instances are ephemeral with dynamic IPs
- Keys change on each provisioning
- Security via API authentication

### Why Environment Variables for Config?
- Standard practice for CLIs
- Easy integration with CI/CD
- No config file management