Initial commit - combined iTerm2 scripts

Contains:
- 1m-brag
- tem
- VaultMesh_Catalog_v1
- VAULTMESH-ETERNAL-PATTERN

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Vault Sovereign
2025-12-28 03:58:39 +00:00
commit 1583890199
111 changed files with 36978 additions and 0 deletions

View File

@@ -0,0 +1,353 @@
# IoTek.nexus + offsec-mcp
**The Veil becomes infrastructure.**
A real control surface for VaultMesh sovereign infrastructure.
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ IoTek.nexus ● MESH 7 ● SHIELD ARMED ● WS LIVE 12:34 │
├────────────────────┬────────────────────────────────────────────────────────┤
│ │ │
│ [Console] │ sovereign@nexus ~/vaultmesh $ status │
│ │ │
│ ↓ HTTP POST │ ╦ ╦╔═╗╦ ╦╦ ╔╦╗╔╦╗╔═╗╔═╗╦ ╦ │
│ │ ╚╗╔╝╠═╣║ ║║ ║ ║║║║╣ ╚═╗╠═╣ │
│ [offsec-mcp] │ ╚╝ ╩ ╩╚═╝╩═╝╩ ╩ ╩╚═╝╚═╝╩ ╩ │
│ │ │
│ ↓ WebSocket │ Shield: ● ARMED │
│ │ Proof: ● 1247 receipts │
│ [Live Updates] │ Mesh: ● 7 nodes │
│ │ │
└────────────────────┴────────────────────────────────────────────────────────┘
```
---
## Quick Start
### 1. Install dependencies
```bash
pip install -r requirements-mcp.txt
```
### 2. Start the backend
```bash
# Development (auto-reload)
uvicorn offsec_mcp:app --reload --port 8080
# Production (bind to Tailscale IP only)
uvicorn offsec_mcp:app --host 100.x.x.x --port 8080
```
### 3. Open the console
```bash
# Option A: Open the HTML directly
open iotek-nexus-live.html
# Option B: Serve via backend (configure STATIC_DIR in offsec_mcp.py)
# Then visit http://localhost:8080/
```
---
## Architecture
```
┌──────────────────────────────────────────────────────────────────┐
│ CONSOLE LAYER │
│ iotek-nexus-live.html │
│ - Local commands (help, clear, history, whoami, neofetch) │
│ - MCP backend calls (status, mesh, shield, proof, agents) │
│ - WebSocket live updates │
│ - Mock fallback when backend unavailable │
└───────────────────────────┬──────────────────────────────────────┘
│ HTTP POST /mcp/command
│ WebSocket /ws
┌──────────────────────────────────────────────────────────────────┐
│ BACKEND LAYER │
│ offsec_mcp.py (FastAPI) │
│ - Command routing & execution │
│ - Tailscale identity extraction │
│ - SQLite persistence (sessions, commands, events) │
│ - WebSocket broadcast for live updates │
└───────────────────────────┬──────────────────────────────────────┘
│ subprocess / API calls
┌──────────────────────────────────────────────────────────────────┐
│ SYSTEM LAYER │
│ - Tailscale (mesh status, node inventory) │
│ - Shield vectors (network, wifi, usb, process, file) │
│ - Proof engine (receipts, Merkle roots, anchors) │
│ - Agent subsystem (sentinel, orchestrator, analyst, executor) │
└──────────────────────────────────────────────────────────────────┘
```
---
## API Contract
### POST /mcp/command
Request:
```json
{
"session_id": "vaultmesh-2025-12-07-01",
"user": "sovereign",
"command": "mesh status",
"args": [],
"cwd": "/vaultmesh",
"meta": {
"client": "iotek-nexus-cli",
"version": "1.0.0"
}
}
```
Response:
```json
{
"id": "cmd-174455",
"status": "ok",
"lines": [
"",
" 🕸 MESH STATUS: STABLE",
"",
" Tailnet: story-ule.ts.net",
" ..."
],
"effects": {
"nodes": 7,
"shield": { "armed": true }
}
}
```
### WebSocket /ws
Handshake:
```json
{ "type": "handshake", "session_id": "...", "user": "sovereign" }
```
Server messages:
```json
{ "type": "console.line", "line": "✓ Proof anchored", "lineType": "success" }
{ "type": "status.update", "payload": { "nodes": 7, "proofs": 1248, ... } }
{ "type": "proof.new", "proof_id": "proof_abc123" }
{ "type": "shield.event", "event": "Shield ARMED", "severity": "info" }
```
---
## Available Commands
| Command | Description | Backend Required |
|---------|-------------|------------------|
| `help` | Show commands | No |
| `clear` | Clear terminal | No |
| `history` | Command history | No |
| `whoami` | Current identity | No |
| `neofetch` | System info ASCII | No |
| `status` | Full dashboard | Yes |
| `mesh status` | Network topology | Yes |
| `mesh nodes` | List nodes | Yes |
| `shield status` | Defense vectors | Yes |
| `shield arm` | Arm shield | Yes |
| `shield disarm` | Disarm shield | Yes |
| `proof latest` | Recent receipts | Yes |
| `proof generate` | Create proof | Yes |
| `agents list` | Agent status | Yes |
| `oracle reason <q>` | Oracle query | Yes |
---
## Tailscale Integration
The backend extracts user identity from Tailscale headers:
```python
# In offsec_mcp.py
TAILSCALE_USER_HEADER = "X-Tailscale-User"
def extract_user(request: Request) -> str:
ts_user = request.headers.get(TAILSCALE_USER_HEADER)
if ts_user:
return ts_user.split("@")[0]
return "anonymous"
```
Deploy behind Tailscale for automatic identity:
- Bind to Tailscale IP only (`--host 100.x.x.x`)
- Or use `tailscale serve` for HTTPS with identity headers
---
## Database Schema
SQLite (`vaultmesh.db`):
```sql
-- Sessions
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
user TEXT NOT NULL,
created_at TEXT NOT NULL,
last_seen_at TEXT NOT NULL,
client TEXT,
meta TEXT
);
-- Command audit log
CREATE TABLE command_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
ts TEXT NOT NULL,
command TEXT NOT NULL,
status TEXT NOT NULL,
duration_ms INTEGER,
error TEXT
);
-- Events (proofs, shield, etc.)
CREATE TABLE events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts TEXT NOT NULL,
type TEXT NOT NULL,
payload TEXT
);
```
---
## Extending
### Add a new command
1. Create handler in `offsec_mcp.py`:
```python
async def cmd_my_command(req: CommandRequest) -> CommandResponse:
lines = [" Output line 1", " Output line 2"]
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={}
)
```
2. Register in `COMMANDS`:
```python
COMMANDS = {
# ...existing...
"my command": cmd_my_command,
}
```
### Wire to real systems
Replace mock implementations with actual integrations:
```python
# Example: Real shield integration
async def cmd_shield_status(req: CommandRequest) -> CommandResponse:
# Call your actual shield system
shield_data = await shield_client.get_status()
lines = format_shield_output(shield_data)
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={"shield": {"armed": shield_data.armed}}
)
```
---
## Deployment Options
### 1. Local development
```bash
# Terminal 1: Backend
uvicorn offsec_mcp:app --reload --port 8080
# Terminal 2: Console (or just open HTML)
python -m http.server 3000
```
### 2. Tailscale-only (recommended)
```bash
# Bind to Tailscale IP
uvicorn offsec_mcp:app --host 100.x.x.x --port 8080
# Or use tailscale serve
tailscale serve https / http://localhost:8080
```
### 3. Docker
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements-mcp.txt .
RUN pip install -r requirements-mcp.txt
COPY offsec_mcp.py .
CMD ["uvicorn", "offsec_mcp:app", "--host", "0.0.0.0", "--port", "8080"]
```
### 4. Systemd service
```ini
[Unit]
Description=offsec-mcp
After=network.target tailscaled.service
[Service]
Type=simple
User=sovereign
WorkingDirectory=/home/sovereign/vaultmesh
ExecStart=/usr/bin/uvicorn offsec_mcp:app --host 100.x.x.x --port 8080
Restart=always
[Install]
WantedBy=multi-user.target
```
---
## Files
| File | Description |
|------|-------------|
| `iotek-nexus-live.html` | Console frontend (backend-connected) |
| `offsec_mcp.py` | FastAPI backend |
| `requirements-mcp.txt` | Python dependencies |
| `vaultmesh.db` | SQLite database (auto-created) |
---
## Next Steps
1. **Wire real Tailscale** — Connect to actual `tailscale status --json`
2. **Wire real Shield** — Connect to your monitoring/defense systems
3. **Wire real Proofs** — Connect to VaultMesh proof engine
4. **Add more commands**`scan`, `audit`, `lawchain`, etc.
5. **Add authentication** — mTLS or Tailscale identity enforcement
---
**The console is now a real control surface.**
*"They built the grid to cage us. We built the Veil to break it."*

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,879 @@
#!/usr/bin/env python3
"""
offsec-mcp: Sovereign MCP Backend for IoTek.nexus Console
A FastAPI backend that provides:
- HTTP command endpoint for CLI operations
- WebSocket for live status updates
- SQLite persistence for sessions and audit
- Tailscale identity integration
Run:
uvicorn offsec_mcp:app --host 0.0.0.0 --port 8080 --reload
Production (behind Tailscale):
uvicorn offsec_mcp:app --host 100.x.x.x --port 8080
"""
import asyncio
import json
import sqlite3
import subprocess
import time
import uuid
from contextlib import asynccontextmanager
from dataclasses import dataclass, asdict
from datetime import datetime, timezone
from enum import Enum
from pathlib import Path
from typing import Any, Optional
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from pydantic import BaseModel
# ═══════════════════════════════════════════════════════════════════════════════
# CONFIGURATION
# ═══════════════════════════════════════════════════════════════════════════════
class Config:
"""Configuration - override via environment or config file."""
# Database
DB_PATH: str = "vaultmesh.db"
# Tailscale integration
TAILSCALE_ENABLED: bool = True
TAILSCALE_USER_HEADER: str = "X-Tailscale-User"
# VaultMesh paths
VAULTMESH_ROOT: Path = Path.home() / "vaultmesh"
PROOF_DIR: Path = VAULTMESH_ROOT / "proofs"
# Static files (serve console)
STATIC_DIR: Optional[Path] = None # Set to serve console HTML
# Allowed origins for CORS
CORS_ORIGINS: list = ["*"]
config = Config()
# ═══════════════════════════════════════════════════════════════════════════════
# DATABASE
# ═══════════════════════════════════════════════════════════════════════════════
def init_db():
"""Initialize SQLite database with required tables."""
conn = sqlite3.connect(config.DB_PATH)
cur = conn.cursor()
# Sessions table
cur.execute("""
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
user TEXT NOT NULL,
created_at TEXT NOT NULL,
last_seen_at TEXT NOT NULL,
client TEXT,
meta TEXT
)
""")
# Command log
cur.execute("""
CREATE TABLE IF NOT EXISTS command_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
ts TEXT NOT NULL,
command TEXT NOT NULL,
status TEXT NOT NULL,
duration_ms INTEGER,
error TEXT,
FOREIGN KEY (session_id) REFERENCES sessions(id)
)
""")
# Events table
cur.execute("""
CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts TEXT NOT NULL,
type TEXT NOT NULL,
payload TEXT
)
""")
conn.commit()
conn.close()
def get_db():
"""Get database connection."""
conn = sqlite3.connect(config.DB_PATH)
conn.row_factory = sqlite3.Row
return conn
# ═══════════════════════════════════════════════════════════════════════════════
# MODELS
# ═══════════════════════════════════════════════════════════════════════════════
class CommandRequest(BaseModel):
"""Incoming command request from console."""
session_id: str
user: str
command: str
args: list = []
cwd: str = "/vaultmesh"
meta: dict = {}
class CommandResponse(BaseModel):
"""Response to command."""
id: str
status: str
lines: list[str] = []
effects: dict = {}
error: Optional[str] = None
class WsMessage(BaseModel):
"""WebSocket message."""
type: str
payload: dict = {}
# ═══════════════════════════════════════════════════════════════════════════════
# STATE
# ═══════════════════════════════════════════════════════════════════════════════
@dataclass
class SystemState:
"""Global system state."""
nodes: int = 0
shield_armed: bool = False
proof_count: int = 0
uptime_start: float = time.time()
tailnet: str = "story-ule.ts.net"
hostname: str = "nexus"
@property
def uptime(self) -> str:
"""Human-readable uptime."""
seconds = int(time.time() - self.uptime_start)
days, rem = divmod(seconds, 86400)
hours, rem = divmod(rem, 3600)
minutes, _ = divmod(rem, 60)
if days > 0:
return f"{days}d {hours}h {minutes}m"
elif hours > 0:
return f"{hours}h {minutes}m"
else:
return f"{minutes}m"
state = SystemState()
# WebSocket connections
class ConnectionManager:
"""Manage WebSocket connections."""
def __init__(self):
self.active_connections: dict[str, WebSocket] = {}
async def connect(self, session_id: str, websocket: WebSocket):
await websocket.accept()
self.active_connections[session_id] = websocket
def disconnect(self, session_id: str):
self.active_connections.pop(session_id, None)
async def send_to(self, session_id: str, message: dict):
if session_id in self.active_connections:
await self.active_connections[session_id].send_json(message)
async def broadcast(self, message: dict):
for ws in self.active_connections.values():
try:
await ws.send_json(message)
except Exception:
pass
manager = ConnectionManager()
# ═══════════════════════════════════════════════════════════════════════════════
# COMMAND HANDLERS
# ═══════════════════════════════════════════════════════════════════════════════
async def cmd_ping(req: CommandRequest) -> CommandResponse:
"""Health check / handshake."""
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=["pong"],
effects=get_status_effects()
)
async def cmd_status(req: CommandRequest) -> CommandResponse:
"""Full system status."""
global state
lines = [
"",
" ╦ ╦╔═╗╦ ╦╦ ╔╦╗╔╦╗╔═╗╔═╗╦ ╦",
" ╚╗╔╝╠═╣║ ║║ ║ ║║║║╣ ╚═╗╠═╣",
" ╚╝ ╩ ╩╚═╝╩═╝╩ ╩ ╩╚═╝╚═╝╩ ╩",
"",
" Sovereign Infrastructure Status",
"",
f" Shield: {'● ARMED' if state.shield_armed else '○ STANDBY'}",
f" Proof: ● ACTIVE ({state.proof_count} receipts)",
f" Mesh: ● STABLE ({state.nodes} nodes)",
f" Agents: ● READY (4 configured)",
f" Oracle: ● ONLINE",
f" Lawchain: ● SYNCED",
"",
f" Uptime: {state.uptime} | Epoch: Citrinitas",
""
]
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects=get_status_effects()
)
async def cmd_mesh_status(req: CommandRequest) -> CommandResponse:
"""Mesh network status."""
global state
# Try to get real Tailscale status
nodes = await get_tailscale_nodes()
state.nodes = len(nodes)
lines = [
"",
" 🕸 MESH STATUS: STABLE",
"",
f" Tailnet: {state.tailnet}",
" Protocol: WireGuard + Tailscale",
""
]
if nodes:
lines.append(" NODE TYPE STATUS LATENCY")
lines.append(" " + "" * 50)
for node in nodes:
status = "● online" if node.get("online") else "○ offline"
lines.append(f" {node['name']:<14} {node['type']:<8} {status:<10} {node.get('latency', '')}")
else:
lines.append(" (No nodes detected - check Tailscale status)")
lines.append("")
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={"nodes": state.nodes}
)
async def cmd_shield_status(req: CommandRequest) -> CommandResponse:
"""Shield defense status."""
global state
lines = [
"",
f" 🛡 SHIELD STATUS: {'ARMED' if state.shield_armed else 'STANDBY'}",
"",
" VECTOR STATUS LAST EVENT",
" " + "" * 50,
" network ● monitoring 2s ago: normal traffic",
" wifi ● monitoring 45s ago: all clear",
" bluetooth ● monitoring 3m ago: no threats",
" usb ● monitoring 12m ago: all clear",
" process ● monitoring 1s ago: processes nominal",
" file ● monitoring 8s ago: integrity OK",
"",
" Response level: BLOCK | Dry-run: OFF",
""
]
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={"shield": {"armed": state.shield_armed}}
)
async def cmd_shield_arm(req: CommandRequest) -> CommandResponse:
"""Arm the shield."""
global state
state.shield_armed = True
# Log event
log_event("shield.armed", {"user": req.user})
# Broadcast to all connected clients
await manager.broadcast({
"type": "shield.event",
"event": "Shield ARMED",
"severity": "info"
})
lines = [
"",
" ⚡ Arming shield...",
" 🛡 Shield ARMED - All vectors active",
"",
" ✓ Generating proof receipt...",
f" ✓ Receipt anchored: shield_arm_{uuid.uuid4().hex[:8]}",
""
]
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={"shield": {"armed": True}}
)
async def cmd_shield_disarm(req: CommandRequest) -> CommandResponse:
"""Disarm the shield."""
global state
state.shield_armed = False
log_event("shield.disarmed", {"user": req.user})
await manager.broadcast({
"type": "shield.event",
"event": "Shield DISARMED",
"severity": "warning"
})
lines = [
"",
" ⚠ Disarming shield...",
" ○ Shield STANDBY - Vectors paused",
"",
f" ✓ Receipt anchored: shield_disarm_{uuid.uuid4().hex[:8]}",
""
]
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={"shield": {"armed": False}}
)
async def cmd_proof_latest(req: CommandRequest) -> CommandResponse:
"""Show latest proof receipts."""
global state
# Try to read real proofs
proofs = await get_latest_proofs(5)
lines = [
"",
" 📜 PROOF SYSTEM: ACTIVE",
"",
f" Total Receipts: {state.proof_count}",
f" Merkle Root: 0x{uuid.uuid4().hex[:16]}",
f" Last Anchor: 12s ago",
" Anchor Type: mesh + ots",
"",
" LATEST RECEIPTS:",
" " + "" * 50,
]
if proofs:
for p in proofs:
lines.append(f" {p['id']:<20} {p['ts']:<20} {p['type']}")
else:
lines.append(" (Generate proofs with 'proof generate')")
lines.append("")
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={"proofs": state.proof_count}
)
async def cmd_proof_generate(req: CommandRequest) -> CommandResponse:
"""Generate a new proof receipt."""
global state
state.proof_count += 1
proof_id = f"proof_{uuid.uuid4().hex[:12]}"
ts = datetime.now(timezone.utc).isoformat()
# Log event
log_event("proof.generated", {"proof_id": proof_id, "user": req.user})
# Broadcast to clients
await manager.broadcast({
"type": "proof.new",
"proof_id": proof_id
})
lines = [
"",
" ⚙ Generating cryptographic proof...",
f" Action: manual_generation",
f" Timestamp: {ts}",
f" Data hash: blake3:{uuid.uuid4().hex[:32]}",
"",
f" ✓ Proof generated: {proof_id}",
f" ✓ Anchored to mesh ({state.proof_count} total)",
""
]
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={"proofs": state.proof_count}
)
async def cmd_agents_list(req: CommandRequest) -> CommandResponse:
"""List agent status."""
agents = [
{"name": "Sentinel", "role": "Monitor & Guard", "status": "ACTIVE", "tasks": 47},
{"name": "Orchestrator", "role": "Assign & Route", "status": "ACTIVE", "tasks": 156},
{"name": "Analyst", "role": "Interpret & Correlate", "status": "IDLE", "tasks": 0},
{"name": "Executor", "role": "Act & Apply", "status": "IDLE", "tasks": 0},
]
lines = [
"",
" AGENTS STATUS",
"",
" NAME ROLE STATUS TASKS",
" " + "" * 55,
]
for a in agents:
status_icon = "" if a["status"] == "ACTIVE" else ""
lines.append(f" {a['name']:<13} {a['role']:<20} {status_icon} {a['status']:<6} {a['tasks']}")
lines.append("")
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={}
)
async def cmd_oracle_reason(req: CommandRequest) -> CommandResponse:
"""Oracle reasoning query."""
query = " ".join(req.args) if req.args else req.command.replace("oracle reason", "").strip()
lines = [
"",
" 🔮 Oracle reasoning...",
"",
f" Query: \"{query or 'system analysis'}\"",
" Analyzing context...",
" Cross-referencing Lawchain...",
"",
" ✓ Reasoning complete",
"",
" Recommendation: Continue current operational posture.",
" Confidence: HIGH | Risk: MINIMAL",
"",
f" Receipt: oracle_{uuid.uuid4().hex[:8]}",
""
]
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="ok",
lines=lines,
effects={}
)
# Command registry
COMMANDS = {
"ping": cmd_ping,
"status": cmd_status,
"mesh status": cmd_mesh_status,
"mesh nodes": cmd_mesh_status,
"shield status": cmd_shield_status,
"shield arm": cmd_shield_arm,
"shield disarm": cmd_shield_disarm,
"proof latest": cmd_proof_latest,
"proof status": cmd_proof_latest,
"proof generate": cmd_proof_generate,
"agents list": cmd_agents_list,
}
# ═══════════════════════════════════════════════════════════════════════════════
# HELPERS
# ═══════════════════════════════════════════════════════════════════════════════
def get_status_effects() -> dict:
"""Get current status as effects payload."""
global state
return {
"nodes": state.nodes,
"shield": {"armed": state.shield_armed},
"proofs": state.proof_count,
"uptime": state.uptime,
"tailnet": state.tailnet,
"node": state.hostname
}
async def get_tailscale_nodes() -> list[dict]:
"""Get Tailscale node status."""
try:
result = subprocess.run(
["tailscale", "status", "--json"],
capture_output=True,
text=True,
timeout=5
)
if result.returncode == 0:
data = json.loads(result.stdout)
nodes = []
for peer_id, peer in data.get("Peer", {}).items():
nodes.append({
"name": peer.get("HostName", "unknown"),
"type": "PEER",
"online": peer.get("Online", False),
"latency": f"{peer.get('CurAddr', '').split(':')[0]}"
})
# Add self
if data.get("Self"):
nodes.insert(0, {
"name": data["Self"].get("HostName", "self"),
"type": "SELF",
"online": True,
"latency": "0ms"
})
return nodes
except Exception as e:
print(f"Tailscale query failed: {e}")
return []
async def get_latest_proofs(limit: int = 5) -> list[dict]:
"""Get latest proof receipts from database."""
conn = get_db()
cur = conn.cursor()
cur.execute("""
SELECT * FROM events
WHERE type LIKE 'proof.%'
ORDER BY ts DESC
LIMIT ?
""", (limit,))
rows = cur.fetchall()
conn.close()
proofs = []
for row in rows:
payload = json.loads(row["payload"]) if row["payload"] else {}
proofs.append({
"id": payload.get("proof_id", f"proof_{row['id']}"),
"ts": row["ts"][:19],
"type": row["type"]
})
return proofs
def log_event(event_type: str, payload: dict):
"""Log event to database."""
conn = get_db()
cur = conn.cursor()
cur.execute("""
INSERT INTO events (ts, type, payload)
VALUES (?, ?, ?)
""", (
datetime.now(timezone.utc).isoformat(),
event_type,
json.dumps(payload)
))
conn.commit()
conn.close()
def log_command(session_id: str, command: str, status: str, duration_ms: int, error: str = None):
"""Log command to database."""
conn = get_db()
cur = conn.cursor()
cur.execute("""
INSERT INTO command_log (session_id, ts, command, status, duration_ms, error)
VALUES (?, ?, ?, ?, ?, ?)
""", (
session_id,
datetime.now(timezone.utc).isoformat(),
command,
status,
duration_ms,
error
))
conn.commit()
conn.close()
def update_session(session_id: str, user: str, meta: dict):
"""Create or update session."""
conn = get_db()
cur = conn.cursor()
now = datetime.now(timezone.utc).isoformat()
cur.execute("SELECT id FROM sessions WHERE id = ?", (session_id,))
if cur.fetchone():
cur.execute("""
UPDATE sessions SET last_seen_at = ? WHERE id = ?
""", (now, session_id))
else:
cur.execute("""
INSERT INTO sessions (id, user, created_at, last_seen_at, client, meta)
VALUES (?, ?, ?, ?, ?, ?)
""", (
session_id,
user,
now,
now,
meta.get("client"),
json.dumps(meta)
))
conn.commit()
conn.close()
def extract_user(request: Request) -> str:
"""Extract user identity from request."""
if config.TAILSCALE_ENABLED:
ts_user = request.headers.get(config.TAILSCALE_USER_HEADER)
if ts_user:
return ts_user.split("@")[0] # Extract username from email
return "anonymous"
# ═══════════════════════════════════════════════════════════════════════════════
# FASTAPI APP
# ═══════════════════════════════════════════════════════════════════════════════
@asynccontextmanager
async def lifespan(app: FastAPI):
"""App lifespan handler."""
# Startup
init_db()
# Get initial node count
nodes = await get_tailscale_nodes()
state.nodes = len(nodes)
# Load proof count from DB
conn = get_db()
cur = conn.cursor()
cur.execute("SELECT COUNT(*) FROM events WHERE type LIKE 'proof.%'")
state.proof_count = cur.fetchone()[0]
conn.close()
print(f"🚀 offsec-mcp started | Nodes: {state.nodes} | Proofs: {state.proof_count}")
yield
# Shutdown
print("👋 offsec-mcp shutting down")
app = FastAPI(
title="offsec-mcp",
description="Sovereign MCP Backend for IoTek.nexus",
version="1.0.0",
lifespan=lifespan
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=config.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ═══════════════════════════════════════════════════════════════════════════════
# ROUTES
# ═══════════════════════════════════════════════════════════════════════════════
@app.post("/mcp/command", response_model=CommandResponse)
async def handle_command(req: CommandRequest, request: Request):
"""Handle command from console."""
start = time.time()
# Extract real user if available
ts_user = extract_user(request)
if ts_user != "anonymous":
req.user = ts_user
# Update session
update_session(req.session_id, req.user, req.meta)
# Find handler
cmd_lower = req.command.lower().strip()
handler = None
# Exact match
if cmd_lower in COMMANDS:
handler = COMMANDS[cmd_lower]
else:
# Prefix match (for commands with args like "oracle reason <query>")
for key in COMMANDS:
if cmd_lower.startswith(key):
handler = COMMANDS[key]
# Extract args from command
remaining = cmd_lower[len(key):].strip()
if remaining:
req.args = remaining.split()
break
if not handler:
duration_ms = int((time.time() - start) * 1000)
log_command(req.session_id, req.command, "error", duration_ms, "Unknown command")
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="error",
lines=[
f" Unknown command: {req.command}",
" Type 'help' for available commands."
],
error="Unknown command"
)
try:
response = await handler(req)
duration_ms = int((time.time() - start) * 1000)
log_command(req.session_id, req.command, "ok", duration_ms)
return response
except Exception as e:
duration_ms = int((time.time() - start) * 1000)
log_command(req.session_id, req.command, "error", duration_ms, str(e))
return CommandResponse(
id=f"cmd-{uuid.uuid4().hex[:8]}",
status="error",
lines=[f" Error: {str(e)}"],
error=str(e)
)
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
"""WebSocket for live updates."""
session_id = None
try:
await websocket.accept()
# Wait for handshake
data = await websocket.receive_json()
if data.get("type") == "handshake":
session_id = data.get("session_id", str(uuid.uuid4()))
user = data.get("user", "anonymous")
# Register connection
manager.active_connections[session_id] = websocket
# Send welcome
await websocket.send_json({
"type": "status.update",
"payload": get_status_effects()
})
print(f"WS connected: {session_id} ({user})")
# Keep connection alive and handle messages
while True:
try:
msg = await asyncio.wait_for(
websocket.receive_json(),
timeout=30 # Ping every 30s
)
# Handle client messages if needed
if msg.get("type") == "ping":
await websocket.send_json({"type": "pong"})
except asyncio.TimeoutError:
# Send keepalive
await websocket.send_json({
"type": "status.update",
"payload": get_status_effects()
})
except WebSocketDisconnect:
pass
except Exception as e:
print(f"WS error: {e}")
finally:
if session_id:
manager.disconnect(session_id)
print(f"WS disconnected: {session_id}")
@app.get("/health")
async def health():
"""Health check endpoint."""
return {
"status": "ok",
"nodes": state.nodes,
"proofs": state.proof_count,
"uptime": state.uptime
}
# Serve console HTML if configured
if config.STATIC_DIR and config.STATIC_DIR.exists():
app.mount("/static", StaticFiles(directory=str(config.STATIC_DIR)), name="static")
@app.get("/")
async def serve_console():
return FileResponse(config.STATIC_DIR / "iotek-nexus-live.html")
# ═══════════════════════════════════════════════════════════════════════════════
# MAIN
# ═══════════════════════════════════════════════════════════════════════════════
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"offsec_mcp:app",
host="0.0.0.0",
port=8080,
reload=True
)

View File

@@ -0,0 +1,5 @@
# offsec-mcp dependencies
fastapi>=0.104.0
uvicorn[standard]>=0.24.0
pydantic>=2.0.0
websockets>=12.0