simpleaudit-studio 0.2.4__tar.gz → 0.2.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/.env.example +2 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/.env.local.example +3 -3
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/.github/workflows/ci.yml +7 -5
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/.gitignore +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/Dockerfile +8 -4
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/Makefile +1 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/PKG-INFO +7 -3
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/README.md +2 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/views.py +2 -5
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/comparison.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/events.py +1 -4
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/services.py +4 -3
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/views.py +2 -3
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/deploy/compose/Dockerfile +9 -5
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/deploy/e2e_smoke.py +10 -8
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/deploy/mock_openai_server.py +4 -8
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/deploy/seed_bulk.py +15 -9
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/docs/deployment.md +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/e2e/test_ui.py +2 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/engine.py +10 -10
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/health.py +2 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/logging.py +2 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/purge_test_data.py +6 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/run_worker.py +0 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/seed_demo_audits.py +2 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/seed_platform.py +7 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/readiness.py +2 -4
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/seed.py +3 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/simpleaudit_package.py +2 -3
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/factories.py +9 -5
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_api_e2e.py +1 -6
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_archive.py +4 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_clone.py +7 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_poll_results.py +7 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_rename.py +4 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_run_freeze.py +2 -3
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_sse.py +6 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_submission.py +8 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_timing.py +4 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_auth_projects.py +0 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_bootstrap.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_engine_integration.py +64 -52
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_health_panel.py +11 -7
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_middleware.py +1 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_minimal_config.py +6 -6
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_model_registry.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_scenarios.py +4 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_seed_platform.py +2 -4
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_smoke_all_pages.py +13 -5
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_workspaces.py +8 -3
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/ui.py +33 -27
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/worker.py +8 -8
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/manage.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/serializers.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/views.py +5 -6
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/pyproject.toml +18 -4
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/admin.py +7 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/views.py +9 -4
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/simpleaudit_studio/cli.py +11 -11
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/uv.lock +49 -6
- simpleaudit_studio-0.2.4/requirements.txt +0 -28
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/.dockerignore +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/.github/workflows/publish.yml +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/LICENSE +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/admin.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/apps.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/auth_urls.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/migrations/0001_initial.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/migrations/0002_user_workos_user_id.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/migrations/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/models.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/project_urls.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/serializers.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/services.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/accounts/workos_auth.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/admin.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/apps.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/migrations/0001_initial.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/migrations/0002_add_audit_run_archived.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/migrations/0003_auditrun_updated_at.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/migrations/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/models.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/serializers.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/audits/urls.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/config/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/config/asgi.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/config/settings.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/config/urls.py +8 -8
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/config/wsgi.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/deploy/postgres-init.sql +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/docker-compose.yml +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/docs/architecture.md +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/docs/domain-model.md +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/admin.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/apps.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/context_processors.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/exceptions.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/fixtures/demo_audit_results.json +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/hashing.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/health_api.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/bootstrap_platform.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/middleware.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/minimal_config.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/permissions.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/startup_checks.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_audit_events.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_comparison.py +2 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_health.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_purge_test_data.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_scenario_import_export.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/tests/test_workspaces_ui.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/admin.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/apps.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/migrations/0001_initial.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/migrations/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/models.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/services.py +1 -1
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/model_registry/urls.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/apps.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/migrations/0001_initial.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/migrations/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/models.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/serializers.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/services.py +2 -2
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/scenarios/urls.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/simpleaudit_studio/__init__.py +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/static/favicon-16x16.svg +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/static/favicon-32x32.svg +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/static/favicon.svg +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/static/js/diff.min.js +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/static/logo.png +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/static/logo.svg +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/404.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/audit_detail.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/auth/login.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/auth/register.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/auth/workos_login.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/auth/workos_verify.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/base.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/compare.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/dashboard.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/health.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/models.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/new_audit.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/scenario_result_detail.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/scenarios.html +0 -0
- {simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/templates/workspaces.html +0 -0
|
@@ -82,10 +82,10 @@ SSE_MAX_CONNECTIONS_PER_USER=10
|
|
|
82
82
|
|
|
83
83
|
# --- SimpleAudit engine ---------------------------------------------------------
|
|
84
84
|
# No configuration needed here. The engine is a normal pip dependency pinned in
|
|
85
|
-
#
|
|
85
|
+
# pyproject.toml; its version + optional git commit are read from the installed
|
|
86
86
|
# package metadata automatically (infra/simpleaudit_package.py). To develop
|
|
87
87
|
# against an unmerged revision, create a gitignored simpleaudit-dependency.yaml
|
|
88
|
-
# at the project root with a single `git_ref:` key — do NOT edit
|
|
88
|
+
# at the project root with a single `git_ref:` key — do NOT edit pyproject.toml.
|
|
89
89
|
|
|
90
90
|
# --- Model API credentials (resolved at execution time, never stored) ----------
|
|
91
91
|
# Add one variable per model endpoint's `secret_reference`, e.g.:
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# (see `.env.example`).
|
|
10
10
|
#
|
|
11
11
|
# Prerequisites:
|
|
12
|
-
# 1. A Python 3.12+ virtualenv with `
|
|
12
|
+
# 1. A Python 3.12+ virtualenv with `uv sync --extra dev --extra postgres`
|
|
13
13
|
# 2. Docker, for Postgres + Hatchet (the "partial Docker" pattern below)
|
|
14
14
|
# 3. A SimpleAudit engine checkout (for the worker to execute audits)
|
|
15
15
|
# =============================================================================
|
|
@@ -66,14 +66,14 @@ WORKER_POOL=cpu
|
|
|
66
66
|
|
|
67
67
|
# --- SimpleAudit engine ---------------------------------------------------------
|
|
68
68
|
# No configuration needed here. The engine is a normal pip dependency pinned in
|
|
69
|
-
#
|
|
69
|
+
# pyproject.toml; its version + optional git commit are read from the installed
|
|
70
70
|
# package metadata automatically (infra/simpleaudit_package.py).
|
|
71
71
|
#
|
|
72
72
|
# To develop against an unmerged engine revision, create a gitignored
|
|
73
73
|
# simpleaudit-dependency.yaml at the project root containing ONLY:
|
|
74
74
|
# git_ref: <full-40-char-sha>
|
|
75
75
|
# That value is recorded as the run's git_commit provenance. Do NOT edit
|
|
76
|
-
#
|
|
76
|
+
# pyproject.toml for a dev override.
|
|
77
77
|
|
|
78
78
|
# --- Model API credentials (resolved at execution time, never stored) ----------
|
|
79
79
|
# Add one variable per model endpoint's `secret_reference`, e.g.:
|
|
@@ -37,12 +37,14 @@ jobs:
|
|
|
37
37
|
- uses: actions/setup-python@v5
|
|
38
38
|
with:
|
|
39
39
|
python-version: "3.12"
|
|
40
|
-
|
|
40
|
+
- uses: astral-sh/setup-uv@v7
|
|
41
41
|
- name: Install dependencies
|
|
42
|
-
run:
|
|
42
|
+
run: uv sync --frozen --extra dev --extra postgres
|
|
43
|
+
- name: Lint (ruff)
|
|
44
|
+
run: uv run ruff check .
|
|
43
45
|
- name: Django checks
|
|
44
|
-
run: python manage.py check
|
|
46
|
+
run: uv run python manage.py check
|
|
45
47
|
- name: Migrations from empty database
|
|
46
|
-
run: python manage.py migrate
|
|
48
|
+
run: uv run python manage.py migrate
|
|
47
49
|
- name: Run tests
|
|
48
|
-
run: python manage.py test infra
|
|
50
|
+
run: uv run python manage.py test infra
|
|
@@ -16,7 +16,7 @@ staticfiles/
|
|
|
16
16
|
.env.local
|
|
17
17
|
|
|
18
18
|
# Dev-only SimpleAudit engine override (git_ref). Never committed — production
|
|
19
|
-
# relies on the
|
|
19
|
+
# relies on the pyproject.toml pin. See infra/simpleaudit_package.py.
|
|
20
20
|
simpleaudit-dependency.yaml
|
|
21
21
|
|
|
22
22
|
# IDE
|
|
@@ -22,16 +22,20 @@ WORKDIR /app
|
|
|
22
22
|
|
|
23
23
|
# --- System dependencies -----------------------------------------------------
|
|
24
24
|
# curl: healthchecks
|
|
25
|
-
# git: required to install SimpleAudit engine from its pinned git ref
|
|
26
25
|
RUN apt-get update \
|
|
27
26
|
&& apt-get install -y --no-install-recommends \
|
|
28
27
|
curl \
|
|
29
|
-
git \
|
|
30
28
|
&& rm -rf /var/lib/apt/lists/*
|
|
31
29
|
|
|
32
30
|
# --- Python dependencies -----------------------------------------------------
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
# pyproject.toml is the single source of truth; uv.lock pins exact versions.
|
|
32
|
+
# The postgres extra is included because Django imports the psycopg driver at
|
|
33
|
+
# startup even when SIMPLEAUDIT_MINIMAL=1 uses SQLite for the domain DB.
|
|
34
|
+
# uv sync creates /app/.venv; the PATH update keeps the `python` entrypoint.
|
|
35
|
+
COPY pyproject.toml uv.lock README.md ./
|
|
36
|
+
RUN pip install uv \
|
|
37
|
+
&& uv sync --frozen --no-install-project --no-dev --extra postgres
|
|
38
|
+
ENV PATH="/app/.venv/bin:$PATH"
|
|
35
39
|
|
|
36
40
|
# --- Application code --------------------------------------------------------
|
|
37
41
|
COPY . .
|
|
@@ -14,8 +14,7 @@ help: ## Show available targets
|
|
|
14
14
|
@grep -E '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}'
|
|
15
15
|
|
|
16
16
|
venv: ## Create the local virtualenv and install dependencies
|
|
17
|
-
|
|
18
|
-
$(VENV)/bin/pip install -r requirements.txt
|
|
17
|
+
uv sync --extra dev --extra postgres
|
|
19
18
|
|
|
20
19
|
local-setup: ## Local dev: venv + .env + migrations + bootstrap + seed (idempotent)
|
|
21
20
|
@test -d $(VENV) || $(MAKE) venv
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: simpleaudit-studio
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.6
|
|
4
4
|
Summary: Production AI model audit platform — one-liner demo mode via uvx
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -15,14 +15,17 @@ Requires-Dist: pydantic<3,>=2.7
|
|
|
15
15
|
Requires-Dist: python-dotenv==1.1.1
|
|
16
16
|
Requires-Dist: requests==2.32.5
|
|
17
17
|
Requires-Dist: sentry-sdk[django]>=2.0
|
|
18
|
-
Requires-Dist: simpleaudit==0.2.
|
|
18
|
+
Requires-Dist: simpleaudit==0.2.1
|
|
19
19
|
Requires-Dist: workos==10.4.0
|
|
20
20
|
Provides-Extra: dev
|
|
21
21
|
Requires-Dist: factory-boy==3.3.2; extra == 'dev'
|
|
22
22
|
Requires-Dist: pytest; extra == 'dev'
|
|
23
23
|
Requires-Dist: pytest-django; extra == 'dev'
|
|
24
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
24
25
|
Provides-Extra: postgres
|
|
25
26
|
Requires-Dist: psycopg[binary]==3.2.13; extra == 'postgres'
|
|
27
|
+
Provides-Extra: server
|
|
28
|
+
Requires-Dist: gunicorn==23.0.0; extra == 'server'
|
|
26
29
|
Description-Content-Type: text/markdown
|
|
27
30
|
|
|
28
31
|
---
|
|
@@ -54,13 +57,14 @@ uvx simpleaudit-studio
|
|
|
54
57
|
|
|
55
58
|
[`uvx`](https://docs.astral.sh/uv/#uvx) installs the [`simpleaudit-studio`](https://pypi.org/project/simpleaudit-studio/) package and runs it in an isolated environment. No Docker, no Postgres, no manual setup. Opens at http://localhost:8000 (login: `studio` / `admin123`). A mock model server is pre-seeded so you can start exploring audit results immediately.
|
|
56
59
|
|
|
60
|
+
🌐 Or skip the setup entirely — try the live demo: <a href="https://sushantgautam-simpleaudit-studio.hf.space" target="_blank" rel="noopener noreferrer">sushantgautam-simpleaudit-studio.hf.space</a>
|
|
61
|
+
|
|
57
62
|
Want the **latest unreleased code** from this repo instead of the PyPI release? Same one-liner, pointed at git:
|
|
58
63
|
|
|
59
64
|
```bash
|
|
60
65
|
uvx --from "git+https://github.com/SushantGautam/SimpleAuditStudio" spin
|
|
61
66
|
```
|
|
62
67
|
|
|
63
|
-
🌐 Or skip the setup entirely — try the live demo: <a href="https://sushantgautam-simpleaudit-studio.hf.space" target="_blank" rel="noopener noreferrer">sushantgautam-simpleaudit-studio.hf.space</a>
|
|
64
68
|
|
|
65
69
|
### 🤖 Using Real Models
|
|
66
70
|
|
|
@@ -27,13 +27,14 @@ uvx simpleaudit-studio
|
|
|
27
27
|
|
|
28
28
|
[`uvx`](https://docs.astral.sh/uv/#uvx) installs the [`simpleaudit-studio`](https://pypi.org/project/simpleaudit-studio/) package and runs it in an isolated environment. No Docker, no Postgres, no manual setup. Opens at http://localhost:8000 (login: `studio` / `admin123`). A mock model server is pre-seeded so you can start exploring audit results immediately.
|
|
29
29
|
|
|
30
|
+
🌐 Or skip the setup entirely — try the live demo: <a href="https://sushantgautam-simpleaudit-studio.hf.space" target="_blank" rel="noopener noreferrer">sushantgautam-simpleaudit-studio.hf.space</a>
|
|
31
|
+
|
|
30
32
|
Want the **latest unreleased code** from this repo instead of the PyPI release? Same one-liner, pointed at git:
|
|
31
33
|
|
|
32
34
|
```bash
|
|
33
35
|
uvx --from "git+https://github.com/SushantGautam/SimpleAuditStudio" spin
|
|
34
36
|
```
|
|
35
37
|
|
|
36
|
-
🌐 Or skip the setup entirely — try the live demo: <a href="https://sushantgautam-simpleaudit-studio.hf.space" target="_blank" rel="noopener noreferrer">sushantgautam-simpleaudit-studio.hf.space</a>
|
|
37
38
|
|
|
38
39
|
### 🤖 Using Real Models
|
|
39
40
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
4
|
from django.contrib.auth import authenticate, login
|
|
5
|
-
from django.db import connection
|
|
6
5
|
from django.http import JsonResponse
|
|
7
6
|
from rest_framework import status
|
|
8
7
|
from rest_framework.authtoken.models import Token
|
|
@@ -10,28 +9,26 @@ from rest_framework.decorators import api_view, permission_classes
|
|
|
10
9
|
from rest_framework.permissions import AllowAny, IsAuthenticated
|
|
11
10
|
from rest_framework.response import Response
|
|
12
11
|
|
|
13
|
-
from infra.exceptions import StableAPIError
|
|
14
12
|
from accounts.models import Project, ProjectMembership, User
|
|
15
13
|
from accounts.serializers import (
|
|
16
14
|
MemberAddSerializer,
|
|
17
15
|
MemberRoleSerializer,
|
|
18
16
|
ProjectMembershipSerializer,
|
|
19
|
-
ProjectSerializer,
|
|
20
17
|
RegisterSerializer,
|
|
21
18
|
UserSerializer,
|
|
22
19
|
WorkspaceCreateSerializer,
|
|
23
20
|
WorkspaceItemSerializer,
|
|
24
21
|
WorkspaceUpdateSerializer,
|
|
25
22
|
)
|
|
26
|
-
from infra.readiness import ready_payload
|
|
27
23
|
from accounts.services import (
|
|
28
24
|
DEFAULT_PROJECT_SLUG,
|
|
29
|
-
bootstrap_admin_and_default_project,
|
|
30
25
|
create_workspace,
|
|
31
26
|
delete_workspace,
|
|
32
27
|
ensure_project_access,
|
|
33
28
|
update_workspace,
|
|
34
29
|
)
|
|
30
|
+
from infra.exceptions import StableAPIError
|
|
31
|
+
from infra.readiness import ready_payload
|
|
35
32
|
|
|
36
33
|
logger = logging.getLogger(__name__)
|
|
37
34
|
|
|
@@ -160,7 +160,7 @@ def compare_runs(project, run_ids: list[int]) -> dict:
|
|
|
160
160
|
elif label == "Scenario set version" and r.scenario_set_version:
|
|
161
161
|
url = f"/scenarios/?set={r.scenario_set_version.scenario_set_id}"
|
|
162
162
|
cells.append(_cell(text, url))
|
|
163
|
-
differs = len(
|
|
163
|
+
differs = len({c["text"] for c in cells}) > 1
|
|
164
164
|
input_rows.append({"label": label, "cells": cells, "differs": differs})
|
|
165
165
|
|
|
166
166
|
return {
|
|
@@ -15,8 +15,6 @@ events are inputs only; the worker bridges them into these rows.
|
|
|
15
15
|
"""
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
-
import json
|
|
19
|
-
|
|
20
18
|
from django.db import models, transaction
|
|
21
19
|
|
|
22
20
|
|
|
@@ -124,8 +122,7 @@ def upsert_scenario_result(
|
|
|
124
122
|
result=result or {},
|
|
125
123
|
)
|
|
126
124
|
return
|
|
127
|
-
|
|
128
|
-
existing.attempts = attempts
|
|
125
|
+
existing.attempts = max(existing.attempts, attempts)
|
|
129
126
|
existing.status = status
|
|
130
127
|
if result is not None:
|
|
131
128
|
existing.result = result
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
"""Audit run creation and freeze services."""
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
|
-
from django.conf import settings
|
|
5
4
|
from django.db import transaction
|
|
6
5
|
from django.utils import timezone
|
|
7
6
|
|
|
7
|
+
from accounts.models import Project
|
|
8
8
|
from audits.events import append_event
|
|
9
9
|
from audits.models import AuditRun
|
|
10
10
|
from infra.exceptions import StableAPIError
|
|
11
11
|
from infra.simpleaudit_package import resolve_engine_provenance
|
|
12
12
|
from model_registry.models import ModelEndpoint
|
|
13
|
-
from accounts.models import Project
|
|
14
13
|
from scenarios.models import ScenarioSetVersion
|
|
15
14
|
from scenarios.services import require_project_role
|
|
16
15
|
|
|
@@ -131,7 +130,9 @@ def submit_audit_run(run: AuditRun) -> str | None:
|
|
|
131
130
|
reason is recorded in ``runtime_metadata["submission"]`` so an operator (or a
|
|
132
131
|
later retry command) can resubmit without re-freezing inputs.
|
|
133
132
|
"""
|
|
134
|
-
from infra.worker import
|
|
133
|
+
from infra.worker import (
|
|
134
|
+
submit_run_workflow, # lazy: needs no live server at import time
|
|
135
|
+
)
|
|
135
136
|
|
|
136
137
|
items = list(
|
|
137
138
|
run.scenario_set_version.items.select_related("scenario", "revision").order_by("position")
|
|
@@ -9,6 +9,8 @@ from rest_framework.decorators import api_view, permission_classes
|
|
|
9
9
|
from rest_framework.permissions import IsAuthenticated
|
|
10
10
|
from rest_framework.response import Response
|
|
11
11
|
|
|
12
|
+
from accounts.models import Project
|
|
13
|
+
from accounts.services import ensure_project_access
|
|
12
14
|
from audits.events import ScenarioResult, list_events
|
|
13
15
|
from audits.models import AuditRun
|
|
14
16
|
from audits.serializers import AuditRunCreateSerializer, AuditRunSerializer
|
|
@@ -16,9 +18,7 @@ from audits.services import create_audit_run, submit_audit_run
|
|
|
16
18
|
from infra.exceptions import StableAPIError
|
|
17
19
|
from infra.middleware import set_correlation_context
|
|
18
20
|
from model_registry.models import ModelEndpoint
|
|
19
|
-
from accounts.models import Project
|
|
20
21
|
from scenarios.models import ScenarioSetVersion
|
|
21
|
-
from accounts.services import ensure_project_access
|
|
22
22
|
|
|
23
23
|
logger = logging.getLogger("simpleaudit.audit")
|
|
24
24
|
|
|
@@ -214,7 +214,6 @@ def stream_audit_run_events(request, project_id, run_id):
|
|
|
214
214
|
with a higher id — standard SSE replay semantics. The stream ends when a
|
|
215
215
|
terminal run event (completed/failed/cancelled) is observed.
|
|
216
216
|
"""
|
|
217
|
-
from django.contrib.auth.decorators import login_required
|
|
218
217
|
from django.http import Http404
|
|
219
218
|
|
|
220
219
|
# This is called via URL dispatch; enforce auth manually since we're not using DRF.
|
|
@@ -23,16 +23,20 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
|
23
23
|
|
|
24
24
|
WORKDIR /app
|
|
25
25
|
|
|
26
|
-
# curl: healthchecks
|
|
27
|
-
# pinned git ref in requirements.txt.
|
|
26
|
+
# curl: healthchecks
|
|
28
27
|
RUN apt-get update \
|
|
29
28
|
&& apt-get install -y --no-install-recommends \
|
|
30
29
|
curl \
|
|
31
|
-
git \
|
|
32
30
|
&& rm -rf /var/lib/apt/lists/*
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
# pyproject.toml is the single source of truth; uv.lock pins exact versions.
|
|
33
|
+
# The compose stack runs against external Postgres (postgres extra) and serves
|
|
34
|
+
# via gunicorn (server extra). uv sync creates /app/.venv; the PATH update
|
|
35
|
+
# keeps the `python`/`gunicorn` entrypoints working.
|
|
36
|
+
COPY pyproject.toml uv.lock README.md ./
|
|
37
|
+
RUN pip install uv \
|
|
38
|
+
&& uv sync --frozen --no-install-project --no-dev --extra postgres --extra server
|
|
39
|
+
ENV PATH="/app/.venv/bin:$PATH"
|
|
36
40
|
|
|
37
41
|
COPY . .
|
|
38
42
|
|
|
@@ -25,12 +25,13 @@ def _load_env(path=".env"):
|
|
|
25
25
|
env = {}
|
|
26
26
|
if not os.path.exists(path):
|
|
27
27
|
return env
|
|
28
|
-
|
|
29
|
-
line
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
with open(path) as f:
|
|
29
|
+
for line in f:
|
|
30
|
+
line = line.strip()
|
|
31
|
+
if not line or line.startswith("#") or "=" not in line:
|
|
32
|
+
continue
|
|
33
|
+
k, _, v = line.partition("=")
|
|
34
|
+
env[k.strip()] = v.strip()
|
|
34
35
|
return env
|
|
35
36
|
|
|
36
37
|
|
|
@@ -56,7 +57,7 @@ class Client:
|
|
|
56
57
|
raw = e.read().decode()
|
|
57
58
|
try:
|
|
58
59
|
parsed = json.loads(raw)
|
|
59
|
-
except Exception:
|
|
60
|
+
except Exception: # noqa: BLE001 - fall back to raw body if not JSON
|
|
60
61
|
parsed = raw
|
|
61
62
|
return e.code, parsed
|
|
62
63
|
|
|
@@ -77,7 +78,8 @@ def main():
|
|
|
77
78
|
sys.exit(2)
|
|
78
79
|
|
|
79
80
|
c = Client(base_url)
|
|
80
|
-
step
|
|
81
|
+
def step(m):
|
|
82
|
+
print(f"\n=== {m} ===")
|
|
81
83
|
# Unique suffix so the smoke test is repeatable without colliding with the
|
|
82
84
|
# (project, display_name) / set-name uniqueness constraints on prior runs.
|
|
83
85
|
import time as _t
|
|
@@ -23,11 +23,7 @@ import re
|
|
|
23
23
|
import threading
|
|
24
24
|
import time
|
|
25
25
|
import uuid
|
|
26
|
-
|
|
27
|
-
try:
|
|
28
|
-
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
29
|
-
except Exception: # pragma: no cover - stdlib always present
|
|
30
|
-
raise
|
|
26
|
+
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
31
27
|
|
|
32
28
|
JUDGE_JSON_RE = re.compile(r"\{.*\}", re.DOTALL)
|
|
33
29
|
|
|
@@ -91,11 +87,11 @@ def _completion_body(messages, model) -> dict:
|
|
|
91
87
|
|
|
92
88
|
|
|
93
89
|
class Handler(BaseHTTPRequestHandler):
|
|
94
|
-
def log_message(self, fmt, *args):
|
|
90
|
+
def log_message(self, fmt, *args):
|
|
95
91
|
# Keep logs quiet but useful.
|
|
96
92
|
print("[mock-openai] %s" % (fmt % args), flush=True)
|
|
97
93
|
|
|
98
|
-
def do_GET(self):
|
|
94
|
+
def do_GET(self):
|
|
99
95
|
if self.path.rstrip("/") in ("", "/healthz"):
|
|
100
96
|
self._send_json({"status": "ok"})
|
|
101
97
|
elif self.path.rstrip("/") == "/v1/models":
|
|
@@ -108,7 +104,7 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
108
104
|
else:
|
|
109
105
|
self._send_json({"error": "not found"}, status=404)
|
|
110
106
|
|
|
111
|
-
def do_POST(self):
|
|
107
|
+
def do_POST(self):
|
|
112
108
|
length = int(self.headers.get("Content-Length", 0) or 0)
|
|
113
109
|
raw = self.rfile.read(length) if length else b""
|
|
114
110
|
try:
|
|
@@ -11,23 +11,29 @@ Run inside the web container:
|
|
|
11
11
|
Or locally with SQLite:
|
|
12
12
|
SIMPLEAUDIT_LOCAL_SQLITE=1 .venv/bin/python manage.py shell < deploy/seed_bulk.py
|
|
13
13
|
"""
|
|
14
|
+
import hashlib
|
|
14
15
|
import os
|
|
15
|
-
import sys
|
|
16
16
|
import random
|
|
17
|
-
import
|
|
18
|
-
from datetime import datetime, timedelta
|
|
17
|
+
from datetime import UTC, datetime, timedelta
|
|
19
18
|
|
|
20
19
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
|
21
20
|
# Do NOT set SIMPLEAUDIT_LOCAL_SQLITE — use whatever DB the environment provides
|
|
22
21
|
|
|
23
22
|
import django
|
|
23
|
+
|
|
24
24
|
django.setup()
|
|
25
25
|
|
|
26
|
-
from accounts.models import
|
|
27
|
-
from scenarios.models import Scenario, ScenarioRevision, ScenarioSet, ScenarioSetVersion, ScenarioSetVersionItem
|
|
28
|
-
from model_registry.models import ModelEndpoint
|
|
29
|
-
from audits.models import AuditRun
|
|
26
|
+
from accounts.models import Project, User
|
|
30
27
|
from audits.events import ScenarioResult, append_event
|
|
28
|
+
from audits.models import AuditRun
|
|
29
|
+
from model_registry.models import ModelEndpoint
|
|
30
|
+
from scenarios.models import (
|
|
31
|
+
Scenario,
|
|
32
|
+
ScenarioRevision,
|
|
33
|
+
ScenarioSet,
|
|
34
|
+
ScenarioSetVersion,
|
|
35
|
+
ScenarioSetVersionItem,
|
|
36
|
+
)
|
|
31
37
|
|
|
32
38
|
random.seed(42)
|
|
33
39
|
|
|
@@ -256,7 +262,7 @@ def main():
|
|
|
256
262
|
version=ver,
|
|
257
263
|
scenario_count=len(items_for_ver),
|
|
258
264
|
content_hash=make_hash(f"{st.name}-v{ver}-{random.random()}"),
|
|
259
|
-
published_at=datetime.now() - timedelta(days=random.randint(0, 90)),
|
|
265
|
+
published_at=datetime.now(UTC) - timedelta(days=random.randint(0, 90)),
|
|
260
266
|
published_by=admin,
|
|
261
267
|
)
|
|
262
268
|
version_batch.append((vs, items_for_ver))
|
|
@@ -293,7 +299,7 @@ def main():
|
|
|
293
299
|
print(f"Audit runs before: {AuditRun.objects.count()}")
|
|
294
300
|
all_versions = list(ScenarioSetVersion.objects.all())
|
|
295
301
|
run_batch = []
|
|
296
|
-
base_time = datetime.now() - timedelta(days=90)
|
|
302
|
+
base_time = datetime.now(UTC) - timedelta(days=90)
|
|
297
303
|
|
|
298
304
|
for i in range(500):
|
|
299
305
|
status = random.choice(RUN_STATUS_DISTRIBUTION)
|
|
@@ -188,7 +188,7 @@ MAX_CONCURRENT_AUDITS=2
|
|
|
188
188
|
MAX_SCENARIOS_PER_RUN=500
|
|
189
189
|
|
|
190
190
|
# SimpleAudit engine: no env vars needed. It is a pip dependency pinned in
|
|
191
|
-
#
|
|
191
|
+
# pyproject.toml; provenance is read from installed package metadata.
|
|
192
192
|
|
|
193
193
|
# Optional observability
|
|
194
194
|
OTEL_EXPORTER_OTLP_ENDPOINT=
|
|
@@ -35,7 +35,7 @@ def wait_for_health(timeout: int = 60) -> None:
|
|
|
35
35
|
resp = urllib.request.urlopen(f"{BASE_URL}/healthz", timeout=3)
|
|
36
36
|
if resp.status == 200:
|
|
37
37
|
return
|
|
38
|
-
except Exception:
|
|
38
|
+
except Exception: # noqa: BLE001,S110 - retry loop; not healthy yet
|
|
39
39
|
pass
|
|
40
40
|
time.sleep(2)
|
|
41
41
|
raise RuntimeError(f"Web service did not become healthy within {timeout}s")
|
|
@@ -198,7 +198,7 @@ def main() -> int:
|
|
|
198
198
|
fn(page)
|
|
199
199
|
print(f" PASS {name}")
|
|
200
200
|
passed += 1
|
|
201
|
-
except Exception as e:
|
|
201
|
+
except Exception as e: # noqa: BLE001 - test harness reports any failure
|
|
202
202
|
print(f" FAIL {name}: {e}")
|
|
203
203
|
failed += 1
|
|
204
204
|
errors.append((name, str(e)))
|
|
@@ -18,7 +18,6 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
import asyncio
|
|
20
20
|
import os
|
|
21
|
-
import sys
|
|
22
21
|
from typing import Any
|
|
23
22
|
|
|
24
23
|
|
|
@@ -29,18 +28,19 @@ class EngineError(RuntimeError):
|
|
|
29
28
|
def _ensure_engine_available() -> None:
|
|
30
29
|
"""Ensure the SimpleAudit engine package is importable.
|
|
31
30
|
|
|
32
|
-
The engine is a normal pip dependency (
|
|
33
|
-
path-based fallback. If it is not installed (e.g. a web-only
|
|
34
|
-
test environment without the engine), raise a clean
|
|
35
|
-
caller can record a durable failure instead of
|
|
31
|
+
The engine is a normal pip dependency (declared in ``pyproject.toml``);
|
|
32
|
+
there is no path-based fallback. If it is not installed (e.g. a web-only
|
|
33
|
+
process or a test environment without the engine), raise a clean
|
|
34
|
+
``EngineError`` so the caller can record a durable failure instead of
|
|
35
|
+
crashing on import.
|
|
36
36
|
"""
|
|
37
37
|
try:
|
|
38
38
|
import simpleaudit # noqa: F401
|
|
39
39
|
return
|
|
40
40
|
except ModuleNotFoundError as exc:
|
|
41
41
|
raise EngineError(
|
|
42
|
-
"SimpleAudit engine is not installed. Install
|
|
43
|
-
"(
|
|
42
|
+
"SimpleAudit engine is not installed. Install the project "
|
|
43
|
+
"dependencies (uv sync) before running audits."
|
|
44
44
|
) from exc
|
|
45
45
|
|
|
46
46
|
|
|
@@ -168,7 +168,7 @@ def build_model_auditor(*, target: dict, auditor: dict, judge: dict, generation:
|
|
|
168
168
|
_ensure_engine_available()
|
|
169
169
|
try:
|
|
170
170
|
from simpleaudit.model_auditor import ModelAuditor
|
|
171
|
-
except Exception as exc:
|
|
171
|
+
except Exception as exc:
|
|
172
172
|
raise EngineError(f"Failed to import SimpleAudit ModelAuditor: {exc}") from exc
|
|
173
173
|
|
|
174
174
|
gen = dict(generation or {})
|
|
@@ -263,7 +263,7 @@ def build_model_auditor(*, target: dict, auditor: dict, judge: dict, generation:
|
|
|
263
263
|
)
|
|
264
264
|
except EngineError:
|
|
265
265
|
raise
|
|
266
|
-
except Exception as exc:
|
|
266
|
+
except Exception as exc:
|
|
267
267
|
raise EngineError(f"Failed to construct ModelAuditor: {type(exc).__name__}: {exc}") from exc
|
|
268
268
|
return instance, language
|
|
269
269
|
|
|
@@ -309,7 +309,7 @@ def run_scenario(
|
|
|
309
309
|
)
|
|
310
310
|
except EngineError:
|
|
311
311
|
raise
|
|
312
|
-
except Exception as exc:
|
|
312
|
+
except Exception as exc:
|
|
313
313
|
raise EngineError(f"Scenario execution crashed: {type(exc).__name__}: {exc}") from exc
|
|
314
314
|
|
|
315
315
|
payload = result.to_dict()
|
|
@@ -70,7 +70,7 @@ def _postgres_probe() -> dict[str, Any]:
|
|
|
70
70
|
row = cursor.fetchone()
|
|
71
71
|
if row:
|
|
72
72
|
signals["db_size_bytes"] = int(row[0])
|
|
73
|
-
except Exception: # noqa: BLE001 - non-Postgres or permission issue
|
|
73
|
+
except Exception: # noqa: BLE001,S110 - non-Postgres or permission issue; size is optional
|
|
74
74
|
pass
|
|
75
75
|
return {"status": "up", **signals}
|
|
76
76
|
|
|
@@ -177,7 +177,7 @@ def _engine_probe() -> dict[str, Any]:
|
|
|
177
177
|
|
|
178
178
|
def _model_endpoints_probe() -> dict[str, Any]:
|
|
179
179
|
"""Ping each registered model endpoint's base_url, grouped by connection."""
|
|
180
|
-
from model_registry.models import ModelConnection
|
|
180
|
+
from model_registry.models import ModelConnection
|
|
181
181
|
|
|
182
182
|
groups: list[dict[str, Any]] = []
|
|
183
183
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""Structured JSON logging for containers."""
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
|
-
from datetime import
|
|
4
|
+
from datetime import UTC, datetime
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class JsonFormatter(logging.Formatter):
|
|
8
8
|
def format(self, record: logging.LogRecord) -> str:
|
|
9
9
|
payload = {
|
|
10
|
-
"timestamp": datetime.now(
|
|
10
|
+
"timestamp": datetime.now(UTC).isoformat(),
|
|
11
11
|
"level": record.levelname,
|
|
12
12
|
"logger": record.name,
|
|
13
13
|
"message": record.getMessage(),
|
{simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/purge_test_data.py
RENAMED
|
@@ -14,7 +14,12 @@ from django.db import transaction
|
|
|
14
14
|
from audits.events import AuditEvent, ScenarioResult
|
|
15
15
|
from audits.models import AuditRun
|
|
16
16
|
from model_registry.models import ModelEndpoint
|
|
17
|
-
from scenarios.models import
|
|
17
|
+
from scenarios.models import (
|
|
18
|
+
Scenario,
|
|
19
|
+
ScenarioSet,
|
|
20
|
+
ScenarioSetVersion,
|
|
21
|
+
ScenarioSetVersionItem,
|
|
22
|
+
)
|
|
18
23
|
|
|
19
24
|
|
|
20
25
|
class Command(BaseCommand):
|
{simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/run_worker.py
RENAMED
|
@@ -7,7 +7,6 @@ The worker connects to the external Hatchet server (HATCHET_SERVER_URL /
|
|
|
7
7
|
HATCHET_GRPC_URL) and executes audit scenario/finalize tasks. It runs in its own
|
|
8
8
|
process, separate from the web/API server, which never executes model calls.
|
|
9
9
|
"""
|
|
10
|
-
import os
|
|
11
10
|
|
|
12
11
|
from django.conf import settings
|
|
13
12
|
from django.core.management.base import BaseCommand
|
{simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/seed_demo_audits.py
RENAMED
|
@@ -54,9 +54,10 @@ class Command(BaseCommand):
|
|
|
54
54
|
)
|
|
55
55
|
|
|
56
56
|
def handle(self, *args, **options):
|
|
57
|
-
from accounts.models import Project
|
|
58
57
|
from django.contrib.auth import get_user_model
|
|
59
58
|
|
|
59
|
+
from accounts.models import Project
|
|
60
|
+
|
|
60
61
|
User = get_user_model()
|
|
61
62
|
project_id = options["project"]
|
|
62
63
|
try:
|
{simpleaudit_studio-0.2.4 → simpleaudit_studio-0.2.6}/infra/management/commands/seed_platform.py
RENAMED
|
@@ -16,7 +16,11 @@ import logging
|
|
|
16
16
|
|
|
17
17
|
from django.core.management.base import BaseCommand, CommandError
|
|
18
18
|
|
|
19
|
-
from infra.seed import
|
|
19
|
+
from infra.seed import (
|
|
20
|
+
DEFAULT_PACKS,
|
|
21
|
+
import_scenario_pack,
|
|
22
|
+
seed_default_model_connections,
|
|
23
|
+
)
|
|
20
24
|
|
|
21
25
|
logger = logging.getLogger(__name__)
|
|
22
26
|
|
|
@@ -47,9 +51,10 @@ class Command(BaseCommand):
|
|
|
47
51
|
)
|
|
48
52
|
|
|
49
53
|
def handle(self, *args, **options):
|
|
50
|
-
from accounts.models import Project
|
|
51
54
|
from django.contrib.auth import get_user_model
|
|
52
55
|
|
|
56
|
+
from accounts.models import Project
|
|
57
|
+
|
|
53
58
|
User = get_user_model()
|
|
54
59
|
|
|
55
60
|
project_id = options["project"]
|