- Forbidden tools accept name or name(arg=value) entries, saved and shown in the builder.
- Forbidden values checked in tool-call arguments, tool results and the final answer.
- Retrieval steps recognised from the trace (gen_ai.retrieval.documents), not tool names.
- Trace error check takes no per-scenario exemptions.
- Remove order-specific scope synthesis, access-refused and session-customer logic,
and the isolate-customer flag; the tool reports its own refusals.
- Scenario pack: CUST-001 story, file-name sources, D02/D09 expectations.
- Bootstrap no longer resets the admin password on each start (keeps sessions).
- Cookie Secure flag switchable via SIMPLEAUDIT_SECURE_COOKIES (default unchanged).
- Run-detail: agentic status and judge badge per result, bar filter, tooltips.
Co-Authored-By: Claude <noreply@anthropic.com>
feat(agentic): route traced agent runs through studio agent models
- Traced agent runs use the studio.agent-* wrapper model with agent tool ids.
- Retrieval checks read gen_ai.retrieval.documents instead of data_source.
- Duplicate model-call flags and redundant badge in the timeline.
- Default agentic pack seeded from infra/fixtures; acme demo pack removed.
- Pipelines/Langfuse sidecar removed; chat sync installs RAG overrides and OTLP credentials.
- Service account (trusted-header admin) for chat API calls.
Co-Authored-By: Claude <noreply@anthropic.com>
5 days ago
feat(chat): service account runs agents as admin; worker and chat settings
- chat/api.py: service_token() signs Studio's service account in through the
trusted headers (admin), minted on demand; no stored password or API key.
- model_registry/services.py: connection_api_key() uses that token for
Studio's own Open WebUI connections, so the inner agent hop authenticates.
- chat/config.py: SERVICE_EMAIL / SERVICE_NAME (SIMPLEAUDIT_CHAT_SERVICE_EMAIL).
- docker-compose.yml: worker gets SIMPLEAUDIT_CHAT_UPSTREAM; WEBUI_SECRET_KEY
is required; ENABLE_OTEL on by default.
- chat/proxy.py: a shared WEBUI_SECRET_KEY from the environment wins over the
saved file; tests cover both.
Co-Authored-By: Claude <noreply@anthropic.com>
feat(chat): startup sync of connections, functions, OTLP credentials and agents
- chat/sync.py: startup_sync() runs push_now (connections, bundled functions,
OTLP credentials) and pushes every agent. Best-effort; never fails startup.
ensure_agent_otlp_credentials() gives each Open WebUI Agents connection a
'none' OTLP credential when chat tracing is on, so agent runs show the trace
checkbox.
- sync_chat_startup management command; called by the worker, the compose web
boot, manage.py dev and the spin/uvx launcher.
- docs/chat.md describes the startup sync.
Co-Authored-By: Claude <noreply@anthropic.com>
feat(chat): per-agent retrieval via bundled RAG overrides filter; drop Langfuse pipelines
Retrieval:
- Agent search modes are Semantic and Hybrid; top K, final K (replaces the
reranker-based rerank top K), relevance threshold, BM25 weight and full
context are saved on the agent. Presets and reranker fields are removed.
- chat/openwebui_functions/studio_rag_overrides.py (global Filter) reads
meta.simpleaudit.retrieval and runs retrieval for that model. Models
without those settings use the global RAG settings.
- chat/sync.py installs the filter, keeps it active and global, and
refreshes it at worker start (ensure_chat_functions), on connection sync
and via sync_chat_models. seed_platform does not need a re-seed.
Seeding:
- seed_platform also loads the Acme Agentic Safety scenario set.
Remove the Langfuse pipelines service (OTel export to Langfuse replaces it):
- Delete chat/pipelines_service.py, chat/pipelines_sidecar.py, the
studio_langfuse_capture filter and their tests.
- Drop the pipelines sidecar from dev_server and the uvx CLI, the pipelines
port from…
- Open WebUI pin: v0.12.0.3-subpath -> v0.12.4.1-subpath (compose default and
embedded wheel). v0.12.4.1 is upstream v0.12.4 plus the fork's subpath build fix,
so the /chat frontend base is baked in and the playground iframe loads.
- ENABLE_VERSION_UPDATE_CHECK defaults to false (Studio pins the build, so the
update banner is noise). Override via env var.
- Docs and comments updated to match.
6 days ago
feat: trusted-header metadata discovery for built-in Open WebUI targets
Agent-targeted audits now discover model metadata without a stored API key:
connections pointing at this deployment's own Open WebUI sign in through the
chat module's X-Studio-* trusted-header flow (same auth as the completion API)
and probe /v1/models with the returned session token. Third-party connections
keep pure Bearer-key behavior; sign-in failure degrades to 'unavailable' and
never blocks an audit.
Also collapse the Target Metadata section on run detail pages behind a
click-to-expand summary.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
feat: make demo-mode login banner overridable via DEMO_BANNER_HTML
Add DEMO_BANNER_HTML env var that replaces the built-in demo banner with
custom HTML when set. Empty (default) keeps the existing banner. Documented
in .env.example and deployment.md.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
docs: expand target-metadata doc with storage and UI display details
Closes #61.
- Discover optional nested JSON model metadata on GET /v1/models/{id},
with fallback to GET /v1/models (also recognizes Open WebUI info.meta).
- Capture once per new run as frozen target metadata; record discovery
status, source, and timestamp. Retries and historical views read the
frozen snapshot only.
- Preserve arbitrary nested prompt bodies, versions, retrieval settings,
tool definitions, and framework-specific fields, with a 256 KiB and
depth limit plus secret-key redaction.
- Show one flattened dot-path row per metadata key in Frozen Manifest,
revealing long values on expansion.
- Add per-key metadata comparisons to Compare Runs Input Parameters,
including missing-key and changed-value highlighting.
- Document the custom compatibility extension; add tests for discovery,
fallback, sanitization, freezing, and comparisons.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Merge remote-tracking branch 'origin/main' into agents/need-explainatory-scenarios-examples-for-agentic
Gravatar avatars are now behind SIMPLEAUDIT_GRAVATAR (default off); when off,
no gravatar.com URL is rendered and templates show the user's initial. The
visualizer sidebar uses the same helper. The Tailwind Play CDN script is pinned
to 3.4.17, the version cdn.tailwindcss.com currently redirects to.
14 days ago
fix: OTLP tracing, timeline merge, port drift, and agent picker
- Fix OTLP_ENABLED frozen before setdefault: move SIMPLEAUDIT_CHAT_OTLP
into manage.py before django.setup() so OWUI exports real spans
- Add _fix_owui_connection_url() to dev_server startup: auto-corrects
the OWUI ModelConnection base_url after port allocation shifts
- Merge synthetic tool/response spans into trajectory timeline when
OWUI only exports CHAIN+LLM (no TOOL/RETRIEVER child spans)
- Add retry-on-empty guard in _streaming_call for SimulaChat's
intermittent empty completions on multi-turn conversations
- Remove leaking {# ... #} template comment from model_pickers.html
- Unify bootstrap password on localdevpass123 (cli, settings, Dockerfile,
docs) + drift-guard test
- Agents target-only in model pickers; server-side guard in parse_design
- OTLP on by default in all modes (.env.example, dev_server, docs)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
feat(privacy): default capture keeps everything the audit needs
- structural (default): span identity, tool arguments and results, retrieval
sources, prompts, and completions
- inputs: structural without model output (completions and output values)
- full: everything, including span events and raw result/output fields
- Secrets are redacted at every level; the verification check follows the contract
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Adds simpleaudit_studio/lifecycle.py so agents can safely start, reuse,
stop, restart, reset and uninstall a local stack without killing unrelated
processes or resetting real data.
- Instance identity: sha256 of canonical checkout path (dev) or data dir
(spin); file locks (owner.lock non-blocking, ports.lock blocking).
- Port allocation before Django starts; worktree baseline 8100.
- _live() validates PID running + create_time + UID to reject PID reuse.
- Destructive boundaries: refuses custom SIMPLEAUDIT_DATA_DIR /
SIMPLEAUDIT_SQLITE_PATH on reset/uninstall; uv cache cleanup is
package-scoped only (never global `uv cache clean`).
- manage.py `dev` and spin CLI dispatch subcommands before django.setup().
- devctl.sh rewritten as a thin compatibility wrapper; all legacy
kill -9 / pgrep / lsof port-based cleanup removed.
Fix orphaned runserver on shutdown: _stop_web now SIGTERMs the reloader
subtree by PID (psutil), never by process group, because the reloader tree
shares the o…
refactor: unify tool name to acme_get_order (single canonical name)
Remove the dual-name confusion between 'acme_lookup_order' (Studio alias)
and 'acme_get_order' (actual OpenWebUI function). All scenario controls,
fixtures, tests, templates, and docs now use the single canonical name
that matches what appears in OTLP traces.
Also repairs pre-existing syntax errors in agentic_scenarios.py
(double docstrings, dangling dict fragments) that prevented the module
from importing, and filters AGENTIC_SCENARIOS to the D-series catalog
core set (D01-D10) as the operational pack.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
feat(agentic): realistic agentic audit demo with real tool execution (#55)
* chore(release): bump version to 0.5.14
Also fixes the missed bump from the 0.5.13 release (pyproject was
still at 0.5.12).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore(release): sync uv.lock version to 0.5.14
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(chat): Open WebUI Function for provider-agnostic Langfuse tracing
The pipelines stub's filter seam already traced chat without touching
providers, but wiring it required either changing a connection's base URL
(connection mode) or running the full open-webui/pipelines sidecar. Add the
bundled 'Studio Langfuse Capture' filter function instead: it runs inside
Open WebUI's own backend, fires on every chat turn for every connection
(OpenAI, Anthropic-compatible, local), and pure-taps inlet/outlet to the
stub. No base URL changes, no extra containers, tracing failures never
break chat. Smoke-tested against the running stub.
docs/chat.md now presents this as the recommend…
feat(audits): single runs become singleton experiments; confirm visibility changes
Anything launched from New Experiment is now an Experiment, even a design
that expands to one run: it gets a singleton Experiment (empty factors) and
redirects to its results page, so every launch has a shareable URL that can
be made public for anonymous viewing. Repeating single setups link their
Monitor to the experiment as well.
- infra/ui: _launch_single always creates the Experiment and links the run
and monitor to it; redirect target is the experiment page
- templates: 'Single run (no comparison)' subtitle on the detail page,
'single run' badge in the experiments list, updated copy
- templates: data-confirm on the Make public / Make private toggles —
making something public warns that anyone with the URL will be able to
view it without an account
- tests: singleton creation/redirect/page rendering; monitor repeat flows
now expect the experiment page and monitor.experiment linkage
- docs: domain-model.md and module docstring updated
Co-authored-by: Copilot <223556219+C…
feat(chat): self-contained Pipelines filter service for Langfuse tracing (issue #21)
Add a tiny FastAPI service that speaks the Open WebUI Pipelines filter
protocol so Studio chats can be traced to Langfuse without Docker or the
pipelines torch/opencv dependency pile. Runs as an opt-in background
sidecar (SIMPLEAUDIT_PIPELINES=on), wired into both manage.py dev and spin.
Captures per chat turn, all at no cost (already in the request/response):
- full messages array (system prompt + history) as trace input/output
- model_parameters (temperature, max_tokens, tools, stop, etc.)
- token usage, finish_reason, requested_model
- first-class session_id (chat id) + user_id for Langfuse Sessions/Users views
- tags: simpleauditstudio
- raw_params catch-all so nothing is silently dropped
Endpoints: /v1/models, /v1/pipelines, /v1/chat/completions (forward or canned),
/v1/{id}/filter/inlet, /v1/{id}/filter/outlet. Uses Langfuse SDK v4 API
(start_as_current_observation + propagate_attributes).
Adds fastapi, uvicorn[standard], langfuse to deps; documents settings in
.env.dev.exampl…
fix(sse): harden live event stream against worker shutdown + gthread workers (#33)
* fix: handle SystemExit and GeneratorExit in SSE event_stream
The long-running SSE poll loop (up to 1 hour) surfaced SystemExit and
GeneratorExit as unhandled errors in Sentry when the worker process was
shut down (SIGTERM during time.sleep) or the client disconnected.
Wrap the polling loop in a try/except that catches these expected
teardown signals, logs at debug level, and re-raises so Python's normal
close semantics apply without surfacing noise in error tracking.
Closes #25
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix(server): run gunicorn with gthread workers for SSE live event streams
Gunicorn's default sync worker cannot heartbeat while actively yielding a
streaming response, so the arbiter SIGABRTs it after the 30s timeout, killing
long-lived SSE streams and raising SystemExit(1). Switch to the threaded
gthread worker, whose main loop heartbeats independently of in-flight requests.
- gunicorn.conf.py (new): gthread workers (workers=2, thre…
25 days ago
Probe /v1/systemone for all OpenAI-compatible connections
/v1/systemone is now a shared System One surface (Ollama, vLLM, OpenRouter
all expose it at {api-root}/v1/systemone), so decision-model detection no
longer special-cases Ollama: every non-OpenRouter connection is probed
once per model, and a 501 (vLLM's "no supported read strategy") is treated
as a definitive "not a decision model" alongside Ollama's 400 "does not
support decision". OpenRouter keeps the typesafe//jev name heuristic
because its /v1/systemone endpoint is a paid proxy with no public model
listing — probing every listed model would bill real inference.
- services: probe_ollama_decision renamed to probe_systemone_decision
(accepts any base_url), 501 handling added; detect_model_capabilities
probes all non-OpenRouter providers, Ollama library name fallback stays
Ollama-only
- ui: comments updated to the provider-agnostic wording
- tests: probe suite renamed + vLLM 501 cases, new OpenAI-compatible
probe cases (vLLM base URL), discover test now asserts the probe for a…
Auto-detect and mark decision models on /connections/
Discover models now fetch rich metadata (id + capabilities) from the
provider. Ollama connections are probed per model via /v1/systemone with a
2-option question: 200 marks the model as a decision model, the
"does not support decision" error marks it as not one (no inference is
spent on non-decision models). OpenRouter connections use the model-id
prefix heuristic (typesafe/, jev) since the decisions catalog is not
public. Decision capability is persisted on RegisteredModel.capabilities,
shown as a badge in the model list and the discover dialog, and is the
gate for using a model as a decision target (SimulaMet/SimpleAudit#104).
- model_registry/services: fetch_remote_models, probe_ollama_decision,
detect_model_capabilities; fetch_remote_model_ids reuses the parser
(also handles Ollama's native {"models": [...]} list shape)
- ConnectionsView add_models trusts discover-probed flags, probes new
ids for Ollama/OpenRouter; ConnectionCheckView contract unchanged
- RegisteredModel.is_…
26 days ago
fix(visualizer): bounded incremental file discovery + fix test gRPC hang
The visualizer file-tree scan (GET /api/visualizer/api/files/) performed an
unbounded os.walk over the results directory, parsing every JSON file with no
limits. When --results_dir resolved to a large tree (e.g. $HOME), the scan
took minutes and the browser fetch stayed pending forever.
Bounded scan (infra/visualizer.py):
- Limits: 5,000 inspected JSON files, 5s budget, depth 8, 100 MB/file —
enforced during traversal, not afterward.
- Partial results with truncated/reason/inspected/elapsed_seconds metadata;
never reports a truncated tree as complete.
- Persistent metadata index (~/.simpleaudit-studio/visualizer-index.json)
keyed by (path, mtime, size) — unchanged files are not re-parsed.
- watchfiles for incremental updates via /api/visualizer/api/files/changed/.
- Frontend shows a truncation warning banner and polls the changed endpoint.
- CLI warns when results dir is home/cwd and displays scan limits.
Test fix (infra/tests/test_api_e2e.py):
- Mock audits.views.submit_audit_…
feat(chat): hide all Open WebUI-backed surfaces when chat is disabled
When SIMPLEAUDIT_CHAT is off (--disable-chat), the Agents surface,
experiment model picker, and Open WebUI-backed Admin Settings tabs are
unavailable, but they still leaked into the UI:
- Sidebar/agents pages and the /agents/ managers are already gated; this
closes the remaining leaks:
- New Experiment model picker no longer offers an "Agents" group (local
reference agent rows were leaking through as pickable models).
- Admin Settings no longer shows the Knowledge & Retrieval / Web Search /
Sub-agents tabs, and their ?tab= URLs redirect to the Overview instead
of calling a down Open WebUI.
agent_models is computed from an empty list while chat is off, so the
existing template guard hides the group; the three admin tabs are added
to the tab list only when chat_enabled() and their dispatch is guarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
28 days ago
Phase 4: Production Readiness (docs + deployment guide)
Seed descriptive Acme scenarios and a completed synthetic run with trace and Agentic verdict rollups, without running a model. Preserve the text-judge result separately from deterministic trace checks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep Open WebUI authoritative while exposing a safe read-only projection to agent authors and freezing that projection into agent audit snapshots without storing credentials.
Caddy is the only front-door implementation. caddyserver is a hard
dependency with wheels for every platform, so the ~520-line Python handler
could only run on a broken install, where it silently diverged from the
Caddyfile it was meant to mirror (second implementation of identity
strip, forward-auth, CSS mask, favicon, /workspace repair and WS piping).
_caddy_binary() now raises instead of returning None and serve() has no
fallback; a missing binary (or Caddy that never binds) surfaces at start,
and the dev/CLI callers stop Open WebUI and continue the rest of the stack.
Removes the fallback-only stubs and their 19 tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
feat: sync agents, knowledge bases and tools to Open WebUI
Agents become Open WebUI workspace model entries (studio.agent-<pk>) that
inherit the base connection model and attach the agent's knowledge bases via
meta.knowledge. Knowledge bases and tools are created/renamed/deleted in
Open WebUI's own stores; Studio keeps only the returned external_id for
listing and the durable audit config.
- Agent.external_id + migration; included in config_snapshot()
- integrations/openwebui: push_agent (idempotent create/update/recreate),
agent_remote (live fetch), delete_agent; chat api gains workspace-model,
KB update/delete and tool read/update/delete endpoints
- API + HTML agent/KB/tool create, update and delete propagate best-effort;
a down Open WebUI is logged, never fatal; next edit retries
- agent detail page and GET /api/agents/<id>/ (openwebui_live) show the
live Open WebUI entry with cached fallback
- Test-in-Chat pins the synced model entry so KBs take effect
- docs/chat.md: new 'Agents, knowledge bases and tools' section
Co-authored-by…
Seed: seed_platform now creates a demo agent (Support Refund Assistant)
linked to an 'Acme Retail Policy' knowledge base (2 sample policy docs)
and an 'Acme Order Lookup' tool. Local rows always; when chat is enabled,
the KB, docs, and toolkit are also pushed to Open WebUI (idempotent by
name/id, external_id backfilled on rerun). Opt out with --skip-demo-agent.
Also fixes the tools endpoints: the Tools page is /api/v1/tools (toolkit
modules), not /api/v1/functions (pipes/filters) - corrected the seed
push and both pull-side readers.
Chat: repair the subpath fork's root-relative /workspace/knowledge hard
navigation (308 back onto the subpath at the front door) and pass
?embed=admin to /chat/authz via X-Studio-Embed since the Caddy rewrite
drops the query.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
feat(chat): unify Studio + Open WebUI behind one Caddy front door at /chat/
Replaces the two-port embedded model (Studio :8000 + OWUI :8801 in an
iframe) with a single-origin, single-port wiring, identical for local dev
and Docker:
- Caddy is the ONLY published listener (:8000). Studio and Open WebUI
publish no ports; /chat/* reverse-proxies to the subpath build with the
prefix preserved (handle, not handle_path); /ai/ and everything else
go to Django.
- Uses the subpath-capable Open WebUI fork wheel (v0.11.4-subpath,
WEBUI_SUBPATH=/chat), so OWUI emits every URL prefixed with /chat and
no Caddy-side URL rewriting is needed.
- Forward-auth to /chat/authz injects trusted identity headers
(X-Studio-Email/Name/Role); client-forged values are stripped at site
level; 401 redirects to the Studio login.
- Studio's /chat/css-mask serves the embed stylesheet (admin vs plain
mask) in place of a mounted custom.css.
- Local dev: manage.py dev manages a bundled Caddy (uvx caddy /
caddyserver) with a generated Caddyfile; Docker: caddy:2-alpine
chat-prox…
refactor: rename .env.local.example to .env.dev.example
The file documents the dev mode (manage.py dev) specifically, not "local"
in general, and now pairs consistently with the dev.sqlite3 default.
Update all references (README, docs, .env.example, config comments).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Docs: README and docs/deployment.md now present exactly four standard,
jargon-free ways to run Studio (one-liner, Docker, Compose, development)
with standard commands, plain-language explanation, where data lives,
and how to disable chat. `uv run manage.py dev` is the only documented
dev entry point; raw `dev_server --embedded` mentions removed.
Single-docker fixes (the old documented command did not work):
- pyproject.toml: the committed [tool.uv.sources] override pointed at a
machine-local editable checkout, so `docker build` failed. Pin the
engine to PyPI simpleaudit 0.3.1 (has the traceparent-to-wire fix
and the tracing APIs this repo imports) and drop the override.
- Dockerfile: set SIMPLEAUDIT_DATA_DIR=/data and pre-create/own /data,
so `-v sa-data:/data` actually persists the app data; document the
standard build+run. The container keeps listening on 7860 (HF Space
convention), so the standard mapping is -p 8000:7860.
Verified: image builds from committed deps; con…
compose: chat on by default (still off-able via .env)
- .env.example ships SIMPLEAUDIT_CHAT=docker + COMPOSE_PROFILES=chat
enabled, so a fresh compose setup starts the chat containers and the
web service serves /chat/
- runtime profile: compose chat is now "on" with chat_mode="docker"
(new ModeProfile.chat_mode field); effective_chat_mode returns the
per-mode chat mode for on-defaults instead of hardcoding "embedded"
- mode command reports the effective chat value incl. compose defaults
- docs (README, deployment, chat, spec) updated: chat is on in every
mode; compose turns it off via SIMPLEAUDIT_CHAT=off + dropping the
chat profile; pre-existing .env files need the two lines added
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`manage.py dev` (and `dev_server --embedded`) now behaves like the uvx CLI
for sign-in: on start it generates a single-use SIMPLEAUDIT_AUTO_LOGIN_TOKEN,
prints a one-time sign-in link, and opens the default browser signed in as
the bootstrap admin (--no-browser skips the pop-up; the link still works once).
- infra/ui.py: the /auto-login/ endpoint gate widens from MINIMAL_CONFIG to
also allow SIMPLEAUDIT_LOCAL_SQLITE (the dev mode). Still one-time, and still
404 in every deployed/container mode.
- dev_server: token is set in the environment before the web process is
spawned, so the runserver child inherits it; the browser-open helper polls
/healthz (not the token URL) so the probe can't consume it.
- dev: --no-browser passthrough.
- Tests: the "disabled outside minimal config" case now proves 404 with
neither flag, and a new case proves the dev SQLite mode signs in.
- Docs: README daily-work, deployment.md dev section + command table.
Verified: 41 affected tests pass; live s…
Introduce a single source of truth for how the stack runs
(config/runtime.py: ModeProfile, resolve_mode, effective_chat_mode) and
expose four modes: single-docker, compose, embedded, dev.
- `manage.py dev` (new): zero-Docker dev stack (SQLite + embedded Hatchet),
chat on by default, with --disable-chat/--no-worker/--no-reload.
- `manage.py mode` (new): diagnostic of the active mode.
- dev_server: the removed legacy external-Postgres path is gone; bare
`dev_server` now errors listing the four modes.
- Chat precedence is flag > env > default, resolved in manage.py before
django.setup() so --disable-chat wins even when a .env pins chat on.
The uvx CLI already applied the same rule.
- Docs: README four-modes section, deployment.md restructure, spec update,
.env.local.example chat section.
Verified: 17 runtime unit tests + 691-test fast suite pass; dev with and
without --disable-chat smoke-tested (8801 up/down accordingly); ruff clean.
Co-authored-by: Copilot <223556219+Copilot…
docs: drop legacy modes; make chat always disableable
Spec update per review: the legacy non-embedded dev_server (external
Postgres + Hatchet) is removed in code and docs, not documented as
"advanced". Chat stays on-by-default for single-process modes but is
always disableable via env (SIMPLEAUDIT_CHAT=off) or CLI flag, with an
explicit env > flag > mode-default precedence.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a spec for an explicit SIMPLEAUDIT_MODE (single-docker, compose,
embedded, dev) with a resolve_mode() source of truth, a uniform chat
default, a `manage.py dev` alias, and a `manage.py mode` diagnostic.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
docs: add Open WebUI resource management implementation plan
Bite-sized TDD plan for the restricted-iframe resource manager:
embed_admin.css mask, proxy admin-marker CSS selection,
AgentResourcesView + template + URL, Resources submenu under
Agents, and live end-to-end verification. Routes and DOM hooks
verified against the running Open WebUI instance (/workspace/*,
#workspace-container).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
docs: revise Open WebUI resource spec to Approach A (restricted iframe)
Per user direction, flip the primary approach from native Studio forms
(B) to a restricted iframe (A): embed Open WebUI's native admin pages
and mask all but the target section, delegating document upload,
chunking, and MCP config to Open WebUI's own UI. Studio only reads via
the existing pull-sync (no push). Adds the admin mask CSS, the
AgentResourcesView, and a "Resources" submenu under Agents at
/agents/resources/.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>