Preview — /tmp/session_handover.sh

/tmp/session_handover.sh

#!/usr/bin/env bash
set -euo pipefail
SCRIPTS="/opt/jfmsrv01/scripts"
HANDOVER="$SCRIPTS/HANDOVER.md"
CHANGELOG="$SCRIPTS/CHANGELOG.md"
PUBLISH="$SCRIPTS/publish_handoff.sh"
DATE="$(date +%F)"

echo "==> Appending to CHANGELOG.md"
cat >> "$CHANGELOG" <<MD

## ${DATE} - AI Gateway + GoSeek Site Tools (major session)

### Added — llmgateway (192.168.100.110)
- New Ubuntu 24.04.4 VM: AI Gateway, dedicated and isolated
- Custom Laravel app at /var/www/gateway, port 8095, Filament admin
- POST /v1/chat/completions — OpenAI-compatible inbound API
[REDACTED SECRET-LIKE LINE]
- Provider routing with encrypted key storage (Laravel encrypt())
- 7 providers seeded: Ollama, DeepSeek, OpenAI, Anthropic, Groq, Google, Kimi
[REDACTED SECRET-LIKE LINE]
- Rules engine: immutable rules (/etc/gateway/rules.immutable.php, root-owned)
  + editable DB rules via Filament UI, fail-closed, default-allow-with-deny-rules
- Budget enforcement (daily/monthly, per-client or global, deny or hold)
- Decision logging (every request evaluated and logged)
[REDACTED SECRET-LIKE LINE]
- Spend dashboard: per-client, per-provider, per-model, per-day, recent requests
- Filament resources: Providers, Models, Clients, Rules, Budgets (all with delete)
- /health endpoint for liveness checks
- Phase 1 hardening: ufw (SSH + 8095 from LAN), timezone Australia/Perth
- ESXi snapshot taken before build

### Added — jfmsrv01 (GoSeek improvements)
[REDACTED SECRET-LIKE LINE]
- GoSeek ssh_exec tool: locked to one build host via /etc/goseek/build_target.php
- Dedicated ed25519 build keypair in /etc/goseek/ (root-owned, outside webroot)
- GoSeek clone_website tool: dual-mode (quick=wget, deep=httrack), browser UA
- GoSeek scan_site tool: crawls local clone, reports broken links + missing resources
- GoSeek fix_site_links tool: bulk find-and-replace across HTML/CSS/JS
- GoSeek serve_site tool: creates nginx vhost for cloned site (narrow sudo for nginx ops)
- GoSeek auto_fix: downloads missing resources from original site
- GoSeek AI Clone: clones site then sends each page through gateway for AI-powered link fixing
- Sites Manager admin page: Clone (quick/deep/AI), Scan, Auto Fix, Manual Fix, Serve, Preview, Delete
- Tools admin page: lists all 16+ tools with usage stats from tool_calls_log
- Sites preview nginx vhost on port 9090 (autoindex /var/www/sites/)
- Narrow sudoers for www-data: nginx test/reload/vhost-write only
- GoSeek gateway provider configured: routes all AI through the gateway
- httrack installed for deep website cloning

### Architecture decisions
- Gateway on dedicated VM for isolation (RULE D1)
- OpenAI-compatible API shape so clients just change base_url at cutover
- Immutable rules in root-owned file: enforcement below the model layer
- Fail-closed: engine/DB error → deny (no ungoverned requests)
[REDACTED SECRET-LIKE LINE]
- Decimal(12,6) for cost columns (exact, no floating-point drift)
- DeepSeek + Kimi at privacy tier 3 (China-based data routing)
- GoSeek ssh_exec key restricted with from= to jfmsrv01 IP only
- HTTrack for deep clones; wget for quick clones; AI for smart clones

### Known issues / incomplete
- Untangle egress lock not yet done (gateway works but bypass still possible)
- GoSeek direct providers not yet disabled (cutover step 2 pending)
[REDACTED SECRET-LIKE LINE]
- Anthropic adapter not built (API not OpenAI-shaped)
- Streaming not supported on gateway endpoint
- Ollama shelved until GPU available; not reachable from llmgateway
- GoSeek models_json UI field still broken (models set via tinker)
- Per-client provider allow-list not built (planned Phase 8c)
- Budget daily-reset not implemented (spent_amount accumulates)
- GoSeek ToolEngine input validation weak (models name args differently)
- Builder sudo on llmgateway to be tightened after build complete
- WordPress backup import feature planned
- Hosting packages (domains, SSL, DB, email) planned
MD

echo "==> Appending to HANDOVER.md"
cat >> "$HANDOVER" <<MD

---

## Update - ${DATE}: AI Gateway + GoSeek Enhancements

### New: llmgateway — AI Gateway Server

- **VM:** llmgateway on ESXi (snapshot taken)
- **OS:** Ubuntu 24.04.4 LTS
- **IP:** 192.168.100.110
- **Purpose:** Centralised AI gateway — all model API traffic routes through here
- **App:** /var/www/gateway (Laravel, Filament admin)
- **DB:** gateway (PostgreSQL, on llmgateway)
- **Port:** 8095 (internal, ufw allows from 192.168.100.0/24)
- **Admin:** http://192.168.100.110:8095/admin
- **API:** POST http://192.168.100.110:8095/v1/chat/completions
- **Login:** see panel (user created via make:filament-user)

**What it does:**
[REDACTED SECRET-LIKE LINE]
- Resolves requested model → provider, decrypts stored API key
- Evaluates request against immutable rules then DB rules then default-allow
[REDACTED SECRET-LIKE LINE]
- Returns OpenAI-shaped response to client
- Fail-closed: any engine/DB error → deny

**Key files on llmgateway:**
| Path | Purpose |
|------|---------|
| /var/www/gateway/ | Laravel gateway application |
| /var/www/gateway/.env | App config (never share) |
| /etc/gateway/rules.immutable.php | Immutable rules (root-owned, gateway can read not write) |
[REDACTED SECRET-LIKE LINE]
| /etc/nginx/sites-available/gateway | Nginx vhost |

**Providers configured (keys via admin UI):**
- Ollama (local, disabled — shelved until GPU)
- DeepSeek (tier 3) — deepseek-v4-flash, deepseek-v4-pro, deepseek-chat, deepseek-reasoner
- OpenAI (tier 2) — gpt-4o, gpt-4o-mini
- Anthropic (tier 2) — claude-sonnet-4-6, claude-haiku-4-5, claude-opus-4-8 (adapter needed)
- Groq (tier 3) — llama-3.3-70b-versatile, llama-3.1-8b-instant
- Google (tier 2) — gemini-2.5-flash
- Kimi/Moonshot (tier 3) — kimi-k2.6, kimi-k2.5

**Admin panel sections:**
- Spend dashboard (cost by client/provider/model/day + recent requests)
- Providers (add/edit/delete, encrypted key storage)
[REDACTED SECRET-LIKE LINE]
[REDACTED SECRET-LIKE LINE]
- Rules (condition→action, priority-ordered, editable)
- Budgets (global or per-client, daily/monthly, deny or hold on exceed)

---

### Updated: GoSeek AI Workbench

**New tools added to ToolEngine (16+ total):**
- ssh_exec — run commands on llmgateway (locked to one host via /etc/goseek/build_target.php)
- clone_website — mirror a website (quick=wget, deep=httrack), browser UA
- scan_site — crawl local clone, report broken links and missing resources
- fix_site_links — bulk find-and-replace across HTML/CSS/JS in a cloned site
- serve_site — create nginx vhost for a cloned site on a domain/port

**New admin pages:**
- Tools — lists all tools with descriptions, call counts, success rates, last used
- Sites Manager — full site management UI:
  - Quick Clone (wget, fast)
  - Deep Clone (httrack, thorough)
  - AI Clone (clones then AI-fixes each page through the gateway)
  - Scan (broken link report)
  - Auto Fix (downloads missing resources)
  - Manual Fix (find-and-replace)
  - Serve (nginx vhost, go live)
  - Preview (opens on :9090)
  - Delete

**GoSeek → Gateway routing:**
- Gateway provider added in GoSeek AI Providers (slug: gateway)
- base_url: http://192.168.100.110:8095 (GoSeek adds /v1/chat/completions)
- API key: [REDACTED]
- All AI requests can now route through the gateway (metered + governed)

**Key files on jfmsrv01:**
| Path | Purpose |
|------|---------|
| /etc/goseek/build_target.php | SSH build target config (root-owned) |
| /etc/goseek/build_id_ed25519 | Build SSH key (www-data-owned, 600) |
| /etc/goseek/known_hosts | SSH known hosts for build target |
| /etc/sudoers.d/020-goseek-nginx | Narrow sudo for serve_site nginx ops |
| /var/www/sites/ | Cloned website storage |
| /etc/nginx/sites-available/sites-preview | Preview vhost on port 9090 |

---

### Cutover status (Phase 10 — partially complete)

- [x] Gateway built and tested end-to-end
- [x] GoSeek gateway provider configured and working
- [x] Requests route through gateway and appear on Spend dashboard
- [ ] GoSeek direct providers not yet disabled
- [ ] Untangle egress lock not yet configured
[REDACTED SECRET-LIKE LINE]
- [ ] Builder sudo on llmgateway to be tightened

---

### Next session priorities

1. Complete cutover: disable direct providers, lock Untangle egress
[REDACTED SECRET-LIKE LINE]
3. Tighten builder sudo on llmgateway
4. WordPress backup import feature
5. Hosting packages (domains, SSL, databases, email)
6. Anthropic adapter for gateway
7. Streaming support on gateway endpoint
8. Fix GoSeek models_json UI field
9. GoSeek ToolEngine input validation (arg-name normalization)
10. Budget daily-reset mechanism
MD

echo "==> Publishing handoff"
if [ -x "$PUBLISH" ]; then
    bash "$PUBLISH"
    echo "    published"
else
    echo "    NOTE: $PUBLISH not found — run manually"
fi

echo ""
echo "==> Session wrapped. Verify:"
echo "    https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/"