# Nushell Plugin Integration Guide\n\n**Version**: 1.0.0\n**Last Updated**: 2025-10-09\n**Target Audience**: Developers, DevOps Engineers, System Administrators\n\n---\n\n## Table of Contents\n\n1. [Overview](#overview)\n2. [Why Native Plugins?](#why-native-plugins)\n3. [Prerequisites](#prerequisites)\n4. [Installation](#installation)\n5. [Quick Start (5 Minutes)](#quick-start-5-minutes)\n6. [Authentication Plugin (nu_plugin_auth)](#authentication-plugin-nu_plugin_auth)\n7. [KMS Plugin (nu_plugin_kms)](#kms-plugin-nu_plugin_kms)\n8. [Orchestrator Plugin (nu_plugin_orchestrator)](#orchestrator-plugin-nu_plugin_orchestrator)\n9. [Integration Examples](#integration-examples)\n10. [Best Practices](#best-practices)\n11. [Troubleshooting](#troubleshooting)\n12. [Migration Guide](#migration-guide)\n13. [Advanced Configuration](#advanced-configuration)\n14. [Security Considerations](#security-considerations)\n15. [FAQ](#faq)\n\n---\n\n## Overview\n\nThe Provisioning Platform provides three native Nushell plugins that dramatically improve performance and user experience compared to traditional HTTP\nAPI calls:\n\n| Plugin | Purpose | Performance Gain |\n| -------- | --------- | ------------------ |\n| **nu_plugin_auth** | JWT authentication, MFA, session management | 20% faster |\n| **nu_plugin_kms** | Encryption/decryption with multiple KMS backends | **10x faster** |\n| **nu_plugin_orchestrator** | Orchestrator operations without HTTP overhead | **50x faster** |\n\n### Architecture Benefits\n\n```\nTraditional HTTP Flow:\nUser Command → HTTP Request → Network → Server Processing → Response → Parse JSON\n  Total: ~50-100 ms per operation\n\nPlugin Flow:\nUser Command → Direct Rust Function Call → Return Nushell Data Structure\n  Total: ~1-10 ms per operation\n```\n\n### Key Features\n\n✅ **Performance**: 10-50x faster than HTTP API\n✅ **Type Safety**: Full Nushell type system integration\n✅ **Pipeline Support**: Native Nushell data structures\n✅ **Offline Capability**: KMS and orchestrator work without network\n✅ **OS Integration**: Native keyring for secure token storage\n✅ **Graceful Fallback**: HTTP still available if plugins not installed\n\n---\n\n## Why Native Plugins\n\n### Performance Comparison\n\nReal-world benchmarks from production workload:\n\n| Operation | HTTP API | Plugin | Improvement | Speedup |\n| ----------- | ---------- | -------- | ------------- | --------- |\n| **KMS Encrypt (RustyVault)** | ~50 ms | ~5 ms | -45 ms | **10x** |\n| **KMS Decrypt (RustyVault)** | ~50 ms | ~5 ms | -45 ms | **10x** |\n| **KMS Encrypt (Age)** | ~30 ms | ~3 ms | -27 ms | **10x** |\n| **KMS Decrypt (Age)** | ~30 ms | ~3 ms | -27 ms | **10x** |\n| **Orchestrator Status** | ~30 ms | ~1 ms | -29 ms | **30x** |\n| **Orchestrator Tasks List** | ~50 ms | ~5 ms | -45 ms | **10x** |\n| **Orchestrator Validate** | ~100 ms | ~10 ms | -90 ms | **10x** |\n| **Auth Login** | ~100 ms | ~80 ms | -20 ms | 1.25x |\n| **Auth Verify** | ~50 ms | ~10 ms | -40 ms | **5x** |\n| **Auth MFA Verify** | ~80 ms | ~60 ms | -20 ms | 1.3x |\n\n### Use Case: Batch Processing\n\n**Scenario**: Encrypt 100 configuration files\n\n```\n# HTTP API approach\nls configs/*.yaml | each { |file|\n    http post http://localhost:9998/encrypt { data: (open $file) }\n} | save encrypted/\n# Total time: ~5 seconds (50 ms × 100)\n\n# Plugin approach\nls configs/*.yaml | each { |file|\n    kms encrypt (open $file) --backend rustyvault\n} | save encrypted/\n# Total time: ~0.5 seconds (5 ms × 100)\n# Result: 10x faster\n```\n\n### Developer Experience Benefits\n\n**1. Native Nushell Integration**\n\n```\n# HTTP: Parse JSON, check status codes\nlet result = http post http://localhost:9998/encrypt { data: "secret" }\nif $result.status == "success" {\n    $result.encrypted\n} else {\n    error make { msg: $result.error }\n}\n\n# Plugin: Direct return values\nkms encrypt "secret"\n# Returns encrypted string directly, errors use Nushell's error system\n```\n\n**2. Pipeline Friendly**\n\n```\n# HTTP: Requires wrapping, JSON parsing\n["secret1", "secret2"] | each { |s|\n    (http post http://localhost:9998/encrypt { data: $s }).encrypted\n}\n\n# Plugin: Natural pipeline flow\n["secret1", "secret2"] | each { |s| kms encrypt $s }\n```\n\n**3. Tab Completion**\n\n```\n# All plugin commands have full tab completion\nkms <TAB>\n# → encrypt, decrypt, generate-key, status, backends\n\nkms encrypt --<TAB>\n# → --backend, --key, --context\n```\n\n---\n\n## Prerequisites\n\n### Required Software\n\n| Software | Minimum Version | Purpose |\n| ---------- | ---------------- | --------- |\n| **Nushell** | 0.107.1 | Shell and plugin runtime |\n| **Rust** | 1.75+ | Building plugins from source |\n| **Cargo** | (included with Rust) | Build tool |\n\n### Optional Dependencies\n\n| Software | Purpose | Platform |\n| ---------- | --------- | ---------- |\n| **gnome-keyring** | Secure token storage | Linux |\n| **kwallet** | Secure token storage | Linux (KDE) |\n| **age** | Age encryption backend | All |\n| **RustyVault** | High-performance KMS | All |\n\n### Platform Support\n\n| Platform | Status | Notes |\n| ---------- | -------- | ------- |\n| **macOS** | ✅ Full | Keychain integration |\n| **Linux** | ✅ Full | Requires keyring service |\n| **Windows** | ✅ Full | Credential Manager integration |\n| **FreeBSD** | ⚠️ Partial | No keyring integration |\n\n---\n\n## Installation\n\n### Step 1: Clone or Navigate to Plugin Directory\n\n```\ncd /Users/Akasha/project-provisioning/provisioning/core/plugins/nushell-plugins\n```\n\n### Step 2: Build All Plugins\n\n```\n# Build in release mode (optimized for performance)\ncargo build --release --all\n\n# Or build individually\ncargo build --release -p nu_plugin_auth\ncargo build --release -p nu_plugin_kms\ncargo build --release -p nu_plugin_orchestrator\n```\n\n**Expected output:**\n\n```\n   Compiling nu_plugin_auth v0.1.0\n   Compiling nu_plugin_kms v0.1.0\n   Compiling nu_plugin_orchestrator v0.1.0\n    Finished release [optimized] target(s) in 2m 15s\n```\n\n### Step 3: Register Plugins with Nushell\n\n```\n# Register all three plugins\nplugin add target/release/nu_plugin_auth\nplugin add target/release/nu_plugin_kms\nplugin add target/release/nu_plugin_orchestrator\n\n# On macOS, full paths:\nplugin add $PWD/target/release/nu_plugin_auth\nplugin add $PWD/target/release/nu_plugin_kms\nplugin add $PWD/target/release/nu_plugin_orchestrator\n```\n\n### Step 4: Verify Installation\n\n```\n# List registered plugins\nplugin list | where name =~ "auth|kms|orch"\n\n# Test each plugin\nauth --help\nkms --help\norch --help\n```\n\n**Expected output:**\n\n```\n╭───┬─────────────────────────┬─────────┬───────────────────────────────────╮\n│ # │          name           │ version │           filename                │\n├───┼─────────────────────────┼─────────┼───────────────────────────────────┤\n│ 0 │ nu_plugin_auth          │ 0.1.0   │ .../nu_plugin_auth                │\n│ 1 │ nu_plugin_kms           │ 0.1.0   │ .../nu_plugin_kms                 │\n│ 2 │ nu_plugin_orchestrator  │ 0.1.0   │ .../nu_plugin_orchestrator        │\n╰───┴─────────────────────────┴─────────┴───────────────────────────────────╯\n```\n\n### Step 5: Configure Environment (Optional)\n\n```\n# Add to ~/.config/nushell/env.nu\n$env.RUSTYVAULT_ADDR = "http://localhost:8200"\n$env.RUSTYVAULT_TOKEN = "your-vault-token"\n$env.CONTROL_CENTER_URL = "http://localhost:3000"\n$env.ORCHESTRATOR_DATA_DIR = "/opt/orchestrator/data"\n```\n\n---\n\n## Quick Start (5 Minutes)\n\n### 1. Authentication Workflow\n\n```\n# Login (password prompted securely)\nauth login admin\n# ✓ Login successful\n# User: admin\n# Role: Admin\n# Expires: 2025-10-09T14:30:00Z\n\n# Verify session\nauth verify\n# {\n#   "active": true,\n#   "user": "admin",\n#   "role": "Admin",\n#   "expires_at": "2025-10-09T14:30:00Z"\n# }\n\n# Enroll in MFA (optional but recommended)\nauth mfa enroll totp\n# QR code displayed, save backup codes\n\n# Verify MFA\nauth mfa verify --code 123456\n# ✓ MFA verification successful\n\n# Logout\nauth logout\n# ✓ Logged out successfully\n```\n\n### 2. KMS Operations\n\n```\n# Encrypt data\nkms encrypt "my secret data"\n# vault:v1:8GawgGuP...\n\n# Decrypt data\nkms decrypt "vault:v1:8GawgGuP..."\n# my secret data\n\n# Check available backends\nkms status\n# {\n#   "backend": "rustyvault",\n#   "status": "healthy",\n#   "url": "http://localhost:8200"\n# }\n\n# Encrypt with specific backend\nkms encrypt "data" --backend age --key age1xxxxxxx\n```\n\n### 3. Orchestrator Operations\n\n```\n# Check orchestrator status (no HTTP call)\norch status\n# {\n#   "active_tasks": 5,\n#   "completed_tasks": 120,\n#   "health": "healthy"\n# }\n\n# Validate workflow\norch validate workflows/deploy.ncl\n# {\n#   "valid": true,\n#   "workflow": { "name": "deploy_k8s", "operations": 5 }\n# }\n\n# List running tasks\norch tasks --status running\n# [ { "task_id": "task_123", "name": "deploy_k8s", "progress": 45 } ]\n```\n\n### 4. Combined Workflow\n\n```\n# Complete authenticated deployment pipeline\nauth login admin\n    | if $in.success { auth verify }\n    | if $in.active {\n        orch validate workflows/production.ncl\n            | if $in.valid {\n                kms encrypt (open secrets.yaml | to json)\n                    | save production-secrets.enc\n              }\n      }\n# ✓ Pipeline completed successfully\n```\n\n---\n\n## Authentication Plugin (nu_plugin_auth)\n\nThe authentication plugin manages JWT-based authentication, MFA enrollment/verification, and session management with OS-native keyring integration.\n\n### Available Commands\n\n| Command | Purpose | Example |\n| --------- | --------- | --------- |\n| `auth login` | Login and store JWT | `auth login admin` |\n| `auth logout` | Logout and clear tokens | `auth logout` |\n| `auth verify` | Verify current session | `auth verify` |\n| `auth sessions` | List active sessions | `auth sessions` |\n| `auth mfa enroll` | Enroll in MFA | `auth mfa enroll totp` |\n| `auth mfa verify` | Verify MFA code | `auth mfa verify --code 123456` |\n\n### Command Reference\n\n#### `auth login <username> [password]`\n\nLogin to provisioning platform and store JWT tokens securely in OS keyring.\n\n**Arguments:**\n\n- `username` (required): Username for authentication\n- `password` (optional): Password (prompted if not provided)\n\n**Flags:**\n\n- `--url <url>`: Control center URL (default: `http://localhost:3000`)\n- `--password <password>`: Password (alternative to positional argument)\n\n**Examples:**\n\n```\n# Interactive password prompt (recommended)\nauth login admin\n# Password: ••••••••\n# ✓ Login successful\n# User: admin\n# Role: Admin\n# Expires: 2025-10-09T14:30:00Z\n\n# Password in command (not recommended for production)\nauth login admin mypassword\n\n# Custom control center URL\nauth login admin --url https://control-center.example.com\n\n# Pipeline usage\nlet creds = { username: "admin", password: (input --suppress-output "Password: ") }\nauth login $creds.username $creds.password\n```\n\n**Token Storage Locations:**\n\n- **macOS**: Keychain Access (`login` keychain)\n- **Linux**: Secret Service API (gnome-keyring, kwallet)\n- **Windows**: Windows Credential Manager\n\n**Security Notes:**\n\n- Tokens encrypted at rest by OS\n- Requires user authentication to access (macOS Touch ID, Linux password)\n- Never stored in plain text files\n\n#### `auth logout`\n\nLogout from current session and remove stored tokens from keyring.\n\n**Examples:**\n\n```\n# Simple logout\nauth logout\n# ✓ Logged out successfully\n\n# Conditional logout\nif (auth verify | get active) {\n    auth logout\n    echo "Session terminated"\n}\n\n# Logout all sessions (requires admin role)\nauth sessions | each { |sess|\n    auth logout --session-id $sess.session_id\n}\n```\n\n#### `auth verify`\n\nVerify current session status and check token validity.\n\n**Returns:**\n\n- `active` (bool): Whether session is active\n- `user` (string): Username\n- `role` (string): User role\n- `expires_at` (datetime): Token expiration\n- `mfa_verified` (bool): MFA verification status\n\n**Examples:**\n\n```\n# Check if logged in\nauth verify\n# {\n#   "active": true,\n#   "user": "admin",\n#   "role": "Admin",\n#   "expires_at": "2025-10-09T14:30:00Z",\n#   "mfa_verified": true\n# }\n\n# Pipeline usage\nif (auth verify | get active) {\n    echo "✓ Authenticated"\n} else {\n    auth login admin\n}\n\n# Check expiration\nlet session = auth verify\nif ($session.expires_at | into datetime) < (date now) {\n    echo "Session expired, re-authenticating..."\n    auth login $session.user\n}\n```\n\n#### `auth sessions`\n\nList all active sessions for current user.\n\n**Examples:**\n\n```\n# List all sessions\nauth sessions\n# [\n#   {\n#     "session_id": "sess_abc123",\n#     "created_at": "2025-10-09T12:00:00Z",\n#     "expires_at": "2025-10-09T14:30:00Z",\n#     "ip_address": "192.168.1.100",\n#     "user_agent": "nushell/0.107.1"\n#   }\n# ]\n\n# Filter recent sessions (last hour)\nauth sessions | where created_at > ((date now) - 1hr)\n\n# Find sessions by IP\nauth sessions | where ip_address =~ "192.168"\n\n# Count active sessions\nauth sessions | length\n```\n\n#### `auth mfa enroll <type>`\n\nEnroll in Multi-Factor Authentication (TOTP or WebAuthn).\n\n**Arguments:**\n\n- `type` (required): MFA type (`totp` or `webauthn`)\n\n**TOTP Enrollment:**\n\n```\nauth mfa enroll totp\n# ✓ TOTP enrollment initiated\n#\n# Scan this QR code with your authenticator app:\n#\n#   ████ ▄▄▄▄▄ █▀█ █▄▀▀▀▄ ▄▄▄▄▄ ████\n#   ████ █   █ █▀▀▀█▄ ▀▀█ █   █ ████\n#   ████ █▄▄▄█ █ █▀▄ ▀▄▄█ █▄▄▄█ ████\n#   (QR code continues...)\n#\n# Or enter manually:\n# Secret: JBSWY3DPEHPK3PXP\n# URL: otpauth://totp/Provisioning:admin?secret=JBSWY3DPEHPK3PXP&issuer=Provisioning\n#\n# Backup codes (save securely):\n# 1. ABCD-EFGH-IJKL\n# 2. MNOP-QRST-UVWX\n# 3. YZAB-CDEF-GHIJ\n# (8 more codes...)\n```\n\n**WebAuthn Enrollment:**\n\n```\nauth mfa enroll webauthn\n# ✓ WebAuthn enrollment initiated\n#\n# Insert your security key and touch the button...\n# (waiting for device interaction)\n#\n# ✓ Security key registered successfully\n# Device: YubiKey 5 NFC\n# Created: 2025-10-09T13:00:00Z\n```\n\n**Supported Authenticator Apps:**\n\n- Google Authenticator\n- Microsoft Authenticator\n- Authy\n- 1Password\n- Bitwarden\n\n**Supported Hardware Keys:**\n\n- YubiKey (all models)\n- Titan Security Key\n- Feitian ePass\n- macOS Touch ID\n- Windows Hello\n\n#### `auth mfa verify --code <code>`\n\nVerify MFA code (TOTP or backup code).\n\n**Flags:**\n\n- `--code <code>` (required): 6-digit TOTP code or backup code\n\n**Examples:**\n\n```\n# Verify TOTP code\nauth mfa verify --code 123456\n# ✓ MFA verification successful\n\n# Verify backup code\nauth mfa verify --code ABCD-EFGH-IJKL\n# ✓ MFA verification successful (backup code used)\n# Warning: This backup code cannot be used again\n\n# Pipeline usage\nlet code = input "MFA code: "\nauth mfa verify --code $code\n```\n\n**Error Cases:**\n\n```\n# Invalid code\nauth mfa verify --code 999999\n# Error: Invalid MFA code\n# → Verify time synchronization on your device\n\n# Rate limited\nauth mfa verify --code 123456\n# Error: Too many failed attempts\n# → Wait 5 minutes before trying again\n\n# No MFA enrolled\nauth mfa verify --code 123456\n# Error: MFA not enrolled for this user\n# → Run: auth mfa enroll totp\n```\n\n### Environment Variables\n\n| Variable | Description | Default |\n| ---------- | ------------- | --------- |\n| `USER` | Default username | Current OS user |\n| `CONTROL_CENTER_URL` | Control center URL | `http://localhost:3000` |\n| `AUTH_KEYRING_SERVICE` | Keyring service name | `provisioning-auth` |\n\n### Troubleshooting Authentication\n\n**"No active session"**\n\n```\n# Solution: Login first\nauth login <username>\n```\n\n**"Keyring error" (macOS)**\n\n```\n# Check Keychain Access permissions\n# System Preferences → Security & Privacy → Privacy → Full Disk Access\n# Add: /Applications/Nushell.app (or /usr/local/bin/nu)\n\n# Or grant access manually\nsecurity unlock-keychain ~/Library/Keychains/login.keychain-db\n```\n\n**"Keyring error" (Linux)**\n\n```\n# Install keyring service\nsudo apt install gnome-keyring      # Ubuntu/Debian\nsudo dnf install gnome-keyring      # Fedora\nsudo pacman -S gnome-keyring        # Arch\n\n# Or use KWallet (KDE)\nsudo apt install kwalletmanager\n\n# Start keyring daemon\neval $(gnome-keyring-daemon --start)\nexport $(gnome-keyring-daemon --start --components=secrets)\n```\n\n**"MFA verification failed"**\n\n```\n# Check time synchronization (TOTP requires accurate time)\n# macOS:\nsudo sntp -sS time.apple.com\n\n# Linux:\nsudo ntpdate pool.ntp.org\n# Or\nsudo systemctl restart systemd-timesyncd\n\n# Use backup code if TOTP not working\nauth mfa verify --code ABCD-EFGH-IJKL\n```\n\n---\n\n## KMS Plugin (nu_plugin_kms)\n\nThe KMS plugin provides high-performance encryption and decryption using multiple backend providers.\n\n### Supported Backends\n\n| Backend | Performance | Use Case | Setup Complexity |\n| --------- | ------------ | ---------- | ------------------ |\n| **rustyvault** | ⚡ Very Fast (~5 ms) | Production KMS | Medium |\n| **age** | ⚡ Very Fast (~3 ms) | Local development | Low |\n| **cosmian** | 🐢 Moderate (~30 ms) | Cloud KMS | Medium |\n| **aws** | 🐢 Moderate (~50 ms) | AWS environments | Medium |\n| **vault** | 🐢 Moderate (~40 ms) | Enterprise KMS | High |\n\n### Backend Selection Guide\n\n**Choose `rustyvault` when:**\n\n- ✅ Running in production with high throughput requirements\n- ✅ Need ~5 ms encryption/decryption latency\n- ✅ Have RustyVault server deployed\n- ✅ Require key rotation and versioning\n\n**Choose `age` when:**\n\n- ✅ Developing locally without external dependencies\n- ✅ Need simple file encryption\n- ✅ Want ~3 ms latency\n- ❌ Don't need centralized key management\n\n**Choose `cosmian` when:**\n\n- ✅ Using Cosmian KMS service\n- ✅ Need cloud-based key management\n- ⚠️ Can accept ~30 ms latency\n\n**Choose `aws` when:**\n\n- ✅ Deployed on AWS infrastructure\n- ✅ Using AWS IAM for access control\n- ✅ Need AWS KMS integration\n- ⚠️ Can accept ~50 ms latency\n\n**Choose `vault` when:**\n\n- ✅ Using HashiCorp Vault enterprise\n- ✅ Need advanced policy management\n- ✅ Require audit trails\n- ⚠️ Can accept ~40 ms latency\n\n### Available Commands\n\n| Command | Purpose | Example |\n| --------- | --------- | --------- |\n| `kms encrypt` | Encrypt data | `kms encrypt "secret"` |\n| `kms decrypt` | Decrypt data | `kms decrypt "vault:v1:..."` |\n| `kms generate-key` | Generate DEK | `kms generate-key --spec AES256` |\n| `kms status` | Backend status | `kms status` |\n\n### Command Reference\n\n#### `kms encrypt <data> [--backend <backend>]`\n\nEncrypt data using specified KMS backend.\n\n**Arguments:**\n\n- `data` (required): Data to encrypt (string or binary)\n\n**Flags:**\n\n- `--backend <backend>`: KMS backend (`rustyvault`, `age`, `cosmian`, `aws`, `vault`)\n- `--key <key>`: Key ID or recipient (backend-specific)\n- `--context <context>`: Additional authenticated data (AAD)\n\n**Examples:**\n\n```\n# Auto-detect backend from environment\nkms encrypt "secret configuration data"\n# vault:v1:8GawgGuP+emDKX5q...\n\n# RustyVault backend\nkms encrypt "data" --backend rustyvault --key provisioning-main\n# vault:v1:abc123def456...\n\n# Age backend (local encryption)\nkms encrypt "data" --backend age --key age1xxxxxxxxx\n# -----BEGIN AGE ENCRYPTED FILE-----\n# YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+...\n# -----END AGE ENCRYPTED FILE-----\n\n# AWS KMS\nkms encrypt "data" --backend aws --key alias/provisioning\n# AQICAHhwbGF0Zm9ybS1wcm92aXNpb25p...\n\n# With context (AAD for additional security)\nkms encrypt "data" --backend rustyvault --key provisioning-main --context "user=admin,env=production"\n\n# Encrypt file contents\nkms encrypt (open config.yaml) --backend rustyvault | save config.yaml.enc\n\n# Encrypt multiple files\nls configs/*.yaml | each { |file|\n    kms encrypt (open $file.name) --backend age\n        | save $"encrypted/($file.name).enc"\n}\n```\n\n**Output Formats:**\n\n- **RustyVault**: `vault:v1:base64_ciphertext`\n- **Age**: `-----BEGIN AGE ENCRYPTED FILE-----...-----END AGE ENCRYPTED FILE-----`\n- **AWS**: `base64_aws_kms_ciphertext`\n- **Cosmian**: `cosmian:v1:base64_ciphertext`\n\n#### `kms decrypt <encrypted> [--backend <backend>]`\n\nDecrypt KMS-encrypted data.\n\n**Arguments:**\n\n- `encrypted` (required): Encrypted data (detects format automatically)\n\n**Flags:**\n\n- `--backend <backend>`: KMS backend (auto-detected from format if not specified)\n- `--context <context>`: Additional authenticated data (must match encryption context)\n\n**Examples:**\n\n```\n# Auto-detect backend from format\nkms decrypt "vault:v1:8GawgGuP..."\n# secret configuration data\n\n# Explicit backend\nkms decrypt "vault:v1:abc123..." --backend rustyvault\n\n# Age decryption\nkms decrypt "-----BEGIN AGE ENCRYPTED FILE-----..."\n# (uses AGE_IDENTITY from environment)\n\n# With context (must match encryption context)\nkms decrypt "vault:v1:abc123..." --context "user=admin,env=production"\n\n# Decrypt file\nkms decrypt (open config.yaml.enc) | save config.yaml\n\n# Decrypt multiple files\nls encrypted/*.enc | each { |file|\n    kms decrypt (open $file.name)\n        | save $"configs/(($file.name | path basename) | str replace '.enc' '')"\n}\n\n# Pipeline decryption\nopen secrets.json\n    | get database_password_enc\n    | kms decrypt\n    | str trim\n    | psql --dbname mydb --password\n```\n\n**Error Cases:**\n\n```\n# Invalid ciphertext\nkms decrypt "invalid_data"\n# Error: Invalid ciphertext format\n# → Verify data was encrypted with KMS\n\n# Context mismatch\nkms decrypt "vault:v1:abc..." --context "wrong=context"\n# Error: Authentication failed (AAD mismatch)\n# → Verify encryption context matches\n\n# Backend unavailable\nkms decrypt "vault:v1:abc..."\n# Error: Failed to connect to RustyVault at http://localhost:8200\n# → Check RustyVault is running: curl http://localhost:8200/v1/sys/health\n```\n\n#### `kms generate-key [--spec <spec>]`\n\nGenerate data encryption key (DEK) using KMS envelope encryption.\n\n**Flags:**\n\n- `--spec <spec>`: Key specification (`AES128` or `AES256`, default: `AES256`)\n- `--backend <backend>`: KMS backend\n\n**Examples:**\n\n```\n# Generate AES-256 key\nkms generate-key\n# {\n#   "plaintext": "rKz3N8xPq...",  # base64-encoded key\n#   "ciphertext": "vault:v1:...",  # encrypted DEK\n#   "spec": "AES256"\n# }\n\n# Generate AES-128 key\nkms generate-key --spec AES128\n\n# Use in envelope encryption pattern\nlet dek = kms generate-key\nlet encrypted_data = ($data | openssl enc -aes-256-cbc -K $dek.plaintext)\n{\n    data: $encrypted_data,\n    encrypted_key: $dek.ciphertext\n} | save secure_data.json\n\n# Later, decrypt:\nlet envelope = open secure_data.json\nlet dek = kms decrypt $envelope.encrypted_key\n$envelope.data | openssl enc -d -aes-256-cbc -K $dek\n```\n\n**Use Cases:**\n\n- Envelope encryption (encrypt large data locally, protect DEK with KMS)\n- Database field encryption\n- File encryption with key wrapping\n\n#### `kms status`\n\nShow KMS backend status, configuration, and health.\n\n**Examples:**\n\n```\n# Show current backend status\nkms status\n# {\n#   "backend": "rustyvault",\n#   "status": "healthy",\n#   "url": "http://localhost:8200",\n#   "mount_point": "transit",\n#   "version": "0.1.0",\n#   "latency_ms": 5\n# }\n\n# Check all configured backends\nkms status --all\n# [\n#   { "backend": "rustyvault", "status": "healthy", ... },\n#   { "backend": "age", "status": "available", ... },\n#   { "backend": "aws", "status": "unavailable", "error": "..." }\n# ]\n\n# Filter to specific backend\nkms status | where backend == "rustyvault"\n\n# Health check in automation\nif (kms status | get status) == "healthy" {\n    echo "✓ KMS operational"\n} else {\n    error make { msg: "KMS unhealthy" }\n}\n```\n\n### Backend Configuration\n\n#### RustyVault Backend\n\n```\n# Environment variables\nexport RUSTYVAULT_ADDR="http://localhost:8200"\nexport RUSTYVAULT_TOKEN="hvs.xxxxxxxxxxxxx"\nexport RUSTYVAULT_MOUNT="transit"  # Transit engine mount point\nexport RUSTYVAULT_KEY="provisioning-main"  # Default key name\n```\n\n```\n# Usage\nkms encrypt "data" --backend rustyvault --key provisioning-main\n```\n\n**Setup RustyVault:**\n\n```\n# Start RustyVault\nrustyvault server -dev\n\n# Enable transit engine\nrustyvault secrets enable transit\n\n# Create encryption key\nrustyvault write -f transit/keys/provisioning-main\n```\n\n#### Age Backend\n\n```\n# Generate Age keypair\nage-keygen -o ~/.age/key.txt\n\n# Environment variables\nexport AGE_IDENTITY="$HOME/.age/key.txt"  # Private key\nexport AGE_RECIPIENT="age1xxxxxxxxx"      # Public key (from key.txt)\n```\n\n```\n# Usage\nkms encrypt "data" --backend age\nkms decrypt (open file.enc) --backend age\n```\n\n#### AWS KMS Backend\n\n```\n# AWS credentials\nexport AWS_REGION="us-east-1"\nexport AWS_ACCESS_KEY_ID="AKIAXXXXX"\nexport AWS_SECRET_ACCESS_KEY="xxxxx"\n\n# KMS configuration\nexport AWS_KMS_KEY_ID="alias/provisioning"\n```\n\n```\n# Usage\nkms encrypt "data" --backend aws --key alias/provisioning\n```\n\n**Setup AWS KMS:**\n\n```\n# Create KMS key\naws kms create-key --description "Provisioning Platform"\n\n# Create alias\naws kms create-alias --alias-name alias/provisioning --target-key-id <key-id>\n\n# Grant permissions\naws kms create-grant --key-id <key-id> --grantee-principal <role-arn> \\n    --operations Encrypt Decrypt GenerateDataKey\n```\n\n#### Cosmian Backend\n\n```\n# Cosmian KMS configuration\nexport KMS_HTTP_URL="http://localhost:9998"\nexport KMS_HTTP_BACKEND="cosmian"\nexport COSMIAN_API_KEY="your-api-key"\n```\n\n```\n# Usage\nkms encrypt "data" --backend cosmian\n```\n\n#### Vault Backend (HashiCorp)\n\n```\n# Vault configuration\nexport VAULT_ADDR="https://vault.example.com:8200"\nexport VAULT_TOKEN="hvs.xxxxxxxxxxxxx"\nexport VAULT_MOUNT="transit"\nexport VAULT_KEY="provisioning"\n```\n\n```\n# Usage\nkms encrypt "data" --backend vault --key provisioning\n```\n\n### Performance Benchmarks\n\n**Test Setup:**\n\n- Data size: 1 KB\n- Iterations: 1000\n- Hardware: Apple M1, 16 GB RAM\n- Network: localhost\n\n**Results:**\n\n| Backend | Encrypt (avg) | Decrypt (avg) | Throughput (ops/sec) |\n| --------- | --------------- | --------------- | ---------------------- |\n| RustyVault | 4.8 ms | 5.1 ms | ~200 |\n| Age | 2.9 ms | 3.2 ms | ~320 |\n| Cosmian HTTP | 31 ms | 29 ms | ~33 |\n| AWS KMS | 52 ms | 48 ms | ~20 |\n| Vault | 38 ms | 41 ms | ~25 |\n\n**Scaling Test (1000 operations):**\n\n```\n# RustyVault: ~5 seconds\n0..1000 | each { |_| kms encrypt "data" --backend rustyvault } | length\n# Age: ~3 seconds\n0..1000 | each { |_| kms encrypt "data" --backend age } | length\n```\n\n### Troubleshooting KMS\n\n**"RustyVault connection failed"**\n\n```\n# Check RustyVault is running\ncurl http://localhost:8200/v1/sys/health\n# Expected: { "initialized": true, "sealed": false }\n\n# Check environment\necho $env.RUSTYVAULT_ADDR\necho $env.RUSTYVAULT_TOKEN\n\n# Test authentication\ncurl -H "X-Vault-Token: $RUSTYVAULT_TOKEN" $RUSTYVAULT_ADDR/v1/sys/health\n```\n\n**"Age encryption failed"**\n\n```\n# Check Age keys exist\nls -la ~/.age/\n# Expected: key.txt\n\n# Verify key format\ncat ~/.age/key.txt | head -1\n# Expected: # created: <date>\n# Line 2: # public key: age1xxxxx\n# Line 3: AGE-SECRET-KEY-xxxxx\n\n# Extract public key\nexport AGE_RECIPIENT=$(grep "public key:" ~/.age/key.txt | cut -d: -f2 | tr -d ' ')\necho $AGE_RECIPIENT\n```\n\n**"AWS KMS access denied"**\n\n```\n# Verify AWS credentials\naws sts get-caller-identity\n# Expected: Account, UserId, Arn\n\n# Check KMS key permissions\naws kms describe-key --key-id alias/provisioning\n\n# Test encryption\naws kms encrypt --key-id alias/provisioning --plaintext "test"\n```\n\n---\n\n## Orchestrator Plugin (nu_plugin_orchestrator)\n\nThe orchestrator plugin provides direct file-based access to orchestrator state, eliminating HTTP overhead for status queries and validation.\n\n### Available Commands\n\n| Command | Purpose | Example |\n| --------- | --------- | --------- |\n| `orch status` | Orchestrator status | `orch status` |\n| `orch validate` | Validate workflow | `orch validate workflow.ncl` |\n| `orch tasks` | List tasks | `orch tasks --status running` |\n\n### Command Reference\n\n#### `orch status [--data-dir <dir>]`\n\nGet orchestrator status from local files (no HTTP, ~1 ms latency).\n\n**Flags:**\n\n- `--data-dir <dir>`: Data directory (default from `ORCHESTRATOR_DATA_DIR`)\n\n**Examples:**\n\n```\n# Default data directory\norch status\n# {\n#   "active_tasks": 5,\n#   "completed_tasks": 120,\n#   "failed_tasks": 2,\n#   "pending_tasks": 3,\n#   "uptime": "2d 4h 15m",\n#   "health": "healthy"\n# }\n\n# Custom data directory\norch status --data-dir /opt/orchestrator/data\n\n# Monitor in loop\nwhile true {\n    clear\n    orch status | table\n    sleep 5sec\n}\n\n# Alert on failures\nif (orch status | get failed_tasks) > 0 {\n    echo "⚠️ Failed tasks detected!"\n}\n```\n\n#### `orch validate <workflow.ncl> [--strict]`\n\nValidate workflow Nickel file syntax and structure.\n\n**Arguments:**\n\n- `workflow.ncl` (required): Path to Nickel workflow file\n\n**Flags:**\n\n- `--strict`: Enable strict validation (warnings as errors)\n\n**Examples:**\n\n```\n# Basic validation\norch validate workflows/deploy.ncl\n# {\n#   "valid": true,\n#   "workflow": {\n#     "name": "deploy_k8s_cluster",\n#     "version": "1.0.0",\n#     "operations": 5\n#   },\n#   "warnings": [],\n#   "errors": []\n# }\n\n# Strict mode (warnings cause failure)\norch validate workflows/deploy.ncl --strict\n# Error: Validation failed with warnings:\n# - Operation 'create_servers': Missing retry_policy\n# - Operation 'install_k8s': Resource limits not specified\n\n# Validate all workflows\nls workflows/*.ncl | each { |file|\n    let result = orch validate $file.name\n    if $result.valid {\n        echo $"✓ ($file.name)"\n    } else {\n        echo $"✗ ($file.name): ($result.errors | str join ', ')"\n    }\n}\n\n# CI/CD validation\ntry {\n    orch validate workflow.ncl --strict\n    echo "✓ Validation passed"\n} catch {\n    echo "✗ Validation failed"\n    exit 1\n}\n```\n\n**Validation Checks:**\n\n- ✅ KCL syntax correctness\n- ✅ Required fields present (`name`, `version`, `operations`)\n- ✅ Dependency graph valid (no cycles)\n- ✅ Resource limits within bounds\n- ✅ Provider configurations valid\n- ✅ Operation types supported\n- ⚠️ Optional: Retry policies defined\n- ⚠️ Optional: Resource limits specified\n\n#### `orch tasks [--status <status>] [--limit <n>]`\n\nList orchestrator tasks from local state.\n\n**Flags:**\n\n- `--status <status>`: Filter by status (`pending`, `running`, `completed`, `failed`)\n- `--limit <n>`: Limit results (default: 100)\n- `--data-dir <dir>`: Data directory\n\n**Examples:**\n\n```\n# All tasks (last 100)\norch tasks\n# [\n#   {\n#     "task_id": "task_abc123",\n#     "name": "deploy_kubernetes",\n#     "status": "running",\n#     "priority": 5,\n#     "created_at": "2025-10-09T12:00:00Z",\n#     "progress": 45\n#   }\n# ]\n\n# Running tasks only\norch tasks --status running\n\n# Failed tasks (last 10)\norch tasks --status failed --limit 10\n\n# Pending high-priority tasks\norch tasks --status pending | where priority > 7\n\n# Monitor active tasks\nwatch {\n    orch tasks --status running\n        | select name progress updated_at\n        | table\n}\n\n# Count tasks by status\norch tasks | group-by status | each { |group|\n    { status: $group.0, count: ($group.1 | length) }\n}\n```\n\n### Environment Variables\n\n| Variable | Description | Default |\n| ---------- | ------------- | --------- |\n| `ORCHESTRATOR_DATA_DIR` | Data directory | `provisioning/platform/orchestrator/data` |\n\n### Performance Comparison\n\n| Operation | HTTP API | Plugin | Latency Reduction |\n| ----------- | ---------- | -------- | ------------------- |\n| Status query | ~30 ms | ~1 ms | **97% faster** |\n| Validate workflow | ~100 ms | ~10 ms | **90% faster** |\n| List tasks | ~50 ms | ~5 ms | **90% faster** |\n\n**Use Case: CI/CD Pipeline**\n\n```\n# HTTP approach (slow)\nhttp get http://localhost:9090/tasks --status running\n    | each { |task| http get $"http://localhost:9090/tasks/($task.id)" }\n# Total: ~500 ms for 10 tasks\n\n# Plugin approach (fast)\norch tasks --status running\n# Total: ~5 ms for 10 tasks\n# Result: 100x faster\n```\n\n### Troubleshooting Orchestrator\n\n**"Failed to read status"**\n\n```\n# Check data directory exists\nls -la provisioning/platform/orchestrator/data/\n\n# Create if missing\nmkdir -p provisioning/platform/orchestrator/data\n\n# Check permissions (must be readable)\nchmod 755 provisioning/platform/orchestrator/data\n```\n\n**"Workflow validation failed"**\n\n```\n# Use strict mode for detailed errors\norch validate workflows/deploy.ncl --strict\n\n# Check Nickel syntax manually\nnickel typecheck workflows/deploy.ncl\nnickel eval workflows/deploy.ncl\n```\n\n**"No tasks found"**\n\n```\n# Check orchestrator running\nps aux | grep orchestrator\n\n# Start orchestrator if not running\ncd provisioning/platform/orchestrator\n./scripts/start-orchestrator.nu --background\n\n# Check task files\nls provisioning/platform/orchestrator/data/tasks/\n```\n\n---\n\n## Integration Examples\n\n### Example 1: Complete Authenticated Deployment\n\nFull workflow with authentication, secrets, and deployment:\n\n```\n# Step 1: Login with MFA\nauth login admin\nauth mfa verify --code (input "MFA code: ")\n\n# Step 2: Verify orchestrator health\nif (orch status | get health) != "healthy" {\n    error make { msg: "Orchestrator unhealthy" }\n}\n\n# Step 3: Validate deployment workflow\nlet validation = orch validate workflows/production-deploy.ncl --strict\nif not $validation.valid {\n    error make { msg: $"Validation failed: ($validation.errors)" }\n}\n\n# Step 4: Encrypt production secrets\nlet secrets = open secrets/production.yaml\nkms encrypt ($secrets | to json) --backend rustyvault --key prod-main\n    | save secrets/production.enc\n\n# Step 5: Submit deployment\nprovisioning cluster create production --check\n\n# Step 6: Monitor progress\nwhile (orch tasks --status running | length) > 0 {\n    orch tasks --status running\n        | select name progress updated_at\n        | table\n    sleep 10sec\n}\n\necho "✓ Deployment complete"\n```\n\n### Example 2: Batch Secret Rotation\n\nRotate all secrets in multiple environments:\n\n```\n# Rotate database passwords\n["dev", "staging", "production"] | each { |env|\n    # Generate new password\n    let new_password = (openssl rand -base64 32)\n\n    # Encrypt with environment-specific key\n    let encrypted = kms encrypt $new_password --backend rustyvault --key $"($env)-main"\n\n    # Save encrypted password\n    {\n        environment: $env,\n        password_enc: $encrypted,\n        rotated_at: (date now | format date "%Y-%m-%d %H:%M:%S")\n    } | save $"secrets/db-password-($env).json"\n\n    echo $"✓ Rotated password for ($env)"\n}\n```\n\n### Example 3: Multi-Environment Deployment\n\nDeploy to multiple environments with validation:\n\n```\n# Define environments\nlet environments = [\n    { name: "dev", validate: "basic" },\n    { name: "staging", validate: "strict" },\n    { name: "production", validate: "strict", mfa_required: true }\n]\n\n# Deploy to each environment\n$environments | each { |env|\n    echo $"Deploying to ($env.name)..."\n\n    # Authenticate if production\n    if $env.mfa_required? {\n        if not (auth verify | get mfa_verified) {\n            auth mfa verify --code (input $"MFA code for ($env.name): ")\n        }\n    }\n\n    # Validate workflow\n    let validation = if $env.validate == "strict" {\n        orch validate $"workflows/($env.name)-deploy.ncl" --strict\n    } else {\n        orch validate $"workflows/($env.name)-deploy.ncl"\n    }\n\n    if not $validation.valid {\n        echo $"✗ Validation failed for ($env.name)"\n        continue\n    }\n\n    # Decrypt secrets\n    let secrets = kms decrypt (open $"secrets/($env.name).enc")\n\n    # Deploy\n    provisioning cluster create $env.name\n\n    echo $"✓ Deployed to ($env.name)"\n}\n```\n\n### Example 4: Automated Backup and Encryption\n\nBackup configuration files with encryption:\n\n```\n# Backup script\nlet backup_dir = $"backups/(date now | format date "%Y%m%d-%H%M%S")"\nmkdir $backup_dir\n\n# Backup and encrypt configs\nls configs/**/*.yaml | each { |file|\n    let encrypted = kms encrypt (open $file.name) --backend age\n    let backup_path = $"($backup_dir)/($file.name | path basename).enc"\n    $encrypted | save $backup_path\n    echo $"✓ Backed up ($file.name)"\n}\n\n# Create manifest\n{\n    backup_date: (date now),\n    files: (ls $"($backup_dir)/*.enc" | length),\n    backend: "age"\n} | save $"($backup_dir)/manifest.json"\n\necho $"✓ Backup complete: ($backup_dir)"\n```\n\n### Example 5: Health Monitoring Dashboard\n\nReal-time health monitoring:\n\n```\n# Health dashboard\nwhile true {\n    clear\n\n    # Header\n    echo "=== Provisioning Platform Health Dashboard ==="\n    echo $"Updated: (date now | format date "%Y-%m-%d %H:%M:%S")"\n    echo ""\n\n    # Authentication status\n    let auth_status = try { auth verify } catch { { active: false } }\n    echo $"Auth: (if $auth_status.active { '✓ Active' } else { '✗ Inactive' })"\n\n    # KMS status\n    let kms_health = kms status\n    echo $"KMS: (if $kms_health.status == 'healthy' { '✓ Healthy' } else { '✗ Unhealthy' })"\n\n    # Orchestrator status\n    let orch_health = orch status\n    echo $"Orchestrator: (if $orch_health.health == 'healthy' { '✓ Healthy' } else { '✗ Unhealthy' })"\n    echo $"Active Tasks: ($orch_health.active_tasks)"\n    echo $"Failed Tasks: ($orch_health.failed_tasks)"\n\n    # Task summary\n    echo ""\n    echo "=== Running Tasks ==="\n    orch tasks --status running\n        | select name progress updated_at\n        | table\n\n    sleep 10sec\n}\n```\n\n---\n\n## Best Practices\n\n### When to Use Plugins vs HTTP\n\n**✅ Use Plugins When:**\n\n- Performance is critical (high-frequency operations)\n- Working in pipelines (Nushell data structures)\n- Need offline capability (KMS, orchestrator local ops)\n- Building automation scripts\n- CI/CD pipelines\n\n**Use HTTP When:**\n\n- Calling from external systems (not Nushell)\n- Need consistent REST API interface\n- Cross-language integration\n- Web UI backend\n\n### Performance Optimization\n\n**1. Batch Operations**\n\n```\n# ❌ Slow: Individual HTTP calls in loop\nls configs/*.yaml | each { |file|\n    http post http://localhost:9998/encrypt { data: (open $file.name) }\n}\n# Total: ~5 seconds (50 ms × 100)\n\n# ✅ Fast: Plugin in pipeline\nls configs/*.yaml | each { |file|\n    kms encrypt (open $file.name)\n}\n# Total: ~0.5 seconds (5 ms × 100)\n```\n\n**2. Parallel Processing**\n\n```\n# Process multiple operations in parallel\nls configs/*.yaml\n    | par-each { |file|\n        kms encrypt (open $file.name) | save $"encrypted/($file.name).enc"\n    }\n```\n\n**3. Caching Session State**\n\n```\n# Cache auth verification\nlet $auth_cache = auth verify\nif $auth_cache.active {\n    # Use cached result instead of repeated calls\n    echo $"Authenticated as ($auth_cache.user)"\n}\n```\n\n### Error Handling\n\n**Graceful Degradation:**\n\n```\n# Try plugin, fallback to HTTP if unavailable\ndef kms_encrypt [data: string] {\n    try {\n        kms encrypt $data\n    } catch {\n        http post http://localhost:9998/encrypt { data: $data } | get encrypted\n    }\n}\n```\n\n**Comprehensive Error Handling:**\n\n```\n# Handle all error cases\ndef safe_deployment [] {\n    # Check authentication\n    let auth_status = try {\n        auth verify\n    } catch {\n        echo "✗ Authentication failed, logging in..."\n        auth login admin\n        auth verify\n    }\n\n    # Check KMS health\n    let kms_health = try {\n        kms status\n    } catch {\n        error make { msg: "KMS unavailable, cannot proceed" }\n    }\n\n    # Validate workflow\n    let validation = try {\n        orch validate workflow.ncl --strict\n    } catch {\n        error make { msg: "Workflow validation failed" }\n    }\n\n    # Proceed if all checks pass\n    if $auth_status.active and $kms_health.status == "healthy" and $validation.valid {\n        echo "✓ All checks passed, deploying..."\n        provisioning cluster create production\n    }\n}\n```\n\n### Security Best Practices\n\n**1. Never Log Decrypted Data**\n\n```\n# ❌ BAD: Logs plaintext password\nlet password = kms decrypt $encrypted_password\necho $"Password: ($password)"  # Visible in logs!\n\n# ✅ GOOD: Use directly without logging\nlet password = kms decrypt $encrypted_password\npsql --dbname mydb --password $password  # Not logged\n```\n\n**2. Use Context (AAD) for Critical Data**\n\n```\n# Encrypt with context\nlet context = $"user=(whoami),env=production,date=(date now | format date "%Y-%m-%d")"\nkms encrypt $sensitive_data --context $context\n\n# Decrypt requires same context\nkms decrypt $encrypted --context $context\n```\n\n**3. Rotate Backup Codes**\n\n```\n# After using backup code, generate new set\nauth mfa verify --code ABCD-EFGH-IJKL\n# Warning: Backup code used\nauth mfa regenerate-backups\n# New backup codes generated\n```\n\n**4. Limit Token Lifetime**\n\n```\n# Check token expiration before long operations\nlet session = auth verify\nlet expires_in = (($session.expires_at | into datetime) - (date now))\nif $expires_in < 5 min {\n    echo "⚠️ Token expiring soon, re-authenticating..."\n    auth login $session.user\n}\n```\n\n---\n\n## Troubleshooting\n\n### Common Issues Across Plugins\n\n**"Plugin not found"**\n\n```\n# Check plugin registration\nplugin list | where name =~ "auth|kms|orch"\n\n# Re-register if missing\ncd provisioning/core/plugins/nushell-plugins\nplugin add target/release/nu_plugin_auth\nplugin add target/release/nu_plugin_kms\nplugin add target/release/nu_plugin_orchestrator\n\n# Restart Nushell\nexit\nnu\n```\n\n**"Plugin command failed"**\n\n```\n# Enable debug mode\n$env.RUST_LOG = "debug"\n\n# Run command again to see detailed errors\nkms encrypt "test"\n\n# Check plugin version compatibility\nplugin list | where name =~ "kms" | select name version\n```\n\n**"Permission denied"**\n\n```\n# Check plugin executable permissions\nls -l provisioning/core/plugins/nushell-plugins/target/release/nu_plugin_*\n# Should show: -rwxr-xr-x\n\n# Fix if needed\nchmod +x provisioning/core/plugins/nushell-plugins/target/release/nu_plugin_*\n```\n\n### Platform-Specific Issues\n\n**macOS Issues:**\n\n```\n# "cannot be opened because the developer cannot be verified"\nxattr -d com.apple.quarantine target/release/nu_plugin_auth\nxattr -d com.apple.quarantine target/release/nu_plugin_kms\nxattr -d com.apple.quarantine target/release/nu_plugin_orchestrator\n\n# Keychain access denied\n# System Preferences → Security & Privacy → Privacy → Full Disk Access\n# Add: /usr/local/bin/nu\n```\n\n**Linux Issues:**\n\n```\n# Keyring service not running\nsystemctl --user status gnome-keyring-daemon\nsystemctl --user start gnome-keyring-daemon\n\n# Missing dependencies\nsudo apt install libssl-dev pkg-config  # Ubuntu/Debian\nsudo dnf install openssl-devel          # Fedora\n```\n\n**Windows Issues:**\n\n```\n# Credential Manager access denied\n# Control Panel → User Accounts → Credential Manager\n# Ensure Windows Credential Manager service is running\n\n# Missing Visual C++ runtime\n# Download from: https://aka.ms/vs/17/release/vc_redist.x64.exe\n```\n\n### Debugging Techniques\n\n**Enable Verbose Logging:**\n\n```\n# Set log level\n$env.RUST_LOG = "debug,nu_plugin_auth=trace"\n\n# Run command\nauth login admin\n\n# Check logs\n```\n\n**Test Plugin Directly:**\n\n```\n# Test plugin communication (advanced)\necho '{"Call": [0, {"name": "auth", "call": "login", "args": ["admin", "password"]}]}' \\n    | target/release/nu_plugin_auth\n```\n\n**Check Plugin Health:**\n\n```\n# Test each plugin\nauth --help       # Should show auth commands\nkms --help        # Should show kms commands\norch --help       # Should show orch commands\n\n# Test functionality\nauth verify       # Should return session status\nkms status        # Should return backend status\norch status       # Should return orchestrator status\n```\n\n---\n\n## Migration Guide\n\n### Migrating from HTTP to Plugin-Based\n\n**Phase 1: Install Plugins (No Breaking Changes)**\n\n```\n# Build and register plugins\ncd provisioning/core/plugins/nushell-plugins\ncargo build --release --all\nplugin add target/release/nu_plugin_auth\nplugin add target/release/nu_plugin_kms\nplugin add target/release/nu_plugin_orchestrator\n\n# Verify HTTP still works\nhttp get http://localhost:9090/health\n```\n\n**Phase 2: Update Scripts Incrementally**\n\n```\n# Before (HTTP)\ndef encrypt_config [file: string] {\n    let data = open $file\n    let result = http post http://localhost:9998/encrypt { data: $data }\n    $result.encrypted | save $"($file).enc"\n}\n\n# After (Plugin with fallback)\ndef encrypt_config [file: string] {\n    let data = open $file\n    let encrypted = try {\n        kms encrypt $data --backend rustyvault\n    } catch {\n        # Fallback to HTTP if plugin unavailable\n        (http post http://localhost:9998/encrypt { data: $data }).encrypted\n    }\n    $encrypted | save $"($file).enc"\n}\n```\n\n**Phase 3: Test Migration**\n\n```\n# Run side-by-side comparison\ndef test_migration [] {\n    let test_data = "test secret data"\n\n    # Plugin approach\n    let start_plugin = date now\n    let plugin_result = kms encrypt $test_data\n    let plugin_time = ((date now) - $start_plugin)\n\n    # HTTP approach\n    let start_http = date now\n    let http_result = (http post http://localhost:9998/encrypt { data: $test_data }).encrypted\n    let http_time = ((date now) - $start_http)\n\n    echo $"Plugin: ($plugin_time)ms"\n    echo $"HTTP: ($http_time)ms"\n    echo $"Speedup: (($http_time / $plugin_time))x"\n}\n```\n\n**Phase 4: Gradual Rollout**\n\n```\n# Use feature flag for controlled rollout\n$env.USE_PLUGINS = true\n\ndef encrypt_with_flag [data: string] {\n    if $env.USE_PLUGINS {\n        kms encrypt $data\n    } else {\n        (http post http://localhost:9998/encrypt { data: $data }).encrypted\n    }\n}\n```\n\n**Phase 5: Full Migration**\n\n```\n# Replace all HTTP calls with plugin calls\n# Remove fallback logic once stable\ndef encrypt_config [file: string] {\n    let data = open $file\n    kms encrypt $data --backend rustyvault | save $"($file).enc"\n}\n```\n\n### Rollback Strategy\n\n```\n# If issues arise, quickly rollback\ndef rollback_to_http [] {\n    # Remove plugin registrations\n    plugin rm nu_plugin_auth\n    plugin rm nu_plugin_kms\n    plugin rm nu_plugin_orchestrator\n\n    # Restart Nushell\n    exec nu\n}\n```\n\n---\n\n## Advanced Configuration\n\n### Custom Plugin Paths\n\n```\n# ~/.config/nushell/config.nu\n$env.PLUGIN_PATH = "/opt/provisioning/plugins"\n\n# Register from custom location\nplugin add $"($env.PLUGIN_PATH)/nu_plugin_auth"\nplugin add $"($env.PLUGIN_PATH)/nu_plugin_kms"\nplugin add $"($env.PLUGIN_PATH)/nu_plugin_orchestrator"\n```\n\n### Environment-Specific Configuration\n\n```\n# ~/.config/nushell/env.nu\n\n# Development environment\nif ($env.ENV? == "dev") {\n    $env.RUSTYVAULT_ADDR = "http://localhost:8200"\n    $env.CONTROL_CENTER_URL = "http://localhost:3000"\n}\n\n# Staging environment\nif ($env.ENV? == "staging") {\n    $env.RUSTYVAULT_ADDR = "https://vault-staging.example.com"\n    $env.CONTROL_CENTER_URL = "https://control-staging.example.com"\n}\n\n# Production environment\nif ($env.ENV? == "prod") {\n    $env.RUSTYVAULT_ADDR = "https://vault.example.com"\n    $env.CONTROL_CENTER_URL = "https://control.example.com"\n}\n```\n\n### Plugin Aliases\n\n```\n# ~/.config/nushell/config.nu\n\n# Auth shortcuts\nalias login = auth login\nalias logout = auth logout\nalias whoami = auth verify | get user\n\n# KMS shortcuts\nalias encrypt = kms encrypt\nalias decrypt = kms decrypt\n\n# Orchestrator shortcuts\nalias status = orch status\nalias tasks = orch tasks\nalias validate = orch validate\n```\n\n### Custom Commands\n\n```\n# ~/.config/nushell/custom_commands.nu\n\n# Encrypt all files in directory\ndef encrypt-dir [dir: string] {\n    ls $"($dir)/**/*" | where type == file | each { |file|\n        kms encrypt (open $file.name) | save $"($file.name).enc"\n        echo $"✓ Encrypted ($file.name)"\n    }\n}\n\n# Decrypt all files in directory\ndef decrypt-dir [dir: string] {\n    ls $"($dir)/**/*.enc" | each { |file|\n        kms decrypt (open $file.name)\n            | save (echo $file.name | str replace '.enc' '')\n        echo $"✓ Decrypted ($file.name)"\n    }\n}\n\n# Monitor deployments\ndef watch-deployments [] {\n    while true {\n        clear\n        echo "=== Active Deployments ==="\n        orch tasks --status running | table\n        sleep 5sec\n    }\n}\n```\n\n---\n\n## Security Considerations\n\n### Threat Model\n\n**What Plugins Protect Against:**\n\n- ✅ Network eavesdropping (no HTTP for KMS/orch)\n- ✅ Token theft from files (keyring storage)\n- ✅ Credential exposure in logs (prompt-based input)\n- ✅ Man-in-the-middle attacks (local file access)\n\n**What Plugins Don't Protect Against:**\n\n- ❌ Memory dumping (decrypted data in RAM)\n- ❌ Malicious plugins (trust registry only)\n- ❌ Compromised OS keyring\n- ❌ Physical access to machine\n\n### Secure Deployment\n\n**1. Verify Plugin Integrity**\n\n```\n# Check plugin signatures (if available)\nsha256sum target/release/nu_plugin_auth\n# Compare with published checksums\n\n# Build from trusted source\ngit clone https://github.com/provisioning-platform/plugins\ncd plugins\ncargo build --release --all\n```\n\n**2. Restrict Plugin Access**\n\n```\n# Set plugin permissions (only owner can execute)\nchmod 700 target/release/nu_plugin_*\n\n# Store in protected directory\nsudo mkdir -p /opt/provisioning/plugins\nsudo chown $(whoami):$(whoami) /opt/provisioning/plugins\nsudo chmod 755 /opt/provisioning/plugins\nmv target/release/nu_plugin_* /opt/provisioning/plugins/\n```\n\n**3. Audit Plugin Usage**\n\n```\n# Log plugin calls (for compliance)\ndef logged_encrypt [data: string] {\n    let timestamp = date now\n    let result = kms encrypt $data\n    { timestamp: $timestamp, action: "encrypt" } | save --append audit.log\n    $result\n}\n```\n\n**4. Rotate Credentials Regularly**\n\n```\n# Weekly credential rotation script\ndef rotate_credentials [] {\n    # Re-authenticate\n    auth logout\n    auth login admin\n\n    # Rotate KMS keys (if supported)\n    kms rotate-key --key provisioning-main\n\n    # Update encrypted secrets\n    ls secrets/*.enc | each { |file|\n        let plain = kms decrypt (open $file.name)\n        kms encrypt $plain | save $file.name\n    }\n}\n```\n\n---\n\n## FAQ\n\n**Q: Can I use plugins without RustyVault/Age installed?**\n\nA: Yes, authentication and orchestrator plugins work independently. KMS plugin requires at least one backend configured (Age is easiest for local\ndev).\n\n**Q: Do plugins work in CI/CD pipelines?**\n\nA: Yes, plugins work great in CI/CD. For headless environments (no keyring), use environment variables for auth or file-based tokens.\n\n```\n# CI/CD example\nexport CONTROL_CENTER_TOKEN="jwt-token-here"\nkms encrypt "data" --backend age\n```\n\n**Q: How do I update plugins?**\n\nA: Rebuild and re-register:\n\n```\ncd provisioning/core/plugins/nushell-plugins\ngit pull\ncargo build --release --all\nplugin add --force target/release/nu_plugin_auth\nplugin add --force target/release/nu_plugin_kms\nplugin add --force target/release/nu_plugin_orchestrator\n```\n\n**Q: Can I use multiple KMS backends simultaneously?**\n\nA: Yes, specify `--backend` for each operation:\n\n```\nkms encrypt "data1" --backend rustyvault\nkms encrypt "data2" --backend age\nkms encrypt "data3" --backend aws\n```\n\n**Q: What happens if a plugin crashes?**\n\nA: Nushell isolates plugin crashes. The command fails with an error, but Nushell continues running. Check logs with `$env.RUST_LOG = "debug"`.\n\n**Q: Are plugins compatible with older Nushell versions?**\n\nA: Plugins require Nushell 0.107.1+. For older versions, use HTTP API.\n\n**Q: How do I backup MFA enrollment?**\n\nA: Save backup codes securely (password manager, encrypted file). QR code can be re-scanned from the same secret.\n\n```\n# Save backup codes\nauth mfa enroll totp | save mfa-backup-codes.txt\nkms encrypt (open mfa-backup-codes.txt) | save mfa-backup-codes.enc\nrm mfa-backup-codes.txt\n```\n\n**Q: Can plugins work offline?**\n\nA: Partially:\n\n- ✅ `kms` with Age backend (fully offline)\n- ✅ `orch` status/tasks (reads local files)\n- ❌ `auth` (requires control center)\n- ❌ `kms` with RustyVault/AWS/Vault (requires network)\n\n**Q: How do I troubleshoot plugin performance?**\n\nA: Use Nushell's timing:\n\n```\ntimeit { kms encrypt "data" }\n# 5 ms 123μs 456 ns\n\ntimeit { http post http://localhost:9998/encrypt { data: "data" } }\n# 52 ms 789μs 123 ns\n```\n\n---\n\n## Related Documentation\n\n- **Security System**: `/Users/Akasha/project-provisioning/docs/architecture/adr-009-security-system-complete.md`\n- **JWT Authentication**: `/Users/Akasha/project-provisioning/docs/architecture/JWT_AUTH_IMPLEMENTATION.md`\n- **Config Encryption**: `/Users/Akasha/project-provisioning/docs/user/CONFIG_ENCRYPTION_GUIDE.md`\n- **RustyVault Integration**: `/Users/Akasha/project-provisioning/RUSTYVAULT_INTEGRATION_SUMMARY.md`\n- **MFA Implementation**: `/Users/Akasha/project-provisioning/docs/architecture/MFA_IMPLEMENTATION_SUMMARY.md`\n- **Nushell Plugins Reference**: `/Users/Akasha/project-provisioning/docs/user/NUSHELL_PLUGINS_GUIDE.md`\n\n---\n\n**Version**: 1.0.0\n**Maintained By**: Platform Team\n**Last Updated**: 2025-10-09\n**Feedback**: Open an issue or contact <platform-team@example.com>
