feat(api): Scalar docs UI + single pyproject config - #62
Merged
Merged
Conversation
…n control Backend was local-only (gitignored); restored to version control and added the canonical greenfield auth module. Auth (new): - apps/accounts: custom email User model (UUID PK, soft-delete) + manager + admin - allauth headless + MFA (TOTP+recovery), Argon2, mandatory email verification, anti-enumeration, bounded sessions; /_allauth/ headless surface mounted - ninja SessionTokenAuth (X-Session-Token); compact endpoints only — GET/PATCH/DELETE /accounts/me/ + POST /accounts/me/export/ - accounts tests (me/patch/export/soft-delete + anon/garbage-token 401) Repo: - remove '.gitignore: backend/' so the backend is tracked again (junk still ignored via __pycache__/ *.sqlite3 .env staticfiles/ rules) Verified: fresh DB migrated, django check clean, health 200, allauth config reports mfa, anon -> 401, full suite 47 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…missing accounts migration - accounts/0001_initial: the custom User migration missing from cf5e2a2 that broke the whole migration graph (all 47 tests errored, runserver dead) - contract tests over all 22 ninja routes: declared status + exact schema key-set; anonymous /accounts/me/* must be 401 not 500 - fleet concurrency tests: prove merge_winner is non-atomic (0/2/3 winners under parallel merges) — RED on purpose until the endpoint is guarded - extensions concurrency tests: F()-counter control, stays correct (green) - loadtest/: Locust rig, 22 routes, response-contract validation under load - requirements: locust - Dockerfile.backend: chown /app so coverage + locust can write there Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Three writes (clear winners, set winner, mark merged) ran in autocommit as separate transactions, so concurrent merges on one run interleaved and left 0 or 2+ winner lanes. Wrap them in transaction.atomic() and lock the run row with select_for_update() so merges serialise. Turns the two RED fleet concurrency tests green; verified under load (200 users, 680 merges, 0 winner-contract violations). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nd update Makefile commands - Updated Docker Compose files to replace 'backend' with 'django' for consistency across local and production environments. - Modified Makefile commands to reflect the new service name, ensuring commands like migrate, migrations, test-backend, and shell operate correctly with the updated service. - Enhanced frontend styles with new CSS variables for improved design consistency and added font imports. - Refactored chat components to support collapsible sidebar functionality and improved settings page structure.
# Conflicts: # .github/workflows/tag_and_release.yml # frontend/app/(workbench)/settings/page.module.css
Reasoning models (Qwen3, DeepSeek-R1) emit a <think> scratchpad that was rendering raw in the message bubble. splitReasoning() in phoenix_core separates it from the answer — including an unterminated block mid-stream — and ReasoningBlock shows it collapsed, one tap to expand. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
/api/v1/docs now renders Scalar instead of django-ninja's bundled Swagger. The @scalar/api-reference bundle (pinned 1.65.1) and the favicon are vendored under backend/static/scalar and served by Django, so the page touches no third-party CDN; the paid Agent is explicitly disabled and the theme is built from the Ember tokens. OpenAPI JSON is untouched, except that SessionTokenAuth now advertises its X-Session-Token header so Try Request can send it. Dependencies and pytest config move into backend/pyproject.toml, replacing requirements.txt and pytest.ini; the image installs with `pip install .`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
production carries #60 and #61 as squashes of work this branch already has, so every file conflicted as add/add. Resolved by keeping the branch side, which is production's content plus the Scalar docs UI; requirements.txt and pytest.ini stay deleted since pyproject.toml now carries both (dependency sets verified identical). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
RunListOut resolved lane_count and done_count with a query each, so GET /api/v1/fleet/runs/ cost 2 queries per row — 18 at 8 rows, growing with the list. Both counts move into one annotate. Django drops a model's Meta.ordering from an aggregate query, so the annotate also needs an explicit order_by; without it the list silently came back in insertion order instead of newest-first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The ruff select list only started applying repo-wide when pyproject.toml was committed, and it flags code that predates it: unsorted imports, noqa markers for rules that no longer fire, and a manage.py carrying a shebang without the executable bit. All fixes are mechanical (ruff --fix plus a mode change). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`pnpm lint` ran `next lint` with no ESLint config and no eslint dependency, so in CI it fell into the interactive "How would you like to configure ESLint?" prompt and exited 1 — the gate had never linted anything. Adds eslint 9 + eslint-config-next with a flat config (FlatCompat over next/core-web-vitals and next/typescript), and points the script at the ESLint CLI since `next lint` is removed in Next 16. pnpm 11 also needs the unrs-resolver build named in pnpm-workspace.yaml or the install itself fails. Then fixes what it found: five unescaped quotes/apostrophes in JSX, an <a> that must be next/link to reach /models, and two unused imports. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The ruff select list applies repo-wide since pyproject shipped, and it flags things that are correct inside tests: fixture credentials, a loopback bind constant, urlopen against a fixture URL, a deliberate broad except while probing settings, and en dashes in prose. Scoped to the test globs only — shipped code keeps the full set. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
nemati-ceo
pushed a commit
that referenced
this pull request
Aug 25, 2026
production carried PR #62 (Scalar docs UI + single pyproject). Conflicts in the five files this branch already reconciled resolve to this branch's side: it is the superset — the remote's newer work was merged here in cfe31e2, and production still holds the pre-scoping versions. Verified after merge: 162 passed, 16 skipped, ruff clean, no pending migrations, health OK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
/api/v1/docsrenders Scalar instead of django-ninja's bundled Swagger UI.@scalar/api-reference(pinned 1.65.1) and the favicon are vendored underbackend/static/scalar/and served by Django, so the docs page contacts no third-party CDN (no jsDelivr, nodjango-ninja.dev, noproxy.scalar.com, nofonts.scalar.com).AgentConfig(disabled=True)); theme built from the Ember tokens viacustom_csswithTheme.NONE.SessionTokenAuthnow advertisesin: header/name: X-Session-Tokenin OpenAPI, so Try Request can actually send the token. The OpenAPI path and schema generation are otherwise untouched.backend/pyproject.toml;requirements.txtandpytest.iniremoved and the image installs withpip install ..Verification
GET /api/v1/docsrenders the Scalar reference (checked in headless Chrome),GET /api/v1/openapi.json200 with 16 paths,GET /api/v1/health/200.backend/apps/core/tests/test_docs.py(4 tests) covers: page is Scalar and not Swagger, assets are first-party, Agent disabled with no key, bundle served withDEBUG=False, security scheme carries the header name.pyproject.toml; suite runs green on this tree (the only failures in an ad-hoc SQLite run were the Postgres-only concurrency tests).Notes
django.views.static.serveon a narrow^scalar/route, because staticfiles only self-serves underDEBUGand prod nginx has no/static/location. Move to nginx/WhiteNoise if backend static ever grows..github/workflows/ci.ymlstill mentionsrequirements.txtin a comment; CI config was left untouched.