laravel-json-ai-settingslisted
Install: claude install-skill Yaz-inc/yazinc-ai-toolkit
# Laravel JSON AI Settings
Runtime AI configuration in `storage/app/ai/settings.json` — encrypted API keys via Laravel `Crypt`, readable/writable from admin UI.
## When to use
- Clients/admins change AI provider or API keys without redeploying `.env`
- Multiple provider keys (Gemini, OpenRouter, OpenAI, Claude) stored securely
- Default provider comes from config; override per installation in JSON
## Stack
- Laravel 10, `Illuminate\Support\Facades\Crypt`
- File: `config('ai.settings_file')` → `storage/app/ai/settings.json`
- Service: `JsonAiSettingsService`
## Do
- **Gitignore** `storage/app/ai/settings.json` — never commit keys
- Use `getDecrypted()` / `setEncrypted()` for `*_api_key` fields
- Use plain `get()` / `set()` for non-secret settings (`ai_provider`, `ai_model`, prompts)
- `sanitizeProvider()` against `config('ai.enabled_providers')` — migrate stale provider on load
- Create directory on first write (`storage/app/ai/`)
## Don't
- Don't store keys in `.env` for production UI-managed setups (optional env fallback OK for dev)
- Don't log decrypted keys
- Don't expose raw settings JSON to non-admin API responses
## Service API
```php
$settings->get('ai_provider', config('ai.provider'));
$settings->get('ai_model', config('ai.fallback_models.gemini'));
$settings->getDecrypted('gemini_api_key');
$settings->setEncrypted('openrouter_api_key', $plainKey);
$settings->all(); // for admin form — mask keys in UI
```
## Config
```php
// config/ai.php
'settings_file'