feat(frontend): serve every library from the instance, and rework the About dialog - #178
Merged
Merged
Conversation
… About dialog
Three changes to what the interface loads and what it says about itself.
**No library is loaded from a CDN any more.** Bootstrap, Bootstrap Icons,
htmx, Tom Select, pell, DOMPurify, Sortable, ECharts, D3, dagre, Leaflet
and the GitLab Sans faces came from jsDelivr, unpkg and d3js.org on every
page. That made the interface unusable on an isolated network, announced
every visitor of a compliance platform to a third party, and put someone
else's uptime in the critical path of a login screen.
They are now declared in core/dependencies.py - the registry the About
modal already answered from - with the exact files each needs and their
Subresource-Integrity digests, and mirrored into static/vendor/ by
`manage.py vendor_assets`. The Docker build runs it, so the published
image needs no network; a direct install fetches whatever is missing on
its first launch and finds it in place on every later one. A download
that does not match its digest is refused rather than written. The
mirror is generated, never committed, so the pins cannot be outranked by
a stale copy in git - the two files vendored by hand are removed
accordingly.
Templates reference the files through {% static %} and carry no version
of their own, which is what lets the tests hold the registry to the
truth: the pinned version must appear in the URL the file is fetched
from, every vendor/... path a template asks for must be a file something
mirrors, and no template may name a CDN host at all.
The pins were behind, so they move to their current releases: Bootstrap
Icons 1.13.1, htmx 2.0.10, Tom Select 2.6.2, DOMPurify 3.4.14, Sortable
1.15.7, ECharts 5.6.0. ECharts stays on the 5.x line - 6.0 is a major
with breaking changes and deserves its own change.
**The About dialog is two columns**, the identity card on the left and
the component inventory on the right, with no collapse to open and a
close cross instead of a footer button. Each library reads
`owner / name - version`, the owner coming from its repository URL, and
they are ordered by owner then name so a publisher's libraries sit
together. The inventory is laid out in columns that read top to bottom.
**It also says whether a newer release exists**, read from the GitHub
releases of the project. The call fires when the modal opens, never on a
page load, and the answer is cached across workers for six hours;
failures are cached too, so a GitHub outage cannot turn the modal into a
five-second wait. `UPDATE_CHECK_ENABLED=False` switches it off for a
deployment whose policy forbids the instance calling out. Exposed at
`GET /api/v1/update-check` and as the `check_for_updates` MCP tool.
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.
Summary
The interface loaded twelve front-end libraries from jsDelivr, unpkg and
d3js.org on every page. This serves all of them from the instance itself, from
the pins in
core/dependencies.py, so an isolated deployment works and no thirdparty is told who browses a compliance platform. The pins were behind, so they
also move to their current releases.
While in the same registry, the About dialog is reworked into two columns and
now reports whether a newer release is published.
Related issue
n/a
Type of change
Changes
core/dependencies.pywiththe exact files it needs and their Subresource-Integrity digests.
manage.py vendor_assetsmirrors them intostatic/vendor/; the Docker buildruns it, and a direct install fetches what is missing on its first launch.
A download that does not match its digest is refused rather than written.
.gitignore), so a stale copy ingit cannot outrank the registry. The two files vendored by hand (
d3,dagre) are removed accordingly.{% static %}and carry no version of theirown. Tests enforce the contract: the pinned version must appear in the URL the
file is fetched from, every
vendor/...path a template asks for must be afile something mirrors, and no template may name a CDN host.
vendor_assets,--check(verify),--force(re-downloadafter a bump),
--print-hashes(produce the digests for a new pin).3.4.14, Sortable 1.15.7, ECharts 5.6.0. ECharts stays on 5.x - 6.0 is a major
with breaking changes and deserves its own change.
close cross instead of a footer button. Entries read
owner / name - version,ordered by owner then name, in columns read top to bottom.
from the project's GitHub releases. Fires when the dialog opens, never on a
page load; cached six hours across workers, failures cached too.
UPDATE_CHECK_ENABLED=Falseswitches it off..env.exampleand thegenerated settings reference:
VENDOR_ASSETS_AUTO_DOWNLOAD,UPDATE_CHECK_ENABLED.Screenshots
Captured against the running instance with the About dialog open:
the right with the three stacks sharing the same column split, no truncated
names.
column below; the update pill fits on one line.
The dialog is not part of the
docs/screenshots/set, so no 2560x1440 capturewas added there.
Checklist
pytestpasses (3177 passed)ruff checkpassesmcp/tools.py(check_for_updates;list_dependenciesdescription updated for the newownerfield)api/(
GET /api/v1/update-check){% trans %}with French translations (noduplicate
msgid;compilemessagespasses)README.mdupdatedCHANGELOG.mdupdated under## [Unreleased]docs/specs/m0-accounts/README.md)in the documented set
🤖 Generated with Claude Code