* fix(ui): hide the redundant Target trace panel when a rep has a trajectory timeline
An agentic rep's timeline already covers every meaningful step, and the
leftover captured spans are structural wrappers. Show the trace card only
when there is no timeline to supersede it.
* feat(otlp): revealable ingest secrets, authenticated Open WebUI export, cheaper receiver
Credentials
- OTLP secrets get a sealed copy (key derived from SECRET_KEY) so an owning
workspace admin can read them back; verification still uses only the hash.
Reveals are logged. Migration 0019 is additive.
- Saving the OTLP dialog with the mode already in use shows the stored secret
instead of rotating it; rotating is an explicit, confirmed action.
Open WebUI
- Open WebUI exports with Basic auth (sa_open_webui + a password derived from
DJANGO_SECRET_KEY, or SIMPLEAUDIT_CHAT_OTLP_PASSWORD). Embedded modes inject it
at launch; the compose entrypoint derives it and drops the raw key before
Open WebUI starts. …
Remove stale [tool.uv.sources] path override; resolve simpleaudit from PyPI
The [tool.uv.sources] override pointed simpleaudit at a local ../SimpleAudit
checkout, breaking fresh-clone uvx and PyPI publish. The published
simpleaudit==0.3.0 wheel already includes the tracing module (verified:
parse_otlp_json, SpanStore, BuiltinOTLP all present), so the override is
stale.
- Remove [tool.uv.sources] block from pyproject.toml
- Regenerate uv.lock (simpleaudit now resolves from PyPI registry)
- Remove git clone steps from ci.yml, docker.yml, root Dockerfile,
and deploy/compose/Dockerfile (no longer needed)
- Update remaining repo links (SushantGautam/kelkalot → SimulaMet)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Revert "ci(pages): add GitHub Actions job to deploy the gh-pages site"
The marketing site at https://simpleauditstudio.sushant.no lives on the
gh-pages branch and was being deployed by hand. Add the "GitHub default"
Pages deploy job (actions/deploy-pages) that publishes the gh-pages branch
on push (plus manual dispatch), so the site updates via CI instead of
manual deploys.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix(docker): clone core for local path dependency
The Dockerfiles run uv sync which fails because pyproject.toml points
simpleaudit at ../SimpleAudit (editable) for the tracing layer. Clone the
core repo into /SimpleAudit (which is ../SimpleAudit relative to /app)
before uv sync. Add git to the base image.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix(ci): clone core with git instead of checkout action
actions/checkout cannot write outside the workspace. Use git clone to
place the core repo at ../SimpleAudit.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix(ci): checkout core repo for local path dependency
The pyproject.toml points simpleaudit at ../SimpleAudit (editable) so the
studio can use the tracing layer not yet in the published wheel. CI was
failing at uv sync because that path did not exist. Clone the core repo
into ../SimpleAudit before syncing.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrate test runner to pytest; fix ruff lint errors
- Switch CI from manage.py test to pytest --testmon -n auto with a
.testmondata cache for affected-test selection
- Update README test section to document pytest commands (fast, full,
affected-only, targeting)
- Fix 21 pre-existing ruff errors (unused imports, unsorted imports,
Optional[X] -> X | None, f-strings, startswith tuple, nested with)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ci: build Docker images only when Docker-related files change
Moves the image build out of ci.yml into docker.yml with a path filter
(Dockerfiles, compose, dependencies, settings, minimal config, CLI), so
everyday pushes skip it.
feat: interactive runs dashboard, security fixes and codebase cleanup
Dashboard
- Tabulator grid with server-side paging/sort/filter (/runs/data/), bulk
archive/unarchive/cancel, CSV export that follows filters
- Multi-select Target / Scenario set / Experiment filters, date presets,
filters kept in the URL; one-line toolbar
- Columns menu: show/hide, drag to reorder, resize; layout saved per user
(User.preferences) and in the browser; saved only on user actions
- Cancelled stat card so the cards add up to All
- Compare page: run names in headers, jumps to the comparison
Security
- Run snapshots no longer store raw API keys; the worker resolves keys at
execution time (migration strips keys from existing runs)
- UI forms require admin/auditor, same rule as the API; edit controls hidden
for viewers and archived workspaces
- Connection ping scoped to the user's workspaces
- Fix stored XSS (run event log, health page, scenario errors) and broken
inline confirm handlers; data-confirm pattern for forms
Cleanup
- Remove MinIO/boto3, CORS, pytest, u…
Add paths filter so CI only runs when application code, templates,
dependencies, or the workflow itself changes. Docs, deploy configs,
and e2e scripts no longer trigger a full test run.
The project uses no Postgres-specific features (no ArrayField, JSONB,
select_for_update, or window functions). Switching to SQLite:
- Eliminates the Postgres service container (~6s startup + health check)
- Removes the --extra postgres dependency from the test job
- Simplifies the workflow (no env vars for DB connection)
Verified: all 247 tests pass identically on SQLite.
The venv cache caused a race: if the lint job populated the cache first
(with a partial venv), the test job would restore it and skip its own
install, missing psycopg2. Removed the cache — uv sync is only ~2s on
GitHub runners with their warm package cache, not worth the complexity.
Both jobs now always install full deps (--extra dev --extra postgres).
Splits the single 'foundation' job into two independent jobs that run
concurrently:
- lint: ruff check (no Postgres needed, ~5s)
- test: parallel test suite + conditional embedded Hatchet (~85s)
Total wall time is now max(lint, test) instead of lint + test.
- concurrency group cancels stale runs on force-push/new commits
- cache .venv keyed on uv.lock hash (saves ~2s on cache hit)
- remove 'manage.py check' and 'migrate' steps (redundant: Django
test runner performs system checks and creates the test DB from
migrations automatically)
fix(django): allow all hosts to fix HF Spaces proxy DisallowedHost errors
HF Spaces injects unpredictable internal hostnames (e.g.
proxy.spaces.internal.huggingface.tech) that were not in ALLOWED_HOSTS,
causing recurring 400 DisallowedHost errors. Set DJANGO_ALLOWED_HOSTS=*
across all deployment targets and remove the startup check that blocked
wildcard hosts when DEBUG=false. CSRF_TRUSTED_ORIGINS still enforces
origin checks on POST requests.
fix(docker): remove --mock from HF Space, always use OpenAI base URL
The HF Space now points at https://api.openai.com/v1 like local runs.
Users add their API key in the UI to run real audits. No more mock
server or localhost URLs in the demo.
chore: consolidate deps to pyproject.toml + fix all ruff lint errors
Single source of truth: delete requirements.txt, standardize on uv.
- pyproject.toml is now the only dependency manifest (uv.lock pins versions)
- Makefile, Dockerfiles, CI all use 'uv sync' instead of 'pip install -r'
- Add 'server' extra (gunicorn) for the compose image
- Bump simpleaudit 0.2.0 -> 0.2.1 in uv.lock (was already in pyproject)
Fix all 169 pre-existing ruff errors so CI lint step passes:
- Auto-fix: I001, RUF100, UP017, PLR1730, F401, etc. (94)
- Ignore RUF012 (Django Meta/admin/factory false positives) via config
- BLE001: add justified noqa on intentional broad catches (16)
- SIM117: merge nested with statements (5)
- S110/DTZ005/SIM115/EXE001/TRY004/TRY203: targeted fixes (8)
chore: add ruff linting, fix lint violations, fix test indentation
PyPI versions cannot be re-uploaded, so the auto-publish-on-release
workflow causes 400 errors when a tag is re-cut. Publish manually with
twine instead.
- Rewrite README for public release with Quick Start, live demo link
- Add MIT LICENSE
- Publish to PyPI; pin simpleaudit to 0.2.0
- Allow uvx to build from git (hatchling direct-reference metadata)
- Consolidate self-hosting docs to two paths (uvx + docker compose)
- Remove internal process artifacts (AGENTS.md, ADRs, ROADMAP, plans)
- Add 'Report issue or suggest change?' link to footer
- Remove banner.png from repository
fix: make root Dockerfile the HF Space image (was crash-looping)
Root cause: HF Spaces only build the root Dockerfile (there is no
frontmatter key to point elsewhere). The root Dockerfile was the
compose-only application image — no Postgres, no Hatchet, no start.sh,
serving :8000. But the Space expects the app on :7860, so gunicorn
started yet nothing answered on 7860 -> health check failed -> restart
loop.
Fix:
- Root Dockerfile is now the self-contained single-container Space image
(Postgres + Hatchet + web + worker via supervisord, serves :7860).
- Compose application image moved to deploy/compose/Dockerfile; updated
docker-compose.yml and CI to reference it.
- Removed redundant deploy/hf-space/Dockerfile.
- Made supervisord postgres path version-agnostic (matches start.sh).
Verified locally: root image builds, starts healthy, serves :7860 with
bootstrap + seed completing; compose image still builds for the stack.
The root Dockerfile was a comment-only stub, yet compose declared
'build: .' for web/worker/mock-model — the local build fallback would
have produced a broken image. It now builds the actual Django app
image (non-root, healthcheck, gunicorn default CMD) used by the
compose stack and published to GHCR. The HF Space all-in-one variant
stays in deploy/hf-space/Dockerfile.
Add GHCR image pipeline for clone-free deployment
CI builds the app image from the pushed commit via a remote git build
context (no checkout on the runner) and pushes it to GHCR tagged by
branch, semver, and SHA. Compose services now reference
SIMPLEAUDIT_IMAGE with a local build fallback, so hosts without a repo
clone can deploy via 'docker compose pull && up'.
fix(ci): update test target from 'core' to 'infra' after app split