Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Dockerfile.nginx-alpine
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,14 @@ COPY manage.py ./
COPY dojo/ ./dojo/
# Build Tailwind CSS
RUN cd components && yarn build:css
# the CSS is built, so drop the dev-only toolchain (tailwind cli, lightningcss and their native binaries) before static is collected
RUN cd components && yarn install --production --ignore-scripts
# always collect static for debug toolbar as we can't make it dependant on env variables or build arguments without breaking docker layer caching
RUN env DD_SECRET_KEY='.' DD_DJANGO_DEBUG_TOOLBAR_ENABLED=True python3 manage.py collectstatic --noinput --verbosity=2 && true
# skip files the pages never load: source maps, typescript sources and declarations, and the npm lockfiles some packages ship
# in their tarballs
RUN env DD_SECRET_KEY='.' DD_DJANGO_DEBUG_TOOLBAR_ENABLED=True python3 manage.py collectstatic --noinput --verbosity=2 \
--ignore yarn.lock --ignore package-lock.json --ignore npm-shrinkwrap.json --ignore pnpm-lock.yaml \
--ignore '*.map' --ignore '*.ts' --ignore '*.mts' --ignore '*.cts' && true

FROM nginx:1.29.3-alpine3.22@sha256:b3c656d55d7ad751196f21b7fd2e8d4da9cb430e32f646adcf92441b72f82b14 AS release
ARG uid=1001
Expand Down
6 changes: 3 additions & 3 deletions components/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2507,9 +2507,9 @@ ms@^2.1.3:
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==

nanoid@^3.3.16:
version "3.3.16"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.16.tgz#a04d8ec4b1f10009d2d533947aefe4293737816c"
integrity sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==
version "3.3.19"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.19.tgz#336d4aa4bcd4fb24d2cddede7ffeae40bec03f0a"
integrity sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==

nanoid@^5.0.7, nanoid@^5.1.6:
version "5.1.16"
Expand Down
9 changes: 8 additions & 1 deletion dojo/api_v3/reference_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"""
from __future__ import annotations

import json
from typing import TYPE_CHECKING

from django.http import HttpResponse
Expand All @@ -38,6 +39,11 @@
# Path inside components/node_modules (a STATICFILES_DIRS entry); version pinned in package.json.
SCALAR_STATIC_PATH = "@scalar/api-reference/dist/browser/standalone.js"

# Scalar enables its hosted AI assistant ("Ask AI") by default. That is a third-party service, so
# it is turned off to keep the page self-contained, for the same reason the bundle is not loaded
# from a CDN.
SCALAR_CONFIGURATION = json.dumps({"agent": {"disabled": True}})

_PAGE = """<!doctype html>
<html>
<head>
Expand All @@ -49,7 +55,7 @@
<noscript>The interactive API reference requires JavaScript.
The OpenAPI schema is at <a href="{openapi_url}">{openapi_url}</a>;
Swagger UI is at <a href="{docs_url}">{docs_url}</a>.</noscript>
<script id="api-reference" data-url="{openapi_url}"></script>
<script id="api-reference" data-url="{openapi_url}" data-configuration='{configuration}'></script>
<script src="{script_url}"></script>
</body>
</html>"""
Expand All @@ -61,4 +67,5 @@ def scalar_reference(request: HttpRequest) -> HttpResponse:
openapi_url=reverse("api_v3:openapi-json"),
docs_url=reverse("api_v3:openapi-view"),
script_url=static(SCALAR_STATIC_PATH),
configuration=SCALAR_CONFIGURATION,
))
9 changes: 9 additions & 0 deletions unittests/api_v3/test_apiv3_reference_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from __future__ import annotations

import json
import re
from pathlib import Path

from django.templatetags.static import static
Expand Down Expand Up @@ -51,6 +52,14 @@ def test_page_points_at_v3_schema_and_swagger_fallback(self):
# Swagger (framework-bundled assets) remains linked for noscript.
self.assertIn(reverse("api_v3:openapi-view"), html)

def test_hosted_ai_assistant_is_disabled(self):
# Scalar turns its hosted "Ask AI" assistant on by default; the page keeps it off so it
# never talks to a third-party service.
html = self._get().content.decode()
match = re.search(r"data-configuration='([^']*)'", html)
self.assertIsNotNone(match, "the Scalar script tag must carry a data-configuration")
self.assertTrue(json.loads(match.group(1))["agent"]["disabled"])

def test_reference_page_is_not_an_api_operation(self):
# A plain Django view: it must NOT appear in the OpenAPI schema (and therefore places no
# obligations on the authz/query completeness gates, which walk the schema).
Expand Down
Loading