# MSP Mode API Specification

**Version:** 1.0.0
**Last Updated:** 2026-01-16
**Status:** Design Phase

---

## Overview

FastAPI-based REST API providing secure access to MSP tracking database on Jupiter server. Designed for multi-machine access with JWT authentication and comprehensive audit logging.

---

## Base Configuration

**Base URL:** `https://msp-api.azcomputerguru.com`
**API Version:** `/api/v1/`
**Protocol:** HTTPS only (no HTTP)
**Authentication:** JWT Bearer tokens
**Content-Type:** `application/json`

---

## Authentication

### JWT Token Structure

#### Access Token (Short-lived: 1 hour)
```json
{
  "sub": "mike@azcomputerguru.com",
  "scopes": ["msp:read", "msp:write", "msp:admin"],
  "machine": "windows-workstation",
  "exp": 1234567890,
  "iat": 1234567890,
  "jti": "unique-token-id"
}
```

#### Refresh Token (Long-lived: 30 days)
- Stored securely in Gitea config
- Used to obtain new access tokens
- Can be revoked server-side

### Permission Scopes

- **`msp:read`** - Read sessions, clients, work items
- **`msp:write`** - Create/update sessions, work items
- **`msp:admin`** - Manage clients, credentials, delete operations

### Authentication Endpoints

#### POST /api/v1/auth/token
Obtain JWT access token.

**Request:**
```json
{
  "refresh_token": "string"
}
```

**Response:**
```json
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "bearer",
  "expires_in": 3600,
  "scopes": ["msp:read", "msp:write"]
}
```

**Status Codes:**
- `200` - Token issued successfully
- `401` - Invalid refresh token
- `403` - Token revoked

#### POST /api/v1/auth/refresh
Refresh expired access token.

**Request:**
```json
{
  "refresh_token": "string"
}
```

**Response:**
```json
{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "expires_in": 3600
}
```

---

## Core API Endpoints

### Machine Detection & Management

#### GET /api/v1/machines
List all registered machines.

**Query Parameters:**
- `is_active` (boolean) - Filter by active status
- `platform` (string) - Filter by platform (win32, darwin, linux)

**Response:**
```json
{
  "machines": [
    {
      "id": "uuid",
      "hostname": "ACG-M-L5090",
      "friendly_name": "Main Laptop",
      "platform": "win32",
      "has_vpn_access": true,
      "vpn_profiles": ["dataforth", "grabb"],
      "has_docker": true,
      "powershell_version": "7.4",
      "available_mcps": ["claude-in-chrome", "filesystem"],
      "available_skills": ["pdf", "commit", "review-pr"],
      "last_seen": "2026-01-16T10:30:00Z"
    }
  ]
}
```

#### POST /api/v1/machines
Register new machine (auto-detection on first session).

**Request:**
```json
{
  "hostname": "ACG-M-L5090",
  "machine_fingerprint": "sha256hash",
  "platform": "win32",
  "os_version": "Windows 11 Pro",
  "username": "MikeSwanson",
  "friendly_name": "Main Laptop",
  "has_vpn_access": true,
  "vpn_profiles": ["dataforth", "grabb"],
  "has_docker": true,
  "powershell_version": "7.4",
  "preferred_shell": "powershell",
  "available_mcps": ["claude-in-chrome"],
  "available_skills": ["pdf", "commit"]
}
```

**Response:**
```json
{
  "id": "uuid",
  "machine_fingerprint": "sha256hash",
  "created_at": "2026-01-16T10:00:00Z"
}
```

#### GET /api/v1/machines/{fingerprint}
Get machine by fingerprint (for session start auto-detection).

**Response:**
```json
{
  "id": "uuid",
  "hostname": "ACG-M-L5090",
  "friendly_name": "Main Laptop",
  "capabilities": {
    "vpn_profiles": ["dataforth", "grabb"],
    "has_docker": true,
    "powershell_version": "7.4"
  }
}
```

#### PUT /api/v1/machines/{id}
Update machine capabilities.

### Sessions

#### POST /api/v1/sessions
Create new MSP session.

**Request:**
```json
{
  "client_id": "uuid",
  "project_id": "uuid",
  "machine_id": "uuid",
  "session_date": "2026-01-16",
  "start_time": "2026-01-16T10:00:00Z",
  "session_title": "Dataforth - DOS UPDATE.BAT enhancement",
  "technician": "Mike Swanson",
  "status": "in_progress"
}
```

**Response:**
```json
{
  "id": "uuid",
  "session_date": "2026-01-16",
  "start_time": "2026-01-16T10:00:00Z",
  "status": "in_progress",
  "created_at": "2026-01-16T10:00:00Z"
}
```

**Status Codes:**
- `201` - Session created
- `400` - Invalid request data
- `401` - Unauthorized
- `404` - Client/Project not found

#### GET /api/v1/sessions
Query sessions with filters.

**Query Parameters:**
- `client_id` (uuid) - Filter by client
- `project_id` (uuid) - Filter by project
- `machine_id` (uuid) - Filter by machine
- `date_from` (date) - Start date range
- `date_to` (date) - End date range
- `is_billable` (boolean) - Filter billable sessions
- `status` (string) - Filter by status
- `limit` (int) - Max results (default: 50)
- `offset` (int) - Pagination offset

**Response:**
```json
{
  "sessions": [
    {
      "id": "uuid",
      "client_name": "Dataforth",
      "project_name": "DOS Machine Management",
      "session_date": "2026-01-15",
      "duration_minutes": 210,
      "billable_hours": 3.5,
      "session_title": "DOS UPDATE.BAT v2.0 completion",
      "summary": "Completed UPDATE.BAT automation...",
      "status": "completed"
    }
  ],
  "total": 45,
  "limit": 50,
  "offset": 0
}
```

#### GET /api/v1/sessions/{id}
Get session details with related work items.

**Response:**
```json
{
  "id": "uuid",
  "client_id": "uuid",
  "client_name": "Dataforth",
  "project_name": "DOS Machine Management",
  "session_date": "2026-01-15",
  "start_time": "2026-01-15T14:00:00Z",
  "end_time": "2026-01-15T17:30:00Z",
  "duration_minutes": 210,
  "billable_hours": 3.5,
  "session_title": "DOS UPDATE.BAT v2.0",
  "summary": "markdown summary",
  "work_items": [
    {
      "id": "uuid",
      "category": "development",
      "title": "Enhanced UPDATE.BAT with version checking",
      "status": "completed"
    }
  ],
  "tags": ["dos", "batch", "automation", "dataforth"],
  "technologies_used": ["dos-6.22", "batch", "networking"]
}
```

#### PUT /api/v1/sessions/{id}
Update session (typically at session end).

**Request:**
```json
{
  "end_time": "2026-01-16T12:30:00Z",
  "status": "completed",
  "summary": "markdown summary",
  "billable_hours": 2.5,
  "notes": "Additional session notes"
}
```

### Work Items

#### POST /api/v1/work-items
Create work item for session.

**Request:**
```json
{
  "session_id": "uuid",
  "category": "troubleshooting",
  "title": "Fixed Apache SSL certificate expiration",
  "description": "Problem: ERR_SSL_PROTOCOL_ERROR\nCause: Cert expired\nFix: certbot renew",
  "status": "completed",
  "priority": "high",
  "is_billable": true,
  "actual_minutes": 45,
  "affected_systems": ["jupiter", "172.16.3.20"],
  "technologies_used": ["apache", "ssl", "certbot"]
}
```

**Response:**
```json
{
  "id": "uuid",
  "session_id": "uuid",
  "category": "troubleshooting",
  "title": "Fixed Apache SSL certificate expiration",
  "created_at": "2026-01-16T10:15:00Z"
}
```

#### GET /api/v1/work-items
Query work items.

**Query Parameters:**
- `session_id` (uuid) - Filter by session
- `category` (string) - Filter by category
- `status` (string) - Filter by status
- `date_from` (date) - Start date
- `date_to` (date) - End date

### Clients

#### GET /api/v1/clients
List all clients.

**Query Parameters:**
- `type` (string) - Filter by type (msp_client, internal, project)
- `is_active` (boolean) - Active clients only

**Response:**
```json
{
  "clients": [
    {
      "id": "uuid",
      "name": "Dataforth",
      "type": "msp_client",
      "network_subnet": "192.168.0.0/24",
      "is_active": true
    }
  ]
}
```

#### POST /api/v1/clients
Create new client record.

**Request:**
```json
{
  "name": "Client Name",
  "type": "msp_client",
  "network_subnet": "192.168.1.0/24",
  "domain_name": "client.local",
  "primary_contact": "John Doe",
  "notes": "Additional information"
}
```

**Requires:** `msp:admin` scope

#### GET /api/v1/clients/{id}
Get client details with infrastructure.

**Response:**
```json
{
  "id": "uuid",
  "name": "Dataforth",
  "network_subnet": "192.168.0.0/24",
  "infrastructure": [
    {
      "hostname": "AD2",
      "ip_address": "192.168.0.6",
      "asset_type": "domain_controller",
      "os": "Windows Server 2022"
    }
  ],
  "active_projects": 3,
  "recent_sessions": 15
}
```

### Credentials

#### GET /api/v1/credentials
Query credentials (encrypted values not returned by default).

**Query Parameters:**
- `client_id` (uuid) - Filter by client
- `service_id` (uuid) - Filter by service
- `credential_type` (string) - Filter by type

**Response:**
```json
{
  "credentials": [
    {
      "id": "uuid",
      "client_name": "Dataforth",
      "service_name": "AD2 Administrator",
      "username": "sysadmin",
      "credential_type": "password",
      "requires_vpn": true,
      "last_rotated_at": "2025-12-01T00:00:00Z"
    }
  ]
}
```

**Note:** Password values not included. Use decrypt endpoint.

#### POST /api/v1/credentials
Store new credential (encrypted).

**Request:**
```json
{
  "client_id": "uuid",
  "service_name": "AD2 Administrator",
  "username": "sysadmin",
  "password": "plaintext-password",
  "credential_type": "password",
  "requires_vpn": true,
  "requires_2fa": false
}
```

**Response:**
```json
{
  "id": "uuid",
  "service_name": "AD2 Administrator",
  "created_at": "2026-01-16T10:00:00Z"
}
```

**Requires:** `msp:write` scope

#### GET /api/v1/credentials/{id}/decrypt
Decrypt and return credential value.

**Response:**
```json
{
  "credential_id": "uuid",
  "service_name": "AD2 Administrator",
  "username": "sysadmin",
  "password": "decrypted-password",
  "accessed_at": "2026-01-16T10:30:00Z"
}
```

**Side Effects:**
- Creates audit log entry
- Records access in `credential_audit_log` table

**Requires:** `msp:read` scope minimum

### Infrastructure

#### GET /api/v1/infrastructure
Query infrastructure assets.

**Query Parameters:**
- `client_id` (uuid) - Filter by client
- `asset_type` (string) - Filter by type
- `hostname` (string) - Search by hostname

**Response:**
```json
{
  "infrastructure": [
    {
      "id": "uuid",
      "client_name": "Dataforth",
      "hostname": "D2TESTNAS",
      "ip_address": "192.168.0.9",
      "asset_type": "nas_storage",
      "os": "ReadyNAS OS",
      "environmental_notes": "Manual WINS install, SMB1 only",
      "powershell_version": null,
      "has_gui": true
    }
  ]
}
```

#### GET /api/v1/infrastructure/{id}/insights
Get environmental insights for infrastructure.

**Response:**
```json
{
  "infrastructure_id": "uuid",
  "hostname": "D2TESTNAS",
  "insights": [
    {
      "category": "custom_installations",
      "title": "WINS: Manual Samba installation",
      "description": "WINS service manually installed via Samba nmbd...",
      "examples": ["ssh root@192.168.0.9 'ps aux | grep nmbd'"],
      "priority": 9
    }
  ],
  "limitations": ["no_native_wins_service", "smb1_only"],
  "recommended_commands": {
    "check_wins": "ssh root@192.168.0.9 'ps aux | grep nmbd'"
  }
}
```

### Commands & Failures

#### POST /api/v1/commands
Log command execution (with failure tracking).

**Request:**
```json
{
  "work_item_id": "uuid",
  "session_id": "uuid",
  "command_text": "Get-LocalUser",
  "host": "old-server-2008",
  "shell_type": "powershell",
  "success": false,
  "exit_code": 1,
  "error_message": "Get-LocalUser : The term Get-LocalUser is not recognized",
  "failure_category": "compatibility"
}
```

**Response:**
```json
{
  "id": "uuid",
  "created_at": "2026-01-16T10:00:00Z",
  "failure_logged": true
}
```

**Side Effects:**
- If failure: Triggers Failure Analysis Agent
- May create `failure_patterns` entry
- May update `environmental_insights`

#### GET /api/v1/failure-patterns
Query known failure patterns.

**Query Parameters:**
- `infrastructure_id` (uuid) - Patterns for specific infrastructure
- `pattern_type` (string) - Filter by type

**Response:**
```json
{
  "patterns": [
    {
      "id": "uuid",
      "pattern_signature": "PowerShell 7 cmdlets on Server 2008",
      "error_pattern": "Get-LocalUser.*not recognized",
      "root_cause": "Server 2008 only has PowerShell 2.0",
      "recommended_solution": "Use Get-WmiObject Win32_UserAccount",
      "occurrence_count": 5,
      "severity": "major"
    }
  ]
}
```

### Tasks & Todo Items

#### GET /api/v1/pending-tasks
Query open tasks.

**Query Parameters:**
- `client_id` (uuid) - Filter by client
- `priority` (string) - Filter by priority
- `status` (string) - Filter by status

**Response:**
```json
{
  "tasks": [
    {
      "id": "uuid",
      "client_name": "Dataforth",
      "title": "Create Datasheets share",
      "priority": "high",
      "status": "blocked",
      "blocked_by": "Waiting on Engineering",
      "due_date": "2026-01-20"
    }
  ]
}
```

#### POST /api/v1/pending-tasks
Create pending task.

**Request:**
```json
{
  "client_id": "uuid",
  "project_id": "uuid",
  "title": "Task title",
  "description": "Task description",
  "priority": "high",
  "due_date": "2026-01-20"
}
```

### External Integrations

#### GET /api/v1/integrations
List configured integrations (SyncroMSP, MSP Backups, etc.).

**Response:**
```json
{
  "integrations": [
    {
      "integration_name": "syncro",
      "integration_type": "psa",
      "is_active": true,
      "last_tested_at": "2026-01-15T08:00:00Z",
      "last_test_status": "success"
    }
  ]
}
```

#### POST /api/v1/integrations/{name}/test
Test integration connection.

**Response:**
```json
{
  "integration_name": "syncro",
  "status": "success",
  "message": "Connection successful",
  "tested_at": "2026-01-16T10:00:00Z"
}
```

#### GET /api/v1/syncro/tickets
Search SyncroMSP tickets.

**Query Parameters:**
- `customer` (string) - Filter by customer name
- `subject` (string) - Search ticket subjects
- `status` (string) - Filter by status

**Response:**
```json
{
  "tickets": [
    {
      "ticket_id": "12345",
      "ticket_number": "T12345",
      "subject": "Backup configuration for NAS",
      "customer": "Dataforth",
      "status": "open",
      "created_at": "2026-01-10T12:00:00Z"
    }
  ]
}
```

#### POST /api/v1/syncro/tickets/{id}/comment
Add comment to SyncroMSP ticket.

**Request:**
```json
{
  "comment": "Work completed: configured Veeam backup..."
}
```

**Response:**
```json
{
  "comment_id": "67890",
  "created_at": "2026-01-16T10:00:00Z"
}
```

**Side Effects:**
- Creates `external_integrations` log entry
- Links to current session

### Health & Monitoring

#### GET /api/v1/health
Health check endpoint.

**Response:**
```json
{
  "status": "healthy",
  "database": "connected",
  "timestamp": "2026-01-16T10:00:00Z",
  "version": "1.0.0"
}
```

**Status Codes:**
- `200` - Service healthy
- `503` - Service unavailable

#### GET /api/v1/metrics
Prometheus metrics (optional).

**Response:** Prometheus format metrics

---

## Error Handling

### Standard Error Response Format

```json
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Client ID is required",
    "details": {
      "field": "client_id",
      "constraint": "not_null"
    }
  },
  "timestamp": "2026-01-16T10:00:00Z",
  "request_id": "uuid"
}
```

### HTTP Status Codes

- **200** - Success
- **201** - Created
- **400** - Bad Request (invalid input)
- **401** - Unauthorized (missing/invalid token)
- **403** - Forbidden (insufficient permissions)
- **404** - Not Found
- **409** - Conflict (duplicate record)
- **429** - Too Many Requests (rate limit)
- **500** - Internal Server Error (never expose DB errors)
- **503** - Service Unavailable

### Error Codes

- `INVALID_REQUEST` - Malformed request
- `UNAUTHORIZED` - Missing or invalid authentication
- `FORBIDDEN` - Insufficient permissions
- `NOT_FOUND` - Resource not found
- `DUPLICATE_ENTRY` - Unique constraint violation
- `RATE_LIMIT_EXCEEDED` - Too many requests
- `DATABASE_ERROR` - Internal database error (details hidden)
- `ENCRYPTION_ERROR` - Credential encryption/decryption failed

---

## Rate Limiting

**Default Limits:**
- 100 requests per minute per token
- 1000 requests per hour per token
- Credential decryption: 20 per minute

**Headers:**
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1234567890
```

**Exceeded Response:**
```json
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Retry after 60 seconds.",
    "retry_after": 60
  }
}
```

---

## Agent Coordination Patterns

### Agent API Access

All specialized agents use the same API with agent-specific tokens:

**Agent Token Claims:**
```json
{
  "sub": "agent:context-recovery",
  "agent_type": "context_recovery",
  "scopes": ["msp:read"],
  "parent_session": "uuid",
  "exp": 1234567890
}
```

### Agent Communication Flow

```
Main Claude (JWT: user token)
  ↓
  Launches Agent (JWT: agent token, scoped to parent session)
  ↓
  Agent makes API calls (authenticated with agent token)
  ↓
  API logs agent activity (tracks parent session)
  ↓
  Agent returns summary to Main Claude
```

### Example: Context Recovery Agent

**Request Flow:**
1. Main Claude: POST /api/v1/agents/context-recovery
2. API issues agent token (scoped: msp:read, session_id)
3. Agent executes:
   - GET /api/v1/sessions?client_id=X&limit=5
   - GET /api/v1/pending-tasks?client_id=X
   - GET /api/v1/infrastructure?client_id=X
4. Agent processes results, generates summary
5. Agent returns to Main Claude (API logs all agent activity)

**Agent Audit Trail:**
- All agent API calls logged with parent session
- Agent execution time tracked
- Agent results cached (avoid redundant queries)

---

## Security Considerations

### Encryption
- **In Transit:** HTTPS only (TLS 1.2+)
- **At Rest:** AES-256-GCM for credentials
- **Key Management:** Environment variable or vault (not in database)

### Authentication
- JWT tokens with short expiration (1 hour access, 30 day refresh)
- Token rotation supported
- Revocation list for compromised tokens

### Audit Logging
- All credential access logged (`credential_audit_log`)
- All API requests logged (`api_audit_log`)
- User ID, IP address, timestamp, action recorded

### Input Validation
- Pydantic models validate all inputs
- SQL injection prevention via SQLAlchemy ORM
- XSS prevention (JSON only, no HTML)

### Rate Limiting
- Per-token rate limits
- Credential access rate limits (stricter)
- IP-based limits (optional)

---

## Configuration Storage

### Gitea Repository
**Repo:** `azcomputerguru/msp-config`

**File:** `msp-api-config.json`
```json
{
  "api_url": "https://msp-api.azcomputerguru.com",
  "refresh_token": "encrypted_token_value",
  "database_schema_version": "1.0.0",
  "machine_id": "uuid"
}
```

**Encryption:** git-crypt or encrypted JSON values

---

## Implementation Status

- [OK] API Design (this document)
- ⏳ FastAPI implementation
- ⏳ Database schema deployment
- ⏳ JWT authentication flow
- ⏳ Agent token system
- ⏳ External integrations (SyncroMSP, MSP Backups)

---

## Version History

**v1.0.0 (2026-01-16):**
- Initial API specification
- Machine detection endpoints
- Core CRUD operations
- Authentication flow
- Agent coordination patterns
- External integrations design
