Files
test/VaultMesh_Catalog_v1/files/iotek-nexus-live.html
Vault Sovereign 1583890199 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>
2025-12-28 03:58:39 +00:00

1356 lines
54 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IoTek.nexus — Sovereign Console</title>
<meta name="description" content="Live control surface for VaultMesh sovereign infrastructure.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
<style>
:root {
--onyx: #0a0a0f;
--onyx-deep: #050508;
--void: #000000;
--neon-green: #00ff88;
--neon-emerald: #00ff66;
--neon-ruby: #ff0044;
--neon-purple: #6600ff;
--neon-cyan: #00ffff;
--neon-gold: #ffaa00;
--platinum: #c0c0c0;
--silver: #888899;
--steel: #1a1a2e;
--grid: #0d0d15;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'JetBrains Mono', monospace;
background: var(--onyx);
color: var(--platinum);
min-height: 100vh;
overflow-x: hidden;
}
.code-rain {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
pointer-events: none;
z-index: 0;
overflow: hidden;
opacity: 0.06;
}
.rain-column {
position: absolute;
top: -100%;
font-family: 'JetBrains Mono', monospace;
font-size: 12px;
line-height: 1.2;
color: var(--neon-green);
text-shadow: 0 0 5px var(--neon-green);
writing-mode: vertical-rl;
animation: rain-fall linear infinite;
}
@keyframes rain-fall {
0% { transform: translateY(-100%); }
100% { transform: translateY(200vh); }
}
.app-container {
display: flex;
flex-direction: column;
height: 100vh;
position: relative;
z-index: 10;
}
/* ═══════════════════════════════════════════════════════════
HEADER BAR
═══════════════════════════════════════════════════════════ */
.header-bar {
height: 40px;
background: linear-gradient(to bottom, var(--steel) 0%, var(--onyx) 100%);
border-bottom: 1px solid var(--steel);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1rem;
flex-shrink: 0;
}
.header-left {
display: flex;
align-items: center;
gap: 1rem;
}
.logo {
font-size: 0.75rem;
font-weight: 700;
color: var(--neon-green);
text-shadow: 0 0 10px var(--neon-green);
letter-spacing: 0.05em;
}
.logo span { color: var(--platinum); text-shadow: none; }
.status-pills {
display: flex;
gap: 0.5rem;
}
.status-pill {
font-size: 0.6rem;
padding: 0.2rem 0.5rem;
border-radius: 2px;
display: flex;
align-items: center;
gap: 0.3rem;
letter-spacing: 0.05em;
transition: all 0.3s ease;
}
.status-pill.mesh {
background: rgba(0, 255, 136, 0.15);
color: var(--neon-green);
border: 1px solid rgba(0, 255, 136, 0.3);
}
.status-pill.shield {
background: rgba(255, 0, 68, 0.15);
color: var(--neon-ruby);
border: 1px solid rgba(255, 0, 68, 0.3);
}
.status-pill.ws {
background: rgba(102, 0, 255, 0.15);
color: var(--neon-purple);
border: 1px solid rgba(102, 0, 255, 0.3);
}
.status-pill.ws.connected {
background: rgba(0, 255, 136, 0.15);
color: var(--neon-green);
border: 1px solid rgba(0, 255, 136, 0.3);
}
.status-dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: currentColor;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.header-right {
display: flex;
align-items: center;
gap: 1rem;
}
.header-time {
font-size: 0.65rem;
color: var(--silver);
}
.header-btn {
width: 12px;
height: 12px;
border-radius: 50%;
border: none;
cursor: pointer;
}
.header-btn.minimize { background: var(--neon-gold); }
.header-btn.maximize { background: var(--neon-green); }
.header-btn.close { background: var(--neon-ruby); }
/* ═══════════════════════════════════════════════════════════
MAIN CONTENT
═══════════════════════════════════════════════════════════ */
.main-content {
flex: 1;
display: flex;
overflow: hidden;
}
/* ═══════════════════════════════════════════════════════════
SIDEBAR
═══════════════════════════════════════════════════════════ */
.sidebar {
width: 220px;
background: var(--onyx-deep);
border-right: 1px solid var(--steel);
display: flex;
flex-direction: column;
flex-shrink: 0;
}
.sidebar-section {
padding: 1rem;
border-bottom: 1px solid var(--steel);
}
.sidebar-label {
font-size: 0.6rem;
color: var(--silver);
letter-spacing: 0.15em;
text-transform: uppercase;
margin-bottom: 0.75rem;
}
.sidebar-item {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
margin: 0.25rem 0;
font-size: 0.75rem;
color: var(--platinum);
cursor: pointer;
border-radius: 3px;
transition: all 0.2s ease;
}
.sidebar-item:hover {
background: rgba(0, 255, 136, 0.1);
color: var(--neon-green);
}
.sidebar-item.active {
background: rgba(0, 255, 136, 0.15);
color: var(--neon-green);
border-left: 2px solid var(--neon-green);
margin-left: -2px;
}
.sidebar-item-icon { font-size: 0.9rem; }
.agent-list { flex: 1; overflow-y: auto; }
.agent-item {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.4rem 0.75rem;
font-size: 0.7rem;
color: var(--silver);
cursor: pointer;
transition: all 0.2s ease;
}
.agent-item:hover {
background: rgba(255, 255, 255, 0.03);
color: var(--platinum);
}
.agent-dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
.agent-dot.sentinel { background: #f472b6; }
.agent-dot.orchestrator { background: #a78bfa; }
.agent-dot.analyst { background: #60a5fa; }
.agent-dot.executor { background: #34d399; }
.agent-status {
margin-left: auto;
font-size: 0.6rem;
padding: 0.1rem 0.3rem;
border-radius: 2px;
}
.agent-status.active {
background: rgba(0, 255, 136, 0.2);
color: var(--neon-green);
}
.agent-status.idle {
background: rgba(136, 136, 153, 0.2);
color: var(--silver);
}
/* ═══════════════════════════════════════════════════════════
TERMINAL
═══════════════════════════════════════════════════════════ */
.terminal-area {
flex: 1;
display: flex;
flex-direction: column;
background: var(--onyx);
overflow: hidden;
}
.terminal-tabs {
display: flex;
background: var(--onyx-deep);
border-bottom: 1px solid var(--steel);
flex-shrink: 0;
}
.terminal-tab {
padding: 0.6rem 1rem;
font-size: 0.7rem;
color: var(--silver);
cursor: pointer;
border-right: 1px solid var(--steel);
display: flex;
align-items: center;
gap: 0.5rem;
transition: all 0.2s ease;
}
.terminal-tab:hover {
background: rgba(255, 255, 255, 0.03);
}
.terminal-tab.active {
background: var(--onyx);
color: var(--neon-green);
border-bottom: 1px solid var(--onyx);
margin-bottom: -1px;
}
.terminal-tab-close {
font-size: 0.8rem;
opacity: 0.5;
cursor: pointer;
}
.terminal-tab-close:hover {
opacity: 1;
color: var(--neon-ruby);
}
.terminal-output {
flex: 1;
overflow-y: auto;
padding: 1rem;
font-size: 0.8rem;
line-height: 1.6;
}
.terminal-output::-webkit-scrollbar { width: 8px; }
.terminal-output::-webkit-scrollbar-track { background: var(--onyx-deep); }
.terminal-output::-webkit-scrollbar-thumb { background: var(--steel); border-radius: 4px; }
.output-line {
margin-bottom: 0.25rem;
white-space: pre-wrap;
word-break: break-word;
}
.output-line.command { color: var(--platinum); }
.output-line.command .prompt { color: var(--neon-green); }
.output-line.command .path { color: var(--neon-cyan); }
.output-line.response { color: var(--silver); }
.output-line.success { color: var(--neon-green); }
.output-line.error { color: var(--neon-ruby); }
.output-line.warning { color: var(--neon-gold); }
.output-line.info { color: var(--neon-cyan); }
.output-line.highlight {
color: var(--platinum);
background: rgba(0, 255, 136, 0.1);
padding: 0.5rem;
margin: 0.5rem 0;
border-left: 2px solid var(--neon-green);
}
.output-line.ascii {
color: var(--neon-green);
text-shadow: 0 0 5px var(--neon-green);
}
.output-line.dimmed { color: var(--steel); }
.output-table {
margin: 0.5rem 0;
border-collapse: collapse;
width: 100%;
font-size: 0.75rem;
}
.output-table th {
text-align: left;
color: var(--silver);
padding: 0.3rem 1rem 0.3rem 0;
border-bottom: 1px solid var(--steel);
}
.output-table td {
padding: 0.3rem 1rem 0.3rem 0;
color: var(--platinum);
}
.output-table .status-ok { color: var(--neon-green); }
.output-table .status-warn { color: var(--neon-gold); }
.output-table .status-error { color: var(--neon-ruby); }
/* ═══════════════════════════════════════════════════════════
INPUT
═══════════════════════════════════════════════════════════ */
.input-area {
border-top: 1px solid var(--steel);
padding: 0.75rem 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
background: var(--onyx-deep);
flex-shrink: 0;
}
.input-prompt {
color: var(--neon-green);
font-size: 0.8rem;
flex-shrink: 0;
}
.input-path {
color: var(--neon-cyan);
font-size: 0.8rem;
flex-shrink: 0;
}
.input-field {
flex: 1;
background: transparent;
border: none;
outline: none;
color: var(--platinum);
font-family: 'JetBrains Mono', monospace;
font-size: 0.8rem;
caret-color: var(--neon-green);
}
.input-field::placeholder { color: var(--steel); }
.input-field:disabled { opacity: 0.5; }
.input-hint {
font-size: 0.65rem;
color: var(--steel);
flex-shrink: 0;
}
.input-spinner {
width: 14px;
height: 14px;
border: 2px solid var(--steel);
border-top-color: var(--neon-green);
border-radius: 50%;
animation: spin 0.8s linear infinite;
display: none;
}
.input-spinner.active { display: block; }
@keyframes spin {
to { transform: rotate(360deg); }
}
/* ═══════════════════════════════════════════════════════════
STATUS BAR
═══════════════════════════════════════════════════════════ */
.status-bar {
height: 24px;
background: var(--steel);
border-top: 1px solid var(--onyx);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1rem;
font-size: 0.6rem;
color: var(--silver);
flex-shrink: 0;
}
.status-bar-left,
.status-bar-right {
display: flex;
align-items: center;
gap: 1rem;
}
.status-indicator {
display: flex;
align-items: center;
gap: 0.3rem;
}
.status-indicator .dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
.status-indicator .dot.green { background: var(--neon-green); }
.status-indicator .dot.yellow { background: var(--neon-gold); }
.status-indicator .dot.red { background: var(--neon-ruby); }
@media (max-width: 768px) {
.sidebar { display: none; }
.header-left .status-pills { display: none; }
}
</style>
</head>
<body>
<div class="code-rain" id="codeRain"></div>
<div class="app-container">
<div class="header-bar">
<div class="header-left">
<span class="logo">IoTek<span>.nexus</span></span>
<div class="status-pills">
<span class="status-pill mesh" id="meshPill">
<span class="status-dot"></span>
<span id="meshStatus">MESH INIT</span>
</span>
<span class="status-pill shield" id="shieldPill">
<span class="status-dot"></span>
<span id="shieldStatus">SHIELD INIT</span>
</span>
<span class="status-pill ws" id="wsPill">
<span class="status-dot"></span>
<span id="wsStatus">WS CONNECTING</span>
</span>
</div>
</div>
<div class="header-right">
<span class="header-time" id="headerTime">00:00:00</span>
<button class="header-btn minimize"></button>
<button class="header-btn maximize"></button>
<button class="header-btn close"></button>
</div>
</div>
<div class="main-content">
<div class="sidebar">
<div class="sidebar-section">
<div class="sidebar-label">Navigation</div>
<div class="sidebar-item active" data-cmd="status">
<span class="sidebar-item-icon"></span>
Dashboard
</div>
<div class="sidebar-item" data-cmd="shield status">
<span class="sidebar-item-icon">🛡</span>
Shield
</div>
<div class="sidebar-item" data-cmd="proof latest">
<span class="sidebar-item-icon">📜</span>
Proof
</div>
<div class="sidebar-item" data-cmd="mesh status">
<span class="sidebar-item-icon">🕸</span>
Mesh
</div>
</div>
<div class="sidebar-section agent-list">
<div class="sidebar-label">Agents</div>
<div class="agent-item" data-cmd="agents list">
<span class="agent-dot sentinel"></span>
Sentinel
<span class="agent-status" id="agentSentinel"></span>
</div>
<div class="agent-item" data-cmd="agents list">
<span class="agent-dot orchestrator"></span>
Orchestrator
<span class="agent-status" id="agentOrchestrator"></span>
</div>
<div class="agent-item" data-cmd="agents list">
<span class="agent-dot analyst"></span>
Analyst
<span class="agent-status" id="agentAnalyst"></span>
</div>
<div class="agent-item" data-cmd="agents list">
<span class="agent-dot executor"></span>
Executor
<span class="agent-status" id="agentExecutor"></span>
</div>
</div>
<div class="sidebar-section">
<div class="sidebar-label">Quick Commands</div>
<div class="sidebar-item" data-cmd="help">
<span class="sidebar-item-icon">?</span>
Help
</div>
<div class="sidebar-item" data-cmd="clear">
<span class="sidebar-item-icon"></span>
Clear
</div>
<div class="sidebar-item" data-cmd="history">
<span class="sidebar-item-icon"></span>
History
</div>
</div>
</div>
<div class="terminal-area">
<div class="terminal-tabs">
<div class="terminal-tab active">
<span><span id="tabUser">sovereign</span>@nexus</span>
<span class="terminal-tab-close">×</span>
</div>
<div class="terminal-tab" style="opacity: 0.5;">
<span>+ New Tab</span>
</div>
</div>
<div class="terminal-output" id="terminalOutput"></div>
<div class="input-area">
<span class="input-prompt" id="promptUser">sovereign</span>
<span class="input-prompt">@nexus</span>
<span class="input-path">~/vaultmesh</span>
<span class="input-prompt">$</span>
<input type="text" class="input-field" id="commandInput" placeholder="Enter command..." autocomplete="off" spellcheck="false">
<div class="input-spinner" id="inputSpinner"></div>
<span class="input-hint">Tab to autocomplete</span>
</div>
</div>
</div>
<div class="status-bar">
<div class="status-bar-left">
<span class="status-indicator">
<span class="dot" id="connDot"></span>
<span id="connStatus">Connecting...</span>
</span>
<span id="tailnetInfo">Tailnet: —</span>
<span id="nodeInfo">Node: —</span>
</div>
<div class="status-bar-right">
<span id="proofsInfo">Proofs: —</span>
<span id="uptimeInfo">Uptime: —</span>
<span>v1.0.0-sovereign</span>
</div>
</div>
</div>
<script>
// ═══════════════════════════════════════════════════════════════════════════
// CONFIGURATION
// ═══════════════════════════════════════════════════════════════════════════
const CONFIG = {
// Backend endpoints - adjust for your deployment
MCP_ENDPOINT: '/mcp/command', // HTTP endpoint for commands
WS_ENDPOINT: null, // WebSocket endpoint (null = derive from location)
// Session
SESSION_ID: `vaultmesh-${Date.now().toString(36)}`,
// Fallback to mock mode if backend unavailable
MOCK_FALLBACK: true,
// Retry settings
WS_RETRY_DELAY: 3000,
HTTP_TIMEOUT: 10000
};
// Derive WebSocket URL from current location
if (!CONFIG.WS_ENDPOINT) {
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
CONFIG.WS_ENDPOINT = `${wsProtocol}//${window.location.host}/ws`;
}
// ═══════════════════════════════════════════════════════════════════════════
// STATE
// ═══════════════════════════════════════════════════════════════════════════
const state = {
user: 'sovereign',
commandHistory: [],
historyIndex: -1,
wsConnected: false,
backendAvailable: false,
proofCount: 0,
uptime: '—',
nodes: 0,
shieldArmed: false,
pendingCommand: false
};
let socket = null;
// ═══════════════════════════════════════════════════════════════════════════
// LOCAL COMMANDS (client-side only)
// ═══════════════════════════════════════════════════════════════════════════
const localCommands = {
help: () => ({
type: 'multi',
lines: [
{ type: 'info', text: ' IoTek.nexus — Sovereign Console\n' },
{ type: 'table', headers: ['Command', 'Description'],
rows: [
['help', 'Show this help'],
['clear', 'Clear terminal'],
['history', 'Show command history'],
['status', 'System status dashboard'],
['mesh status', 'Mesh network status'],
['mesh nodes', 'List mesh nodes'],
['shield status', 'Shield defense status'],
['shield arm', 'Arm the shield'],
['shield disarm', 'Disarm the shield'],
['proof latest', 'Latest proof receipts'],
['proof generate', 'Generate new proof'],
['proof verify <id>', 'Verify a proof'],
['agents list', 'List all agents'],
['agent task <desc>', 'Dispatch agent task'],
['oracle reason <q>', 'Oracle reasoning'],
['whoami', 'Current identity'],
['neofetch', 'System info display'],
]
},
{ type: 'dimmed', text: '\n Commands without local handlers are sent to MCP backend.' }
]
}),
clear: () => ({ type: 'clear' }),
history: () => ({
type: 'multi',
lines: state.commandHistory.length === 0
? [{ type: 'dimmed', text: ' No command history.' }]
: state.commandHistory.slice(0, 20).map((cmd, i) => ({
type: 'response',
text: ` ${String(i + 1).padStart(3)} ${cmd}`
}))
}),
whoami: () => ({
type: 'multi',
lines: [
{ type: 'success', text: state.user },
{ type: 'response', text: `Session: ${CONFIG.SESSION_ID}` },
{ type: 'response', text: `Backend: ${state.backendAvailable ? 'connected' : 'offline (mock mode)'}` },
{ type: 'response', text: `WebSocket: ${state.wsConnected ? 'connected' : 'disconnected'}` }
]
}),
neofetch: () => ({
type: 'multi',
lines: [
{ type: 'ascii', text: `
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ${state.user}@nexus
██████████████████ ──────────────────
████ ████████ ████ OS: VaultMesh 1.0
████ ██████ ████ Kernel: sovereign-mesh
████ ████ ████ Shell: nexus-cli
████████████████████████ Terminal: IoTek.nexus
████████████████████████
████ ██████████ ██████ Mesh: ${state.nodes} nodes
████ ██████████ ██████ Proofs: ${state.proofCount}
████████████████████████ Uptime: ${state.uptime}
██████████████████████
████████████████████ Shield: ${state.shieldArmed ? 'ARMED' : 'STANDBY'}
██████████████████ Backend: ${state.backendAvailable ? 'LIVE' : 'MOCK'}
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ Epoch: Citrinitas` }
]
})
};
// ═══════════════════════════════════════════════════════════════════════════
// MOCK COMMANDS (when backend unavailable)
// ═══════════════════════════════════════════════════════════════════════════
const mockCommands = {
status: () => ({
type: 'multi',
lines: [
{ type: 'warning', text: ' ⚠ Running in MOCK MODE (backend unavailable)\n' },
{ type: 'ascii', text: `
╦ ╦╔═╗╦ ╦╦ ╔╦╗╔╦╗╔═╗╔═╗╦ ╦
╚╗╔╝╠═╣║ ║║ ║ ║║║║╣ ╚═╗╠═╣
╚╝ ╩ ╩╚═╝╩═╝╩ ╩ ╩╚═╝╚═╝╩ ╩` },
{ type: 'info', text: '\n Sovereign Infrastructure Status (simulated)\n' },
{ type: 'table', headers: ['System', 'Status', 'Details'],
rows: [
['Shield', '● MOCK', 'Simulated status'],
['Proof', '● MOCK', 'No real receipts'],
['Mesh', '● MOCK', 'No real nodes'],
['Agents', '● MOCK', 'Simulated agents'],
]
},
{ type: 'dimmed', text: '\n Start offsec-mcp backend for live data.' }
]
}),
'mesh status': () => ({
type: 'multi',
lines: [
{ type: 'warning', text: ' ⚠ MOCK MODE\n' },
{ type: 'response', text: ' Would query real Tailnet status via MCP backend.' },
{ type: 'dimmed', text: ' Start: uvicorn offsec_mcp:app --reload' }
]
}),
'shield status': () => ({
type: 'multi',
lines: [
{ type: 'warning', text: ' ⚠ MOCK MODE\n' },
{ type: 'response', text: ' Would query real Shield vectors via MCP backend.' }
]
}),
'proof latest': () => ({
type: 'multi',
lines: [
{ type: 'warning', text: ' ⚠ MOCK MODE\n' },
{ type: 'response', text: ' Would fetch real proof receipts via MCP backend.' }
]
}),
'agents list': () => ({
type: 'multi',
lines: [
{ type: 'warning', text: ' ⚠ MOCK MODE\n' },
{ type: 'response', text: ' Would list real agent status via MCP backend.' }
]
})
};
// ═══════════════════════════════════════════════════════════════════════════
// RENDERING
// ═══════════════════════════════════════════════════════════════════════════
const outputEl = document.getElementById('terminalOutput');
function renderOutput(result) {
if (result.type === 'clear') {
outputEl.innerHTML = '';
return;
}
if (result.type === 'multi') {
result.lines.forEach(line => renderOutput(line));
return;
}
if (result.type === 'table') {
const table = document.createElement('table');
table.className = 'output-table';
const thead = document.createElement('thead');
const headerRow = document.createElement('tr');
result.headers.forEach(h => {
const th = document.createElement('th');
th.textContent = h;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
const tbody = document.createElement('tbody');
result.rows.forEach(row => {
const tr = document.createElement('tr');
row.forEach(cell => {
const td = document.createElement('td');
td.innerHTML = cell
.replace(/●/g, '<span class="status-ok">●</span>')
.replace(/○/g, '<span class="status-warn">○</span>');
tr.appendChild(td);
});
tbody.appendChild(tr);
});
table.appendChild(tbody);
outputEl.appendChild(table);
return;
}
const line = document.createElement('div');
line.className = `output-line ${result.type || 'response'}`;
line.textContent = result.text;
outputEl.appendChild(line);
}
function printLine(text, type = 'response') {
renderOutput({ type, text });
outputEl.scrollTop = outputEl.scrollHeight;
}
function printCommand(input) {
const cmdLine = document.createElement('div');
cmdLine.className = 'output-line command';
cmdLine.innerHTML = `<span class="prompt">${state.user}@nexus</span> <span class="path">~/vaultmesh</span> $ ${escapeHtml(input)}`;
outputEl.appendChild(cmdLine);
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// ═══════════════════════════════════════════════════════════════════════════
// MCP BACKEND COMMUNICATION
// ═══════════════════════════════════════════════════════════════════════════
async function sendToMCP(command, args = []) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), CONFIG.HTTP_TIMEOUT);
try {
const response = await fetch(CONFIG.MCP_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
session_id: CONFIG.SESSION_ID,
user: state.user,
command: command,
args: args,
cwd: '/vaultmesh',
meta: {
client: 'iotek-nexus-cli',
version: '1.0.0'
}
}),
signal: controller.signal
});
clearTimeout(timeout);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
state.backendAvailable = true;
updateConnectionStatus();
return data;
} catch (err) {
clearTimeout(timeout);
if (err.name === 'AbortError') {
throw new Error('Request timeout');
}
state.backendAvailable = false;
updateConnectionStatus();
throw err;
}
}
// ═══════════════════════════════════════════════════════════════════════════
// WEBSOCKET
// ═══════════════════════════════════════════════════════════════════════════
function connectWebSocket() {
try {
socket = new WebSocket(CONFIG.WS_ENDPOINT);
socket.onopen = () => {
state.wsConnected = true;
updateWsStatus();
// Send handshake
socket.send(JSON.stringify({
type: 'handshake',
session_id: CONFIG.SESSION_ID,
user: state.user
}));
};
socket.onmessage = (event) => {
try {
const msg = JSON.parse(event.data);
handleWsMessage(msg);
} catch (e) {
console.error('WS parse error:', e);
}
};
socket.onclose = () => {
state.wsConnected = false;
updateWsStatus();
// Retry connection
setTimeout(connectWebSocket, CONFIG.WS_RETRY_DELAY);
};
socket.onerror = (err) => {
console.error('WS error:', err);
state.wsConnected = false;
updateWsStatus();
};
} catch (err) {
console.error('WS connect failed:', err);
state.wsConnected = false;
updateWsStatus();
setTimeout(connectWebSocket, CONFIG.WS_RETRY_DELAY);
}
}
function handleWsMessage(msg) {
switch (msg.type) {
case 'console.line':
printLine(msg.line, msg.lineType || 'response');
break;
case 'status.update':
if (msg.payload) {
updateStatusFromPayload(msg.payload);
}
break;
case 'agent.update':
updateAgentStatus(msg.agent, msg.status);
break;
case 'proof.new':
state.proofCount++;
document.getElementById('proofsInfo').textContent = `Proofs: ${state.proofCount}`;
printLine(`✓ New proof anchored: ${msg.proof_id}`, 'success');
break;
case 'shield.event':
printLine(`🛡 Shield: ${msg.event}`, msg.severity === 'high' ? 'warning' : 'info');
break;
case 'error':
printLine(`! ${msg.message}`, 'error');
break;
}
}
// ═══════════════════════════════════════════════════════════════════════════
// COMMAND EXECUTION
// ═══════════════════════════════════════════════════════════════════════════
async function executeCommand(input) {
const trimmed = input.trim();
if (!trimmed) return;
// Add to history
state.commandHistory.unshift(trimmed);
state.historyIndex = -1;
// Echo command
printCommand(trimmed);
// Check local commands first
const localKey = trimmed.toLowerCase();
if (localCommands[localKey]) {
const result = localCommands[localKey]();
renderOutput(result);
outputEl.scrollTop = outputEl.scrollHeight;
return;
}
// Try MCP backend
if (state.backendAvailable || !CONFIG.MOCK_FALLBACK) {
setLoading(true);
try {
const data = await sendToMCP(trimmed);
// Render response lines
if (data.lines && Array.isArray(data.lines)) {
data.lines.forEach(line => printLine(line));
}
// Apply effects to UI state
if (data.effects) {
updateStatusFromPayload(data.effects);
}
} catch (err) {
printLine(`! MCP error: ${err.message}`, 'error');
// Fallback to mock if enabled
if (CONFIG.MOCK_FALLBACK) {
printLine(' Falling back to mock mode...', 'dimmed');
executeMock(localKey);
}
} finally {
setLoading(false);
}
} else {
// Mock mode
executeMock(localKey);
}
// Add spacer
const spacer = document.createElement('div');
spacer.innerHTML = '&nbsp;';
outputEl.appendChild(spacer);
outputEl.scrollTop = outputEl.scrollHeight;
}
function executeMock(key) {
// Find matching mock command
const mockKey = Object.keys(mockCommands).find(k => key.startsWith(k));
if (mockKey && mockCommands[mockKey]) {
renderOutput(mockCommands[mockKey]());
} else {
printLine(` Command "${key}" requires MCP backend.`, 'warning');
printLine(' Start: uvicorn offsec_mcp:app --reload', 'dimmed');
}
}
function setLoading(loading) {
state.pendingCommand = loading;
document.getElementById('inputSpinner').classList.toggle('active', loading);
document.getElementById('commandInput').disabled = loading;
}
// ═══════════════════════════════════════════════════════════════════════════
// UI UPDATES
// ═══════════════════════════════════════════════════════════════════════════
function updateConnectionStatus() {
const dot = document.getElementById('connDot');
const status = document.getElementById('connStatus');
if (state.backendAvailable) {
dot.className = 'dot green';
status.textContent = 'Connected';
} else {
dot.className = 'dot yellow';
status.textContent = 'Mock Mode';
}
}
function updateWsStatus() {
const pill = document.getElementById('wsPill');
const status = document.getElementById('wsStatus');
if (state.wsConnected) {
pill.classList.add('connected');
status.textContent = 'WS LIVE';
} else {
pill.classList.remove('connected');
status.textContent = 'WS OFFLINE';
}
}
function updateStatusFromPayload(payload) {
if (payload.nodes !== undefined) {
state.nodes = payload.nodes;
document.getElementById('meshStatus').textContent = `MESH ${payload.nodes}`;
}
if (payload.shield !== undefined) {
state.shieldArmed = payload.shield.armed;
document.getElementById('shieldStatus').textContent =
payload.shield.armed ? 'SHIELD ARMED' : 'SHIELD STANDBY';
}
if (payload.proofs !== undefined) {
state.proofCount = payload.proofs;
document.getElementById('proofsInfo').textContent = `Proofs: ${payload.proofs}`;
}
if (payload.uptime !== undefined) {
state.uptime = payload.uptime;
document.getElementById('uptimeInfo').textContent = `Uptime: ${payload.uptime}`;
}
if (payload.tailnet !== undefined) {
document.getElementById('tailnetInfo').textContent = `Tailnet: ${payload.tailnet}`;
}
if (payload.node !== undefined) {
document.getElementById('nodeInfo').textContent = `Node: ${payload.node}`;
}
}
function updateAgentStatus(agent, status) {
const el = document.getElementById(`agent${agent.charAt(0).toUpperCase() + agent.slice(1)}`);
if (el) {
el.textContent = status.toUpperCase();
el.className = `agent-status ${status === 'active' ? 'active' : 'idle'}`;
}
}
// ═══════════════════════════════════════════════════════════════════════════
// BOOT SEQUENCE
// ═══════════════════════════════════════════════════════════════════════════
async function bootSequence() {
const bootLines = [
{ delay: 0, type: 'dimmed', text: '> Initializing IoTek.nexus...' },
{ delay: 150, type: 'dimmed', text: '> Loading sovereign-mesh kernel...' },
];
for (const line of bootLines) {
await sleep(line.delay);
printLine(line.text, line.type);
}
// Try to connect to backend
printLine('> Connecting to MCP backend...', 'dimmed');
try {
const data = await sendToMCP('ping');
printLine('> ✓ MCP backend connected', 'success');
if (data.effects) {
updateStatusFromPayload(data.effects);
}
// Fetch initial status
printLine('> Fetching system status...', 'dimmed');
const statusData = await sendToMCP('status');
if (statusData.effects) {
updateStatusFromPayload(statusData.effects);
}
printLine('> ✓ Status synchronized', 'success');
} catch (err) {
printLine('> ⚠ MCP backend unavailable', 'warning');
printLine('> Running in MOCK MODE', 'warning');
printLine('> Start backend: uvicorn offsec_mcp:app --reload', 'dimmed');
}
// Connect WebSocket
printLine('> Connecting WebSocket...', 'dimmed');
connectWebSocket();
await sleep(500);
if (state.wsConnected) {
printLine('> ✓ WebSocket connected', 'success');
} else {
printLine('> ○ WebSocket connecting...', 'dimmed');
}
printLine('\n Welcome to IoTek.nexus — Sovereign Console v1.0', 'info');
printLine(' Type "help" for commands.\n', 'dimmed');
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// ═══════════════════════════════════════════════════════════════════════════
// EVENT LISTENERS
// ═══════════════════════════════════════════════════════════════════════════
document.getElementById('commandInput').addEventListener('keydown', (e) => {
const input = e.target;
if (e.key === 'Enter' && !state.pendingCommand) {
executeCommand(input.value);
input.value = '';
}
if (e.key === 'ArrowUp') {
e.preventDefault();
if (state.historyIndex < state.commandHistory.length - 1) {
state.historyIndex++;
input.value = state.commandHistory[state.historyIndex];
}
}
if (e.key === 'ArrowDown') {
e.preventDefault();
if (state.historyIndex > 0) {
state.historyIndex--;
input.value = state.commandHistory[state.historyIndex];
} else {
state.historyIndex = -1;
input.value = '';
}
}
if (e.key === 'Tab') {
e.preventDefault();
const partial = input.value.toLowerCase();
const allCommands = [
...Object.keys(localCommands),
...Object.keys(mockCommands),
'status', 'mesh status', 'mesh nodes', 'shield status', 'shield arm',
'shield disarm', 'proof latest', 'proof generate', 'agents list',
'oracle reason'
];
const matches = [...new Set(allCommands)].filter(c => c.startsWith(partial));
if (matches.length === 1) {
input.value = matches[0];
}
}
if (e.key === 'c' && e.ctrlKey) {
if (state.pendingCommand) {
printLine('^C', 'dimmed');
setLoading(false);
}
}
});
// Sidebar clicks
document.querySelectorAll('.sidebar-item, .agent-item').forEach(item => {
item.addEventListener('click', () => {
const cmd = item.dataset.cmd;
if (cmd && !state.pendingCommand) {
document.getElementById('commandInput').value = cmd;
executeCommand(cmd);
}
});
});
// Focus input
document.querySelector('.terminal-area').addEventListener('click', () => {
document.getElementById('commandInput').focus();
});
// ═══════════════════════════════════════════════════════════════════════════
// CODE RAIN
// ═══════════════════════════════════════════════════════════════════════════
function createCodeRain() {
const container = document.getElementById('codeRain');
const chars = '01アイウエオカキクケコサシスセソ><{}[]|;:.,/*-+';
const columnCount = Math.floor(window.innerWidth / 25);
for (let i = 0; i < columnCount; i++) {
const column = document.createElement('div');
column.className = 'rain-column';
column.style.left = (i * 25) + 'px';
column.style.animationDuration = (10 + Math.random() * 15) + 's';
column.style.animationDelay = (Math.random() * 10) + 's';
column.style.opacity = 0.3 + Math.random() * 0.4;
let str = '';
const length = 15 + Math.floor(Math.random() * 20);
for (let j = 0; j < length; j++) {
str += chars[Math.floor(Math.random() * chars.length)];
}
column.textContent = str;
container.appendChild(column);
}
}
// ═══════════════════════════════════════════════════════════════════════════
// CLOCK
// ═══════════════════════════════════════════════════════════════════════════
function updateClock() {
document.getElementById('headerTime').textContent =
new Date().toTimeString().split(' ')[0];
}
// ═══════════════════════════════════════════════════════════════════════════
// INIT
// ═══════════════════════════════════════════════════════════════════════════
document.addEventListener('DOMContentLoaded', () => {
createCodeRain();
updateClock();
setInterval(updateClock, 1000);
updateConnectionStatus();
updateWsStatus();
bootSequence().then(() => {
document.getElementById('commandInput').focus();
});
});
</script>
</body>
</html>