The concurrency group only deduplicates live work on a branch; a run that was queued or still building kept its runner after the branch was deleted or its pull request closed. A delete and a pull_request closed trigger now cancel everything of that branch that has not completed, minus the cancelling run itself, which shares the head branch on a pull request event.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every push started its own run, so two pushes to the same branch raced through the same jobs and burned runner minutes twice. One concurrency group per ref now covers all six jobs, including the reusable workflows. Pull request runs cancel their predecessor; branch pushes queue instead, so a release push is never cancelled between the per-architecture push and the manifest merge.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The SHA-pinned actions, the two base images, the compose file, the Python project and the npm assets had no update stream, so a pinned reference only moved when someone noticed it by hand. Adds a daily Dependabot config for all five.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The publish job built a single-arch image on ubuntu-latest, so every release manifest carried linux/amd64 only. Split it into a version job that exports the semver tag and image name, a matrix publish job that builds each architecture on its own native runner (ubuntu-latest, ubuntu-24.04-arm) and pushes an arch-suffixed tag, and a manifest job that joins both under the release tag. Native runners avoid the QEMU emulation layer.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
recalcWhileCollapsing ran a requestAnimationFrame loop and cancelled it on
the header's max-height transitionend. When no max-height transition ran,
for example because the header was already in its target state, that event
never fired and the loop recalculated the scroll container on every frame
for the rest of the page's life; each further call started another such
loop. The loop now continues only while header.getAnimations() reports a
running animation.
The resize handler entered or exited fullscreen on every resize event. It
now returns early when the UI fullscreen state already matches the body
class, so a resize that changes nothing starts no recalc loop.
A Cypress spec spies on adjustScrollContainerHeight after exitFullscreen()
and requires the call count to stop growing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
observeIframeNavigation read iframe.contentWindow.location.href once,
outside any guard. For a cross-origin iframe that read throws a
SecurityError, which escaped as an uncaught exception and never reached
the polling loop, whose own read of the same property is already guarded.
The first read is now guarded as well, and the observer returns because it
cannot follow a cross-origin frame anyway.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The handler assigned through an optional chain,
this.nextElementSibling?.style.display='inline-block'. An optional chain
is not a valid assignment target, so the whole attribute failed to compile
("SyntaxError: Invalid left-hand side in assignment") whenever an icon
image failed to load: the broken image stayed visible and the fallback
<i> icon never appeared. An explicit null check does the same and
compiles.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
base.html.j2 set window.I18N from an executable inline <script>. A host
CSP can only allow an inline script by hash or by 'unsafe-inline', and this
script's content changes with every language, so no hash can cover it.
Infinito.Nexus serves the dashboard with a hash-based script-src-elem
whenever its logout feature is off, and there the script was blocked:
every page logged "Executing inline script violates the following Content
Security Policy directive 'script-src-elem ...'" and window.I18N stayed
undefined.
The strings now ship as <script id="i18n" type="application/json">, which
the browser does not execute and CSP does not govern; modal.js parses the
block before its first use. tojson escapes <, > and &, so a string that
contains "</script>" cannot end the block early.
Integration tests require that a page ships no executable inline script
and that a catalogue string containing "</script>" survives the round trip
through the block.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 23:25:51 +02:00
17 changed files with 258 additions and 62 deletions
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.