Files
command-center/agent/managed-skills/openwebui-picker-acl-repair/SKILL.md
T

3.1 KiB

name, description
name description
openwebui-picker-acl-repair Add, enable, or repair a model in the Dankclaw OpenWebUI 0.6 picker: connection enable + model row + access_grant trio, verified via /api/models as admin and role=user.

OpenWebUI 0.6 picker: add / enable / repair a model (Dankclaw)

Symptoms: non-admin sees "No results found"/"Model not found" while admin sees the model (repair); endpoint live, model_ids correct, model absent from picker (add).

Law — a picker entry needs ALL legs, keyed by the EXACT upstream served id

  1. openai.api_configs (config table, JSON map by idx): that connection has enable: true and model_ids containing the upstream id. Non-empty model_ids = no upstream fetch (llama.cpp's Ollama-shaped /v1/models is invisible to discovery; halogen/radiance are OpenAI-shaped, model_ids stays authoritative).
  2. model table row: id == upstream id (alias rows with base_model_id set render in the picker but chat fails "Model not found"), base_model_id NULL, is_active 1, user_id = admin uid, params {"context":{"length": PER-SLOT window}}, meta {"description": "..."}.
  3. access_grant row: resource_type=model, resource_id=, principal_type=user, principal_id='*', permission=read. Without it only admins see the model (get_filtered_models drops info-less rows for role=user).

URLs: on-host endpoints via host.containers.internal: (bridge cannot hairpin the host LAN IP); other hosts via LAN IP.

Steps

  1. Snapshot: cp -a webui.db webui.db.bak-.
  2. Apply with host python3 over ssh (no sqlite3 CLI on Dankclaw) on /home/dank/Containers/open-webui/data/webui.db: read-modify-write the whole openai.api_configs JSON value; insert model row (epoch-ms created_at/updated_at); insert access_grant (uuid4 id).
  3. Restart: systemctl --user restart open-webui.service (rootless quadlet) to drop the cached model list. Restart kills browser JWTs: expect one SSO re-round-trip per tab; kill stale tabs first so OAuth state cookies don't race.
  4. Verify (mint tokens in the container; create_token is in open_webui.utils.auth; export WEBUI_SECRET_KEY from /app/backend/.webui_secret_key):
    • GET /api/models (key data) lists the id as admin AND as a role=user token (e.g. qa-e2e-admin uid). This is the picker truth.
    • POST /api/chat/completions, prompt "Reply with exactly one word: pong", max_tokens 1500 (thinking models give empty content + finish_reason length on small budgets).
    • NEVER gate on GET /api/v1/models/list (key items): on 0.6.x it lists workspace models only, [] for connection-backed models (measured 2026-10-09).
  • User API keys need user.permissions JSON features.api_keys=true in config (default false).
  • SSO signups land role pending (ui.default_user_role=pending): UPDATE "user" SET role='user' WHERE email=... (table user, singular, no active column); row exists only after first login.
  • Anubis gates ai.franksdank.cloud for headless browsers; drive direct :3005.
  • The trio is DB-only, lost on a fresh volume. Record changes in serverAppConfigs-docs/Dankclaw/OpenWebUI.md (Facts, backends table, History): the model id is a foreign key across three tables, so any endpoint alias rename must ship the same re-key.