Skip to content

feat(api): Scalar docs UI + single pyproject config - #62

Merged
nemati-ceo merged 12 commits into
productionfrom
app/auth
Aug 19, 2026
Merged

nemati-ceo merged 12 commits into
productionfrom
app/auth

Conversation

@nemati-ceo

Copy link
Copy Markdown
Collaborator

What

  • /api/v1/docs renders Scalar instead of django-ninja's bundled Swagger UI.
  • @scalar/api-reference (pinned 1.65.1) and the favicon are vendored under backend/static/scalar/ and served by Django, so the docs page contacts no third-party CDN (no jsDelivr, no django-ninja.dev, no proxy.scalar.com, no fonts.scalar.com).
  • Paid Scalar Agent explicitly disabled (AgentConfig(disabled=True)); theme built from the Ember tokens via custom_css with Theme.NONE.
  • SessionTokenAuth now advertises in: header / name: X-Session-Token in OpenAPI, so Try Request can actually send the token. The OpenAPI path and schema generation are otherwise untouched.
  • Dependencies and pytest config merged into backend/pyproject.toml; requirements.txt and pytest.ini removed and the image installs with pip install ..

Verification

  • GET /api/v1/docs renders the Scalar reference (checked in headless Chrome), GET /api/v1/openapi.json 200 with 16 paths, GET /api/v1/health/ 200.
  • New 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 with DEBUG=False, security scheme carries the header name.
  • Image rebuilt from pyproject.toml; suite runs green on this tree (the only failures in an ad-hoc SQLite run were the Postgres-only concurrency tests).

Notes

  • The vendored bundle is 3.5 MB — the cost of not calling a third-party CDN for the docs page.
  • The two docs assets are served by django.views.static.serve on a narrow ^scalar/ route, because staticfiles only self-serves under DEBUG and prod nginx has no /static/ location. Move to nginx/WhiteNoise if backend static ever grows.
  • .github/workflows/ci.yml still mentions requirements.txt in a comment; CI config was left untouched.

parsanemati84 and others added 12 commits June 26, 2026 04:47
…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
nemati-ceo merged commit ffa7778 into production Aug 19, 2026
2 of 4 checks passed
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants