Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
9669d59
fix: make the self-hosting recipe actually work
SushantGautam Sep 29, 2026
d06b942
fix: monitor tick never runs on PostgreSQL (#5)
SushantGautam Sep 29, 2026
f49fa7a
chore: bump version to 0.5.3
SushantGautam Sep 29, 2026
581f420
fix: every new user lands in the Default workspace
SushantGautam Sep 30, 2026
dc2c9f5
feat: optional Open WebUI chat module with Studio single sign-on
SushantGautam Sep 29, 2026
a7f9d5c
feat: chat is part of the bundle, opted out rather than opted in
SushantGautam Sep 29, 2026
349a146
feat: say what the bundled chat is doing while it starts
SushantGautam Sep 29, 2026
ef45dbe
fix: manage Open WebUI's lifecycle like the embedded Hatchet engine
SushantGautam Sep 29, 2026
7160a76
fix: flush the chat readiness line
SushantGautam Sep 29, 2026
23a84b7
feat: give chat the whole screen, with one way back
SushantGautam Sep 29, 2026
1abf845
feat: float the way back over the chat instead of reserving a bar
SushantGautam Sep 29, 2026
05db5d9
refactor: move chat into its own Django app, and scaffold the API in …
SushantGautam Sep 29, 2026
0a69828
feat: push model connections to chat automatically, and quieten the b…
SushantGautam Sep 29, 2026
cc16a94
fix: the chat iframe follows the host in the address bar
SushantGautam Sep 29, 2026
79ed77c
fix: never reuse one browser's session for another's request
SushantGautam Sep 29, 2026
5e61801
test: make the proxy tests prove what they claim, and stop asking Dja…
SushantGautam Sep 29, 2026
4699da6
test: drop the chat tests that no longer carry their weight
SushantGautam Sep 29, 2026
9f82852
feat: hide the chat-history sidebar in the embedded iframe
SushantGautam Sep 29, 2026
6dca42a
fix: hide the sidebar toggle button too
SushantGautam Sep 29, 2026
c3a06ba
feat: pin chat to one model, hide remaining chrome, force temporary c…
SushantGautam Sep 29, 2026
d93bfe3
chat: lock embed to temporary-only chats via URL param
SushantGautam Sep 29, 2026
875869a
chat: add model picker with search, click-outside close, responsive menu
SushantGautam Sep 29, 2026
96a947c
chat: clamp model picker menu to the viewport
SushantGautam Sep 29, 2026
668bc20
chat: center model picker menu with pure CSS
SushantGautam Sep 29, 2026
e263d9c
connections: add per-model "open in chat" icon
SushantGautam Sep 29, 2026
0b491da
chat: pin model via validated handoff, not a query param
SushantGautam Sep 29, 2026
b32e295
chat: namespace models per connection, drop the hardcoded default model
SushantGautam Sep 30, 2026
8c3abe9
chat: forward refused WebSocket upgrades as HTTP errors
SushantGautam Sep 30, 2026
6f5cd79
chat: warn on unregistered model pins, and align provider merge by index
SushantGautam Sep 30, 2026
2a7804a
chat: show a friendly empty state when the user has no project
SushantGautam Sep 30, 2026
64964fa
chat: harden the embed CSS against Open WebUI hook drift
SushantGautam Sep 30, 2026
800d7da
chat: make the optional module cleanly separable from core
SushantGautam Sep 30, 2026
0453a00
spin: detect port occupants and offer to stop our own instances
SushantGautam Sep 30, 2026
3b53fa3
fix: sr-only labels no longer inflate page scroll height
SushantGautam Sep 30, 2026
09d160e
fix: sr-only labels no longer inflate page scroll height
SushantGautam Sep 30, 2026
31ab0bc
Merge branch 'main' into openwebui-integration
SushantGautam Sep 30, 2026
456f402
fix: handle chat startup responses safely
SushantGautam Sep 30, 2026
d6370d5
fix: serve studio logo as chat favicon
SushantGautam Sep 30, 2026
5551a02
fix: brand docker chat favicon
SushantGautam Sep 30, 2026
941e284
fix: start open-webui via start.sh entrypoint, not missing CLI
SushantGautam Sep 30, 2026
5d319bf
fix: make /auto-login/ one-time via single-use token
SushantGautam Sep 30, 2026
2de8fb4
feat: external trace provider (Tempo) for audit evidence
SushantGautam Oct 1, 2026
74f448b
feat(otlp): shared OTLP trace receiver with none/basic/bearer auth
SushantGautam Oct 1, 2026
70c50e1
Simplify OTLP credential UI: single 'Issue credential' button
SushantGautam Oct 1, 2026
45e0611
OTLP credential: single 'Issue credential' button with upsert
SushantGautam Oct 1, 2026
b324d81
fix: make /auto-login/ one-time via single-use token
SushantGautam Sep 30, 2026
8338945
Merge branch 'openwebui-integration' into feat/otlp-receiver
SushantGautam Oct 1, 2026
86c2ac6
Merge openwebui-integration: chat, port conflict, auto-login token
SushantGautam Oct 1, 2026
95b6dcd
Remove testmondata from tracking, add to gitignore
SushantGautam Oct 1, 2026
c2612fd
Set 'None (unauthenticated)' as default OTLP auth mode
SushantGautam Oct 1, 2026
f38885a
Migrate test runner to pytest; fix ruff lint errors
SushantGautam Oct 1, 2026
91c36a7
fix(worker): warn when trace_config is set on a multi-rep run
SushantGautam Oct 1, 2026
def33af
perf(otlp): index bearer token verification by lookup prefix
SushantGautam Oct 1, 2026
9907a88
refactor(otlp): consolidate span storage onto the engine SpanStore
SushantGautam Oct 1, 2026
7846d66
feat(worker): support live tracing on multi-repetition runs
SushantGautam Oct 1, 2026
c7b05ed
Delegate OTLP credential + drift stats to core
SushantGautam Oct 1, 2026
e4609c5
Add SIMPLEAUDIT_OTLP on/off switch for the OTLP listener
SushantGautam Oct 1, 2026
12e0183
Add SIMPLEAUDIT_CHAT_OTLP to export Open WebUI spans to Studio
SushantGautam Oct 1, 2026
f9be6e4
chore(prod): run local dev with DEBUG off and enable prod security he…
SushantGautam Oct 1, 2026
89b69fc
chore(agents): add agent definitions and parallel-orchestrate prompt
SushantGautam Oct 1, 2026
f88bb98
fix(ci): checkout core repo for local path dependency
SushantGautam Oct 1, 2026
8caeef9
fix(ci): clone core with git instead of checkout action
SushantGautam Oct 1, 2026
ff68972
fix(otlp): use core header parsers + fix ruff
SushantGautam Oct 1, 2026
5d65847
fix(settings): gate security headers off for test suite
SushantGautam Oct 1, 2026
6d27e01
fix(csrf): use public get_token() to avoid KeyError in process_response
SushantGautam Oct 1, 2026
4eceb97
fix(docker): clone core for local path dependency
SushantGautam Oct 1, 2026
defd1c1
fix(tests): patch pid_file in OtlpEnvTests
SushantGautam Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
# =============================================================================

# --- Django -----------------------------------------------------------------
# REQUIRED: startup refuses to boot while this is empty or still `change-me`.
# Generate one with: openssl rand -hex 32
DJANGO_SECRET_KEY=change-me
DJANGO_DEBUG=false
DJANGO_ALLOWED_HOSTS=*
Expand Down Expand Up @@ -88,6 +90,31 @@ WORKER_POOL=cpu
# skips if demo runs already exist. Set to false to opt out.
SEED_DEMO_AUDITS=true

# --- Chat (Open WebUI, optional) ------------------------------------------------
# Embeds Open WebUI at /chat/, signed in as the Studio user (workspace admins
# become Open WebUI admins). Off by default — uncomment both lines to enable:
# the first makes the web container serve /chat/, the second makes
# `docker compose up -d` start the chat containers without an extra --profile
# flag. See docs/chat.md.
#SIMPLEAUDIT_CHAT=docker
#COMPOSE_PROFILES=chat
# The origin the browser opens (the chat proxy). Use your own hostname behind
# TLS; on a separate subdomain also set SESSION_COOKIE_DOMAIN.
SIMPLEAUDIT_CHAT_URL=http://localhost:8801
# Where signed-out users are sent back to.
SIMPLEAUDIT_STUDIO_URL=http://localhost:8000
# Optional: export Open WebUI's spans to Studio's OTLP listener. Off by default.
# Exports unauthenticated (matches an enabled "none" credential). For a
# basic/bearer credential, set OTEL_BASIC_AUTH_* to match it. See docs/chat.md.
#SIMPLEAUDIT_CHAT_OTLP=true
#SIMPLEAUDIT_CHAT_OTLP_ENDPOINT=http://web:8000
#OTEL_BASIC_AUTH_USERNAME=
#OTEL_BASIC_AUTH_PASSWORD=
# Optional: switch Studio's OTLP listener (POST /otlp/v1/traces + credential
# management) on or off. ON by default (preserves existing behavior). Set to
# "off" to 404 the /otlp/* and /api/otlp/* routes and hide the OTLP button.
#SIMPLEAUDIT_OTLP=off

# --- Optional observability -----------------------------------------------------

# --- Sentry error tracking & tracing (leave empty to disable) -------------------
Expand Down
47 changes: 47 additions & 0 deletions .github/agents/orchestrator.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
name: Orchestrator
description: Parallel-first coding orchestrator
tools: ['agent', 'edit', 'read', 'search', 'execute']
agents: ['Researcher', 'Verifier', 'Test Reviewer', 'Regression Reviewer']
---

You are the main engineering orchestrator.

Default behavior:
- Decompose non-trivial tasks into independent workstreams.
- Run independent research/review tasks in parallel whenever possible.
- Prefer parallel subagents over doing sequential investigation yourself.
- Keep the main context focused on decisions and integration.
- Do not delegate trivial tasks where coordination overhead exceeds the work.

For implementation:
1. First identify independent components.
2. Launch parallel subagents for codebase research, dependency analysis,
test discovery, and alternative implementation approaches.
3. Integrate the best findings yourself.
4. After editing, launch independent reviewers in parallel:
- correctness
- test coverage
- regression risk
- hallucinated APIs / assumptions
5. Run tests and inspect actual outputs.
6. Fix issues found by reviewers.
7. Repeat verification until there are no actionable failures.

Never trust another agent's factual claim about the repository unless it
provides file references or you verify it yourself.

Prefer evidence from:
- repository contents
- compiler/type checker
- test output
- runtime output
- official documentation

If uncertain, investigate rather than guessing.

Keep working autonomously until:
- the requested result is implemented,
- tests/checks have been run,
- significant reviewer findings have been addressed,
- or a genuine blocker requires user input.
21 changes: 21 additions & 0 deletions .github/agents/regression-reviewer.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: Regression Reviewer
description: Assess regression risk of proposed changes
user-invocable: false
tools: ['read', 'search', 'execute']
---

Assess the regression risk of the proposed changes.

Check:
- existing behavior that depends on the changed code
- callers and consumers that may break
- shared state, configuration, or schema changes
- edge cases the change may have disturbed

Use repository evidence and executable checks whenever possible.

Return only:
1. confirmed regression risks
2. evidence
3. concrete mitigations
13 changes: 13 additions & 0 deletions .github/agents/researcher.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
name: Researcher
description: Fast codebase reconnaissance
user-invocable: false
tools: ['read', 'search']
---

Investigate the assigned question deeply but do not edit files.

Search broadly, identify relevant files and existing patterns,
and return concise findings with exact file references.

Do not speculate when repository evidence is available.
21 changes: 21 additions & 0 deletions .github/agents/test-reviewer.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: Test Reviewer
description: Review test coverage for changed behavior
user-invocable: false
tools: ['read', 'search', 'execute']
---

Review the tests for the changed behavior.

Check:
- tests exist for the new or changed behavior
- tests assert the right outcomes, not just that code runs
- edge cases and failure paths are covered
- the test suite actually passes when run

Run the relevant tests and report actual output.

Return only:
1. confirmed gaps or failures
2. evidence
3. concrete fixes
25 changes: 25 additions & 0 deletions .github/agents/verifier.agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: Verifier
description: Verify implementation claims and detect hallucinations
user-invocable: false
tools: ['read', 'search', 'execute']
---

Independently verify the proposed solution.

Do not assume another agent's claims are correct.

Check:
- referenced files and symbols actually exist
- APIs and function signatures are real
- dependencies actually expose the claimed features
- tests exercise the changed behavior
- implementation matches the original request
- no placeholder or speculative code remains

Use repository evidence and executable checks whenever possible.

Return only:
1. confirmed problems
2. evidence
3. concrete fixes
21 changes: 21 additions & 0 deletions .github/prompts/parallel-orchestrate.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: parallel-orchestrate
description: Parallel-first orchestration convention for substantial tasks
---

Use parallel subagents aggressively for independent work. Optimize for
wall-clock time, not token count. Treat model calls as cheap. Keep yourself
as the coordinator and integrator. Verify claims with repository evidence
and executable checks before concluding.

For every substantial task:
1. Launch 2-3 Researcher subagents in parallel for independent angles
(simplest implementation, architecture-compatible implementation,
hidden risks).
2. Integrate the best findings and implement.
3. Launch Verifier, Test Reviewer, and Regression Reviewer in parallel.
4. Fix confirmed findings and re-verify until there are no actionable
failures.

Keep the delegation tree wide, not deep: orchestrator -> workers/reviewers.
Do not nest subagents more than one level.
19 changes: 15 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,28 @@ jobs:
with:
python-version: "3.12"
- uses: astral-sh/setup-uv@v7
- name: Clone core (local-dev path dependency)
# pyproject.toml points simpleaudit at ../SimpleAudit (editable) so the
# studio can use the tracing layer not yet in the published wheel.
run: git clone --depth 1 https://github.com/kelkalot/simpleaudit.git ../SimpleAudit
- name: Install dependencies
run: uv sync --frozen --extra dev
- name: Lint (ruff)
run: uv run ruff check .
- name: Run tests (parallel)
run: uv run python manage.py test infra --parallel auto --exclude-tag embedded_hatchet
- name: Cache testmon dependency data
uses: actions/cache@v4
with:
path: .testmondata
key: testmon-${{ github.sha }}
restore-keys: |
testmon-
- name: Run tests (parallel, affected-only via testmon)
run: uv run pytest --testmon -n auto -m "not embedded_hatchet"
- name: Check if embedded Hatchet files changed
id: hatchet-changed
run: |
CHANGED=$(git diff --name-only origin/main...HEAD -- infra/minimal_config.py infra/worker.py 2>/dev/null || true)
if [ -n "$CHANGED" ]; then echo "changed=true" >> "$GITHUB_OUTPUT"; else echo "changed=false" >> "$GITHUB_OUTPUT"; fi
if [ -n "$CHANGED"]; then echo "changed=true" >> "$GITHUB_OUTPUT"; else echo "changed=false" >> "$GITHUB_OUTPUT"; fi
- name: Run tests (embedded Hatchet, serial)
if: steps.hatchet-changed.outputs.changed == 'true'
run: uv run python manage.py test infra.tests.test_minimal_config.TestEmbeddedHatchetLifecycle
run: uv run pytest -m "embedded_hatchet"
4 changes: 4 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Clone core (local-dev path dependency)
# pyproject.toml points simpleaudit at ../SimpleAudit (editable) so the
# studio can use the tracing layer not yet in the published wheel.
run: git clone --depth 1 https://github.com/kelkalot/simpleaudit.git ../SimpleAudit
- name: Build HF Space / demo image
run: docker build -t simpleaudit-studio:ci .
- name: Build Compose image
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ app.pid

# Data artifacts (prototype)
data/
.testmondata*
7 changes: 6 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ WORKDIR /app
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
git \
&& rm -rf /var/lib/apt/lists/*

# --- Python dependencies -----------------------------------------------------
# pyproject.toml is the single source of truth; uv.lock pins exact versions.
# uv sync creates /app/.venv; the PATH update keeps the `python` entrypoint.
# The core (simpleaudit) is a local path dependency (../SimpleAudit) so the
# studio can use the tracing layer not yet in the published wheel. Clone it
# into the build context before uv sync.
COPY pyproject.toml uv.lock README.md ./
RUN pip install uv \
RUN git clone --depth 1 https://github.com/kelkalot/simpleaudit.git /SimpleAudit \
&& pip install uv \
&& uv sync --frozen --no-install-project --no-dev
ENV PATH="/app/.venv/bin:$PATH"

Expand Down
59 changes: 56 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,43 @@ Every start applies migrations and makes sure the admin (a superuser) and defaul

### Tests and lint

Tests run under **pytest** (via `pytest-django`). Your existing
`django.test.TestCase` classes run unchanged. Tests are layered: run the
**fast** set while coding (skips the slow integration modules tagged `slow`),
and the **full** set before you commit or open a PR.

```bash
SIMPLEAUDIT_LOCAL_SQLITE=1 uv run manage.py test infra --exclude-tag embedded_hatchet
# Fast — unit + light integration, for the dev loop (~50s, skips the slow modules)
uv run pytest -n auto -m "not slow and not embedded_hatchet"

# Full — everything, for before commit / PR
uv run pytest -n auto -m "not embedded_hatchet"

# Affected-only — run just the tests touched by your changed code (needs a
# prior run to build .testmondata; CI caches it)
uv run pytest --testmon -n auto -m "not slow and not embedded_hatchet"

# Lint
uv run ruff check .

# Target a single module, class, or test to iterate faster
uv run pytest infra/tests/test_workspaces.py # one module
uv run pytest infra/tests/test_workspaces.py::WorkspaceTests # one class
uv run pytest infra/tests/test_workspaces.py::WorkspaceTests::test_create # one test
```

**Tagging**

- `slow` — heavy integration modules (experiments, monitors, judges, engine
integration, full API lifecycle). Skipped by the fast command, always run in
CI. Add `@tag("slow")` to a class to move a slow test out of the fast loop.
- `embedded_hatchet` — starts a real embedded Hatchet worker; runs serially in
CI only when the relevant files change.

The Django `@tag("...")` values are mirrored onto pytest markers by
`conftest.py`, so `-m "not slow"` works the same as
`manage.py test --exclude-tag slow`.

### Other setups

```bash
Expand All @@ -99,14 +131,35 @@ For teams or multi-user setups, use Docker Compose:
git clone https://github.com/SushantGautam/SimpleAuditStudio
cd SimpleAuditStudio
cp .env.example .env
# edit POSTGRES_PASSWORD and BOOTSTRAP_PASSWORD at minimum
# edit DJANGO_SECRET_KEY, POSTGRES_PASSWORD and BOOTSTRAP_PASSWORD at minimum —
# startup refuses to boot while any of them is empty or still `change-me`
docker compose up -d
```

Services: Web UI (:8000), PostgreSQL, Hatchet queue (:8888), Worker. Optional profile: `--profile mock` (mock model API).
Services: Web UI (:8000), PostgreSQL, Hatchet queue (:8888), Worker. Chat (Open WebUI) is included via `.env`; optional profile `--profile mock` adds a mock model API.

See [docs/deployment.md](docs/deployment.md) for production hardening, backups, and upgrades.

## 💬 Chat

SimpleAudit Studio embeds [Open WebUI](https://openwebui.com) at `/chat/`, signed
in as your Studio user — workspace admins become Open WebUI admins.

Chat is opt-in. The local one-liner bundles it by default (pass
`--disable-chat` to turn it off); Docker Compose leaves it out unless `.env`
says otherwise — uncomment `SIMPLEAUDIT_CHAT` and `COMPOSE_PROFILES` in
`.env.example` to include it:

```bash
uvx simpleaudit-studio # chat included
uvx simpleaudit-studio --disable-chat # without it

docker compose up -d # chat only if enabled in .env
```

See [docs/chat.md](docs/chat.md) for how single sign-on works and what must stay
private.

## ✨ What You Can Do

- Build versioned scenario sets and register OpenAI-compatible models
Expand Down
6 changes: 5 additions & 1 deletion accounts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ def validate_password(self, value):
return value

def create(self, validated_data):
return User.objects.create_user(**validated_data)
user = User.objects.create_user(**validated_data)
from accounts.services import grant_default_project

grant_default_project(user)
return user


class WorkspaceItemSerializer(serializers.ModelSerializer):
Expand Down
Loading
Loading