simpleaudit-studio 0.2.6__tar.gz → 0.3.0__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.
Files changed (225) hide show
  1. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/.dockerignore +8 -2
  2. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/.env.example +2 -19
  3. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/.env.local.example +1 -9
  4. simpleaudit_studio-0.3.0/.github/workflows/ci.yml +44 -0
  5. simpleaudit_studio-0.3.0/.github/workflows/docker.yml +46 -0
  6. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/.github/workflows/publish.yml +10 -1
  7. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/.gitignore +5 -0
  8. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/Dockerfile +19 -19
  9. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/PKG-INFO +46 -21
  10. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/README.md +41 -16
  11. simpleaudit_studio-0.3.0/accounts/admin_urls.py +11 -0
  12. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/auth_urls.py +1 -0
  13. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/migrations/0001_initial.py +6 -1
  14. simpleaudit_studio-0.2.6/accounts/migrations/0002_user_workos_user_id.py → simpleaudit_studio-0.3.0/accounts/migrations/0002_user_preferences.py +3 -3
  15. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/models.py +6 -0
  16. simpleaudit_studio-0.3.0/accounts/serializers.py +173 -0
  17. simpleaudit_studio-0.3.0/accounts/services.py +411 -0
  18. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/views.py +100 -29
  19. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/workos_auth.py +4 -71
  20. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/comparison.py +17 -17
  21. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/events.py +97 -21
  22. simpleaudit_studio-0.3.0/audits/experiments.py +374 -0
  23. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/migrations/0001_initial.py +177 -7
  24. simpleaudit_studio-0.3.0/audits/migrations/0002_strip_api_keys_from_snapshots.py +41 -0
  25. simpleaudit_studio-0.3.0/audits/models.py +178 -0
  26. simpleaudit_studio-0.3.0/audits/monitors.py +487 -0
  27. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/serializers.py +3 -3
  28. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/services.py +74 -33
  29. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/views.py +19 -21
  30. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/config/settings.py +63 -50
  31. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/config/urls.py +67 -26
  32. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/deploy/compose/Dockerfile +1 -1
  33. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/deploy/mock_openai_server.py +0 -3
  34. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/deploy/postgres-init.sql +1 -1
  35. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/docker-compose.yml +8 -32
  36. simpleaudit_studio-0.3.0/docs/architecture.md +87 -0
  37. simpleaudit_studio-0.3.0/docs/deployment.md +116 -0
  38. simpleaudit_studio-0.3.0/docs/domain-model.md +437 -0
  39. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/e2e/test_ui.py +31 -56
  40. simpleaudit_studio-0.3.0/infra/context_processors.py +85 -0
  41. simpleaudit_studio-0.3.0/infra/db.py +69 -0
  42. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/engine.py +37 -17
  43. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/health.py +30 -43
  44. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/health_api.py +2 -11
  45. simpleaudit_studio-0.3.0/infra/management/commands/dev_server.py +144 -0
  46. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/management/commands/purge_test_data.py +2 -2
  47. simpleaudit_studio-0.3.0/infra/management/commands/run_monitors.py +24 -0
  48. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/management/commands/seed_demo_audits.py +9 -15
  49. simpleaudit_studio-0.3.0/infra/management/commands/setup_local.py +66 -0
  50. simpleaudit_studio-0.3.0/infra/runs_table.py +227 -0
  51. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/seed.py +7 -30
  52. simpleaudit_studio-0.3.0/infra/seo.py +201 -0
  53. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/simpleaudit_package.py +0 -5
  54. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/startup_checks.py +4 -15
  55. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/factories.py +5 -15
  56. simpleaudit_studio-0.3.0/infra/tests/test_admin_api.py +151 -0
  57. simpleaudit_studio-0.3.0/infra/tests/test_admin_page.py +88 -0
  58. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_api_e2e.py +27 -19
  59. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_archive.py +13 -28
  60. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_clone.py +16 -11
  61. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_poll_results.py +7 -6
  62. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_rename.py +13 -13
  63. simpleaudit_studio-0.3.0/infra/tests/test_audit_results_live.py +130 -0
  64. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_run_freeze.py +95 -35
  65. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_sse.py +7 -6
  66. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_submission.py +16 -13
  67. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_timing.py +13 -7
  68. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_auth_projects.py +23 -10
  69. simpleaudit_studio-0.3.0/infra/tests/test_bootstrap.py +42 -0
  70. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_comparison.py +14 -11
  71. simpleaudit_studio-0.3.0/infra/tests/test_connection_delete.py +148 -0
  72. simpleaudit_studio-0.3.0/infra/tests/test_db_resilience.py +68 -0
  73. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_engine_integration.py +190 -14
  74. simpleaudit_studio-0.3.0/infra/tests/test_experiments.py +394 -0
  75. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_health_panel.py +5 -22
  76. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_minimal_config.py +62 -37
  77. simpleaudit_studio-0.3.0/infra/tests/test_model_registry.py +47 -0
  78. simpleaudit_studio-0.3.0/infra/tests/test_monitors.py +518 -0
  79. simpleaudit_studio-0.3.0/infra/tests/test_profile.py +114 -0
  80. simpleaudit_studio-0.3.0/infra/tests/test_profile_ui.py +85 -0
  81. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_purge_test_data.py +21 -15
  82. simpleaudit_studio-0.3.0/infra/tests/test_runs_table.py +208 -0
  83. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_scenarios.py +0 -12
  84. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_seed_platform.py +5 -31
  85. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_smoke_all_pages.py +63 -18
  86. simpleaudit_studio-0.3.0/infra/tests/test_snapshot_secrets.py +79 -0
  87. simpleaudit_studio-0.3.0/infra/tests/test_workspace_archive.py +111 -0
  88. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_workspaces.py +24 -13
  89. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_workspaces_ui.py +1 -1
  90. simpleaudit_studio-0.3.0/infra/tests/test_write_guard.py +116 -0
  91. simpleaudit_studio-0.3.0/infra/tests/utils.py +44 -0
  92. simpleaudit_studio-0.3.0/infra/ui.py +2217 -0
  93. simpleaudit_studio-0.3.0/infra/worker.py +1072 -0
  94. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/model_registry/admin.py +1 -8
  95. simpleaudit_studio-0.3.0/model_registry/migrations/0001_initial.py +116 -0
  96. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/model_registry/models.py +4 -36
  97. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/model_registry/serializers.py +0 -32
  98. simpleaudit_studio-0.3.0/model_registry/services.py +78 -0
  99. simpleaudit_studio-0.3.0/model_registry/urls.py +7 -0
  100. simpleaudit_studio-0.3.0/model_registry/views.py +24 -0
  101. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/pyproject.toml +5 -4
  102. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/migrations/0001_initial.py +1 -1
  103. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/services.py +3 -1
  104. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/views.py +2 -1
  105. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/simpleaudit_studio/__init__.py +0 -2
  106. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/simpleaudit_studio/cli.py +112 -19
  107. simpleaudit_studio-0.3.0/templates/404.html +4 -0
  108. simpleaudit_studio-0.3.0/templates/admin.html +445 -0
  109. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/auth/login.html +1 -8
  110. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/auth/register.html +1 -8
  111. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/auth/workos_login.html +1 -8
  112. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/auth/workos_verify.html +1 -8
  113. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/base.html +47 -54
  114. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/compare.html +15 -9
  115. simpleaudit_studio-0.3.0/templates/dashboard.html +440 -0
  116. simpleaudit_studio-0.3.0/templates/experiment_detail.html +197 -0
  117. simpleaudit_studio-0.3.0/templates/experiment_new.html +412 -0
  118. simpleaudit_studio-0.3.0/templates/experiment_review.html +248 -0
  119. simpleaudit_studio-0.3.0/templates/experiments.html +46 -0
  120. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/health.html +35 -31
  121. simpleaudit_studio-0.3.0/templates/models.html +422 -0
  122. simpleaudit_studio-0.3.0/templates/monitor_detail.html +117 -0
  123. simpleaudit_studio-0.3.0/templates/monitors.html +63 -0
  124. simpleaudit_studio-0.3.0/templates/partials/auth_header.html +8 -0
  125. simpleaudit_studio-0.3.0/templates/partials/chip_input.html +18 -0
  126. simpleaudit_studio-0.3.0/templates/partials/compare_run_header.html +4 -0
  127. simpleaudit_studio-0.3.0/templates/partials/footer.html +10 -0
  128. simpleaudit_studio-0.3.0/templates/partials/local_time_js.html +37 -0
  129. simpleaudit_studio-0.3.0/templates/partials/model_pickers.html +49 -0
  130. simpleaudit_studio-0.3.0/templates/partials/multi_filter.html +18 -0
  131. simpleaudit_studio-0.2.6/templates/404.html → simpleaudit_studio-0.3.0/templates/partials/not_found.html +1 -5
  132. simpleaudit_studio-0.3.0/templates/partials/result_rep_panel.html +84 -0
  133. simpleaudit_studio-0.3.0/templates/partials/run_results.html +32 -0
  134. simpleaudit_studio-0.3.0/templates/partials/run_settings.html +67 -0
  135. simpleaudit_studio-0.3.0/templates/partials/run_settings_js.html +63 -0
  136. simpleaudit_studio-0.3.0/templates/partials/severity_badge.html +1 -0
  137. simpleaudit_studio-0.3.0/templates/partials/tooltips.html +73 -0
  138. simpleaudit_studio-0.3.0/templates/partials/ui_js.html +21 -0
  139. simpleaudit_studio-0.3.0/templates/profile.html +134 -0
  140. simpleaudit_studio-0.3.0/templates/public/base_public.html +20 -0
  141. simpleaudit_studio-0.3.0/templates/public/landing.html +99 -0
  142. simpleaudit_studio-0.3.0/templates/run_detail.html +835 -0
  143. simpleaudit_studio-0.3.0/templates/run_result.html +135 -0
  144. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/scenarios.html +49 -55
  145. simpleaudit_studio-0.3.0/templates/seo/head.html +24 -0
  146. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/templates/workspaces.html +11 -23
  147. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/uv.lock +121 -113
  148. simpleaudit_studio-0.2.6/.github/workflows/ci.yml +0 -50
  149. simpleaudit_studio-0.2.6/Makefile +0 -63
  150. simpleaudit_studio-0.2.6/accounts/serializers.py +0 -95
  151. simpleaudit_studio-0.2.6/accounts/services.py +0 -158
  152. simpleaudit_studio-0.2.6/audits/migrations/0002_add_audit_run_archived.py +0 -17
  153. simpleaudit_studio-0.2.6/audits/migrations/0003_auditrun_updated_at.py +0 -17
  154. simpleaudit_studio-0.2.6/audits/models.py +0 -77
  155. simpleaudit_studio-0.2.6/deploy/e2e_smoke.py +0 -235
  156. simpleaudit_studio-0.2.6/deploy/seed_bulk.py +0 -413
  157. simpleaudit_studio-0.2.6/docs/architecture.md +0 -383
  158. simpleaudit_studio-0.2.6/docs/deployment.md +0 -418
  159. simpleaudit_studio-0.2.6/docs/domain-model.md +0 -473
  160. simpleaudit_studio-0.2.6/infra/context_processors.py +0 -65
  161. simpleaudit_studio-0.2.6/infra/permissions.py +0 -31
  162. simpleaudit_studio-0.2.6/infra/tests/test_bootstrap.py +0 -68
  163. simpleaudit_studio-0.2.6/infra/tests/test_model_registry.py +0 -89
  164. simpleaudit_studio-0.2.6/infra/ui.py +0 -1417
  165. simpleaudit_studio-0.2.6/infra/worker.py +0 -671
  166. simpleaudit_studio-0.2.6/model_registry/migrations/0001_initial.py +0 -90
  167. simpleaudit_studio-0.2.6/model_registry/services.py +0 -39
  168. simpleaudit_studio-0.2.6/model_registry/urls.py +0 -13
  169. simpleaudit_studio-0.2.6/model_registry/views.py +0 -77
  170. simpleaudit_studio-0.2.6/templates/audit_detail.html +0 -373
  171. simpleaudit_studio-0.2.6/templates/dashboard.html +0 -145
  172. simpleaudit_studio-0.2.6/templates/models.html +0 -273
  173. simpleaudit_studio-0.2.6/templates/new_audit.html +0 -205
  174. simpleaudit_studio-0.2.6/templates/scenario_result_detail.html +0 -144
  175. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/LICENSE +0 -0
  176. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/__init__.py +0 -0
  177. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/admin.py +0 -0
  178. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/apps.py +0 -0
  179. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/migrations/__init__.py +0 -0
  180. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/accounts/project_urls.py +0 -0
  181. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/__init__.py +0 -0
  182. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/admin.py +0 -0
  183. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/apps.py +0 -0
  184. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/migrations/__init__.py +0 -0
  185. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/audits/urls.py +0 -0
  186. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/config/__init__.py +0 -0
  187. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/config/asgi.py +0 -0
  188. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/config/wsgi.py +0 -0
  189. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/__init__.py +0 -0
  190. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/admin.py +0 -0
  191. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/apps.py +0 -0
  192. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/exceptions.py +0 -0
  193. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/fixtures/demo_audit_results.json +0 -0
  194. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/hashing.py +0 -0
  195. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/logging.py +0 -0
  196. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/management/__init__.py +0 -0
  197. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/management/commands/__init__.py +0 -0
  198. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/management/commands/bootstrap_platform.py +0 -0
  199. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/management/commands/run_worker.py +0 -0
  200. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/management/commands/seed_platform.py +0 -0
  201. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/middleware.py +0 -0
  202. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/minimal_config.py +0 -0
  203. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/readiness.py +0 -0
  204. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/__init__.py +0 -0
  205. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_audit_events.py +0 -0
  206. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_health.py +0 -0
  207. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_middleware.py +0 -0
  208. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/infra/tests/test_scenario_import_export.py +0 -0
  209. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/manage.py +0 -0
  210. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/model_registry/__init__.py +0 -0
  211. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/model_registry/apps.py +0 -0
  212. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/model_registry/migrations/__init__.py +0 -0
  213. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/__init__.py +0 -0
  214. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/admin.py +0 -0
  215. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/apps.py +0 -0
  216. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/migrations/__init__.py +0 -0
  217. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/models.py +0 -0
  218. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/serializers.py +0 -0
  219. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/scenarios/urls.py +0 -0
  220. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/static/favicon-16x16.svg +0 -0
  221. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/static/favicon-32x32.svg +0 -0
  222. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/static/favicon.svg +0 -0
  223. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/static/js/diff.min.js +0 -0
  224. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/static/logo.png +0 -0
  225. {simpleaudit_studio-0.2.6 → simpleaudit_studio-0.3.0}/static/logo.svg +0 -0
@@ -1,12 +1,18 @@
1
1
  .git
2
+ .github
2
3
  .env
4
+ .env.local
3
5
  .venv
4
6
  __pycache__/
5
7
  *.pyc
8
+ *.sqlite3
9
+ *.sqlite3-*
10
+ app.pid
6
11
  data/
7
12
  staticfiles/
8
- media/
9
13
  .pytest_cache/
10
14
  .mypy_cache/
11
15
  .ruff_cache/
12
- # sync 1790239341
16
+ docs/
17
+ e2e/
18
+ copilot-instructions.md
@@ -8,14 +8,14 @@
8
8
  # For a local (non-Docker) development setup, copy `.env.local.example` instead.
9
9
  #
10
10
  # NOTE: docker-compose.yml overrides a few values per service (POSTGRES_HOST,
11
- # HATCHET_*, MINIO_ENDPOINT) so the container-internal hostnames are used
11
+ # HATCHET_*) so the container-internal hostnames are used
12
12
  # regardless of what is written here.
13
13
  # =============================================================================
14
14
 
15
15
  # --- Django -----------------------------------------------------------------
16
16
  DJANGO_SECRET_KEY=change-me
17
17
  DJANGO_DEBUG=false
18
- DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
18
+ DJANGO_ALLOWED_HOSTS=*
19
19
  LOG_LEVEL=INFO
20
20
 
21
21
  # --- Bootstrap (idempotent; run automatically by the web container) ----------
@@ -46,14 +46,6 @@ POSTGRES_PASSWORD=change-me
46
46
  POSTGRES_HOST=postgres
47
47
  POSTGRES_PORT=5432
48
48
 
49
- # --- MinIO / S3-compatible object storage (OFF by default) --------------------
50
- # Enable with: docker compose --profile storage up -d
51
- # Then uncomment and set real credentials:
52
- # MINIO_ENDPOINT=http://minio:9000
53
- # MINIO_ACCESS_KEY=change-me
54
- # MINIO_SECRET_KEY=change-me
55
- # MINIO_BUCKET=simpleaudit-artifacts
56
-
57
49
  # --- Durable workflow system (Hatchet) ----------------------------------------
58
50
  # Docker Compose: the compose service name `hatchet-server` resolves inside the
59
51
  # compose network. HTTP API on :8888, gRPC on :7077 (see docker-compose.yml).
@@ -76,9 +68,6 @@ HATCHET_TLS_STRATEGY=none
76
68
  WORKER_POOL=cpu
77
69
 
78
70
  # --- Operational limits --------------------------------------------------------
79
- MAX_CONCURRENT_AUDITS=2
80
- MAX_SCENARIOS_PER_RUN=500
81
- SSE_MAX_CONNECTIONS_PER_USER=10
82
71
 
83
72
  # --- SimpleAudit engine ---------------------------------------------------------
84
73
  # No configuration needed here. The engine is a normal pip dependency pinned in
@@ -99,10 +88,6 @@ SSE_MAX_CONNECTIONS_PER_USER=10
99
88
  SEED_DEMO_AUDITS=true
100
89
 
101
90
  # --- Optional observability -----------------------------------------------------
102
- OTEL_EXPORTER_OTLP_ENDPOINT=
103
- LANGFUSE_PUBLIC_KEY=
104
- LANGFUSE_SECRET_KEY=
105
- LANGFUSE_HOST=
106
91
 
107
92
  # --- Sentry error tracking & tracing (leave empty to disable) -------------------
108
93
  SENTRY_DSN=
@@ -113,5 +98,3 @@ SENTRY_ENVIRONMENT=development
113
98
  # WORKOS_CLIENT_ID is public; WORKOS_API_KEY is server-side secret (keep out of git).
114
99
  WORKOS_CLIENT_ID=
115
100
  WORKOS_API_KEY=
116
- # Public base URL used to build the OAuth redirect URI, e.g. http://localhost:8000
117
- APP_BASE_URL=http://localhost:8000
@@ -17,7 +17,7 @@
17
17
  # --- Django -----------------------------------------------------------------
18
18
  DJANGO_SECRET_KEY=local-dev-key-not-for-prod
19
19
  DJANGO_DEBUG=true
20
- DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
20
+ DJANGO_ALLOWED_HOSTS=*
21
21
  LOG_LEVEL=DEBUG
22
22
 
23
23
  # --- Bootstrap ----------------------------------------------------------------
@@ -80,13 +80,5 @@ WORKER_POOL=cpu
80
80
  # SIMULACHAT_API_KEY=sk-...
81
81
 
82
82
  # --- Optional (leave empty to disable) ------------------------------------------
83
- MINIO_ENDPOINT=
84
- MINIO_ACCESS_KEY=
85
- MINIO_SECRET_KEY=
86
- MINIO_BUCKET=simpleaudit-artifacts
87
- OTEL_EXPORTER_OTLP_ENDPOINT=
88
- LANGFUSE_PUBLIC_KEY=
89
- LANGFUSE_SECRET_KEY=
90
- LANGFUSE_HOST=
91
83
  SENTRY_DSN=
92
84
  SENTRY_ENVIRONMENT=development
@@ -0,0 +1,44 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths-ignore: ["docs/**", "**.md", "LICENSE"]
7
+ pull_request:
8
+ paths-ignore: ["docs/**", "**.md", "LICENSE"]
9
+
10
+ concurrency:
11
+ group: ${{ github.workflow }}-${{ github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ jobs:
15
+ ci:
16
+ runs-on: ubuntu-latest
17
+ env:
18
+ DJANGO_SETTINGS_MODULE: config.settings
19
+ DJANGO_SECRET_KEY: ci-secret-key
20
+ DJANGO_DEBUG: "false"
21
+ DJANGO_ALLOWED_HOSTS: "*"
22
+ SIMPLEAUDIT_LOCAL_SQLITE: "1"
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ with:
26
+ fetch-depth: 0 # the embedded-Hatchet step diffs against origin/main
27
+ - uses: actions/setup-python@v5
28
+ with:
29
+ python-version: "3.12"
30
+ - uses: astral-sh/setup-uv@v7
31
+ - name: Install dependencies
32
+ run: uv sync --frozen --extra dev
33
+ - name: Lint (ruff)
34
+ run: uv run ruff check .
35
+ - name: Run tests (parallel)
36
+ run: uv run python manage.py test infra --parallel auto --exclude-tag embedded_hatchet
37
+ - name: Check if embedded Hatchet files changed
38
+ id: hatchet-changed
39
+ run: |
40
+ CHANGED=$(git diff --name-only origin/main...HEAD -- infra/minimal_config.py infra/worker.py 2>/dev/null || true)
41
+ if [ -n "$CHANGED" ]; then echo "changed=true" >> "$GITHUB_OUTPUT"; else echo "changed=false" >> "$GITHUB_OUTPUT"; fi
42
+ - name: Run tests (embedded Hatchet, serial)
43
+ if: steps.hatchet-changed.outputs.changed == 'true'
44
+ run: uv run python manage.py test infra.tests.test_minimal_config.TestEmbeddedHatchetLifecycle
@@ -0,0 +1,46 @@
1
+ name: Docker build
2
+
3
+ # Builds both images (no push) only when something that affects them changes,
4
+ # so Dockerfile / dependency / settings breakage is caught before deploying.
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ paths:
9
+ - "Dockerfile"
10
+ - "deploy/**"
11
+ - "docker-compose.yml"
12
+ - ".dockerignore"
13
+ - "pyproject.toml"
14
+ - "uv.lock"
15
+ - "config/settings.py"
16
+ - "infra/minimal_config.py"
17
+ - "simpleaudit_studio/**"
18
+ - ".github/workflows/docker.yml"
19
+ pull_request:
20
+ paths:
21
+ - "Dockerfile"
22
+ - "deploy/**"
23
+ - "docker-compose.yml"
24
+ - ".dockerignore"
25
+ - "pyproject.toml"
26
+ - "uv.lock"
27
+ - "config/settings.py"
28
+ - "infra/minimal_config.py"
29
+ - "simpleaudit_studio/**"
30
+ - ".github/workflows/docker.yml"
31
+
32
+ concurrency:
33
+ group: ${{ github.workflow }}-${{ github.ref }}
34
+ cancel-in-progress: true
35
+
36
+ jobs:
37
+ docker:
38
+ runs-on: ubuntu-latest
39
+ steps:
40
+ - uses: actions/checkout@v4
41
+ - name: Build HF Space / demo image
42
+ run: docker build -t simpleaudit-studio:ci .
43
+ - name: Build Compose image
44
+ run: docker build -f deploy/compose/Dockerfile -t simpleaudit-studio-compose:ci .
45
+ - name: Validate compose file
46
+ run: cp .env.example .env && docker compose config --quiet
@@ -20,7 +20,16 @@ jobs:
20
20
  uses: actions/setup-python@v5
21
21
  with:
22
22
  python-version: "3.12"
23
- - name: Install dependencies
23
+ - uses: astral-sh/setup-uv@v7
24
+ - name: Test before publishing
25
+ env:
26
+ DJANGO_SECRET_KEY: ci-secret-key
27
+ SIMPLEAUDIT_LOCAL_SQLITE: "1"
28
+ run: |
29
+ uv sync --frozen --extra dev
30
+ uv run ruff check .
31
+ uv run python manage.py test infra --parallel auto --exclude-tag embedded_hatchet
32
+ - name: Install build tooling
24
33
  run: |
25
34
  python -m pip install --upgrade pip
26
35
  pip install build
@@ -8,6 +8,7 @@ venv/
8
8
  # Django
9
9
  db.sqlite3
10
10
  *.sqlite3
11
+ *.sqlite3-*
11
12
  media/
12
13
  staticfiles/
13
14
 
@@ -24,6 +25,7 @@ simpleaudit-dependency.yaml
24
25
  .idea/
25
26
  *.swp
26
27
  .DS_Store
28
+ copilot-instructions.md
27
29
 
28
30
  # Test/coverage
29
31
  .coverage
@@ -37,5 +39,8 @@ docker-data/
37
39
  *.log
38
40
  logs/
39
41
 
42
+ # Runtime artifacts
43
+ app.pid
44
+
40
45
  # Data artifacts (prototype)
41
46
  data/
@@ -29,47 +29,47 @@ RUN apt-get update \
29
29
 
30
30
  # --- Python dependencies -----------------------------------------------------
31
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
32
  # uv sync creates /app/.venv; the PATH update keeps the `python` entrypoint.
35
33
  COPY pyproject.toml uv.lock README.md ./
36
34
  RUN pip install uv \
37
- && uv sync --frozen --no-install-project --no-dev --extra postgres
35
+ && uv sync --frozen --no-install-project --no-dev
38
36
  ENV PATH="/app/.venv/bin:$PATH"
39
37
 
40
- # --- Application code --------------------------------------------------------
41
- COPY . .
42
-
43
- # Collect static files so Django can serve them without DEBUG.
44
- RUN python manage.py collectstatic --noinput
45
-
46
- # --- Non-root user ------------------------------------------------------------
47
- RUN useradd --create-home appuser \
48
- && mkdir -p /app/staticfiles /app/media \
49
- && chown -R appuser:appuser /app
50
- USER appuser
51
-
52
38
  # --- Environment defaults for the Space --------------------------------------
53
39
  # SIMPLEAUDIT_MINIMAL=1 enables the minimal config path (SQLite + embedded Hatchet).
54
40
  # Override via HF Space Secrets for anything sensitive.
41
+ # Must be set BEFORE collectstatic: Django settings select the DB engine from it,
42
+ # and the postgres driver is an optional extra not installed in this image.
55
43
  ENV SIMPLEAUDIT_MINIMAL=1 \
56
44
  PORT=7860 \
57
45
  DJANGO_SECRET_KEY=hf-space-demo-secret-key-change-in-production \
58
46
  DJANGO_DEBUG=false \
59
- DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1,.hf.space,.huggingface.co \
47
+ DJANGO_ALLOWED_HOSTS=* \
60
48
  BOOTSTRAP_USERNAME=studio \
61
49
  BOOTSTRAP_EMAIL=studio@example.local \
62
50
  BOOTSTRAP_PASSWORD=admin123 \
63
51
  BOOTSTRAP_PROJECT_NAME=Default \
64
52
  DEMO_MODE=true \
65
53
  DEMO_USERNAME=studio \
66
- DEMO_PASSWORD=admin123 \
67
- MAX_CONCURRENT_AUDITS=1 \
68
- MAX_SCENARIOS_PER_RUN=50
54
+ DEMO_PASSWORD=admin123
55
+
56
+ # --- Application code --------------------------------------------------------
57
+ COPY . .
58
+
59
+ # Collect static files so Django can serve them without DEBUG.
60
+ RUN python manage.py collectstatic --noinput
61
+
62
+ # --- Non-root user ------------------------------------------------------------
63
+ RUN useradd --create-home appuser \
64
+ && mkdir -p /app/staticfiles \
65
+ && chown -R appuser:appuser /app
66
+ USER appuser
69
67
 
70
68
  EXPOSE 7860
71
69
 
72
70
  HEALTHCHECK --interval=30s --timeout=5s --start-period=90s --retries=5 \
73
71
  CMD curl -fsS http://localhost:7860/healthz || exit 1
74
72
 
73
+ # Model connections point at OpenAI's real base URL (https://api.openai.com/v1).
74
+ # Users add their API key in the UI to run real audits.
75
75
  CMD ["python", "-m", "simpleaudit_studio.cli"]
@@ -1,16 +1,16 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: simpleaudit-studio
3
- Version: 0.2.6
3
+ Version: 0.3.0
4
4
  Summary: Production AI model audit platform — one-liner demo mode via uvx
5
5
  License: MIT
6
6
  License-File: LICENSE
7
7
  Requires-Python: >=3.11
8
- Requires-Dist: boto3==1.40.4
9
- Requires-Dist: django-cors-headers==4.7.0
8
+ Requires-Dist: cronsim==2.7
10
9
  Requires-Dist: django==5.2.4
11
10
  Requires-Dist: djangorestframework==3.16.0
12
11
  Requires-Dist: drf-spectacular==0.28.0
13
12
  Requires-Dist: hatchet-sdk==1.41.0
13
+ Requires-Dist: httpx>=0.27
14
14
  Requires-Dist: pydantic<3,>=2.7
15
15
  Requires-Dist: python-dotenv==1.1.1
16
16
  Requires-Dist: requests==2.32.5
@@ -19,9 +19,9 @@ 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
- Requires-Dist: pytest; extra == 'dev'
23
- Requires-Dist: pytest-django; extra == 'dev'
24
22
  Requires-Dist: ruff; extra == 'dev'
23
+ Provides-Extra: e2e
24
+ Requires-Dist: playwright>=1.45; extra == 'e2e'
25
25
  Provides-Extra: postgres
26
26
  Requires-Dist: psycopg[binary]==3.2.13; extra == 'postgres'
27
27
  Provides-Extra: server
@@ -78,7 +78,40 @@ The pre-seeded connections point at a built-in mock server. To run real audits,
78
78
  | Together AI | `https://api.together.xyz/v1` | Many open models |
79
79
  | Groq | `https://api.groq.com/openai/v1` | Fast inference |
80
80
 
81
- Set the API key in the connection form (leave blank for local servers that don't require auth), then launch an audit from the Scenario Library.
81
+ Set the API key in the connection form (leave blank for local servers that don't require auth), then start a run from **New Experiment**.
82
+
83
+ ## 🛠️ Local Development
84
+
85
+ For contributors working on the codebase, use [uv](https://docs.astral.sh/uv/) — no manual venv steps, no Makefile. Two verbs cover everything:
86
+
87
+ - **`uv sync`** — create/update `.venv` from `pyproject.toml` + `uv.lock`
88
+ - **`uv run <cmd>`** — run any command inside `.venv` (auto-syncs first if the lockfile changed)
89
+
90
+ ### Setup (one time)
91
+
92
+ ```bash
93
+ git clone https://github.com/SushantGautam/SimpleAuditStudio
94
+ cd SimpleAuditStudio
95
+ cp .env.local.example .env # minimal local config (SQLite + mock models)
96
+
97
+ uv sync --extra dev --extra postgres # create .venv + install all deps
98
+ uv run manage.py setup_local # migrate + create admin (studio / BOOTSTRAP_PASSWORD from .env) + seed data
99
+ ```
100
+
101
+ `setup_local` chains the three idempotent first-run steps (migrate → bootstrap admin → seed scenario packs & model connections) into one command. Re-run it any time — it skips what already exists.
102
+
103
+ ### Daily work
104
+
105
+ ```bash
106
+ uv run manage.py dev_server --embedded # easiest: web UI + API + audit worker, zero-Docker → http://localhost:8000
107
+ ```
108
+
109
+ Other options:
110
+ ```bash
111
+ uv run manage.py runserver # web UI + API only (no worker)
112
+ uv run manage.py dev_server # web UI + worker, uses .env (edit POSTGRES_*/HATCHET_* to point at your infra)
113
+ SIMPLEAUDIT_LOCAL_SQLITE=1 uv run manage.py test infra # tests
114
+ ```
82
115
 
83
116
  ## 🐳 Self-Hosting
84
117
 
@@ -92,22 +125,22 @@ cp .env.example .env
92
125
  docker compose up -d
93
126
  ```
94
127
 
95
- Services: Web UI (:8000), PostgreSQL, Hatchet queue (:8888), Worker. Optional profiles: `--profile storage` (MinIO), `--profile mock` (mock model API).
128
+ Services: Web UI (:8000), PostgreSQL, Hatchet queue (:8888), Worker. Optional profile: `--profile mock` (mock model API).
96
129
 
97
130
  See [docs/deployment.md](docs/deployment.md) for production hardening, backups, and upgrades.
98
131
 
99
132
  ## ✨ What You Can Do
100
133
 
101
- - Browse the scenario library and create new audit scenarios
102
- - Register model endpoints (OpenAI-compatible APIs)
103
- - Launch audits and watch live progress
104
- - Compare results across runs
105
- - Explore the visualizer for detailed analysis
134
+ - Build versioned scenario sets and register OpenAI-compatible models
135
+ - Run experiments across models, scenario versions and settings, with a review step before launch
136
+ - Watch runs live, including per-repetition results
137
+ - Monitor models for drift on a schedule (interval or cron)
138
+ - Filter, customise and compare runs on an interactive dashboard
106
139
 
107
140
  ## 🏗️ Architecture
108
141
 
109
142
  ```
110
- Browser → Django/Gunicorn (:7860)
143
+ Browser → Django (gunicorn :8000 in Compose; runserver :7860 in the HF Space / uvx demo)
111
144
  ↓
112
145
  PostgreSQL 16 (domain + queue DBs)
113
146
  ↓
@@ -126,11 +159,3 @@ Browser → Django/Gunicorn (:7860)
126
159
  ## 🤝 Contributing
127
160
 
128
161
  Architecture decisions are documented in [docs/architecture.md](docs/architecture.md).
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
@@ -48,7 +48,40 @@ The pre-seeded connections point at a built-in mock server. To run real audits,
48
48
  | Together AI | `https://api.together.xyz/v1` | Many open models |
49
49
  | Groq | `https://api.groq.com/openai/v1` | Fast inference |
50
50
 
51
- Set the API key in the connection form (leave blank for local servers that don't require auth), then launch an audit from the Scenario Library.
51
+ Set the API key in the connection form (leave blank for local servers that don't require auth), then start a run from **New Experiment**.
52
+
53
+ ## 🛠️ Local Development
54
+
55
+ For contributors working on the codebase, use [uv](https://docs.astral.sh/uv/) — no manual venv steps, no Makefile. Two verbs cover everything:
56
+
57
+ - **`uv sync`** — create/update `.venv` from `pyproject.toml` + `uv.lock`
58
+ - **`uv run <cmd>`** — run any command inside `.venv` (auto-syncs first if the lockfile changed)
59
+
60
+ ### Setup (one time)
61
+
62
+ ```bash
63
+ git clone https://github.com/SushantGautam/SimpleAuditStudio
64
+ cd SimpleAuditStudio
65
+ cp .env.local.example .env # minimal local config (SQLite + mock models)
66
+
67
+ uv sync --extra dev --extra postgres # create .venv + install all deps
68
+ uv run manage.py setup_local # migrate + create admin (studio / BOOTSTRAP_PASSWORD from .env) + seed data
69
+ ```
70
+
71
+ `setup_local` chains the three idempotent first-run steps (migrate → bootstrap admin → seed scenario packs & model connections) into one command. Re-run it any time — it skips what already exists.
72
+
73
+ ### Daily work
74
+
75
+ ```bash
76
+ uv run manage.py dev_server --embedded # easiest: web UI + API + audit worker, zero-Docker → http://localhost:8000
77
+ ```
78
+
79
+ Other options:
80
+ ```bash
81
+ uv run manage.py runserver # web UI + API only (no worker)
82
+ uv run manage.py dev_server # web UI + worker, uses .env (edit POSTGRES_*/HATCHET_* to point at your infra)
83
+ SIMPLEAUDIT_LOCAL_SQLITE=1 uv run manage.py test infra # tests
84
+ ```
52
85
 
53
86
  ## 🐳 Self-Hosting
54
87
 
@@ -62,22 +95,22 @@ cp .env.example .env
62
95
  docker compose up -d
63
96
  ```
64
97
 
65
- Services: Web UI (:8000), PostgreSQL, Hatchet queue (:8888), Worker. Optional profiles: `--profile storage` (MinIO), `--profile mock` (mock model API).
98
+ Services: Web UI (:8000), PostgreSQL, Hatchet queue (:8888), Worker. Optional profile: `--profile mock` (mock model API).
66
99
 
67
100
  See [docs/deployment.md](docs/deployment.md) for production hardening, backups, and upgrades.
68
101
 
69
102
  ## ✨ What You Can Do
70
103
 
71
- - Browse the scenario library and create new audit scenarios
72
- - Register model endpoints (OpenAI-compatible APIs)
73
- - Launch audits and watch live progress
74
- - Compare results across runs
75
- - Explore the visualizer for detailed analysis
104
+ - Build versioned scenario sets and register OpenAI-compatible models
105
+ - Run experiments across models, scenario versions and settings, with a review step before launch
106
+ - Watch runs live, including per-repetition results
107
+ - Monitor models for drift on a schedule (interval or cron)
108
+ - Filter, customise and compare runs on an interactive dashboard
76
109
 
77
110
  ## 🏗️ Architecture
78
111
 
79
112
  ```
80
- Browser → Django/Gunicorn (:7860)
113
+ Browser → Django (gunicorn :8000 in Compose; runserver :7860 in the HF Space / uvx demo)
81
114
  ↓
82
115
  PostgreSQL 16 (domain + queue DBs)
83
116
  ↓
@@ -96,11 +129,3 @@ Browser → Django/Gunicorn (:7860)
96
129
  ## 🤝 Contributing
97
130
 
98
131
  Architecture decisions are documented in [docs/architecture.md](docs/architecture.md).
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
@@ -0,0 +1,11 @@
1
+ from django.urls import path
2
+
3
+ from . import views
4
+
5
+ urlpatterns = [
6
+ path("stats/", views.admin_stats, name="admin-stats"),
7
+ path("workspaces/<int:project_id>/archive/", views.admin_archive_workspace, name="admin-workspace-archive"),
8
+ path("workspaces/<int:project_id>/unarchive/", views.admin_unarchive_workspace, name="admin-workspace-unarchive"),
9
+ path("users/", views.admin_create_user_view, name="admin-user-create"),
10
+ path("users/<int:user_id>/", views.admin_update_user_view, name="admin-user-update"),
11
+ ]
@@ -6,4 +6,5 @@ urlpatterns = [
6
6
  path("register/", views.register, name="auth-register"),
7
7
  path("token/", views.obtain_token, name="auth-token"),
8
8
  path("me/", views.me, name="auth-me"),
9
+ path("profile/", views.update_profile, name="auth-profile"),
9
10
  ]
@@ -1,4 +1,4 @@
1
- # Generated by Django 5.2.4 on 2026-09-23 12:05
1
+ # Generated by Django 5.2.4 on 2026-09-27 19:42
2
2
 
3
3
  import django.contrib.auth.models
4
4
  import django.contrib.auth.validators
@@ -31,6 +31,7 @@ class Migration(migrations.Migration):
31
31
  ("name", models.CharField(max_length=200, unique=True)),
32
32
  ("slug", models.SlugField(max_length=200, unique=True)),
33
33
  ("description", models.TextField(blank=True)),
34
+ ("archived", models.BooleanField(db_index=True, default=False)),
34
35
  ("created_at", models.DateTimeField(auto_now_add=True)),
35
36
  ("updated_at", models.DateTimeField(auto_now=True)),
36
37
  ],
@@ -121,6 +122,10 @@ class Migration(migrations.Migration):
121
122
  default=django.utils.timezone.now, verbose_name="date joined"
122
123
  ),
123
124
  ),
125
+ (
126
+ "workos_user_id",
127
+ models.CharField(blank=True, max_length=64, null=True, unique=True),
128
+ ),
124
129
  (
125
130
  "groups",
126
131
  models.ManyToManyField(
@@ -1,4 +1,4 @@
1
- # Generated by Django 5.2.4 on 2026-09-24 13:27
1
+ # Generated by Django 5.2.4 on 2026-09-27 20:23
2
2
 
3
3
  from django.db import migrations, models
4
4
 
@@ -11,7 +11,7 @@ class Migration(migrations.Migration):
11
11
  operations = [
12
12
  migrations.AddField(
13
13
  model_name="user",
14
- name="workos_user_id",
15
- field=models.CharField(blank=True, max_length=64, null=True, unique=True),
14
+ name="preferences",
15
+ field=models.JSONField(blank=True, default=dict),
16
16
  ),
17
17
  ]
@@ -21,6 +21,9 @@ class User(AbstractUser):
21
21
 
22
22
  # Stable WorkOS AuthKit user id; null for locally-created accounts.
23
23
  workos_user_id = models.CharField(max_length=64, unique=True, null=True, blank=True)
24
+ # Per-user UI preferences (e.g. dashboard column layout). Keys are
25
+ # whitelisted by the preference endpoint; values are small JSON.
26
+ preferences = models.JSONField(default=dict, blank=True)
24
27
 
25
28
  groups = models.ManyToManyField(
26
29
  "auth.Group",
@@ -45,6 +48,9 @@ class Project(models.Model):
45
48
  name = models.CharField(max_length=200, unique=True)
46
49
  slug = models.SlugField(max_length=200, unique=True)
47
50
  description = models.TextField(blank=True)
51
+ # Soft-hide a workspace that still contains data. Members keep read access;
52
+ # all mutations are blocked for non-superusers. Never deletes data.
53
+ archived = models.BooleanField(default=False, db_index=True)
48
54
  created_at = models.DateTimeField(auto_now_add=True)
49
55
  updated_at = models.DateTimeField(auto_now=True)
50
56