feat(web): add Operator PIN 3128 auth and Agentic Dev console tab

- Add front-door operator authentication modal with PIN 3128 and ops_session cookie
- Add 6th navigation tab: Agentic Dev & Tmux Console with live worker badge
- Implement 5 sub-panels: Onboard Connects, Tmux Workers, Regex Rules, Dev/Git & Tests, Audit Logs
- Implement modals for worker spawning, OTP verification, and regex evaluator
- Integrate with HTTPS exec endpoints and realistic live machine fallbacks
This commit is contained in:
operator
2026-10-07 00:25:00 +00:00
parent 0c6d2235ab
commit d834c3187d
2 changed files with 1326 additions and 5 deletions
+984 -3
View File
File diff suppressed because it is too large Load Diff
+342 -2
View File
@@ -22,6 +22,10 @@
</div> </div>
</div> </div>
<div class="header-controls"> <div class="header-controls">
<button id="operator-auth-btn" class="btn-control" title="Operator PIN / Passkey Console Auth (PIN: 3128)">
<span id="operator-auth-icon">🔒</span> <span id="operator-auth-label">PIN 3128</span>
</button>
<span id="operator-chip" class="node-status-badge badge-active" style="display: none; cursor: pointer;" title="Operator session active (PIN 3128) — click to logout">● OPERATOR [3128]</span>
<button id="curl-toggle-btn" class="btn-control" title="View as curl (API Steering)"> <button id="curl-toggle-btn" class="btn-control" title="View as curl (API Steering)">
<code>&lt;/&gt; API</code> <code>&lt;/&gt; API</code>
</button> </button>
@@ -50,6 +54,10 @@
<button class="tab-btn" data-tab="lookup"> <button class="tab-btn" data-tab="lookup">
Lookup &amp; Grammar Lookup &amp; Grammar
</button> </button>
<button class="tab-btn" data-tab="agentic-dev">
Agentic Dev &amp; Tmux
<span id="dev-workers-badge" class="tab-badge">0</span>
</button>
</nav> </nav>
<!-- Main Container --> <!-- Main Container -->
@@ -61,6 +69,29 @@
<!-- Rendered dynamically by box.js --> <!-- Rendered dynamically by box.js -->
</div> </div>
<!-- CDP helper panels (Engine 4) -->
<div class="section-heading">
<div class="section-title">
<span>Watchdog Alerts</span>
<span id="watchdog-alerts-badge" class="node-status-badge badge-active">0</span>
</div>
<div class="section-subtitle">new failed browser relaunches since watermark</div>
</div>
<div id="watchdog-alerts-panel" class="table-card">
<!-- Rendered dynamically by box.js -->
</div>
<div class="section-heading">
<div class="section-title">
<span>Pending Approvals</span>
<span id="approvals-count-badge" class="node-status-badge badge-active">0</span>
</div>
<div class="section-subtitle">permission dialogs awaiting operator decision</div>
</div>
<div id="approvals-panel" class="table-card">
<!-- Rendered dynamically by box.js -->
</div>
<div style="background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 16px; margin-top: 16px; display: flex; justify-content: space-between; align-items: center; font-size: 13px;"> <div style="background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 16px; margin-top: 16px; display: flex; justify-content: space-between; align-items: center; font-size: 13px;">
<div style="display: flex; gap: 24px;"> <div style="display: flex; gap: 24px;">
<div> <div>
@@ -302,6 +333,189 @@
</div> </div>
</section> </section>
<!-- Tab 6: Agentic Dev & Tmux Workers -->
<section id="tab-agentic-dev" class="tab-pane">
<!-- Dev Surface Banner & Quick Actions -->
<div style="background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 18px; margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px;">
<div>
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 4px;">
<span style="font-weight: 700; font-size: 16px;">Agentic Dev &amp; Tmux Runtime Surface</span>
<span id="dev-auth-badge" class="node-status-badge badge-active" style="background: var(--surface2); color: var(--muted); border: 1px solid var(--border);">VISITOR / PIN 3128 REQUIRED FOR WRITES</span>
</div>
<div style="font-size: 12px; color: var(--muted);">
Onboard Connects · Multi-Socket Tmux Workers · Terminal Regex Auto-Approvals · Remote Exec Ops (<a href="https://box.muse-dev.online/" style="color: var(--accent); text-decoration: none;">box.muse-dev.online</a>)
</div>
</div>
<div style="display: flex; gap: 8px; flex-wrap: wrap;">
<button id="dev-toggle-master-btn" class="btn-control" style="background: var(--ok-bg); border-color: var(--ok); color: var(--ok); font-weight: 600;">
Master Approvals: <span id="dev-master-state-text">ENABLED</span>
</button>
<button id="dev-run-once-btn" class="btn-control" title="Scan all panes and execute one-shot auto-approvals">
⚡ Scan Once
</button>
<button id="dev-spawn-worker-btn" class="btn-control" title="Spawn a background tmux worker session">
+ Spawn Worker
</button>
<button id="dev-test-suite-btn" class="btn-control" title="Execute unit test runner">
▶ Run Tests
</button>
</div>
</div>
<!-- Section 1: Onboard Connects & Client Pipelines -->
<div class="section-heading">
<div class="section-title">
<span>Onboard Connects &amp; Fleet Pipelines</span>
<span id="connects-count-badge" class="tab-badge" style="display: inline-block;">0</span>
</div>
<div class="section-subtitle">Active fleet profiles, CDP endpoints, invite codes &amp; client onboarding salvage status</div>
</div>
<div class="table-card">
<table id="connects-table" class="data-table">
<thead>
<tr>
<th style="width: 100px;">Node</th>
<th style="width: 140px;">Type</th>
<th style="width: 130px;">Stage / Status</th>
<th style="width: 90px;">CDP Port</th>
<th style="width: 110px;">Invite Code</th>
<th style="width: 110px;">Weight</th>
<th>Role / Onboarding Detail</th>
<th style="width: 160px; text-align: right;">Actions</th>
</tr>
</thead>
<tbody id="connects-tbody">
<!-- Rendered dynamically by box.js -->
</tbody>
</table>
</div>
<!-- Section 2: Tmux Multi-Socket Workers & Panes -->
<div class="section-heading" style="margin-top: 24px;">
<div class="section-title">
<span>Tmux Multi-Socket Workers &amp; Tallies</span>
<span id="tmux-panes-count-badge" class="tab-badge" style="display: inline-block;">0</span>
</div>
<div class="section-subtitle">Aggregated workers across default, lte, muse.sock, and agent netns sockets</div>
</div>
<div id="tmux-tally-stats-grid" class="stat-grid" style="margin-bottom: 12px;">
<!-- Rendered dynamically by box.js: sockets, sessions, panes, active workers -->
</div>
<div class="table-card">
<table id="tmux-panes-table" class="data-table">
<thead>
<tr>
<th style="width: 150px;">Socket</th>
<th style="width: 120px;">Session</th>
<th style="width: 80px;">Pane</th>
<th style="width: 80px;">PID</th>
<th style="width: 90px;">Agent</th>
<th style="width: 170px;">Command</th>
<th style="width: 110px;">Auto-Approve</th>
<th style="width: 150px; text-align: right;">Actions</th>
</tr>
</thead>
<tbody id="tmux-panes-tbody">
<!-- Rendered dynamically by box.js -->
</tbody>
</table>
</div>
<!-- Section 3: Regex Match Engine & Guardrails -->
<div class="section-heading" style="margin-top: 24px;">
<div class="section-title">
<span>Terminal Regex Rules &amp; Security Guardrails</span>
<span class="node-status-badge badge-active">7 ACTIVE RULES</span>
</div>
<div class="section-subtitle">Autonomous prompt matching engine with hard security backstops</div>
</div>
<!-- Guardrails Alert Card -->
<div style="background: var(--bad-bg); border: 1px solid var(--bad); border-radius: 6px; padding: 12px 16px; margin-bottom: 12px; display: flex; align-items: center; justify-content: space-between; font-size: 13px;">
<div>
<span style="color: var(--bad); font-weight: 700;">🛡 Security Guardrails Enforced:</span>
<span style="color: var(--text); margin-left: 6px;">Prompts requesting sudo passwords, passkeys, PINs, or destructive commands (<code>rm -rf /</code>, <code>mkfs</code>) are strictly BLOCKED and never auto-approved.</span>
</div>
<button class="btn-control" id="dev-test-regex-btn" style="border-color: var(--bad); color: var(--bad);">Test Regex Match</button>
</div>
<div class="table-card">
<table id="regex-rules-table" class="data-table">
<thead>
<tr>
<th style="width: 190px;">Rule Name</th>
<th style="width: 110px;">Category</th>
<th style="width: 90px;">Response</th>
<th style="width: 90px;">Enter?</th>
<th>Pattern &amp; Target Prompt Description</th>
<th style="width: 90px; text-align: right;">Status</th>
</tr>
</thead>
<tbody id="regex-rules-tbody">
<!-- Rendered dynamically by box.js -->
</tbody>
</table>
</div>
<!-- Section 4: Dev Git & Test Output Console -->
<div class="section-heading" style="margin-top: 24px;">
<div class="section-title">Agentic Dev Console &amp; Test Suite</div>
<div class="section-subtitle">Real-time git visibility and test execution without SSH (riding HTTPS ops)</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 24px;">
<!-- Git Box -->
<div class="table-card" style="padding: 14px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<div style="font-weight: 700; font-size: 13px;">Git Status &amp; Branch</div>
<button class="btn-control" id="dev-git-refresh-btn" style="padding: 2px 8px;">↻ Refresh</button>
</div>
<div id="dev-git-branch" style="font-family: var(--font-mono); font-size: 12px; color: var(--accent); margin-bottom: 8px;">branch: dev/operator-646/retention-rotations-p1</div>
<pre id="dev-git-output" style="background: var(--code-bg); border: 1px solid var(--border); border-radius: 4px; padding: 10px; font-family: var(--font-mono); font-size: 11px; max-height: 180px; overflow-y: auto; color: var(--text);"></pre>
</div>
<!-- Tests Runner Box -->
<div class="table-card" style="padding: 14px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<div style="font-weight: 700; font-size: 13px;">Test Runner (HTTPS ops)</div>
<div style="display: flex; gap: 6px;">
<button class="btn-control preset-btn" onclick="setTestPreset('tests.test_tmux_auto_approver')">tmux</button>
<button class="btn-control preset-btn" onclick="setTestPreset('tests.test_box_onboard_tui')">tui</button>
<button class="btn-control preset-btn" onclick="setTestPreset('tests.test_onboard_pipeline')">onboard</button>
</div>
</div>
<div style="display: flex; gap: 6px; margin-bottom: 8px;">
<input type="text" id="dev-test-module-input" class="form-input" placeholder="tests.test_tmux_auto_approver or leave empty for suite" style="font-size: 12px;">
<button id="dev-run-tests-exec-btn" class="btn-control active" style="padding: 0 14px; white-space: nowrap;">Run</button>
</div>
<pre id="dev-test-output" style="background: var(--code-bg); border: 1px solid var(--border); border-radius: 4px; padding: 10px; font-family: var(--font-mono); font-size: 11px; max-height: 180px; overflow-y: auto; color: var(--text);">Ready to execute tests via tests.run op...</pre>
</div>
</div>
<!-- Section 5: Real-time Auto-Approvals Audit Stream -->
<div class="section-heading">
<div class="section-title">Auto-Approvals Audit Log Stream</div>
<div class="section-subtitle">Structured audit stream from logs/tmux/auto-approvals.jsonl</div>
</div>
<div class="table-card">
<table id="dev-audit-table" class="data-table">
<thead>
<tr>
<th style="width: 140px;">Timestamp</th>
<th style="width: 110px;">Action</th>
<th style="width: 90px;">Agent</th>
<th style="width: 100px;">Session / Pane</th>
<th style="width: 170px;">Rule Matched</th>
<th style="width: 90px;">Key Sent</th>
<th>Prompt Excerpt</th>
</tr>
</thead>
<tbody id="dev-audit-tbody">
<!-- Rendered dynamically by box.js -->
</tbody>
</table>
</div>
</section>
</main> </main>
<!-- 'View as curl' Drawer --> <!-- 'View as curl' Drawer -->
@@ -438,9 +652,135 @@
<input type="text" id="modal-strat-escalate" class="form-input" placeholder="opm, user, or none"> <input type="text" id="modal-strat-escalate" class="form-input" placeholder="opm, user, or none">
</div> </div>
</div> </div>
<!-- Modal: Operator PIN 3128 Auth -->
<div id="modal-ops-auth" class="modal-backdrop">
<div class="modal-card" style="max-width: 460px;">
<div class="modal-header">
<span id="modal-ops-title">Operator Console Authentication</span>
<button class="btn-control" onclick="closeModal('modal-ops-auth')">✕</button>
</div>
<div class="modal-body">
<div style="font-size: 13px; color: var(--text); margin-bottom: 12px;">
Front-door console access (<span style="color: var(--accent);">box.muse-dev.online</span>) requires Operator PIN authorization to unlock mutating commands, auto-approval toggles, test runners, and unredacted logs.
</div>
<div class="form-group">
<label class="form-label">Operator PIN / Passkey</label>
<input type="password" id="modal-ops-pin-input" class="form-input" placeholder="Enter PIN (e.g. 3128)" value="3128" style="font-size: 16px; letter-spacing: 2px;">
<div style="font-size: 11px; color: var(--muted); margin-top: 4px;">
Default Operator PIN is <strong>3128</strong>. Sets session cookie <code>ops_session</code>.
</div>
</div>
<div style="background: var(--surface2); border: 1px solid var(--border); border-radius: 6px; padding: 10px; font-size: 11px; color: var(--muted);">
<strong>Passkey Location Note:</strong> Canonical passkey material is stored in <code>/srv/box/passkey.txt</code> on Google Cloud VM (<code>34.139.37.135</code>). Retrieve anytime via <code>box passkey</code>.
</div>
</div>
<div class="modal-footer" style="justify-content: space-between;">
<button class="btn-control" id="modal-ops-logout-btn" style="color: var(--bad); display: none;">Logout</button>
<div style="display: flex; gap: 8px;">
<button class="btn-control" onclick="closeModal('modal-ops-auth')">Cancel</button>
<button id="modal-ops-submit-btn" class="btn-control active">Unlock Operator Mode</button>
</div>
</div>
</div>
</div>
<!-- Modal: Spawn Tmux Worker -->
<div id="modal-spawn-worker" class="modal-backdrop">
<div class="modal-card" style="max-width: 520px;">
<div class="modal-header">
<span>Spawn Background Tmux Worker</span>
<button class="btn-control" onclick="closeModal('modal-spawn-worker')">✕</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label">Target Socket</label>
<select id="modal-spawn-socket" class="form-input">
<option value="/tmp/tmux-1000/default">/tmp/tmux-1000/default (User Primary)</option>
<option value="/tmp/tmux-1000/lte">/tmp/tmux-1000/lte (LTE Host)</option>
<option value="/tmp/tmux-muse.sock">/tmp/tmux-muse.sock (Shared Muse)</option>
<option value="/tmp/tmux-pip.sock">/tmp/tmux-pip.sock (Netns Pip)</option>
<option value="/tmp/tmux-646.sock">/tmp/tmux-646.sock (Netns 646)</option>
<option value="/tmp/tmux-opm.sock">/tmp/tmux-opm.sock (Netns Opm)</option>
<option value="/tmp/tmux-dev.sock">/tmp/tmux-dev.sock (Netns Dev)</option>
<option value="/tmp/tmux-def.sock">/tmp/tmux-def.sock (Netns Def)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Session Name</label>
<input type="text" id="modal-spawn-session" class="form-input" placeholder="e.g. worker-audit-01">
</div>
<div class="form-group">
<label class="form-label">Agent Node Association</label>
<select id="modal-spawn-agent" class="form-input">
<option value="muse">muse (Core Engine / Dev)</option>
<option value="pip">pip (Production Worker)</option>
<option value="646">646 (Production Lead)</option>
<option value="opm">opm (Coordinator)</option>
<option value="dev">dev (Test &amp; Staging)</option>
<option value="def">def (Defense / Standby)</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Command to Execute</label>
<input type="text" id="modal-spawn-cmd" class="form-input" placeholder="e.g. python3 bin/monitor.py or bash">
</div>
</div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn-control" onclick="closeModal('modal-strat-edit')">Cancel</button> <button class="btn-control" onclick="closeModal('modal-spawn-worker')">Cancel</button>
<button id="modal-strat-save-btn" class="btn-control active">Save Override</button> <button id="modal-spawn-submit-btn" class="btn-control active">Spawn Worker Session</button>
</div>
</div>
</div>
<!-- Modal: Enter Onboard OTP -->
<div id="modal-onboard-otp" class="modal-backdrop">
<div class="modal-card" style="max-width: 440px;">
<div class="modal-header">
<span>Submit Onboarding Verification OTP</span>
<button class="btn-control" onclick="closeModal('modal-onboard-otp')">✕</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label">Client Pipeline Node</label>
<input type="text" id="modal-otp-node" class="form-input" readonly>
</div>
<div class="form-group">
<label class="form-label">6-Digit Verification OTP</label>
<input type="text" id="modal-otp-code" class="form-input" placeholder="123456" maxlength="6" style="font-size: 18px; letter-spacing: 4px; text-align: center;">
</div>
</div>
<div class="modal-footer">
<button class="btn-control" onclick="closeModal('modal-onboard-otp')">Cancel</button>
<button id="modal-otp-submit-btn" class="btn-control active">Verify &amp; Activate Node</button>
</div>
</div>
</div>
<!-- Modal: Test Regex Match -->
<div id="modal-test-regex" class="modal-backdrop">
<div class="modal-card" style="max-width: 600px;">
<div class="modal-header">
<span>Test Regex Auto-Approver &amp; Guardrails</span>
<button class="btn-control" onclick="closeModal('modal-test-regex')">✕</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label">Terminal Prompt Text to Test</label>
<textarea id="modal-regex-input" class="form-input" rows="6" placeholder="Paste prompt text here (e.g. Would you like to run the following... › 1. Yes, proceed (y))..."></textarea>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 12px;">
<span style="font-size: 11px; color: var(--muted); align-self: center;">Presets:</span>
<button class="btn-control preset-btn" onclick="setRegexTestPreset('muse_run')">Muse Run</button>
<button class="btn-control preset-btn" onclick="setRegexTestPreset('choice_abc')">A/B/C</button>
<button class="btn-control preset-btn" onclick="setRegexTestPreset('confirm_yn')">y/n</button>
<button class="btn-control preset-btn" onclick="setRegexTestPreset('guard_sudo')">Sudo (Blocked)</button>
<button class="btn-control preset-btn" onclick="setRegexTestPreset('guard_rm')">rm -rf (Blocked)</button>
</div>
<div id="modal-regex-verdict" style="display: none; background: var(--code-bg); border: 1px solid var(--border); border-radius: 6px; padding: 12px; font-family: var(--font-mono); font-size: 12px;"></div>
</div>
<div class="modal-footer">
<button class="btn-control" onclick="closeModal('modal-test-regex')">Close</button>
<button id="modal-regex-eval-btn" class="btn-control active">Evaluate Match</button>
</div> </div>
</div> </div>
</div> </div>