
## 2026-05-29 - GoSeek AI Workbench + aiepyc01

### Added
- aiepyc01: New Ubuntu 24.04 VM on EPYC ESXi, 60 vCPU, 280GB RAM
- aiepyc01: Ollama 0.24.0 installed, listening on 10.133.133.2:11434
- aiepyc01: llama3.3:70b and llama3.2:3b models installed
- jfmsrv01: Second NIC (ens192) added, 10.133.133.1/24, direct link to aiepyc01
- GoSeek: New Laravel/Filament AI workbench at /var/www/goseek port 8090
- GoSeek: 10 AI providers configured (Ollama, Anthropic, OpenAI, Google, Deepseek, Kimi, Groq, Mistral, xAI, Cohere)
- GoSeek: Tool engine (read files, run commands, logs, database queries, Ollama management)
- GoSeek: Groq API key configured and working (248ms response time)
- GoSeek: AI Provider management UI with encrypted key storage
- GoSeek: Full screen chat interface

### Architecture
- Direct 10.133.133.x network for AI traffic bypasses Untangle
- API keys encrypted with Laravel encrypt() - never plaintext in DB

## 2026-05-30 - Repair GoSeek AI Provider form namespace

### Fixed
- Repaired GoSeek AI Provider Filament resource after the API key save patch caused a class namespace error.
- Form input components such as `TextInput` now use the Filament Forms component namespace instead of the Filament Schemas namespace.
- Confirmed Groq's existing API key remains stored and reports as encrypted without exposing the key value.

### Changed
- Confirmed this server now uses the generic `/opt/jfmsrv01/scripts/` handover workflow, not the old `/opt/legaltranscribe/scripts/` path.

## 2026-05-30 - Fix GoSeek external provider key saving and selection

### Fixed
- GoSeek `AiProvider` model now supports a virtual `api_key_input` attribute that encrypts into `api_key`.
- AI Provider create/edit pages now preserve existing keys when the field is blank and pass new key input to the model mutator.
- API key input is dehydrated only when filled, preventing blank edits from wiping existing keys.
- Provider selector now returns enabled providers that are local or have a stored key.

### Security
- API keys are still never pre-filled into the browser.
- Verification reports only `empty`, `encrypted`, or `legacy_or_invalid`; it does not print key values.

## 2026-05-30 - Fix GoSeek OpenAI provider save using real api_key field

### Fixed
- Replaced the virtual AI Provider key input save path with the real `api_key` model field.
- `AiProvider::setApiKeyAttribute()` now encrypts raw browser input and preserves already encrypted values.
- Edit form blanks the API key field before display so stored keys are never sent back to the browser.
- Blank key field on edit keeps the existing encrypted key.
- Provider selector continues to list only enabled providers that are local or have a stored key.

### Validation
- Model save was tested inside a rolled-back transaction.
- The test confirmed `enabled=yes`, encrypted key status, and successful decrypt match without persisting or printing a real key.

## 2026-05-30 - Add OpenAI model options for GoSeek selector

### Fixed
- Added selectable OpenAI model options when the OpenAI provider has no models configured.
- Updated GoSeek provider API output to return enabled local providers or enabled keyed external providers with model lists.
- Updated `AiProviderSeeder` so OpenAI is no longer reseeded with an empty model list.

### Validation
- `/chat-api/providers` was checked after cache clear.
- Verification output reports provider visibility and model counts only; it does not print API keys.

## 2026-05-30 - Complete GoSeek provider dropdown loading fix

### Fixed
- Completed the provider dropdown repair after the first patch script stopped on a Python regex escaping error.
- Patched `ChatController::models()` safely.
- Ensured `ProviderRouter::all()` uses normalised model options.
- Normalised existing provider model data so `/chat-api/providers` no longer fails when models are stored as strings.

### Validation
- PHP lint passed.
- Direct `ProviderRouter::all()` was checked.
- `/chat-api/providers` was checked for HTTP 200.

## 2026-05-30 - Fix GoSeek provider classification and OpenAI visibility

### Fixed
- Normalised GoSeek provider records so only Ollama is treated as local.
- Cloud providers are now classified as cloud/external.
- OpenAI is enabled automatically when a saved key is present.
- Provider API now strictly returns Ollama as local and keyed external providers as cloud.
- Confirmed provider API returns JSON after cache clear.

### Security
- No API key values are printed or published; checks only show key status.

## 2026-05-30 - Securely set GoSeek OpenAI provider

### Fixed
- OpenAI provider was not visible in the GoSeek selector because it was not passing the enabled/keyed provider filter.
- OpenAI provider was securely set using a hidden terminal prompt.
- OpenAI is now classified as cloud, enabled, keyed, and configured with selectable models.

### Security
- The OpenAI API key was not printed to the terminal, handover, changelog, or chat.
- Verification output reports only key status, not key value.

## 2026-05-30 - Refresh jfmsrv01 handoff and publish PHP source

- Replaced stale transcribe01/legaltranscribe wording with current jfmsrv01 generic server layout.
- Updated workflow paths to /opt/jfmsrv01/scripts.
- Documented mainsite, admin, GoSeek and handoff portal.
- Published first-party PHP source browsers for active development inspection.
- Excluded .env, vendor, node_modules, storage logs/cache, sessions and private files.

## 2026-05-30 - Fix handoff aliases and add fresh run publishing

### Fixed
- Non-slug aliases such as /server/HANDOVER.html now read from the canonical slug tree instead of stale root-level files.
- Added no-cache headers to the handoff HTTPS vhost.
- Redirected the accidental missing-v slug to the canonical slug.

### Added
- Added /opt/jfmsrv01/scripts/publish_fresh_handoff_run.sh.
- Each fresh publish creates /runs/<timestamp>/ so ChatGPT/browser inspection can use a new URL and avoid stale cache.

## 20260530-160357 - Publish fresh handoff run

### Changed
- Published unique cache-busting handoff run: runs/20260530-160357/
- Updated latest-run pointers.
- Added fresh run links to the canonical handoff index.

### URLs
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260530-160357/
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260530-160357/server/HANDOVER.html
- https://vqngx6j8dc9q1lvt7g2a7a646q2t.jfmcommunications.com.au/vqngx6j8dc9q1lvt7g2a7a646q2t/runs/20260530-160357/source/goseek/index.html

## 2026-05-30 - Fix GoSeek AI Provider API key saving through the UI

### Fixed
- AiProviderResource api_key field declared dehydrated() twice; the trailing
  dehydrated(false) won, so the field was stripped from the form payload and
  the Create/Edit page mutators never received it. No API key entered in the
  UI was ever persisted.
- api_key now dehydrates only when filled; blank-on-edit preserves the existing
  encrypted key via the page mutators. This also restores cloud provider
  visibility in the chat selector, since ProviderRouter::all() requires a key.

### Security
- API keys remain encrypted at rest and are never pre-filled into the browser,
  printed, logged, or published.
