Compare commits

...
Author SHA1 Message Date
James Brunton a243056c3e Merge branch 'main' into processor-restructure 2026-08-07 09:36:43 +01:00
James Brunton aa6ac5c7a3 (scripted) Restructure frontend so processor and editor are more distinct in the tree 2026-08-06 17:18:41 +01:00
James Brunton 71ef9dcde8 (scripted) Update paths for new frontend structure 2026-08-06 17:17:54 +01:00
James Brunton b9d3a3128b Fix Storybook Vite interaction 2026-08-06 17:17:20 +01:00
James Brunton 0bf35a98c0 Fix hidden circular dependency in watched folders code 2026-08-06 17:17:20 +01:00
James Brunton 10d9127d29 Drop me (Setup scripts) 2026-08-06 17:17:20 +01:00
Ludy fa2eb67124 deps(frontend): align dependency scopes and remove redundant ESLint packages (#6991)
# Description of Changes

This change reorganizes frontend dependencies by moving development-only
packages into `devDependencies`, removing obsolete packages, and
updating several development tooling dependencies to newer versions.

### What was changed

- Moved runtime-independent packages to `devDependencies`:
  - `@iconify/react`
  - `globals`
- Removed unused TypeScript ESLint packages:
  - `@typescript-eslint/eslint-plugin`
  - `@typescript-eslint/parser`
- Updated development dependencies:
  - `@iconify-json/material-symbols` → `1.2.83`
  - `@iconify/utils` → `3.1.4`
  - `globals` → `17.7.0`

These changes reduce redundant dependency declarations and ensure
packages are classified according to their actual usage. The main
challenge was distinguishing direct dependencies from packages already
provided transitively by frontend tooling.


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 14:56:12 +00:00
Ludy 86d4a34476 deps: Upgrade posthog-js to 1.405.2 (#7115)
# Description of Changes

- Updated the frontend `posthog-js` dependency from `^1.268.0` to
`^1.405.2`.
- Refreshed `frontend/package-lock.json` and updated related PostHog
transitive dependencies.
- Removed obsolete OpenTelemetry and protobuf-related transitive
packages no longer required by the newer PostHog version.
- The existing PostHog APIs used by Stirling-PDF remain compatible.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 13:54:44 +00:00
ConnorYoh 74c53001cf fix(saas): give auth-bootstrap data fetching a single owner (#7194)
## The problem

Three pieces of user data (pro status, avatar metadata, profile picture)
were being fetched from four different places: `initializeAuth` on
mount, the `SIGNED_IN` handler, the `TOKEN_REFRESHED` handler, and the
post-upgrade path.

On a fresh login the first two both see a session, so everything got
fetched twice. It didn't stop after login either — Supabase re-fires
`SIGNED_IN` on token refresh and tab-visibility wakeups, so a refresh
that emitted both events cost around 7 Supabase reads.

## The fix

All four call sites now go through one `loadUserData(session)` that is
idempotent per identity.

The guard key is `user.id` + `is_anonymous`:

- not the access token, which changes on every refresh and would defeat
the guard entirely
- the anonymous flag matters because a guest to authenticated upgrade
keeps the same user id, and that is the one case where the data
genuinely does need reloading

**Per login: 6 fetches to 3. A repeat `SIGNED_IN` or `TOKEN_REFRESHED`
fetches nothing.** The tests count real calls rather than asserting on
shape.

## Two behaviour changes worth naming

- `initializeAuth` now awaits the full load, so the initial spinner also
waits on the profile-picture URL. Net login is still faster, since an
entire duplicate pass is gone.
- A tab-wake `SIGNED_IN` no longer revalidates entitlements. That
revalidation was accidental rather than designed — `refreshProStatus()`
is the intended path, and post-checkout is already handled by
`CheckoutContext`.

## Scope

Supabase-origin traffic only. This does not touch the ~20 authenticated
requests hitting `SupabaseAuthenticationFilter`, because those go to the
Stirling backend rather than the hosted Supabase project. That is a
separate problem and is unmeasured, so it needs measuring before
anything is optimised. Remaining items (a double `/api/v1/team/my`
fetch, an effect keyed on `[user]` identity in `FolderContext`, the
`portalAccess` spinner flash, and caching the auth filter's per-request
Postgres round-trips) are tracked separately.

## Verification

```
npx tsc --noEmit --project editor/src/saas/tsconfig.json   # exit 0
npx eslint --max-warnings=0 editor/src/saas/auth            # exit 0
npx prettier --check editor/src/saas/auth/                  # clean
npx vitest run --project saas                               # 75 passed (20 files)
```
2026-08-06 13:05:24 +00:00
dependabot[bot] ad8830b645 build(deps): bump com.sun.xml.bind:jaxb-core from 4.0.7 to 4.0.9 (#7270)
Bumps com.sun.xml.bind:jaxb-core from 4.0.7 to 4.0.9.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.sun.xml.bind:jaxb-core&package-manager=gradle&previous-version=4.0.7&new-version=4.0.9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 12:20:38 +00:00
dependabot[bot] de93a1b5e2 build(deps): bump org.sonarqube from 7.2.3.7755 to 7.3.1.8318 (#7271)
Bumps org.sonarqube from 7.2.3.7755 to 7.3.1.8318.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.sonarqube&package-manager=gradle&previous-version=7.2.3.7755&new-version=7.3.1.8318)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 12:20:33 +00:00
dependabot[bot] 8476d3cdec build(deps-dev): bump eslint from 10.1.0 to 10.8.0 in /frontend in the eslint group across 1 directory (#7274)
Bumps the eslint group with 1 update in the /frontend directory:
[eslint](https://github.com/eslint/eslint).

Updates `eslint` from 10.1.0 to 10.8.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslint/releases">eslint's
releases</a>.</em></p>
<blockquote>
<h2>v10.8.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/2fee9bb7416116cbed4d8c8100b1ae713b6356a1"><code>2fee9bb</code></a>
feat: export <code>ConfigObject</code> from <code>eslint/config</code>
(<a
href="https://redirect.github.com/eslint/eslint/issues/21082">#21082</a>)
(sethamus)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/6b8d2f7589b8a7c8b91b8ca2a2ef6d46178760d8"><code>6b8d2f7</code></a>
fix: escape reserved characters in rule id in <code>html</code>
formatter (<a
href="https://redirect.github.com/eslint/eslint/issues/21129">#21129</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/90910715011211a20d011d807d398a7005127f35"><code>9091071</code></a>
fix: prevent <code>no-unreachable-loop</code> crash when all loop types
are ignored (<a
href="https://redirect.github.com/eslint/eslint/issues/21116">#21116</a>)
(Pixel)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e23fafe8d4b15355adef6cdebef414c3a2019454"><code>e23fafe</code></a>
fix: prefer-object-spread add semicolon when adding parenthesis (<a
href="https://redirect.github.com/eslint/eslint/issues/21081">#21081</a>)
(synthex-byte)</li>
<li><a
href="https://github.com/eslint/eslint/commit/20b5ad052360a443786a202e94624a3f81846511"><code>20b5ad0</code></a>
fix: quadratic-time regex in <code>prefer-template</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21096">#21096</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8b6f6c0b33411f34485512456d94f221daf7321f"><code>8b6f6c0</code></a>
fix: apply ignore configs to computed methods in class-methods-use-this
(<a
href="https://redirect.github.com/eslint/eslint/issues/21094">#21094</a>)
(Pixel)</li>
<li><a
href="https://github.com/eslint/eslint/commit/b2c608c014a396800a24a89343265d0616bee2d8"><code>b2c608c</code></a>
fix: NewExpression with parenthesized callee in
<code>preserve-caught-error</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21083">#21083</a>)
(Francesco Trotta)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/6ddf8587e5cfeeb7328332601bb76d98b8a198ea"><code>6ddf858</code></a>
docs: fix broken Specify Parser Options anchor link (<a
href="https://redirect.github.com/eslint/eslint/issues/21106">#21106</a>)
(Minsu)</li>
<li><a
href="https://github.com/eslint/eslint/commit/784dfbe98f0222426fd200153a5ce2e5624151f0"><code>784dfbe</code></a>
docs: Clarify <code>no-eq-null</code> description (<a
href="https://redirect.github.com/eslint/eslint/issues/21120">#21120</a>)
(Park Harin)</li>
<li><a
href="https://github.com/eslint/eslint/commit/7ec733a3ba5acb053a73ac656030a3879aa48fda"><code>7ec733a</code></a>
docs: Fix typos and grammar in glossary (<a
href="https://redirect.github.com/eslint/eslint/issues/21095">#21095</a>)
(Marry (Subin Yang))</li>
<li><a
href="https://github.com/eslint/eslint/commit/92bb13f13065db72d62454b9830d3ae52db15c76"><code>92bb13f</code></a>
docs: replace quake link (<a
href="https://redirect.github.com/eslint/eslint/issues/21108">#21108</a>)
(Jung Hyeon Jun)</li>
<li><a
href="https://github.com/eslint/eslint/commit/68eb4a57572409dbdcfeb3bc5c92ddbba46bc770"><code>68eb4a5</code></a>
docs: fix broken Specify Globals anchor links in rule pages (<a
href="https://redirect.github.com/eslint/eslint/issues/21103">#21103</a>)
(Minsu)</li>
<li><a
href="https://github.com/eslint/eslint/commit/d28f697e0d32d7446c825fd89c362db028450134"><code>d28f697</code></a>
docs: replace Code Climate CLI links with Qlty CLI links (<a
href="https://redirect.github.com/eslint/eslint/issues/21099">#21099</a>)
(Jung Hyeon Jun)</li>
<li><a
href="https://github.com/eslint/eslint/commit/eccc68d42564e46bc9020d19ec52d2988f3b7bfa"><code>eccc68d</code></a>
docs: correct --suppressions-location option description (<a
href="https://redirect.github.com/eslint/eslint/issues/21093">#21093</a>)
(Ga eun Lee)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c5963f74bfa82a5b7ccc0607dcdcc695b8c97a31"><code>c5963f7</code></a>
docs: Update README (GitHub Actions Bot)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/4fbf46d140120ae838db08cbe49544c985956490"><code>4fbf46d</code></a>
test: pin <code>webpack</code> version to 5.108.4 (<a
href="https://redirect.github.com/eslint/eslint/issues/21137">#21137</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/2d063e224e9bb0ccb0a28c120f7e380a8d62f320"><code>2d063e2</code></a>
chore: update HTTP URLs to HTTPS in JSDoc and comments (<a
href="https://redirect.github.com/eslint/eslint/issues/21101">#21101</a>)
(Bo Hyun Kim)</li>
<li><a
href="https://github.com/eslint/eslint/commit/eccbe7bc9257a6c99880468e452c8dfafbf47f74"><code>eccbe7b</code></a>
test: add error locations to <code>no-class-assign</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21123">#21123</a>)
(devoil)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e7d1e4373bf626f8da76d62ce024c28928bc99bc"><code>e7d1e43</code></a>
ci: bump actions/setup-go from 6 to 7 (<a
href="https://redirect.github.com/eslint/eslint/issues/21118">#21118</a>)
(dependabot[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/e9d66d0cde1a7752c29dee53ab7b62632835a87a"><code>e9d66d0</code></a>
ci: bump actions/setup-node from 6 to 7 (<a
href="https://redirect.github.com/eslint/eslint/issues/21119">#21119</a>)
(dependabot[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/ee225b60c26f0cc5f4d71641888a5bd2ec5626d6"><code>ee225b6</code></a>
test: Add error location details to <code>no-eq-null</code> rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21117">#21117</a>)
(Park Harin)</li>
<li><a
href="https://github.com/eslint/eslint/commit/044a627fa3e28ee1410d515acc5378eb4b49f8ba"><code>044a627</code></a>
chore: update minimatch to ^10.2.5 (<a
href="https://redirect.github.com/eslint/eslint/issues/21107">#21107</a>)
(김채영)</li>
<li><a
href="https://github.com/eslint/eslint/commit/fb09aa8ff09730d3ccf68859e065f99666b52466"><code>fb09aa8</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21115">#21115</a>)
(ESLint Bot)</li>
<li><a
href="https://github.com/eslint/eslint/commit/5abd878740fe417fd8a910cac3741f2a0317b365"><code>5abd878</code></a>
test: add error locations to <code>no-proto</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21114">#21114</a>)
(Gihyeon Jeong / 정기현)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9715887ec94a5ff936447d7b680d039fbe2f0541"><code>9715887</code></a>
test: Add error location details to <code>no-div-regex</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21110">#21110</a>)
(Park Harin)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a746ec6ea4a2249b1eb3f512264da5f4d5f7c886"><code>a746ec6</code></a>
test: add error locations to <code>no-new-wrappers</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21109">#21109</a>)
(Gihyeon Jeong / 정기현)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8dde64570e240f3ef8af873d59a752db6d8519aa"><code>8dde645</code></a>
test: add error locations to <code>no-ex-assign</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21102">#21102</a>)
(devoil)</li>
<li><a
href="https://github.com/eslint/eslint/commit/13ab0ec447650c079d8a5e5d67222f79e69c741e"><code>13ab0ec</code></a>
test: add error locations to <code>no-label-var</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21098">#21098</a>)
(Gihyeon Jeong / 정기현)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a99906ffb8342dde03336b5c6372b5658f21d5f2"><code>a99906f</code></a>
test: Add error location details to <code>no-delete-var</code> rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21105">#21105</a>)
(Park Harin)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c47e8dc9bbfba797430db45ae08cb6f7392cfc9d"><code>c47e8dc</code></a>
chore: add missing backticks to <code>languages/js/index.js</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21104">#21104</a>)
(beeen)</li>
<li><a
href="https://github.com/eslint/eslint/commit/0174428dd7543d118cf67a823b98dd97032fe68c"><code>0174428</code></a>
chore: add missing backticks to <code>translate-cli-options.js</code>
(<a
href="https://redirect.github.com/eslint/eslint/issues/21097">#21097</a>)
(dongkyu lee)</li>
<li><a
href="https://github.com/eslint/eslint/commit/3d36589a4917326500f0707bb41745160f387d00"><code>3d36589</code></a>
chore: add missing backticks to <code>serialization.js</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21091">#21091</a>)
(이규환)</li>
<li><a
href="https://github.com/eslint/eslint/commit/dcc9312c1081931de0fe1b555fbb6aa82fe696b9"><code>dcc9312</code></a>
test: add error locations to <code>eqeqeq</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21090">#21090</a>)
(Ga eun Lee)</li>
<li><a
href="https://github.com/eslint/eslint/commit/2710b182472cd1a95e4aff6186cb2c4fbadb4ee0"><code>2710b18</code></a>
ci: Add explicit permissions to rebuild-docs-sites workflow (<a
href="https://redirect.github.com/eslint/eslint/issues/21089">#21089</a>)
(Marry (Subin Yang))</li>
<li><a
href="https://github.com/eslint/eslint/commit/5d2f8663ee60701e9036b0b0933a12efd9d93269"><code>5d2f866</code></a>
chore: update dependency prettier to v3.9.5 (<a
href="https://redirect.github.com/eslint/eslint/issues/21086">#21086</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/d584e31098f262563b97dc5d5f23a63a187879a0"><code>d584e31</code></a>
chore: fix failing ecosystem test for <code>eslint-plugin-unicorn</code>
(<a
href="https://redirect.github.com/eslint/eslint/issues/21084">#21084</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/bf3eda049bd690f1e9a5a0c4520a6329b3e4ec85"><code>bf3eda0</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21079">#21079</a>)
(ESLint Bot)</li>
</ul>
<h2>v10.7.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/cf2a9bf2d982642f760370c15f1196f4658f4e27"><code>cf2a9bf</code></a>
feat: add errorClassNames option to preserve-caught-error rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21032">#21032</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f8b873aae53610b80b5c1005606716e05ed3b91f"><code>f8b873a</code></a>
feat: max-nested-callbacks option for constructor callbacks (<a
href="https://redirect.github.com/eslint/eslint/issues/21063">#21063</a>)
(fnx)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/749dfed106f44d77bf3af2402ebfae20cdbf59ee"><code>749dfed</code></a>
10.8.0</li>
<li><a
href="https://github.com/eslint/eslint/commit/4bd0d75b22ffd44809a92659f113c972c5be0770"><code>4bd0d75</code></a>
Build: changelog update for 10.8.0</li>
<li><a
href="https://github.com/eslint/eslint/commit/4fbf46d140120ae838db08cbe49544c985956490"><code>4fbf46d</code></a>
test: pin <code>webpack</code> version to 5.108.4 (<a
href="https://redirect.github.com/eslint/eslint/issues/21137">#21137</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/6ddf8587e5cfeeb7328332601bb76d98b8a198ea"><code>6ddf858</code></a>
docs: fix broken Specify Parser Options anchor link (<a
href="https://redirect.github.com/eslint/eslint/issues/21106">#21106</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/784dfbe98f0222426fd200153a5ce2e5624151f0"><code>784dfbe</code></a>
docs: Clarify <code>no-eq-null</code> description (<a
href="https://redirect.github.com/eslint/eslint/issues/21120">#21120</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/6b8d2f7589b8a7c8b91b8ca2a2ef6d46178760d8"><code>6b8d2f7</code></a>
fix: escape reserved characters in rule id in <code>html</code>
formatter (<a
href="https://redirect.github.com/eslint/eslint/issues/21129">#21129</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/2d063e224e9bb0ccb0a28c120f7e380a8d62f320"><code>2d063e2</code></a>
chore: update HTTP URLs to HTTPS in JSDoc and comments (<a
href="https://redirect.github.com/eslint/eslint/issues/21101">#21101</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/eccbe7bc9257a6c99880468e452c8dfafbf47f74"><code>eccbe7b</code></a>
test: add error locations to <code>no-class-assign</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/21123">#21123</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/2fee9bb7416116cbed4d8c8100b1ae713b6356a1"><code>2fee9bb</code></a>
feat: export <code>ConfigObject</code> from <code>eslint/config</code>
(<a
href="https://redirect.github.com/eslint/eslint/issues/21082">#21082</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e7d1e4373bf626f8da76d62ce024c28928bc99bc"><code>e7d1e43</code></a>
ci: bump actions/setup-go from 6 to 7 (<a
href="https://redirect.github.com/eslint/eslint/issues/21118">#21118</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslint/compare/v10.1.0...v10.8.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 12:20:27 +00:00
dependabot[bot] 94fbc74271 build(deps): bump the uv group across 1 directory with 3 updates (#7287)
Bumps the uv group with 3 updates in the /engine directory:
[cryptography](https://github.com/pyca/cryptography),
[aiohttp](https://github.com/aio-libs/aiohttp) and
[datamodel-code-generator](https://github.com/koxudaxi/datamodel-code-generator).

Updates `cryptography` from 49.0.0 to 50.0.0
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst">cryptography's
changelog</a>.</em></p>
<blockquote>
<p>50.0.0 - 2026-07-31</p>
<pre><code>
* **SECURITY ISSUE**:

:func:`~cryptography.hazmat.primitives.serialization.pkcs7.pkcs7_decrypt_der`
and its PEM and S/MIME variants no longer expose distinguishable errors
or
timing when unwrapping a ``RecipientInfo``'s ``encryptedKey``, which
could
act as a Bleichenbacher oracle for callers that decrypt untrusted
messages.
A random key is now substituted on failure, as described in :rfc:`3218`.
  Credit to **@X1AOxiang** for reporting the issue. **CVE-2026-69247**
* Deprecated Diffie-Hellman key exchange over finite fields (FFDH).
  Everything FFDH is deprecated, including the types in
``cryptography.hazmat.primitives.asymmetric.dh`` and loading FFDH keys
or
  parameters with the key loading APIs. Users should migrate to a more
  modern key exchange algorithm.
* Added ``xof()`` class methods to
  :class:`~cryptography.hazmat.primitives.hashes.SHAKE128` and
:class:`~cryptography.hazmat.primitives.hashes.SHAKE256` for
constructing
  algorithm instances configured for use with
  :class:`~cryptography.hazmat.primitives.hashes.XOFHash`.
* The :mod:`X.509 verification &lt;cryptography.x509.verification&gt;`
APIs are now
  considered stable and are subject to our API stability policy.
* Added the :doc:`/cobblestone` recipe, an implementation of the
  Cobblestone-128 and Cobblestone-256 instantiations of the `C2SP
  chunked-encryption specification
&lt;https://c2sp.org/chunked-encryption&gt;`_ for streaming
authenticated
  encryption of large messages.
* Parsing a Signed Certificate Timestamp list now rejects encodings that
carry trailing bytes after the list or after an individual SCT, instead
of
  silently ignoring them.
* Added support for using :class:`~cryptography.x509.Name` as a field
type in
  the :doc:`/hazmat/asn1/index` module.
* Loading a public key or an EC private key now rejects DER where the
``subjectPublicKey`` (or EC ``publicKey``) ``BIT STRING`` declares a
non-zero
  number of unused bits, instead of silently ignoring it.
* Parsing a CRL entry's ``InvalidityDate`` extension now rejects a
``GeneralizedTime`` that carries fractional seconds or another non-DER
form,
matching the strict encoding already required for every other X.509 time
  field.
* :func:`~cryptography.x509.ocsp.load_der_ocsp_request` and
:func:`~cryptography.x509.ocsp.load_der_ocsp_response` now reject a
request
or response whose ``version`` field is not ``v1``, the only version
defined
by RFC 6960, matching the version validation already performed when
loading
  certificates, CSRs and CRLs.
* :class:`~cryptography.hazmat.primitives.hashes.XOFHash` is now
supported
  when building against AWS-LC.
* HMAC (and therefore PBKDF2-HMAC) with SHA-3 hashes is now supported
when
  building against AWS-LC.
* Diffie-Hellman (:doc:`/hazmat/primitives/asymmetric/dh`) is now
supported
  when building against AWS-LC.
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pyca/cryptography/commit/dcb7050b807b00392fa9fe2eac7cb362fcf355cc"><code>dcb7050</code></a>
Prepare for 50.0.0 release (<a
href="https://redirect.github.com/pyca/cryptography/issues/15372">#15372</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/53fccd93413a8d7f07d6d8999681f27b75cffa3f"><code>53fccd9</code></a>
Don't leak how PKCS#7 encryptedKey decryption failed (<a
href="https://redirect.github.com/pyca/cryptography/issues/15369">#15369</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/d472f978470fbefa521b86d98b2ecccbbb4d1dd8"><code>d472f97</code></a>
Add <code>from __future__ import annotations</code> to all src/ Python
files (<a
href="https://redirect.github.com/pyca/cryptography/issues/15371">#15371</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/908773d53829fb1466c6db364b31321c3cd8eb9a"><code>908773d</code></a>
Bump downstream dependencies in CI (<a
href="https://redirect.github.com/pyca/cryptography/issues/15368">#15368</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/2cc07cc948948211899bcb0cddd1fddf86e95812"><code>2cc07cc</code></a>
Bump BoringSSL, OpenSSL, AWS-LC in CI (<a
href="https://redirect.github.com/pyca/cryptography/issues/15367">#15367</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/c94ede9f040fa44942f7139772603419000acf66"><code>c94ede9</code></a>
chore(deps): bump ruff from 0.16.0 to 0.16.1 (<a
href="https://redirect.github.com/pyca/cryptography/issues/15366">#15366</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/67a8308dc9ea4cce6056e0f1438f903c208c3f35"><code>67a8308</code></a>
chore(deps): bump virtualenv from 21.7.0 to 21.7.1 (<a
href="https://redirect.github.com/pyca/cryptography/issues/15365">#15365</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/95018ffcdbbc510fd92fc872e3a3e80aa6e58596"><code>95018ff</code></a>
Release the GIL in one-shot AEAD encrypt/decrypt (<a
href="https://redirect.github.com/pyca/cryptography/issues/15361">#15361</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/6954733eaf55a0074abf88f06f7242dfca3a5d02"><code>6954733</code></a>
Release the GIL during DH and DSA parameter generation (<a
href="https://redirect.github.com/pyca/cryptography/issues/15364">#15364</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/6893b94c33e948f6240082461424cfb5da2dacc6"><code>6893b94</code></a>
Import _serialization instead of serialization in x509/extensions (<a
href="https://redirect.github.com/pyca/cryptography/issues/15363">#15363</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pyca/cryptography/compare/49.0.0...50.0.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `aiohttp` from 3.14.1 to 3.14.3
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst">aiohttp's
changelog</a>.</em></p>
<blockquote>
<h1>3.14.3 (2026-07-22)</h1>
<h2>Bug fixes</h2>
<ul>
<li>
<p>Fixed the client dropping only the first <code>Authorization</code>,
<code>Cookie</code> and
<code>Proxy-Authorization</code> header when a redirect crossed an
origin -- by :user:<code>arshsmith1</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>13180</code>.</p>
</li>
<li>
<p>Fixed error message construction in the C HTTP parser -- by
:user:<code>bdraco</code>.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>13222</code>.</p>
</li>
</ul>
<hr />
<h1>3.14.2 (2026-07-20)</h1>
<h2>Bug fixes</h2>
<ul>
<li>
<p>Fixed :py:attr:<code>~aiohttp.web.StreamResponse.last_modified</code>
rounding a
:class:<code>datetime.datetime</code> with a fractional second down.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>5303</code>.</p>
</li>
<li>
<p>Fixed resolving <code>localhost</code> on Windows to fall back
without <code>AI_ADDRCONFIG</code>
when the first lookup fails, so <code>localhost</code> still works
without an active
network.</p>
<p><em>Related issues and pull requests on GitHub:</em>
:issue:<code>5357</code>.</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/5e392ce0456f5235a4ee6ad46f0e806df2f15873"><code>5e392ce</code></a>
Release v3.14.3 (<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13225">#13225</a>)</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/49f65d54150397892f7bcc4aae887767d51c322d"><code>49f65d5</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13222">#13222</a>/f4866933
backport][3.14] Build C parser error message from bounded...</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/240099e5216a01b32919dcd8dd5c6c0b1bf83671"><code>240099e</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13180">#13180</a>/ee53d655
backport][3.14] drop every copy of credential headers on ...</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/d93f30a302f8b930074fe14a2be7b2088ba28111"><code>d93f30a</code></a>
Bump version (<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13202">#13202</a>)</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/c1b9212ad3d93c24b5fc66ad0849597166bc816e"><code>c1b9212</code></a>
Release v3.14.2 (<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13201">#13201</a>)</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/380d4b55e8df48dfd62f1addfb530426f6bc4106"><code>380d4b5</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13054">#13054</a>/ed8b040c
backport][3.14] escape backslashes in digest auth quoted-...</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/e1e1bee363dfba04a9a75c8801717da2ed5bdcb9"><code>e1e1bee</code></a>
Make llhttp method array size dynamic (<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13174">#13174</a>)
(<a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13196">#13196</a>)</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/aa4cf29b6a5ad6f4d21fa1dd3f69193dc2f5d505"><code>aa4cf29</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13170">#13170</a>/2b906869
backport][3.14] Fix StreamResponse.last_modified rounding...</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/71b57b40d85a0723c92b0a5a37ebdf518210d2ea"><code>71b57b4</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13172">#13172</a>/a57747ed
backport][3.14] Fix C parser folding fragment into query_...</li>
<li><a
href="https://github.com/aio-libs/aiohttp/commit/64a03fb620b623e5a5a1b7103c07ae3e536a0d40"><code>64a03fb</code></a>
[PR <a
href="https://redirect.github.com/aio-libs/aiohttp/issues/13169">#13169</a>/1adc0cd7
backport][3.14] Upgrade http:// to https:// in README.rst...</li>
<li>Additional commits viewable in <a
href="https://github.com/aio-libs/aiohttp/compare/v3.14.1...v3.14.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `datamodel-code-generator` from 0.56.0 to 0.64.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/koxudaxi/datamodel-code-generator/releases">datamodel-code-generator's
releases</a>.</em></p>
<blockquote>
<h2>0.64.0</h2>
<h2>Breaking Changes</h2>
<h3>Code Generation Changes</h3>
<ul>
<li>Self-referencing fields are now quoted with
<code>--disable-future-imports</code> - When
<code>--disable-future-imports</code> is set (no <code>from __future__
import annotations</code> and no native PEP 649 deferred evaluation on
Python &lt; 3.14), self-referencing and forward-referencing field
annotations in regular <code>BaseModel</code> classes are now emitted as
quoted forward references instead of bare names. Previously such
annotations were left unquoted, producing invalid code that raised
<code>NameError</code> (Ruff F821) at class-evaluation time. Output for
the common case (with <code>from __future__ import annotations</code> or
Python 3.14 native deferred annotations) is unchanged. Users who
snapshot/golden-file generated output for the
<code>--disable-future-imports</code> configuration with
self-referencing models will see the annotation change from unquoted to
quoted, e.g. <code>children: Optional[List[Node]]</code> →
<code>children: Optional[List[&quot;Node&quot;]]</code>. (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3387">#3387</a>)</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Update CHANGELOG for 0.63.0 by <a
href="https://github.com/dcg-generated-docs"><code>@​dcg-generated-docs</code></a>[bot]
in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3345">koxudaxi/datamodel-code-generator#3345</a></li>
<li>Deduplicate module content builder by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3346">koxudaxi/datamodel-code-generator#3346</a></li>
<li>Deduplicate import reference helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3348">koxudaxi/datamodel-code-generator#3348</a></li>
<li>Refactor jsonschema root model registration by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3352">koxudaxi/datamodel-code-generator#3352</a></li>
<li>Refactor XML Schema literal helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3349">koxudaxi/datamodel-code-generator#3349</a></li>
<li>Move builtin formatter helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3351">koxudaxi/datamodel-code-generator#3351</a></li>
<li>Deduplicate Pydantic v2 config helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3350">koxudaxi/datamodel-code-generator#3350</a></li>
<li>Deduplicate DataType type hint rendering by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3354">koxudaxi/datamodel-code-generator#3354</a></li>
<li>Fix <code>constr()</code> for string fields carrying
minItems/maxItems by <a
href="https://github.com/DarkaMaul"><code>@​DarkaMaul</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3353">koxudaxi/datamodel-code-generator#3353</a></li>
<li>Cover non-finite import idempotence by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3367">koxudaxi/datamodel-code-generator#3367</a></li>
<li>Deduplicate input text detection by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3357">koxudaxi/datamodel-code-generator#3357</a></li>
<li>Remove stale protobuf coverage pragma by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3358">koxudaxi/datamodel-code-generator#3358</a></li>
<li>Cover explicit null OpenAPI media schemas by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3360">koxudaxi/datamodel-code-generator#3360</a></li>
<li>Simplify Python version feature checks by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3361">koxudaxi/datamodel-code-generator#3361</a></li>
<li>Speed up CI checks by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3378">koxudaxi/datamodel-code-generator#3378</a></li>
<li>Add maintainer link to docs footer and README by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3379">koxudaxi/datamodel-code-generator#3379</a></li>
<li>Use builtin formatter in CI by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3380">koxudaxi/datamodel-code-generator#3380</a></li>
<li>Split coverage by OS by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3381">koxudaxi/datamodel-code-generator#3381</a></li>
<li>Simplify import removal cleanup by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3362">koxudaxi/datamodel-code-generator#3362</a></li>
<li>Pin deprecation warning stacklevel by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3363">koxudaxi/datamodel-code-generator#3363</a></li>
<li>Pin public module exports by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3364">koxudaxi/datamodel-code-generator#3364</a></li>
<li>Cover to_hashable branch cases by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3366">koxudaxi/datamodel-code-generator#3366</a></li>
<li>Cover stable toposort behavior by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3369">koxudaxi/datamodel-code-generator#3369</a></li>
<li>Extract registry render helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3371">koxudaxi/datamodel-code-generator#3371</a></li>
<li>Fix minItems for arrays of URI strings by <a
href="https://github.com/sjh9714"><code>@​sjh9714</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3377">koxudaxi/datamodel-code-generator#3377</a></li>
<li>Deduplicate config value validators by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3372">koxudaxi/datamodel-code-generator#3372</a></li>
<li>Cover CLI option metadata helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3374">koxudaxi/datamodel-code-generator#3374</a></li>
<li>Cover Pydantic v2 version fallback by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3368">koxudaxi/datamodel-code-generator#3368</a></li>
<li>Fix nullable JSON Schema const enums by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3355">koxudaxi/datamodel-code-generator#3355</a></li>
<li>Pin patchable generation seams by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3365">koxudaxi/datamodel-code-generator#3365</a></li>
<li>Cover utility helper behavior by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3375">koxudaxi/datamodel-code-generator#3375</a></li>
<li>Cover DefaultPutDict behavior by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3376">koxudaxi/datamodel-code-generator#3376</a></li>
<li>Cover validator config normalization by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3373">koxudaxi/datamodel-code-generator#3373</a></li>
<li>Avoid expensive runtime type checks by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3382">koxudaxi/datamodel-code-generator#3382</a></li>
<li>Avoid eager builtin formatter import by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3383">koxudaxi/datamodel-code-generator#3383</a></li>
<li>Avoid eager TOML parser import by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3384">koxudaxi/datamodel-code-generator#3384</a></li>
<li>Stabilize msgspec payload tests by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3385">koxudaxi/datamodel-code-generator#3385</a></li>
<li>Avoid eager input parser imports by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3386">koxudaxi/datamodel-code-generator#3386</a></li>
<li>Avoid eager parser model imports by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3388">koxudaxi/datamodel-code-generator#3388</a></li>
<li>Avoid eager AsyncAPI converter imports by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3389">koxudaxi/datamodel-code-generator#3389</a></li>
<li>Dispose parser on parse errors by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3390">koxudaxi/datamodel-code-generator#3390</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/koxudaxi/datamodel-code-generator/blob/main/CHANGELOG.md">datamodel-code-generator's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/koxudaxi/datamodel-code-generator/releases/tag/0.64.0">0.64.0</a>
- 2026-06-14</h2>
<h2>Breaking Changes</h2>
<h3>Code Generation Changes</h3>
<ul>
<li>Self-referencing fields are now quoted with
<code>--disable-future-imports</code> - When
<code>--disable-future-imports</code> is set (no <code>from __future__
import annotations</code> and no native PEP 649 deferred evaluation on
Python &lt; 3.14), self-referencing and forward-referencing field
annotations in regular <code>BaseModel</code> classes are now emitted as
quoted forward references instead of bare names. Previously such
annotations were left unquoted, producing invalid code that raised
<code>NameError</code> (Ruff F821) at class-evaluation time. Output for
the common case (with <code>from __future__ import annotations</code> or
Python 3.14 native deferred annotations) is unchanged. Users who
snapshot/golden-file generated output for the
<code>--disable-future-imports</code> configuration with
self-referencing models will see the annotation change from unquoted to
quoted, e.g. <code>children: Optional[List[Node]]</code> →
<code>children: Optional[List[&quot;Node&quot;]]</code>. (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3387">#3387</a>)</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Update CHANGELOG for 0.63.0 by <a
href="https://github.com/dcg-generated-docs"><code>@​dcg-generated-docs</code></a>[bot]
in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3345">koxudaxi/datamodel-code-generator#3345</a></li>
<li>Deduplicate module content builder by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3346">koxudaxi/datamodel-code-generator#3346</a></li>
<li>Deduplicate import reference helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3348">koxudaxi/datamodel-code-generator#3348</a></li>
<li>Refactor jsonschema root model registration by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3352">koxudaxi/datamodel-code-generator#3352</a></li>
<li>Refactor XML Schema literal helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3349">koxudaxi/datamodel-code-generator#3349</a></li>
<li>Move builtin formatter helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3351">koxudaxi/datamodel-code-generator#3351</a></li>
<li>Deduplicate Pydantic v2 config helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3350">koxudaxi/datamodel-code-generator#3350</a></li>
<li>Deduplicate DataType type hint rendering by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3354">koxudaxi/datamodel-code-generator#3354</a></li>
<li>Fix <code>constr()</code> for string fields carrying
minItems/maxItems by <a
href="https://github.com/DarkaMaul"><code>@​DarkaMaul</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3353">koxudaxi/datamodel-code-generator#3353</a></li>
<li>Cover non-finite import idempotence by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3367">koxudaxi/datamodel-code-generator#3367</a></li>
<li>Deduplicate input text detection by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3357">koxudaxi/datamodel-code-generator#3357</a></li>
<li>Remove stale protobuf coverage pragma by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3358">koxudaxi/datamodel-code-generator#3358</a></li>
<li>Cover explicit null OpenAPI media schemas by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3360">koxudaxi/datamodel-code-generator#3360</a></li>
<li>Simplify Python version feature checks by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3361">koxudaxi/datamodel-code-generator#3361</a></li>
<li>Speed up CI checks by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3378">koxudaxi/datamodel-code-generator#3378</a></li>
<li>Add maintainer link to docs footer and README by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3379">koxudaxi/datamodel-code-generator#3379</a></li>
<li>Use builtin formatter in CI by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3380">koxudaxi/datamodel-code-generator#3380</a></li>
<li>Split coverage by OS by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3381">koxudaxi/datamodel-code-generator#3381</a></li>
<li>Simplify import removal cleanup by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3362">koxudaxi/datamodel-code-generator#3362</a></li>
<li>Pin deprecation warning stacklevel by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3363">koxudaxi/datamodel-code-generator#3363</a></li>
<li>Pin public module exports by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3364">koxudaxi/datamodel-code-generator#3364</a></li>
<li>Cover to_hashable branch cases by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3366">koxudaxi/datamodel-code-generator#3366</a></li>
<li>Cover stable toposort behavior by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3369">koxudaxi/datamodel-code-generator#3369</a></li>
<li>Extract registry render helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3371">koxudaxi/datamodel-code-generator#3371</a></li>
<li>Fix minItems for arrays of URI strings by <a
href="https://github.com/sjh9714"><code>@​sjh9714</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3377">koxudaxi/datamodel-code-generator#3377</a></li>
<li>Deduplicate config value validators by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3372">koxudaxi/datamodel-code-generator#3372</a></li>
<li>Cover CLI option metadata helpers by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3374">koxudaxi/datamodel-code-generator#3374</a></li>
<li>Cover Pydantic v2 version fallback by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3368">koxudaxi/datamodel-code-generator#3368</a></li>
<li>Fix nullable JSON Schema const enums by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3355">koxudaxi/datamodel-code-generator#3355</a></li>
<li>Pin patchable generation seams by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3365">koxudaxi/datamodel-code-generator#3365</a></li>
<li>Cover utility helper behavior by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3375">koxudaxi/datamodel-code-generator#3375</a></li>
<li>Cover DefaultPutDict behavior by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3376">koxudaxi/datamodel-code-generator#3376</a></li>
<li>Cover validator config normalization by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3373">koxudaxi/datamodel-code-generator#3373</a></li>
<li>Avoid expensive runtime type checks by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3382">koxudaxi/datamodel-code-generator#3382</a></li>
<li>Avoid eager builtin formatter import by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3383">koxudaxi/datamodel-code-generator#3383</a></li>
<li>Avoid eager TOML parser import by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3384">koxudaxi/datamodel-code-generator#3384</a></li>
<li>Stabilize msgspec payload tests by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3385">koxudaxi/datamodel-code-generator#3385</a></li>
<li>Avoid eager input parser imports by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3386">koxudaxi/datamodel-code-generator#3386</a></li>
<li>Avoid eager parser model imports by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3388">koxudaxi/datamodel-code-generator#3388</a></li>
<li>Avoid eager AsyncAPI converter imports by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3389">koxudaxi/datamodel-code-generator#3389</a></li>
<li>Dispose parser on parse errors by <a
href="https://github.com/koxudaxi"><code>@​koxudaxi</code></a> in <a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/pull/3390">koxudaxi/datamodel-code-generator#3390</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/53a25ab8ddb132ac68a2795247fc855b8f445d84"><code>53a25ab</code></a>
Fast path schema output (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3410">#3410</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/ee2087f32e6100f5c3642e7ea8506aa38e9df26c"><code>ee2087f</code></a>
Skip discriminator import scan (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3411">#3411</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/bdf5ddfc27f94a06ba8d289759193bb09daadd34"><code>bdf5ddf</code></a>
fix: quote self-referencing fields when --disable-future-imports is set
(<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3387">#3387</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/ad4ec877fa6708baebdaaf820171d24bfe5bf0cb"><code>ad4ec87</code></a>
Cache payload validation strategies (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3409">#3409</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/b191d52a0a1d83edeac9553119f70b2f5c131126"><code>b191d52</code></a>
Shard Python tests (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3408">#3408</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/29dd6d74c95dd7799d51f2c707db24862809eb23"><code>29dd6d7</code></a>
Cache parsed sources (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3407">#3407</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/93e2fe3cf5774d5e4d2083fac365e5bcbf0a647a"><code>93e2fe3</code></a>
Defer generation refresh (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3406">#3406</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/bb01d9c628f9077cc5dd72320ae60a18abd5b790"><code>bb01d9c</code></a>
Lazy root format exports (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3405">#3405</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/48237ed8c3af3bb58b5e6b274925ebb646412d3a"><code>48237ed</code></a>
Fast path JSON schemas (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3404">#3404</a>)</li>
<li><a
href="https://github.com/koxudaxi/datamodel-code-generator/commit/b21d106c88ac22f137cd4562389ad95a50c2e912"><code>b21d106</code></a>
Slot generation facts (<a
href="https://redirect.github.com/koxudaxi/datamodel-code-generator/issues/3403">#3403</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/koxudaxi/datamodel-code-generator/compare/0.56.0...0.64.0">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 12:20:17 +00:00
posthog-eu[bot] 5c319f13cb Fix pt-BR download label mislabeled as "Baixar (JSON)" (#7043)
# Description of Changes

- **What:** Corrected the pt-BR (Brazilian Portuguese) `download`
translation from `"Baixar (JSON)"` to `"Baixar"` in
`frontend/editor/public/locales/pt-BR/translation.toml`, in both the
root table (line 32) and the `[fileManager]` section (line 3577).
- **Why:** The generic `download` key flows through
`useFileActionTerminology` (`download: t("download", "Download")`) into
the shared download button rendered on tool-result screens (e.g.
`ReviewToolStep`). Because the string was `"Baixar (JSON)"`, every
tool's Download button showed "Baixar (JSON)" for pt-BR users — implying
a JSON export regardless of the actual output format. This mislabeling
was locale-wide (all pt-BR users, all tool downloads). Session
autocapture confirmed the confusion: a pt-BR user on `/convert`
repeatedly clicked a button whose text was exactly "Baixar (JSON)", then
abandoned the flow. Nothing crashed — it's a confusing label, not a
functional break.
- **Scope / verification:** en-US uses plain `"Download"` for this key
and pt-PT already uses `"Transferir"`; no other locale carried the
`"(JSON)"` suffix on the download key, so the defect was isolated to
pt-BR. Only translation values changed — no keys added/removed, so
translation counts are unaffected.

Note: I scoped this to the mislabel — the exact symptom users observed.
The report also mentions the download being a silent anchor-click with
no success toast; that's a separate, broader UX enhancement in
`ReviewToolStep`/`WorkbenchBar`/`downloadService`, so it's intentionally
left out of this focused translation fix.

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Translations (if applicable)

- [x] Only a value correction in `pt-BR`; no translation tags added or
removed.

---
*Created with [PostHog Code](https://posthog.com/code?ref=pr) from [an
inbox
report](posthog-code://inbox/019f655d-bd60-78c2-ba59-98c23243ed57).*

Co-authored-by: posthog-eu[bot] <226701856+posthog-eu[bot]@users.noreply.github.com>
2026-08-06 12:13:30 +00:00
dependabot[bot] 7aeec93032 build(deps): bump softprops/action-gh-release from 3.0.0 to 3.0.2 (#7273)
Bumps
[softprops/action-gh-release](https://github.com/softprops/action-gh-release)
from 3.0.0 to 3.0.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/releases">softprops/action-gh-release's
releases</a>.</em></p>
<blockquote>
<h2>v3.0.2</h2>
<p><code>3.0.2</code> is a patch release focused on release reliability
and compatibility. It
reuses existing draft releases when publishing prereleases, supports
replacing
release assets on Gitea, hardens streamed asset uploads, and provides
clearer
release-creation diagnostics. It also includes TypeScript, coverage, and
tooling
maintenance merged since <code>3.0.1</code>.</p>
<p>This release fixes <a
href="https://redirect.github.com/softprops/action-gh-release/issues/795">#795</a>,
<a
href="https://redirect.github.com/softprops/action-gh-release/issues/438">#438</a>,
and <a
href="https://redirect.github.com/softprops/action-gh-release/issues/803">#803</a>.
The upload transport hardening covers the
historical failure reported in <a
href="https://redirect.github.com/softprops/action-gh-release/issues/790">#790</a>,
although current hosted Node 24 runners did
not reproduce it naturally. The diagnostics work is related to <a
href="https://redirect.github.com/softprops/action-gh-release/issues/786">#786</a>
and does not
claim a reproducible release-creation fix.</p>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<ul>
<li>feat: improve release error reporting and test coverage by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/813">softprops/action-gh-release#813</a></li>
</ul>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: publish existing draft releases as prereleases by <a
href="https://github.com/godfengliang"><code>@​godfengliang</code></a>
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/801">softprops/action-gh-release#801</a></li>
<li>fix: upload small checksum assets reliably by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/815">softprops/action-gh-release#815</a></li>
<li>fix: replace existing release assets on Gitea by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/816">softprops/action-gh-release#816</a></li>
<li>fix: clarify release creation 404 errors by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/817">softprops/action-gh-release#817</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore(deps): upgrade TypeScript to 7 by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/812">softprops/action-gh-release#812</a></li>
<li>chore(deps): remove unused TypeScript tooling by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/814">softprops/action-gh-release#814</a></li>
<li>dependency, Node 24 pin, and CI maintenance merged since
<code>3.0.1</code></li>
</ul>
<h2>v3.0.1</h2>
<h2>3.0.1</h2>
<ul>
<li>maintenance release with updated dependencies</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md">softprops/action-gh-release's
changelog</a>.</em></p>
<blockquote>
<h2>3.0.2</h2>
<p><code>3.0.2</code> is a patch release focused on release reliability
and compatibility. It
reuses existing draft releases when publishing prereleases, supports
replacing
release assets on Gitea, hardens streamed asset uploads, and provides
clearer
release-creation diagnostics. It also includes TypeScript, coverage, and
tooling
maintenance merged since <code>3.0.1</code>.</p>
<p>This release fixes <a
href="https://redirect.github.com/softprops/action-gh-release/issues/795">#795</a>,
<a
href="https://redirect.github.com/softprops/action-gh-release/issues/438">#438</a>,
and <a
href="https://redirect.github.com/softprops/action-gh-release/issues/803">#803</a>.
The upload transport hardening covers the
historical failure reported in <a
href="https://redirect.github.com/softprops/action-gh-release/issues/790">#790</a>,
although current hosted Node 24 runners did
not reproduce it naturally. The diagnostics work is related to <a
href="https://redirect.github.com/softprops/action-gh-release/issues/786">#786</a>
and does not
claim a reproducible release-creation fix.</p>
<h2>What's Changed</h2>
<h3>Exciting New Features 🎉</h3>
<ul>
<li>feat: improve release error reporting and test coverage by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/813">softprops/action-gh-release#813</a></li>
</ul>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: publish existing draft releases as prereleases by <a
href="https://github.com/godfengliang"><code>@​godfengliang</code></a>
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/801">softprops/action-gh-release#801</a></li>
<li>fix: upload small checksum assets reliably by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/815">softprops/action-gh-release#815</a></li>
<li>fix: replace existing release assets on Gitea by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/816">softprops/action-gh-release#816</a></li>
<li>fix: clarify release creation 404 errors by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/817">softprops/action-gh-release#817</a></li>
</ul>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore(deps): upgrade TypeScript to 7 by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/812">softprops/action-gh-release#812</a></li>
<li>chore(deps): remove unused TypeScript tooling by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/814">softprops/action-gh-release#814</a></li>
<li>dependency, Node 24 pin, and CI maintenance merged since
<code>3.0.1</code></li>
</ul>
<h2>3.0.1</h2>
<ul>
<li>maintenance release with updated dependencies</li>
</ul>
<h2>3.0.0</h2>
<p><code>3.0.0</code> is a major release that moves the action runtime
from Node 20 to Node 24.
Use <code>v3</code> on GitHub-hosted runners and self-hosted fleets that
already support the
Node 24 Actions runtime. <code>v2.6.2</code> was the final Node
20-compatible release and is
no longer maintained or supported.</p>
<h2>What's Changed</h2>
<h3>Other Changes 🔄</h3>
<ul>
<li>Move the action runtime and bundle target to Node 24</li>
<li>Update <code>@types/node</code> to the Node 24 line and allow future
Dependabot updates</li>
<li>Keep the floating major tag on <code>v3</code>; freeze
<code>v2</code> at the final <code>v2.6.2</code> release</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/softprops/action-gh-release/commit/3d0d9888cb7fd7b750713d6e236d1fcb99157228"><code>3d0d988</code></a>
release 3.0.2 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/818">#818</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/7e13ed4ac596a4adf801d3812be5a089356949aa"><code>7e13ed4</code></a>
fix: clarify release creation 404 errors (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/817">#817</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/e6c70a53cf67373fbff7eeebca7782b4fe8f106c"><code>e6c70a5</code></a>
fix: replace existing release assets on Gitea (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/816">#816</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/f3453378888d5ef6208e2788af1c5ba50d8a898d"><code>f345337</code></a>
fix: publish existing draft releases as prereleases (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/801">#801</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/d8a89a206684ded8435bf16d6f698bf04ab05164"><code>d8a89a2</code></a>
fix: upload small checksum assets reliably (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/815">#815</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/45ece40c3178522904ac6c51c21d8a4e3565f3c8"><code>45ece40</code></a>
chore(deps): remove unused TypeScript tooling (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/814">#814</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/f6b913c3f95302d88e8ef7cb2859c2e7656aa01e"><code>f6b913c</code></a>
feat: improve release error reporting and test coverage (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/813">#813</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/15f193d7d8aa9623b5181913a31fafceb4e8cef9"><code>15f193d</code></a>
chore(deps): upgrade TypeScript to 7 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/812">#812</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/cc8268d46a81d57ec9b061f27b0dd68ebd7fb17f"><code>cc8268d</code></a>
chore(deps): bump actions/checkout in the github-actions group (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/810">#810</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/fd0ed1e85b6730f87f5c67d7355751c46ad513d6"><code>fd0ed1e</code></a>
chore(deps): bump the npm group with 3 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/811">#811</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/softprops/action-gh-release/compare/b4309332981a82ec1c5618f44dd2e27cc8bfbfda...3d0d9888cb7fd7b750713d6e236d1fcb99157228">compare
view</a></li>
</ul>
</details>
<br />

<details>
<summary>Most Recent Ignore Conditions Applied to This Pull
Request</summary>

| Dependency Name | Ignore Conditions |
| --- | --- |
| softprops/action-gh-release | [>= 2.2.a, < 2.3] |
</details>


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=softprops/action-gh-release&package-manager=github_actions&previous-version=3.0.0&new-version=3.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 12:01:20 +00:00
dependabot[bot] ddc0baa41d build(deps-dev): bump ip-address from 10.2.0 to 10.4.0 in /frontend (#7278)
Bumps [ip-address](https://github.com/beaugunderson/ip-address) from
10.2.0 to 10.4.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/beaugunderson/ip-address/releases">ip-address's
releases</a>.</em></p>
<blockquote>
<h2>v10.4.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Add GitHub Actions CI by <a
href="https://github.com/beaugunderson"><code>@​beaugunderson</code></a>
in <a
href="https://redirect.github.com/beaugunderson/ip-address/pull/213">beaugunderson/ip-address#213</a></li>
<li>Keep the package loadable on node 12, and enforce it by <a
href="https://github.com/beaugunderson"><code>@​beaugunderson</code></a>
in <a
href="https://redirect.github.com/beaugunderson/ip-address/pull/216">beaugunderson/ip-address#216</a></li>
<li>Validate the byte arrays Address6 is given by <a
href="https://github.com/beaugunderson"><code>@​beaugunderson</code></a>
in <a
href="https://redirect.github.com/beaugunderson/ip-address/pull/217">beaugunderson/ip-address#217</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/beaugunderson/ip-address/compare/v10.3.1...v10.4.0">https://github.com/beaugunderson/ip-address/compare/v10.3.1...v10.4.0</a></p>
<h2>v10.3.1</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/beaugunderson/ip-address/compare/v10.3.0...v10.3.1">https://github.com/beaugunderson/ip-address/compare/v10.3.0...v10.3.1</a></p>
<h2>v10.3.0</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/beaugunderson/ip-address/compare/v10.2.2...v10.3.0">https://github.com/beaugunderson/ip-address/compare/v10.2.2...v10.3.0</a></p>
<h2>v10.2.2</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/beaugunderson/ip-address/compare/v10.2.1...v10.2.2">https://github.com/beaugunderson/ip-address/compare/v10.2.1...v10.2.2</a></p>
<h2>v10.2.1</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/beaugunderson/ip-address/compare/v10.2.0...v10.2.1">https://github.com/beaugunderson/ip-address/compare/v10.2.0...v10.2.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/fbb8db28f1559842b7191cab7d8ea6408ed82f7b"><code>fbb8db2</code></a>
10.4.0</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/45a2b11ec254a2e5620de66e248adcb33d16e669"><code>45a2b11</code></a>
Validate the byte arrays Address6 is given (<a
href="https://redirect.github.com/beaugunderson/ip-address/issues/217">#217</a>)</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/bac8810b3935cab123316a4bc5ebaa22db140299"><code>bac8810</code></a>
Keep the package loadable on node 12, and enforce it (<a
href="https://redirect.github.com/beaugunderson/ip-address/issues/216">#216</a>)</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/9b3d8488d15e6bfe5f5503867b088ce056723e08"><code>9b3d848</code></a>
Add a security policy and a README section on security posture</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/e84a7b381d02cb97ed114023e44133efae151254"><code>e84a7b3</code></a>
Order the README API reference Address4, Address6, AddressError</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/015160b85ee60b39548219817a5de3c4e828a6d6"><code>015160b</code></a>
Collapse each class in the README API reference</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/34061a897d526b7a063c3605402cd30a8363a035"><code>34061a8</code></a>
Pin checkout and setup-node to commits in the release job</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/c5fae5d9bdfe8ded7f4ca01a3d3ea8d97f8f1277"><code>c5fae5d</code></a>
Pin action-gh-release to a commit and move it to 3.0.2</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/e0ef0484193218b0d28cfbb53795bc44ddb3cc21"><code>e0ef048</code></a>
Replace CircleCI with GitHub Actions</li>
<li><a
href="https://github.com/beaugunderson/ip-address/commit/5e3ceb779aee6ad3f33264e66225e8e7584ab612"><code>5e3ceb7</code></a>
Add GitHub Actions CI across Node 20, 22, 24 and 25 (<a
href="https://redirect.github.com/beaugunderson/ip-address/issues/213">#213</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/beaugunderson/ip-address/compare/v10.2.0...v10.4.0">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for ip-address since your current version.</p>
</details>
<details>
<summary>Install script changes</summary>
<p>This version adds <code>prepare</code> script that runs during
installation. Review the package contents before updating.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ip-address&package-manager=npm_and_yarn&previous-version=10.2.0&new-version=10.4.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-06 12:00:50 +00:00
Ludy 8094765bab build(licenses): Module-specific license. Add dependency overrides. (#7049)
# Description of Changes

This change adds a version-scoped override mechanism for dependencies
whose published metadata does not expose a detectable license.

- Added `app/license-overrides.json` with verified Apache License 2.0
metadata for:
  - `com.hubspot.immutables:immutables-exceptions:1.9`
  - `com.hubspot:algebra:1.5`
- Added `ModuleLicenseOverrideFilter` as custom `buildSrc` logic for the
Gradle dependency license report plugin.
- Applied overrides only when the exact `group:artifact:version` matches
and no usable license metadata was detected.
- Added automatic maintenance of the override file:
  - Removes overrides when the dependency is no longer resolved.
- Removes overrides when the dependency starts publishing valid license
metadata.
- Migrates stale overrides to newer unresolved versions and clears their
metadata for re-verification.
- Adds null-valued placeholders for newly detected dependencies without
license metadata.
- Preserves populated overrides for newer versions when already present.
- Added Gradle version-aware dependency ordering for override migration.
- Registered `app/license-overrides.json` as an input for license-report
and license-check preparation tasks.
- Centralized the dependency license report plugin version in
`buildSrc`.
- Added unit tests covering override application, cleanup, migration,
exact-version matching, concurrent versions, placeholder generation, and
numeric version ordering.
- Added documentation describing the override lifecycle, verification
requirements, maintenance workflow, and validation commands.
- Replaced broad null-license allowances for the two HubSpot modules
with explicit Apache License 2.0 metadata.
- Added accepted GNU Lesser General Public License name variants
encountered in dependency metadata.

The change was made because some dependencies have known upstream
licenses but do not publish license metadata in a form detected by the
Gradle license report plugin. Previously, these dependencies were
permitted through module-specific null-license exceptions, leaving
incomplete information in the generated report. The new mechanism
supplies verified metadata without overriding valid metadata published
by dependencies.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 11:44:12 +00:00
Ludy 2265e48b32 chore(ci): optimize GitHub Actions Gradle caching across workflows (#7299)
# Description of Changes

This PR refactors Gradle caching across the GitHub Actions workflows to
improve cache reuse, reduce dependency resolution overhead, and shorten
CI execution times.

### What was changed

- Replaced multiple `gradle/actions/setup-gradle` steps with a unified
`actions/cache`-based Gradle User Home cache strategy.
- Standardized cache paths across workflows to include:
  - `~/.gradle/caches`
  - `~/.gradle/wrapper`
- Introduced consistent cache keys using:
  - Runner OS
  - Runner architecture
  - JDK version
- Hashes of Gradle wrapper, version catalog, Gradle build files, and
project build scripts.
- Added restore keys to maximize cache hit rates across similar
environments.
- Added a new **`gradle-cache-prime`** job in the main build workflow
that:
  - Restores or creates the shared Gradle cache.
  - Resolves backend dependencies before downstream jobs execute.
  - Makes the populated cache available to subsequent jobs.
- Updated workflow dependencies so Gradle-based jobs wait for the cache
priming job before execution.
- Simplified and unified Gradle cache handling across numerous CI
workflows, including backend builds, OpenAPI generation, database
migration tests, Docker tests, Tauri builds, Swagger generation,
enterprise builds, release workflows, and license generation.
- Updated workflow comments to reflect the new caching strategy and
shared cache behavior.

### Why the change was made

The previous workflows used a mixture of Gradle setup actions and
partial dependency caches, leading to duplicated dependency downloads,
inconsistent cache behavior, and longer CI runtimes. Consolidating all
workflows onto a shared Gradle User Home cache with a dedicated cache
priming job improves cache reuse, reduces unnecessary dependency
resolution, and makes CI execution more consistent.



---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 11:43:53 +00:00
Ludy b10fc1b2de fix(java): prevent executor, task, regex, and stream resource leaks (#7284)
# Description of Changes

- Added graceful shutdown handling for service-owned executors in
`JobExecutorService`, `PolicyEngine`, and `AsyncConfig`.
- Added expiration and cleanup for abandoned pending jobs in
`TaskManager`.
- Replaced the unbounded regex pattern cache with a bounded cache
limited to 512 entries.
- Ensured `Files.walk()` is closed correctly in `MobileScannerService`.
- These changes prevent unbounded heap growth, lingering virtual-thread
executors, and file-descriptor leaks.
- Added configurable pending-job expiration through
`stirling.job.pendingExpiryMinutes`, defaulting to 24 hours.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 11:06:28 +00:00
Ludy 866e56728d fix(storage): delete share access records before expired share links (#7161)
# Description of Changes

- Updated expired share-link cleanup to delete related `FileShareAccess`
records before deleting their parent `FileShare` records.
- Wrapped the cleanup operation in a transaction to ensure the deletion
order is enforced atomically.
- Prevents foreign-key constraint violations and scheduled-task failures
during cleanup.
- The full backend check was limited by a Gradle distribution
download/network error.

```cmd
[backend:dev:proprietary] 16:25:43.362 [scheduled-vt-2] WARN  org.hibernate.orm.jdbc.error - HHH000247: ErrorCode: 23503, SQLState: 23503
[backend:dev:proprietary] 16:25:43.362 [scheduled-vt-2] WARN  org.hibernate.orm.jdbc.error - Referentielle Integrität verletzt: "FKQ6V4QH5LFCAWII0ABRVSJO5SG: PUBLIC.FILE_SHARE_ACCESSES FOREIGN KEY(FILE_SHARE_ID) REFERENCES PUBLIC.FILE_SHARES(FILE_SHARE_ID) (CAST(97 AS BIGINT))"
[backend:dev:proprietary] Referential integrity constraint violation: "FKQ6V4QH5LFCAWII0ABRVSJO5SG: PUBLIC.FILE_SHARE_ACCESSES FOREIGN KEY(FILE_SHARE_ID) REFERENCES PUBLIC.FILE_SHARES(FILE_SHARE_ID) (CAST(97 AS BIGINT))"; SQL statement:
[backend:dev:proprietary] delete from file_shares where file_share_id=? [23503-240]
[backend:dev:proprietary] 16:25:43.380 [scheduled-vt-2] ERROR o.s.s.s.TaskUtils$LoggingErrorHandler - Unexpected error occurred in scheduled task
[backend:dev:proprietary] org.springframework.dao.DataIntegrityViolationException: could not execute statement [Referentielle Integrität verletzt: "FKQ6V4QH5LFCAWII0ABRVSJO5SG: PUBLIC.FILE_SHARE_ACCESSES FOREIGN KEY(FILE_SHARE_ID) REFERENCES PUBLIC.FILE_SHARES(FILE_SHARE_ID) (CAST(97 AS BIGINT))"
[backend:dev:proprietary] Referential integrity constraint violation: "FKQ6V4QH5LFCAWII0ABRVSJO5SG: PUBLIC.FILE_SHARE_ACCESSES FOREIGN KEY(FILE_SHARE_ID) REFERENCES PUBLIC.FILE_SHARES(FILE_SHARE_ID) (CAST(97 AS BIGINT))"; SQL statement:
[backend:dev:proprietary] delete from file_shares where file_share_id=? [23503-240]] [delete from file_shares where file_share_id=?]; SQL [delete from file_shares where file_share_id=?]; constraint [FKQ6V4QH5LFCAWII0ABRVSJO5SG]
[backend:dev:proprietary]       at org.springframework.orm.jpa.hibernate.HibernateExceptionTranslator.convertHibernateAccessException(HibernateExceptionTranslator.java:169)
[backend:dev:proprietary]       at org.springframework.orm.jpa.hibernate.HibernateExceptionTranslator.convertHibernateAccessException(HibernateExceptionTranslator.java:131)
[backend:dev:proprietary]       at org.springframework.orm.jpa.hibernate.HibernateExceptionTranslator.translateExceptionIfPossible(HibernateExceptionTranslator.java:105)
[backend:dev:proprietary]       at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
[backend:dev:proprietary]       at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:557)
[backend:dev:proprietary]       at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:794)
[backend:dev:proprietary]       at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:757)
[backend:dev:proprietary]       at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:687)
[backend:dev:proprietary]       at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:408)
[backend:dev:proprietary]       at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:130)
[backend:dev:proprietary]       at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[backend:dev:proprietary]       at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:135)
[backend:dev:proprietary]       at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[backend:dev:proprietary]       at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:166)
[backend:dev:proprietary]       at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[backend:dev:proprietary]       at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:222)
[backend:dev:proprietary]       at jdk.proxy4/jdk.proxy4.$Proxy246.deleteAll(Unknown Source)
[backend:dev:proprietary]       at stirling.software.proprietary.storage.service.StorageCleanupService.cleanupExpiredShareLinks(StorageCleanupService.java:71)
[backend:dev:proprietary]       at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
[backend:dev:proprietary]       at java.base/java.lang.reflect.Method.invoke(Method.java:565)
[backend:dev:proprietary]       at org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:128)
[backend:dev:proprietary]       at org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$1(ScheduledMethodRunnable.java:122)
[backend:dev:proprietary]       at io.micrometer.observation.Observation.observe(Observation.java:569)
[backend:dev:proprietary]       at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:122)
[backend:dev:proprietary]       at org.springframework.scheduling.config.Task$OutcomeTrackingRunnable.run(Task.java:88)
[backend:dev:proprietary]       at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
[backend:dev:proprietary]       at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545)
[backend:dev:proprietary]       at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:369)
[backend:dev:proprietary]       at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:310)
[backend:dev:proprietary]       at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
[backend:dev:proprietary]       at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
[backend:dev:proprietary]       at java.base/java.lang.VirtualThread.run(VirtualThread.java:460)
[backend:dev:proprietary] Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement [Referentielle Integrität verletzt: "FKQ6V4QH5LFCAWII0ABRVSJO5SG: PUBLIC.FILE_SHARE_ACCESSES FOREIGN KEY(FILE_SHARE_ID) REFERENCES PUBLIC.FILE_SHARES(FILE_SHARE_ID) (CAST(97 AS BIGINT))"
[backend:dev:proprietary] Referential integrity constraint violation: "FKQ6V4QH5LFCAWII0ABRVSJO5SG: PUBLIC.FILE_SHARE_ACCESSES FOREIGN KEY(FILE_SHARE_ID) REFERENCES PUBLIC.FILE_SHARES(FILE_SHARE_ID) (CAST(97 AS BIGINT))"; SQL statement:
[backend:dev:proprietary] delete from file_shares where file_share_id=? [23503-240]] [delete from file_shares where file_share_id=?]
[backend:dev:proprietary]       at org.hibernate.dialect.H2Dialect.lambda$buildSQLExceptionConversionDelegate$0(H2Dialect.java:840)
[backend:dev:proprietary]       at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:34)
[backend:dev:proprietary]       at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:115)
[backend:dev:proprietary]       at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:184)
[backend:dev:proprietary]       at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:145)
[backend:dev:proprietary]       at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:53)
[backend:dev:proprietary]       at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:66)
[backend:dev:proprietary]       at org.hibernate.persister.entity.mutation.AbstractDeleteCoordinator.doStaticDelete(AbstractDeleteCoordinator.java:268)
[backend:dev:proprietary]       at org.hibernate.persister.entity.mutation.AbstractDeleteCoordinator.delete(AbstractDeleteCoordinator.java:79)
[backend:dev:proprietary]       at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:119)
[backend:dev:proprietary]       at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:634)
[backend:dev:proprietary]       at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:505)
[backend:dev:proprietary]       at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:381)
[backend:dev:proprietary]       at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
[backend:dev:proprietary]       at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:138)
[backend:dev:proprietary]       at org.hibernate.internal.SessionImpl.fireFlush(SessionImpl.java:1484)
[backend:dev:proprietary]       at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:481)
[backend:dev:proprietary]       at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2111)
[backend:dev:proprietary]       at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2033)
[backend:dev:proprietary]       at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:410)
[backend:dev:proprietary]       at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:166)
[backend:dev:proprietary]       at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commitNoRollbackOnly(JdbcResourceLocalTransactionCoordinatorImpl.java:248)
[backend:dev:proprietary]       at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:242)
[backend:dev:proprietary]       at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:89)
[backend:dev:proprietary]       at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:553)
[backend:dev:proprietary]       ... 27 common frames omitted
[backend:dev:proprietary] Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referentielle Integrität verletzt: "FKQ6V4QH5LFCAWII0ABRVSJO5SG: PUBLIC.FILE_SHARE_ACCESSES FOREIGN KEY(FILE_SHARE_ID) REFERENCES PUBLIC.FILE_SHARES(FILE_SHARE_ID) (CAST(97 AS BIGINT))"
[backend:dev:proprietary] Referential integrity constraint violation: "FKQ6V4QH5LFCAWII0ABRVSJO5SG: PUBLIC.FILE_SHARE_ACCESSES FOREIGN KEY(FILE_SHARE_ID) REFERENCES PUBLIC.FILE_SHARES(FILE_SHARE_ID) (CAST(97 AS BIGINT))"; SQL statement:
[backend:dev:proprietary] delete from file_shares where file_share_id=? [23503-240]
[backend:dev:proprietary]       at org.h2.message.DbException.getJdbcSQLException(DbException.java:520)
[backend:dev:proprietary]       at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
[backend:dev:proprietary]       at org.h2.message.DbException.get(DbException.java:223)
[backend:dev:proprietary]       at org.h2.message.DbException.get(DbException.java:199)
[backend:dev:proprietary]       at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:363)
[backend:dev:proprietary]       at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:380)
[backend:dev:proprietary]       at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:254)
[backend:dev:proprietary]       at org.h2.table.Table.fireConstraints(Table.java:1208)
[backend:dev:proprietary]       at org.h2.table.Table.fireAfterRow(Table.java:1226)
[backend:dev:proprietary]       at org.h2.command.dml.Delete.update(Delete.java:81)
[backend:dev:proprietary]       at org.h2.command.dml.DataChangeStatement.update(DataChangeStatement.java:77)
[backend:dev:proprietary]       at org.h2.command.CommandContainer.update(CommandContainer.java:139)
[backend:dev:proprietary]       at org.h2.command.Command.executeUpdate(Command.java:306)
[backend:dev:proprietary]       at org.h2.command.Command.executeUpdate(Command.java:250)
[backend:dev:proprietary]       at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:213)
[backend:dev:proprietary]       at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:172)
[backend:dev:proprietary]       at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
[backend:dev:proprietary]       at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
[backend:dev:proprietary]       at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:181)
[backend:dev:proprietary]       ... 48 common frames omitted
```

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 11:06:16 +00:00
brios e560ee4cc4 chore(deps): update junrar dependency to version 8.0.0 (#7210)
# Description of Changes

Since this was a major version update i tested manually, afterwards
figured i'll submit as PR.

This version of junrar adds long-awaited (by me) RAR 5 support to the
library. RAR 5 is newest version of the RAR file format and was not
available in previous Junrar version, but is somewhat common for CBR
files to be RAR 5.


For junrar release notes see:
https://github.com/junrar/junrar/releases/tag/v8.0.0

Changes:
- Bumped junrar dep to version 8.0.0


<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 10:25:22 +00:00
brios 7cccee4c34 refactor(get-info): remove redundant PDF validation logic (#7213)
# Description of Changes

Could not get past validation, since very few endpoint have such
validation, i think redundant.

Changes:
* Removed the `validatePdfFile` method, which previously checked for
file presence, size limits, and content type, from `GetInfoOnPDF.java`.
* Deleted the invocation of `validatePdfFile` and its associated error
handling from the `getPdfInfo` method, so uploaded files are no longer
validated at this layer.

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 10:17:27 +00:00
brios 934ad180cb fix(ui): handle 404 policy error on upload without toast popup (#7254)
# Description of Changes

Fixes policy error pop-ups that sometimes happen upon upload.

Changes:
- Improved the error handling in `runPolicyOnFile` to log detailed debug
information when policy dispatch fails, making it easier to trace issues
such as missing policies or backend errors.
- Updated the `runStoredPolicy` function to pass `{ suppressErrorToast:
true }` to the API client, preventing error toasts from appearing in the
UI when the policy run fails.

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 10:16:15 +00:00
briosandAnthony Stirling 9aaf417303 perf(ui): lazy-load MobileScannerPage and optimize bundle splitting (#7122)
# Description of Changes


This pull request improves the frontend's performance and code
organization by optimizing how certain pages are loaded and by updating
the application's bundle splitting strategy.

Changes:
* Updated the `manualChunks` configuration in `vite.config.ts` to more
granularly split vendor dependencies into separate chunks based on their
library or usage, which can improve caching and load performance.
* Updated MobileScanner code to be lazy loaded

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-06 10:11:26 +00:00
brios cc1c6bc9e3 style(people): Fix convert dropdown single-category formatting and admin table header styling (#7139)
# Description of Changes

The dropdown table with the people looked out-place mainly due to the
blue, i think... this simplifies and make more consistent with the rest
of the "new" UI and not so aggresive with the colour schema.


### New:

<img width="2204" height="852" alt="image"
src="https://github.com/user-attachments/assets/0e329092-a532-445b-a27d-7afbd0a16d4c"
/>


### Old:

<img width="2210" height="838" alt="image"
src="https://github.com/user-attachments/assets/6e251d6f-f22c-4b9e-aebf-96e7fea40144"
/>



<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [X] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 10:01:46 +00:00
brios 732a602503 style(scanner-effect): remove padding from ToolButton of Scanner-effect (#7205)
# Description of Changes


### New
<img width="1650" height="612" alt="image"
src="https://github.com/user-attachments/assets/3046ad8e-b7a5-4fb6-b941-04ae7dcda4e4"
/>



### Old
<img width="1756" height="730" alt="image"
src="https://github.com/user-attachments/assets/e722146e-bebb-4744-9e95-4eee11444623"
/>

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [X] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 10:00:43 +00:00
brios e5c6ceedc5 fix(ui): resolve double scrollbar issue in Sidebar Categories modal (#7142)
# Description of Changes

Resolves double scrollbar design bug.

### New

<img width="1036" height="990" alt="image"
src="https://github.com/user-attachments/assets/454a521c-7ccf-4ebc-98be-22f13b107abe"
/>


### Old

<img width="1036" height="984" alt="image"
src="https://github.com/user-attachments/assets/c2847698-e625-48da-a5bc-e6b68050a426"
/>


<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 10:00:25 +00:00
brios a2dd0298dc refactor(api): replace length checks with isEmpty (#7214)
# Description of Changes

Stylistic problem reported by static analyzer. 


Changes:
* Replaced `sb.length() > 0` and `sb.length() == 0` with `!sb.isEmpty()`
and `sb.isEmpty()` for `StringBuilder`, `String`, and collections
throughout the codebase, improving readability and aligning with modern
Java best practices.


<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-06 10:00:04 +00:00
EthanHealy01 789be2d351 Non-blocking classification, pipelined batch enforcement, and selector-based file-state re-renders (#7085)
## Goal

Three related improvements to how policies and file state behave in the
editor: classification no longer blocks the user, policy enforcement
pipelines across a batch upload instead of waiting for the whole drop,
and file-state changes no longer re-render the entire UI.

## 1. Classification never blocks (and never versions)

Classification is metadata-only — it reads a document and records
labels; it never rewrites the file. Previously it ran like an
enforcement policy: it blocked viewing/editing behind the "Enforcing
policy…" overlay, forked a new versioned child (an `automate` entry in
version history), and could run before other policies — letting the user
in, then a later enforcement policy would fork a version and drop their
edits.

Now classification:
- **Never blocks.** A classification run never marks a file `enforcing`
(badge map + viewer overlay both skip it), so the file stays fully
viewable/editable while it runs.
- **No version bump, no history entry.** Its result is stamped onto the
file's existing stub in place (workspace + IndexedDB) — the labels just
appear as tags. It targets the document's *current leaf*, so an edit
made during the async run still gets the tags; a run that completes with
no outputs settles cleanly instead of pinning in-flight.
- **Always runs last** in an enforcement chain (regardless of configured
order, pinned at persist-time too), so every enforcement policy finishes
forking versions before the user is let in.

## 2. Pipeline policy enforcement across a batch upload

Dropping ~50 files enforced policies only *after the whole drop finished
scanning* — every file got the "Enforcing policy" overlay together, then
processing began. Root cause: the chunked `ADD_FILES` dispatches in
`addFiles` were never separated by an event-loop yield, so React batched
them into a single commit and the enforcement effect fired once over the
full list.

**Fix** (`core/contexts/file/fileActions.ts`): after each chunk, `await`
that chunk's IndexedDB writes, then yield a macrotask so React commits
the rows and runs the enforcement dispatch *before* the next chunk
scans. Files start enforcing as their rows land, overlapping with the
rest of the drop. Persistence is streamed per chunk (the policy auto-run
reads bytes from IndexedDB with no in-memory fallback).

**Second fix — bounded dispatch window**
(`proprietary/components/policies/usePolicyAutoRun.ts`): even with
streamed dispatch, the drop still *looked* serial — each dispatch POSTs
the file's bytes, and firing them all at once saturates the browser's
per-origin connection pool, so the status polls and output downloads of
already-running files queued behind the pending uploads; nothing visibly
progressed until the last upload drained. Dispatch is now gated behind a
small concurrency window (4), keeping connections free so early files
run, poll, and complete while later ones are still dispatching. The
first status poll also fires at 500ms (then the normal 2s cadence) so
fresh runs show real progress immediately. The batch test asserts the
window (dispatches overlap but never exceed 4).

## 3. Selector subscriptions for file state (no more whole-UI
re-renders)

`FileContext` published `{state, selectors}` through a plain React
context, so **every** consumer re-rendered on **every** state change —
one file's new version re-rendered the entire workspace.

**Phase 1 — infra** (`file/contexts.ts`, `file/fileHooks.ts`,
`FileContext.tsx`): the state context is replaced by a stable
subscription store (`FileStoreContext`); hooks are rebuilt on
`useSyncExternalStoreWithSelector` (the `use-sync-external-store` shim
react-redux uses — new direct dep, React 19 compatible). Each consumer
now re-renders only when its selected slice changes:
- `useStirlingFileStub(id)` → only that file's record
- `useAllFiles` → file-list changes only (immune to selection/UI churn)
- `useFileSelection`/`useSelectedFiles` → selection + the *selected*
files' records only
- `useFileUI` → its three UI scalars; `useFileContext` → files + pinned
slices
- `useFileState` keeps its whole-state contract for existing broad
consumers

A render-count test (`fileHooks.selector.test.tsx`) locks the bail-out
contract.

**Phase 2 — hot-path rows**: sidebar `FileItem` is memoized (with stable
empty-array props), so one file's change re-renders one row, not the
list. Active Files thumbnails were already memoized.

**Phase 3 — narrow the hottest consumers**: always-mounted whole-state
consumers migrated to slices — `Workbench`, `EmbedPdfViewer`, `Viewer`,
`NonPdfViewer`, `WorkbenchBar`, `ViewerContext`, `ViewerShareButton`,
`ZoomAPIBridge`, `ViewerAnnotationControls`, `ConvertSettings`,
`DismissAllErrorsButton`, `FileEditorThumbnail`,
`usePageEditorDropdownState`, `useSaveShortcut`, plus a new
non-subscribing `useFileSelectors()` for event-time reads
(`ReviewToolStep`, `useViewerReadAloud`, `useExitWarning`). Net effect:
selection/UI churn no longer re-renders the viewer/workbench, and a
version landing touches only components observing the files slice.

Broad readers (`FileSidebar`, `PageEditor`, `FileEditor`, `Redact`,
`FormFill`) deliberately stay on `useFileState` — they read most of the
state anyway.

**Hardening**: store notifications run in a layout effect (subscribers
re-render before paint — no stale frames), and outside production
`useFileSelectors()` wraps its selectors to `console.error` if one is
invoked during render (those reads don't subscribe, so render-time use
would silently go stale — not statically lintable, so it's guarded at
runtime; the full test suite passes under the guard).

## 4. Policy indicators: shared icons, non-blocking run chip, no pulse

- Badges and enforcement overlays now take their glyph from the shared
`policyCategoryIcon` map (the same source the processor's catalogue
uses) — label icon for classification, shield for security — instead of
a hardcoded shield everywhere.
- A non-blocking run (classification) shows a small accent-tinted pill
in the top-right of the Active Files card (category icon + loader) and
the normal spinning badge in the sidebar, via a new `background` badge
flag that nothing gates on. When the run finishes, the tagged files keep
a plain category badge.
- The post-run pulse/glow on sidebar badges is gone (with its `recent`
plumbing): spinner while running, static category icon when done.

## Verification

Full CI gate locally: `og:check`, `typecheck:all` (all variants),
`lint`, `format:check`, `build`, `test` (1366 — incl. the render-count
contract test, the classification-order/import unit tests, and the
61-file batch integration test driving the real dispatch → poll → import
→ chain effects), `storybook:build` — all green.

## Held for follow-up (not in this PR)

- **Reuse one PDFium engine across viewer file switches** (kills the
per-open "Loading PDF Engine" rebuild). Implemented on branch
`viewer/reuse-pdfium-engine`, but review found a confirmed leak
(orphaned PDFium handles when switching files mid-load); needs an
in-flight-load teardown before shipping.
2026-08-05 16:31:24 +00:00
ConnorYoh d0d197f09f Procurement: draft Enterprise Agreement + signature, legal pages & consent, quote/agreement split (#7021)
Consolidates the enterprise procurement and legal work into one PR off
`main`. Supersedes #7020 (closed; every commit from it is contained
here). Sits on top of PAYG prepaid bundles (#7032) and the `--color-*` →
`--c-*` portal token rename.

## Why

Enterprise procurement was a mock. The stage screens read from a fake
state machine, the "agreement" was prose hardcoded in a component, and
nothing a buyer did was recorded anywhere. To actually sell to an
enterprise we need three things it didn't have: a real document they can
read and sign, a record that proves they signed that exact version, and
a licence that flips when they pay.

## What

**The agreement is a real versioned document**

- Registry at `resources/legal/manifest.json` +
`legal/<id>/<version>/*.md`. Publishing a new version is a markdown file
and a manifest bump, no code change. `@`-prefixed parts are generated
sections.
- `AgreementAssembler` builds MSA (Part A) + generated Order Form (Part
B) + DPA (Part C) as one document. Only the Order Form varies per deal.
- `AgreementPdfRenderer` goes through our own pipeline (commonmark →
`FileToPdf`/WeasyPrint), so we dogfood it.
- Immutable signature record pinning document id and version, a SHA-256
of the exact rendered markdown, the variable snapshot, typed signatory
details, timestamp and IP.

**Legal document pages and consent logging**

- `GET /api/v1/legal/{docId}` serves any registry document; a viewer
modal renders it with a draft badge. The SLA exhibit is viewable for the
first time.
- `legal_consent` + `POST /api/v1/legal/consent`. EULA clickwrap is
recorded once: at trial start, or at the quote step only if there was no
trial.

**Quote and Agreement are separate steps**

The quote step is a plain itemised review (figures, renewal, PO) with
download and "Accept quote". Accepting advances to the agreement and
does not charge Stripe. Signing the agreement is still the commitment
point.

**One quote number**

We no longer mint our own reference. The Stripe quote number is the
identifier everywhere, so the UI and the memo can't disagree.
`quote_number` is nullable until Stripe assigns it at finalisation
(`20260808000000`).

**Payment takes the deal live**

`invoice.paid` on the stripe-webhook moves the deal to live and the UI
reflects it. Nothing watched for payment before, so a paid customer sat
in "payment" forever. Needs `invoice.paid` enabled on the webhook
endpoint in the Stripe dashboard.

**Security**

Any signup could self-issue a $0 enterprise licence, from three things
compounding: leader-on-signup, no entitlement gate, and no ACV floor.
So: `startTrial` now has a stage guard (it was replacing committed
licences), the offline `.lic` is gated on entitlement, the ACV floor is
enforced before the quote persists, and the air-gap check reads the
quote's deployment rather than the deal's. Invitee emails are redacted
in logs. Dev and Storybook were hitting real Stripe; both now route
through `resolveDemoResponse`.

**Removed the dead procurement island**

The original stage-by-stage page survived the rebuild with no route and
no consumer, so it was invisible to review but still cost a reader's
time. 16 unreferenced files, 182 lines of superseded API, 53 orphaned
en-US keys, and `Procurement.css` from 1665 to 968 lines. Nothing
deleted had a live consumer.

## Screenshots

Home, deal underway (hero card footer):

<!-- home-in-procurement.png -->

Quote builder, step 1:

<!-- quote-builder.png -->

Agreement, ready to sign:

<!-- agreement-signing.png -->

Payment and live:

<!-- stage-payment.png / stage-live.png -->

## How to test

**Storybook** covers every state without a backend:

```bash
cd frontend && npm run storybook
```

Then `Portal/Procurement/*`:

| Story | What to look at |
| --- | --- |
| `DealStatusHero` — Trial / Quote / Agreement / Payment / Live | One
hero per stage: progress band, one-line status, stage CTA |
| `QuoteBuilder` — Default | 4 steps. Users + volume drive the price;
Governance and PDF size are multipliers; step 4 is the itemised review |
| `ProcurementAgreement` — Default / Signing | Header actions,
always-visible scrollbar on the paper, one-line signature row |
| `ProcurementStages` — Payment / Live / License | "View & pay invoice"
opens Stripe directly; licence key and `.lic` download |
| `Views/Home` — Subscribed In Procurement | The hero in real page
context |

Note: `ProcurementAgreement` renders "Could not load the agreement" in
Storybook because it fetches the document from the backend. The chrome
is accurate, the paper body needs the app.

**Full flow** needs SaaS running and a linked team:

1. Home → **Explore enterprise** → trial setup (deployment + seats).
EULA is recorded here.
2. **Build your quote** → 4 steps → Generate. Buyer details are required
first.
3. Review the itemised quote → **Accept quote**. Confirm Stripe was
*not* charged.
4. Agreement → tick, fill signatory, **Sign agreement**. Check
`procurement_signature` for the version and content hash.
5. **View & pay invoice** → pay in Stripe test mode → deal should move
to live on the `invoice.paid` webhook.

Worth reviewing specifically: the licence cannot be issued without
entitlement (step 3 before payment), and `startTrial` on an
already-committed deal is rejected rather than overwriting.

## Verification

- `:saas compileJava` + `spotlessJavaCheck`
- `task frontend:check:all` green end to end: 9 typecheck variants,
eslint at zero warnings, `theme-lint`, `lint:css`, prettier, build,
**1656 tests across 188 files**
- 7 deno tests on the `invoice.paid` handler, covering all four shapes
Stripe uses for the subscription reference

## Open, not addressed here

- **The commercial model contradicts itself in three places.** The Order
Form says annual-in-advance, the MSA §2.3/§3.2 implies otherwise, the
quote engine computes `tcv = annualNet × termYears` flat, and Stripe
only invoices one year. Needs a decision before this is customer-facing.
- The 25 MB data-processing increments vs the ×1.4/×2.4 size multiplier,
deferred pending Matt.
- All legal text is **draft**. It renders with a draft badge and is not
presented as executed; counsel's read is still a publish gate.
- `{{subprocessor_url}}` / `{{eula_url}}` awaiting marketing's final
links.
- `frontend-a11y` is red on pre-existing portal contrast debt, deferred
by decision.

## Schema notes

Two migrations land on the SaaS side (`v3`), both applied by that repo's
PR CI:

- `20260808000000` drops the NOT NULL on
`procurement_quote.quote_number`, which is required rather than cosmetic
— the number now comes from Stripe at finalisation, so a draft holds
NULL, and `ddl-auto` cannot drop an existing NOT NULL itself.
- `20260809000000` adds `procurement_deal.last_paid_invoice_id`,
nullable.

Nothing here needs a migration in this repo: Flyway is not on the
classpath, so the Java side only ever adds via `ddl-auto`, and Postgres
migrations run ahead of the app deploy.
2026-08-05 15:23:50 +00:00
Ludy 8f5344ec7d build(tool-models): separate API model generation from Swagger setup (#7300)
# Description of Changes

- Added internal `_generate` tasks for frontend and engine tool-model
generation.
- Kept the public `tool-models` tasks responsible for dependency
installation and Swagger generation.
- Separated environment preparation from the actual model generation
commands.
- This allows higher-level tasks to prepare the OpenAPI specification
once and invoke both generators without repeating the backend setup.


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-05 14:25:44 +00:00
Anthony StirlingandReece Browne 62e5e28039 Avoid renderer OOM when adding large PDFs to the workbench (#7175)
# Description of Changes

- "Out of Memory" tab crash on merge with big PDFs (Discord report) is a
WebView2 renderer OOM, not system RAM; adding files did 2 full parses +
a parallel full read per file
- IndexedDB now stores files as Blobs (by reference, no JS-side copy);
old ArrayBuffer records stay readable
- Both thumbnail variants now come from one PDFium parse instead of two
- PDFs over 100MB never get a full client-side parse: 2MB
linearized-prefix attempt, placeholder icon otherwise
- Follow-ups if placeholders aren't enough: backend-rendered thumbnails,
PDFium ranged reads in a worker

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: Reece Browne <74901996+reecebrowne@users.noreply.github.com>
2026-08-05 13:10:28 +01:00
Anthony StirlingandReece Browne d7c130fca9 Serve SPA shell for deep frontend routes (#7145)
# Description of Changes

stops the /new urls crashing page on f5 


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: Reece Browne <74901996+reecebrowne@users.noreply.github.com>
2026-08-05 11:03:12 +00:00
EthanHealy01 4d8a86ad28 Fix the two nightly frontend failures (a11y contrast + Firefox Copy menu test) (#7286)
Fixes the two nightly frontend jobs that started failing after #7163
(new design, part one). Two unrelated causes, one small fix each.

## Accessibility scan (`--c-primary-hover`)

The full a11y scan flagged a colour-contrast violation on the portal
pipelines ToolPicker story. #7163 moved the light canvas from
`--p-gray-50` (#f9fafb) to the slightly darker `--p-paper` (#f5f4f1),
but the accent text colour stayed put. That token doubles as the label
colour for quiet and tertiary buttons, so the pairing slipped from
4.64:1 to 4.41:1 purely from the background change.

Darkening the custom-theme mix from 85% to 80% primary puts it back at
4.89:1. It is also the hover fill for primary buttons, where a
marginally deeper blue is if anything more correct.

Only the nightly caught this because PR runs scan just the stories whose
files changed, and #7163 did not touch that story file.

## Cross-browser Playwright (right-click Copy menu)

Failed in Firefox only. The feature itself is fine in every browser. The
test hit-tested a word using a fixed fraction of the page box, and the
page is auto-fit to the viewer, so the rendered text scales with the
viewport. The Firefox and WebKit projects run at 1280x720, where the
page renders about 375px wide and the first line of text is only a few
pixels tall. #7163 shrank the viewer area slightly (the rails now float
with a gutter), which shrank the auto-fit page just enough to tip that
fraction to landing below the glyphs. Nothing was selected, so no menu
appeared.

Pinning 1920x1080 for that one test makes the glyphs comfortably larger
than the click tolerance everywhere, rather than re-tuning a fraction
that was only ever a couple of pixels from failing.

A Firefox skip was considered and rejected: the sibling clipboard test
is already Chromium-only and its comment states the Copy menu is covered
cross-browser by this test, so skipping would leave the menu with no
Firefox coverage at all.

## Verification

Test pinned run is green across chromium, firefox and webkit. Contrast
checked with the theme linter's contrast report.
2026-08-04 20:40:18 +00:00
ConnorYoh 030f9f541e feat(editor): adopt TanStack Query, convert three read-only fetches (#7264)
# Description of Changes

## The problem

The editor has no query client. ~295 `apiClient` call sites, each mount
refetching what the last one just got, and three module-level caches
reimplementing dedupe, retry and invalidation by hand — each shaped
differently.

The Processor (`frontend/editor/src/portal`) has run on TanStack Query
since #7135. The editor never got it.

## End state

The editor has a query client, and the three read-only fetch sites that
convert safely now use it. `@tanstack/react-query` is already a
dependency — no new package.

**Foundation**

| File | |
|---|---|
| `core/query/queryClient.ts` | `baseQueryOptions` + client factory. The
portal now builds its client from the same options. `networkMode:
"always"` — `navigator.onLine` describes internet reachability, which
says nothing about a bundled backend on 127.0.0.1 or a self-hosted
server on the LAN. |
| `core/query/keys.ts` | `["editor", resource, ...params]` |
| `core/query/staleTime.ts` + `desktop/query/staleTime.ts` | Config
staleTime: `Infinity` on web, 5 min on desktop |
| `core/api/config.ts`, `core/api/users.ts` | Fetch functions, mirroring
`portal/api/*` |
| `core/tests/utils/TestQueryProvider.tsx` | |
| `desktop/components/DesktopQueryCacheReset.tsx` | |

`QueryClientProvider` mounts at the top of
`core/components/AppProviders.tsx`. That diff looks large but is one
wrapper plus the reindent underneath it.

**Converted.** All three keep their existing return shape, so no
consumer changes.

| | Before |
|---|---|
| `useFooterInfo` | Fetched twice — Footer and admin legal section |
| `useGroupEnabled` | Refetched on every mount |
| `UserSelector` | Refetched the whole roster on each of two mount
sites, and again whenever `t` or `user` changed identity |

**Desktop needs more than the provider.** `operationRouter` resolves the
same relative path to the local bundled backend, a self-hosted server,
or the SaaS backend. Query caches by key, not by resolved URL, so a
cached entry can outlive the backend that filled it. `group-enabled`
routes this way, so this PR introduces the hazard and carries the fix:
`DesktopQueryCacheReset` calls `resetQueries()` when the connection mode
changes or the self-hosted server goes up or down, and
`CONFIG_STALE_TIME` is finite on desktop as a backstop.

**Behaviour changes**

- All three sites now retry once on failure (client default). None
retried before, so a failing request sits in `loading` for one extra
attempt plus backoff.
- `staleTime: Infinity` on web means admin edits to legal links no
longer appear on remount within a session. Saving those already prompts
a restart, so this is accepted rather than incidental.
- Desktop `useGroupEnabled` shows the *translated* offline reason on
first render. The old code showed raw English for one render.
- `UserSelector` drops three `console.log`s that were dumping user
records to the console.

## Decisions

**1. The foundation doesn't ship alone.** A provider nothing consumes
gives a reviewer nothing to react to and rots if the follow-up stalls,
so it lands with the cheapest safe conversions.

**2. Hooks keep their existing return shape.** The alternative is
switching to `{ data, isPending, error }` and updating consumers now.
Cost of my choice: we carry a `loading`-shaped façade indefinitely, and
consumers don't get `isFetching`/`refetch` without a second pass. Taken
because it's what keeps each later migration a one-file diff.

**3. Shared defaults, separate instances.** The editor and the Processor
mount as *sibling* routes, not nested — they never coexist in one tree.
Both clients now come from the same `baseQueryOptions`, so behaviour
can't drift. A single shared instance would only buy cache surviving
navigation between the two products, which is worth little while they
share no keys, and it breaks the contract three portal tests rely on
(`createPortalQueryClient()` returning a fresh client per test). That
belongs in the collapse PR. Consequence meanwhile: the desktop reset
covers the editor client only — harmless, since the portal isn't in
desktop builds.

**4. The desktop reset is wholesale.** A mode switch already remounts
the SaaS provider tree, so there's nothing to preserve, and an allowlist
of "mode-sensitive" keys would be a trap every new query has to remember
to join.

## Coming next

Ordered by consumers per line changed.

| PR | Scope |
|---|---|
| 2 | `AppConfigContext` + `useEndpointConfig` — ~80 consumers, deletes
~200 lines of hand-rolled cache, retry and dedupe |
| 3 | `useAdminSettings` (20 consumers) and the config sections |
| 4 | Polling loops → `refetchInterval` |
| 5 | Finish the Processor's remaining files, collapse to one client |
| 6 | Tool execution — mutation state only, narrowly scoped |

Not in scope, deliberately: `usePdfLibLinks` (its cache is a refcounted
ArrayBuffer lifetime manager), thumbnail hooks, watched-folder IndexedDB
reads, the desktop health monitors. Unifying
`endpointAvailabilityService` / `saasAppConfigService` with the query
cache would mean handing `operationRouter` a query client — its own PR
if a second reason appears.

## Testing

`task frontend:check` green: 1666 tests across 191 files, typecheck on
all five flavours, eslint `--max-warnings=0`, dpdm, prettier.

New tests cover request de-duplication, per-group key isolation, the
desktop offline short-circuit, and the cache reset. The reset test was
verified to fail against the `clear()` implementation it replaced.
`UserSelector` has no test beyond its existing stories.

One existing test needed a wrapper: `Login.test.tsx` renders `<Login />`
in isolation, and `AuthLayout` → `Footer` → `useFooterInfo` now needs a
client. The real `/login` route is already inside `AppProviders`, so
this is test isolation, not a runtime gap.

Rollback is a clean revert — nothing persists outside the React tree.
2026-08-04 13:08:06 +00:00
Anthony Stirling 921bdac4b7 Desktop installer fixes (#7174)
# Description of Changes

* Adds a `windows-11-arm` CI/release leg (NSIS, Microsoft JDK 25,
updater keys); JPDFium natives deliberately excluded
(`jpdfiumPlatforms=none`) until published, so don't ship ARM64
installers to users yet
* Defaults `WEBKIT_DISABLE_DMABUF_RENDERER=1` on Linux (crash switching
tools on NVIDIA)
* Strips the bundled libwayland from AppImages (blank window on Fedora
Wayland)
* Blocks off-app webview navigation + window drop guard + close failsafe
(drag-drop bricks the app)
* 120s startup grace before the backend is declared unhealthy, restart
success only announced after a real health check ("Backend stopped
unexpectedly" spam and likely the OAuth port churn)
* Verified: green `windows-arm64` build (234 MB NSIS artifact) and green
Linux run with libwayland confirmed stripped
* JPDFium fixes for multi threading issues
---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-04 14:40:41 +01:00
briosandCopilot Autofix powered by AI 120678260a docs(contributing): update CONTRIBUTING.md to include desktop application startup command (#7211)
# Description of Changes

May spare some headaches down the line.

Changes:

- Added desktop dev command to the contributing guide

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-04 12:06:31 +00:00
brios cb45fb159a fix(search): Fix PDF viewer search showing 0 of 0 results (#7228)
# Description of Changes


Fixes that search always showing 0 of 0 result even when there are
multiple hits in the search.

### New

<img width="706" height="284" alt="image"
src="https://github.com/user-attachments/assets/f3507647-2a41-4e60-8c9c-eca43005a5c4"
/>


### Old

<img width="708" height="292" alt="image"
src="https://github.com/user-attachments/assets/7b0a6a66-f7c5-4df8-af89-134afef72eba"
/>


On the same PDF.

Changes:
* Refactored the effect in `SearchInterface` to fetch the latest search
state from `viewerContext` on each interval, preventing stale closure
values and ensuring up-to-date search results and active index are used.
* Updated the "previous" and "next" result buttons to be disabled
whenever there are zero search results, rather than relying on the
current index, making the UI more robust and intuitive.

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-04 12:02:18 +00:00
Reece Browne a8b2957b74 Fix preview on crop/rotate (#7266)
Preview on crop and rotate shows just the original file you uploaded, if
you switch to a new one it doesn't update.
2026-08-04 11:24:43 +00:00
dependabot[bot] b1d03e7fba build(deps): bump com.hubspot.jinjava:jinjava from 2.8.3 to 2.8.4 (#7247)
Bumps [com.hubspot.jinjava:jinjava](https://github.com/HubSpot/jinjava)
from 2.8.3 to 2.8.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/HubSpot/jinjava/releases">com.hubspot.jinjava:jinjava's
releases</a>.</em></p>
<blockquote>
<h2>jinjava-2.8.4</h2>
<h3>2026-07-24 Version 2.8.4 (<a
href="https://search.maven.org/artifact/com.hubspot.jinjava/jinjava/2.8.4/jar">Maven
Central</a>)</h3>
<ul>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1305">Add
support for configurable multi-character delimiters</a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1306">Treat
backslash as an escape character only inside quoted strings, matching
Jinja2</a></li>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1311">Add
<code>keepTrailingNewline</code> option to match Python Jinja2's default
of stripping a single trailing newline</a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1308">Auto-convert
<code>Integer</code> to <code>Long</code> in set filters when the
feature is enabled</a></li>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1313">Add
a boolean parameter to <code>withUnwrapRawOverride</code></a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1289">Introduce
<code>BuiltinFeatures</code></a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1312">Preserve
block tags to maintain reconstruction and execution order</a></li>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1258">Fix
<code>RenderFilter</code>'s handling of deferred values</a></li>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1286">Use
<code>isResolvableObject</code> before building a hashcode in eager
execution</a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1285">Don't
require explicitly pushing the <code>JinjavaInterpreter</code> when
using it directly</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/HubSpot/jinjava/blob/master/CHANGES.md">com.hubspot.jinjava:jinjava's
changelog</a>.</em></p>
<blockquote>
<h3>2026-07-24 Version 2.8.4 (<a
href="https://search.maven.org/artifact/com.hubspot.jinjava/jinjava/2.8.4/jar">Maven
Central</a>)</h3>
<ul>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1305">Add
support for configurable multi-character delimiters</a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1306">Treat
backslash as an escape character only inside quoted strings, matching
Jinja2</a></li>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1311">Add
<code>keepTrailingNewline</code> option to match Python Jinja2's default
of stripping a single trailing newline</a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1308">Auto-convert
<code>Integer</code> to <code>Long</code> in set filters when the
feature is enabled</a></li>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1313">Add
a boolean parameter to <code>withUnwrapRawOverride</code></a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1289">Introduce
<code>BuiltinFeatures</code></a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1312">Preserve
block tags to maintain reconstruction and execution order</a></li>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1258">Fix
<code>RenderFilter</code>'s handling of deferred values</a></li>
<li><a href="https://redirect.github.com/HubSpot/jinjava/pull/1286">Use
<code>isResolvableObject</code> before building a hashcode in eager
execution</a></li>
<li><a
href="https://redirect.github.com/HubSpot/jinjava/pull/1285">Don't
require explicitly pushing the <code>JinjavaInterpreter</code> when
using it directly</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/HubSpot/jinjava/commit/44a958c47e4e4a7bfad7371b4114fbc09dac3d26"><code>44a958c</code></a>
[maven-release-plugin] prepare release jinjava-2.8.4</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/b65631687d1eda5d3137ff32ce9d73042c3f9534"><code>b656316</code></a>
Merge pull request <a
href="https://redirect.github.com/HubSpot/jinjava/issues/1329">#1329</a>
from HubSpot/jasmith_hubspot/jinjava-2.8.4-changelog...</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/c5916777506a3cb67ff1b609244661501a7e4d1f"><code>c591677</code></a>
docs: prepare changelog for jinjava 2.8.4 release</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/97238d530498f15c64df3737cbd18f8f462e55dd"><code>97238d5</code></a>
Merge pull request <a
href="https://redirect.github.com/HubSpot/jinjava/issues/1328">#1328</a>
from HubSpot/jasmith_hubspot/tagnode-default-scanner...</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/bab6ba338ce43b5d4fa3232be193fbb5d39c25a4"><code>bab6ba3</code></a>
fix: default null TokenScannerSymbols to DefaultTokenScannerSymbols</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/df3e3d8f7660b35d6ceaee244df1cd2325a3dc56"><code>df3e3d8</code></a>
Merge pull request <a
href="https://redirect.github.com/HubSpot/jinjava/issues/1325">#1325</a>
from HubSpot/jasmith_hubspot/backport-1305-1306-1311...</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/8511a71073288f166e032cfa88cb7b82d176a023"><code>8511a71</code></a>
Add keepTrailingNewline option to match Python Jinja2 default
behaviour</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/f9e5c21e2c89c6a7ca2a555c74d34a2549a0df84"><code>f9e5c21</code></a>
fix: treat backslash as escape character only inside quoted strings</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/f5e5b7bea7f815870731a9ce20df30411522308e"><code>f5e5b7b</code></a>
feat: add StringTokenScannerSymbols for configurable multi-character
delimiters</li>
<li><a
href="https://github.com/HubSpot/jinjava/commit/5afaece6bad6a096771396eaaddaf54da3a8609e"><code>5afaece</code></a>
Merge pull request <a
href="https://redirect.github.com/HubSpot/jinjava/issues/1309">#1309</a>
from HubSpot/2.8.x-integer-set-to-long-conversion</li>
<li>Additional commits viewable in <a
href="https://github.com/HubSpot/jinjava/compare/jinjava-2.8.3...jinjava-2.8.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.hubspot.jinjava:jinjava&package-manager=gradle&previous-version=2.8.3&new-version=2.8.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 19:25:17 +00:00
dependabot[bot] 80e4a3ae24 build(deps): bump astral-sh/setup-uv from 8.2.0 to 9.0.0 (#7238)
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from
8.2.0 to 9.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/setup-uv/releases">astral-sh/setup-uv's
releases</a>.</em></p>
<blockquote>
<h2>v9.0.0 🌈 Change <code>prune-cache</code> default to
<code>false</code></h2>
<h2>Changes</h2>
<p>This release disables the default cache cache pruning to ease the
load on the PyPi infrastructure.
Since users might experience more GitHub Actions cache usage which might
result in higher costs this is marked as a breaking change. To read more
on why we did this (now) you can read the detailed analysis and
reasoning in <a
href="https://redirect.github.com/astral-sh/setup-uv/issues/967">#967</a></p>
<p>Besides this big breaking change we also have a small bugfix while
building caches for linux distributions that behave a big different than
the &quot;big ones&quot; and a speed up in version resolution by only
reading the version manifest until a matching version is found saving
runtime and network bandwith.</p>
<h2>🚨 Breaking changes</h2>
<ul>
<li>Change <code>prune-cache</code> default to <code>false</code> <a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/967">#967</a>)</li>
</ul>
<h2>🐛 Bug fixes</h2>
<ul>
<li>fix: fall back to distribution ID when os-release has no version
field <a href="https://github.com/cxzhong"><code>@​cxzhong</code></a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/961">#961</a>)</li>
</ul>
<h2>🚀 Enhancements</h2>
<ul>
<li>Speed up version client by partial response reads <a
href="https://github.com/eifinger"><code>@​eifinger</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/807">#807</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>chore: update known checksums for 0.11.30 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/968">#968</a>)</li>
<li>chore: update known checksums for 0.11.29 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/960">#960</a>)</li>
</ul>
<h2>📚 Documentation</h2>
<ul>
<li>docs: update version references to v8.3.2 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/949">#949</a>)</li>
</ul>
<h2>⬆️ Dependency updates</h2>
<ul>
<li>chore(deps): roll up Dependabot updates <a
href="https://github.com/eifinger"><code>@​eifinger</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/970">#970</a>)</li>
<li>chore(deps): roll up Dependabot updates <a
href="https://github.com/eifinger"><code>@​eifinger</code></a> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/962">#962</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/c771a70e6277c0a99b617c7a806ffedaca235ff9"><code>c771a70</code></a>
chore(deps): roll up Dependabot updates (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/970">#970</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/2f537ca87c1ffa233ca2a1b84815388e3e42d845"><code>2f537ca</code></a>
chore: update known checksums for 0.11.30 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/968">#968</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/2269552d547df6f50e57442326930d30d943afe3"><code>2269552</code></a>
Speed up version client by partial response reads (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/807">#807</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/47a7f4fb2e900d6c33a5b5f231fa21dbfaeba52f"><code>47a7f4f</code></a>
Change <code>prune-cache</code> default to <code>false</code> (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/967">#967</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/71966eff34a27b0a62ed4b9f6f6e383e071b1bb5"><code>71966ef</code></a>
chore(deps): roll up Dependabot updates (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/962">#962</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/f12b1f0a84bd6dc2331b36b2bbdbb1d1e617dbcc"><code>f12b1f0</code></a>
fix: fall back to distribution ID when os-release has no version field
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/961">#961</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/ecd24dd710f2fb0dca1693a67af11fc4a5c5ec84"><code>ecd24dd</code></a>
chore: update known checksums for 0.11.29 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/960">#960</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/6a191366842ac1502ba6c07e9b5acd5c2d9d8db3"><code>6a19136</code></a>
docs: update version references to v8.3.2 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/949">#949</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/11f9893b081a58869d3b5fccaea48c9e9e46f990"><code>11f9893</code></a>
chore: roll up Dependabot updates (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/948">#948</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/f79855603231e1609d02bec6956bd0e05cbc46b5"><code>f798556</code></a>
docs: update version references to v8.3.1 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/946">#946</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/setup-uv/compare/fac544c07dec837d0ccb6301d7b5580bf5edae39...c771a70e6277c0a99b617c7a806ffedaca235ff9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=astral-sh/setup-uv&package-manager=github_actions&previous-version=8.2.0&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 19:16:18 +00:00
ConnorYoh 50bc4a7866 fix(storage): don't query the encryption key registry when storage is off (unblocks backend:dev:saas) (#7265)
# Description of Changes

Fixes a startup failure introduced by #7155 and reported against `task
backend:dev:saas`.

**What goes wrong**

`StorageProviderConfig.storageEncryptionState(...)` is created on every
startup, in every profile. When `storage.encryption.enabled` is false —
the default, and what SaaS ships — the `||` short-circuit evaluates
`fileEncryptionKeyRepository.count()`, a live query against
`file_encryption_keys`:

```java
if (writeEnabled || fileEncryptionKeyRepository.count() > 0) {   // <- always runs when the flag is off
```

That table only exists if `ddl-auto=update` managed to create it. When
it cannot — permissions on a shared Supabase branch DB, concurrent DDL
from several developers, schema ordering — **ddl-auto logs and
continues**, so the situation used to be a warning nobody noticed. Now
it is a query that throws during bean creation and takes the whole
context down.

Two things make this sting in SaaS specifically: `storage.enabled` is
false there, so before this feature nothing ever touched the table; and
`hibernate.default_schema=stirling_pdf` means the table has to exist in
a schema the app may not be able to create in.

There is a second exposure on the request path:
`suppressDirectDownloads()` also counts (60s cached), so even a
surviving boot could 500 on downloads.

**Fix**

- The boot probe runs only when `storage.enabled` is true, so a
deployment that does not use storage never touches the table.
- Registry reads are wrapped. The boot probe degrades to "no keys"
rather than propagating; `suppressDirectDownloads()` **fails safe by
suppressing** rather than issuing a presigned URL it cannot vouch for.
Losing the direct-download fast path is recoverable; serving ciphertext
is not.

**Safety is unchanged, and that is the important part.** The decorator
is still installed unconditionally, so any blob carrying the `SPDFEAR1`
magic is still decrypted via lazy materialisation or fails loudly — the
eager probe only ever bought *earlier* master-key verification. A node
that can actually serve stored files has `storage.enabled` on by
definition, which is exactly the node the drifted-node protection is
for; that test now configures it that way, and a new test pins that the
decorator remains installed even with storage off.

**Tests** — storage-disabled never calls `count()`; an unreadable
registry still boots *and* still suppresses direct downloads; the
decorator stays installed with storage off; storage-enabled still
probes. Full proprietary suite green apart from the pre-existing
Windows-symlink `FolderIdentitiesTest` failure, which is environmental
and unrelated.

**Note on scope:** deliberately minimal so it can land quickly. The
Aikido `findAll()` code-quality finding lives in #7173 only
(`rotateMasterKey` does not exist on main), so it is fixed there rather
than here. #7173 will be rebased once this merges.

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-03 16:41:56 +00:00
EthanHealy01andReece Browne c91d63f215 New design, part one: shared branding, nav surfaces and theme tokens (#7163)
## Overview

First part of the move over to the new designs. This lays the groundwork
(shared brand components, button/nav styling, theme tokens) and applies
it across the editor and the processor. Later parts will build on top of
it.

## What's changed

**Branding**
- Shared `Logo` and `BrandMark` components used everywhere, so the mark
and wordmark are identical across the editor, processor, auth pages and
the chat FAB.
- The sidebar logo doubles as the editor to processor switcher, morphing
into a chevron on hover. It only appears for users who can actually
reach the processor.

**Navigation and layout**
- Both sidebars restructured onto the floating nav surface treatment,
with rounded panels sitting on the app canvas.
- The editor file sidebar is now three sections (controls, PDF Library,
settings) and the workbench top bar and tools panel match.
- Added a collapse toggle to both sidebars, with an animated expand and
collapse and a tidy icon rail when collapsed. The processor did not have
a desktop collapse before.

**Components**
- Buttons and action icons now share one styling system, so both react
to the same tokens.
- Secondary buttons in dark mode use a neutral fill and border instead
of inheriting the primary colour.
- Status badges default to a clean dot with no background, with a filled
pill as the alternative.
- Metric strips gained a row layout with an optional leading icon.

**Theme**
- Colour tokens consolidated. Literal colours live only in the palette
file, everything else references the semantic `--c-*` tokens.
- `saas-theme.css` removed and the parts that were genuinely needed
moved into the shared theme, so all builds get them.
- The colour linter enforces this across the app and runs in CI.

## Notes

- Nothing functional should change here, it is styling plus the sidebar
collapse feature.
- Main has been merged in. The Sources and billing pages picked up
changes from main during that merge and are worth a look alongside the
new styling.

---------

Co-authored-by: Reece Browne <74901996+reecebrowne@users.noreply.github.com>
2026-08-03 14:59:28 +00:00
James Brunton 22815b5458 Sign Mac PR builds (#7267)
# Description of Changes
Mac builds in PRs are not currently signed, which means you can't run
them when downloaded. This restores the functionality so that Mac builds
are always signed.
2026-08-03 17:18:21 +01:00
Anthony Stirling 28480d137a Cache Gradle dependencies in the live E2E workflow (#7234)
# Description of Changes

Fixes the `playwright-e2e-live` failure seen on [run
30694073128](https://github.com/Stirling-Tools/Stirling-PDF/actions/runs/30694073128).
The backend never started:

```
> Could not resolve org.springframework.boot:spring-boot-buildpack-platform:4.0.6.
   > Could not GET 'https://repo.maven.apache.org/maven2/.../spring-boot-buildpack-platform-4.0.6.pom'.
     Received status code 429 from server: Too Many Requests
> There are 14 more failures with identical causes.
BUILD FAILED in 21s
```

Gradle was throttled by Maven Central while resolving the buildscript
classpath, `:stirling-pdf:bootRun` died, and the runner's "backend
exited before becoming ready" guard aborted the suite before a single
test ran.

`e2e-live.yml` was the only Java-running workflow with no Gradle
dependency cache, no `setup-gradle`, and no Maven mirror env - every
sibling (`backend-build.yml`, `db-migration-test.yml`,
`coverage-aggregate.yml`) has all three. So it downloaded the Gradle
distribution and resolved the entire classpath cold from Maven Central
on every single run, and eventually got throttled.

Added:

- the same `Cache Gradle dependency artifacts` + `Setup Gradle` pair
used by `backend-build.yml`
- `MAVEN_USER` / `MAVEN_PASSWORD` / `MAVEN_PUBLIC_URL` on the two
Gradle-invoking steps, so runs that have the secrets use the internal
mirror instead of hitting Central
- a `Prime Gradle dependencies` step that retries 3x with backoff.
Gradle does not retry 429s, and doing the cold resolve up front means a
rate-limit failure retries cheaply instead of killing a backgrounded
`bootRun` twenty minutes in

Side benefit: the job gets faster once the cache is warm.

## Notes for reviewers

- The 429 itself is transient infrastructure behaviour - a re-run would
likely have gone green. The defect being fixed is that this job had no
cache to fall back on, so it was exposed to it on every run.
- `:stirling-pdf:classes` does not trigger a frontend build
(`buildWithFrontend` defaults off, `app/core/build.gradle:147`), so
priming before the Vite build step is safe. It is not wasted work either
- `bootRun` compiles the same classes.
- This PR originally also carried a fix for the `tauri-build`
updater-key failure on that same run. #7181 fixes that more simply and
has been merged, so that half has been dropped here.
- Workflow changes cannot be fully verified locally; a CI run on this
branch is the real check.

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-03 14:58:14 +00:00
Anthony Stirling 21dff695fe Add SFTP, FTP and SMB network sources to the processor (#7153)
# Description of Changes

Add SFTP, FTP and SMB network sources to the processor plus UI change to
enable it

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-03 14:58:10 +00:00
James Brunton 19e7095a4f Convert unused translations test to use a trie to more efficiently scan (#7263)
# Description of Changes
Unused translations test takes ~8 seconds to run on my computer with no
contention, but when my CPU is under heavy contention, it often takes
>20 seconds and occasionally goes over the 30 second timeout. This PR
changes the test to use [a trie](https://en.wikipedia.org/wiki/Trie) to
more efficiently search for the strings, taking the test down to ~1.8
seconds. I've also increased the timeout for the missing & unused
translations tests for belt-and-braces.
2026-08-03 14:34:21 +00:00
James BruntonandAnthony Stirling cd199c8659 Define tool inputs & outputs in a structured way (#7204)
# Description of Changes
Change tool APIs to use structured definitions for input/output/type
info because we need that info to be able to validate whether policies
can actually successfully work based on whether one tool accepts the
output of another. There were various bugs in the previous string
definitions because of either misspellings or just incorrect
definitions, so I've gone through and fixed all that I can find.

<img width="729" height="271" alt="image"
src="https://github.com/user-attachments/assets/08357e96-6fbb-4b9c-ba4d-8995420c7b86"
/>

<img width="749" height="264" alt="image"
src="https://github.com/user-attachments/assets/76f46284-1866-4b64-b1ed-2480e01866e9"
/>

<img width="402" height="636" alt="image"
src="https://github.com/user-attachments/assets/8f7a36ca-2845-4f14-a2df-ec9c772e66f6"
/>

<img width="393" height="317" alt="image"
src="https://github.com/user-attachments/assets/46d8b891-9820-4ce3-8109-a8b782277037"
/>

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-03 14:13:43 +00:00
dependabot[bot] 7a5eb73c5b build(deps): bump actions/setup-node from 6.4.0 to 7.0.0 (#7240)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from
6.4.0 to 7.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-node/releases">actions/setup-node's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>What's Changed</h2>
<h3>Enhancements:</h3>
<ul>
<li>Add cache-primary-key and cache-matched-key as outputs by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1577">actions/setup-node#1577</a></li>
<li>Migrate to ESM and upgrade dependencies by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1574">actions/setup-node#1574</a></li>
</ul>
<h3>Bug fixes:</h3>
<ul>
<li>Remove dummy NODE_AUTH_TOKEN export by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1558">actions/setup-node#1558</a></li>
<li>Only use <code>mirrorToken</code> in <code>getManifest</code> if
it's provided by <a
href="https://github.com/deiga"><code>@​deiga</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li>
</ul>
<h3>Documentation updates:</h3>
<ul>
<li>Add documentation for publishing to npm with Trusted Publisher
(OIDC) by <a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li>
<li>docs: Update restore-only cache documentation by <a
href="https://github.com/priya-kinthali"><code>@​priya-kinthali</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1550">actions/setup-node#1550</a></li>
<li>docs: Update caching recommendations to mitigate cache poisoning
risks by <a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1567">actions/setup-node#1567</a></li>
</ul>
<h3>Dependency update:</h3>
<ul>
<li>Upgrade <code>@​actions/cache</code> to 5.1.0, log cache write
denied by <a
href="https://github.com/jasongin"><code>@​jasongin</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li>
<li><a href="https://github.com/deiga"><code>@​deiga</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li>
<li><a href="https://github.com/jasongin"><code>@​jasongin</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-node/compare/v6...v7.0.0">https://github.com/actions/setup-node/compare/v6...v7.0.0</a></p>
<h2>v6.5.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update <code>@​actions/cache</code> to 5.1.0 and add security
overrides for undici and fast-xml-parser by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1579">actions/setup-node#1579</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0">https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/setup-node/commit/820762786026740c76f36085b0efc47a31fe5020"><code>8207627</code></a>
Migrate to ESM and upgrade dependencies (<a
href="https://redirect.github.com/actions/setup-node/issues/1574">#1574</a>)</li>
<li><a
href="https://github.com/actions/setup-node/commit/04be95cf3511ea51ebf9f224ddfb99cc7ab87cd4"><code>04be95c</code></a>
Add cache-primary-key and cache-matched-key as outputs (<a
href="https://redirect.github.com/actions/setup-node/issues/1577">#1577</a>)</li>
<li><a
href="https://github.com/actions/setup-node/commit/7c2c68d20d402ed6a201ada70a81341941093140"><code>7c2c68d</code></a>
docs: Update caching recommendations to mitigate cache poisoning risks
(<a
href="https://redirect.github.com/actions/setup-node/issues/1567">#1567</a>)</li>
<li><a
href="https://github.com/actions/setup-node/commit/6a61c0375d66246de94630495909f12cf8dac84d"><code>6a61c03</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/setup-node/issues/1569">#1569</a>
from jasongin/update-actions-cache-5.1.0</li>
<li><a
href="https://github.com/actions/setup-node/commit/30eb73b41ded577900c1ebf968ef95cdf8f7434f"><code>30eb73b</code></a>
Resolve high-severity audit issues</li>
<li><a
href="https://github.com/actions/setup-node/commit/4e1a87a501d0302f99e30e2748568adcb388d09f"><code>4e1a87a</code></a>
Update dist</li>
<li><a
href="https://github.com/actions/setup-node/commit/360237f0c01778d0c17291f75c56d6feae4f7574"><code>360237f</code></a>
Strict equality</li>
<li><a
href="https://github.com/actions/setup-node/commit/4f8aac5beb2f0854bc79651567a18c67eb0b9de3"><code>4f8aac5</code></a>
Bump <code>@​actions/cache</code> to 5.1.0, log cache write denied</li>
<li><a
href="https://github.com/actions/setup-node/commit/f4a67bbeca970f103397d3d2b9462cf787cd2980"><code>f4a67bb</code></a>
Only use <code>mirrorToken</code> in <code>getManifest</code> if it's
provided (<a
href="https://redirect.github.com/actions/setup-node/issues/1548">#1548</a>)</li>
<li><a
href="https://github.com/actions/setup-node/commit/0355742c943ddb13ca8a6b700f824231caa91e75"><code>0355742</code></a>
Remove dummy NODE_AUTH_TOKEN export (<a
href="https://redirect.github.com/actions/setup-node/issues/1558">#1558</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=6.4.0&new-version=7.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:28:05 +00:00
dependabot[bot] 279b05fc7b build(deps): bump base64 from 0.22.1 to 0.23.0 in /frontend/editor/src-tauri (#7245)
Bumps [base64](https://github.com/marshallpierce/rust-base64) from
0.22.1 to 0.23.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md">base64's
changelog</a>.</em></p>
<blockquote>
<h1>0.23.0</h1>
<ul>
<li>Added more consts for preconfigured configs and engines</li>
<li>Make DecodeError::InvalidLastSymbol more clear by including the
decoded value</li>
<li>Added SIMD-accelerated engines behind the default-on
<code>simd-unsafe</code> feature: <code>Simd</code> picks the best
instruction set at runtime (AVX2 on <code>x86_64</code>, NEON on
<code>aarch64</code>) and falls back to the scalar
<code>GeneralPurpose</code> engine, while <code>Avx2</code> and
<code>Neon</code> target one instruction set with no runtime
detection and work in <code>no_std</code>. The engines support the
standard and URL-safe alphabets.</li>
<li>Update MSRV to 1.71.0</li>
<li>Add support for custom padding symbols</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/9e9220a4166f628de7c8803289e120ae1e944f78"><code>9e9220a</code></a>
v0.23.0</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/870326ec592eebde9d6bfe4c5d8130c591273e9c"><code>870326e</code></a>
Merge pull request <a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/306">#306</a>
from marshallpierce/mp/trailing-bits-docs</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/fbec5f1050f9fc16e6a826ebabaa2b7b0644bd67"><code>fbec5f1</code></a>
Document no trailing trailing bits</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/0a23549968f059b53cf39e96eba8f46779f322a7"><code>0a23549</code></a>
Merge pull request <a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/305">#305</a>
from marshallpierce/mp/edition-2021</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/f10b7e20614135aa61289140683fc93e5a45d338"><code>f10b7e2</code></a>
Update deps &amp; edition</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/9d21a598860645cb6290940e7a43033bc43ebd74"><code>9d21a59</code></a>
Merge pull request <a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/304">#304</a>
from marshallpierce/mp/custom-padding-rebase</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/f70bad2caaa85350b95d988bfb9a0997e824bfd8"><code>f70bad2</code></a>
Support custom padding symbols</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/684d79cd3deb8dfd5323619634c75bc0ff6edfd9"><code>684d79c</code></a>
Merge pull request <a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/301">#301</a>
from marshallpierce/mp/simd-gardening</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/5bf66f2646c6fd99e1b18bf4e2bb0a47d34e1eaa"><code>5bf66f2</code></a>
Merge pull request <a
href="https://redirect.github.com/marshallpierce/rust-base64/issues/284">#284</a>
from AbeZbm/add-tests</li>
<li><a
href="https://github.com/marshallpierce/rust-base64/commit/d3831cfbf7dafe226a8383450c3410e2f67c826a"><code>d3831cf</code></a>
Followups to SIMD work</li>
<li>Additional commits viewable in <a
href="https://github.com/marshallpierce/rust-base64/compare/v0.22.1...v0.23.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:27:38 +00:00
dependabot[bot] df4683e219 build(deps): bump the react group across 1 directory with 3 updates (#7246)
Bumps the react group with 3 updates in the /frontend directory:
[react](https://github.com/react/react/tree/HEAD/packages/react),
[@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react)
and
[react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom).

Updates `react` from 19.2.4 to 19.2.8
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/react/react/releases">react's
releases</a>.</em></p>
<blockquote>
<h2>19.2.8 (July 21st, 2026)</h2>
<h2>React Server Components</h2>
<ul>
<li>Performance improvements when decoding
(<a
href="https://redirect.github.com/facebook/react/pull/37087">#37087</a>
by <a href="https://github.com/eps1lon"><code>@​eps1lon</code></a>)</li>
</ul>
<h2>19.2.7 (June 1st, 2026)</h2>
<h2>React Server Components</h2>
<ul>
<li>Fixed missing <code>FormData</code> entries in Server Actions which
regressed in 19.2.6
(<a
href="https://redirect.github.com/facebook/react/pull/36566">#36566</a>
by <a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a>)</li>
</ul>
<h2>19.2.6 (May 6th, 2026)</h2>
<h2>React Server Components</h2>
<ul>
<li>Type hardening and performance improvements
(<a
href="https://redirect.github.com/facebook/react/pull/36425">#36425</a>
by <a href="https://github.com/eps1lon"><code>@​eps1lon</code></a> and
<a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a>)</li>
</ul>
<h2>19.2.5 (April 8th, 2026)</h2>
<h2>React Server Components</h2>
<ul>
<li>Add more cycle protections (<a
href="https://redirect.github.com/facebook/react/pull/36236">#36236</a>
by <a href="https://github.com/eps1lon"><code>@​eps1lon</code></a> and
<a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/react/react/blob/main/CHANGELOG.md">react's
changelog</a>.</em></p>
<blockquote>
<h2>19.2.7 (June 1, 2026)</h2>
<h3>React Server Components</h3>
<ul>
<li>Fixed missing <code>FormData</code> entries in Server Actions which
regressed in 19.2.6 (<a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a> <a
href="https://redirect.github.com/facebook/react/pull/36566">#36566</a>)</li>
</ul>
<h2>19.2.6 (May 6, 2026)</h2>
<h3>React Server Components</h3>
<ul>
<li>Type hardening and performance improvements (<a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>, <a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a> <a
href="https://redirect.github.com/facebook/react/pull/36425">#36425</a>)</li>
</ul>
<h2>19.2.5 (March 18, 2026)</h2>
<h3>React Server Components</h3>
<ul>
<li>Add more cycle protections (<a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>, <a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a> <a
href="https://redirect.github.com/facebook/react/pull/36236">#36236</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/react/react/commit/1dd4ecbdabf826f527fc9a58c05ea70375b7d170"><code>1dd4ecb</code></a>
[FlightReply] Performance improvements when decoding (<a
href="https://github.com/react/react/tree/HEAD/packages/react/issues/37087">#37087</a>)</li>
<li><a
href="https://github.com/react/react/commit/b0d2fdb78bdfae075a7fa02ddcebbf25f90952c2"><code>b0d2fdb</code></a>
[19.2.x] Update required references to GitHub repo (<a
href="https://github.com/react/react/tree/HEAD/packages/react/issues/36753">#36753</a>)</li>
<li><a
href="https://github.com/react/react/commit/6117d7cca4906492c51fe6a03381e35adfd86e7d"><code>6117d7c</code></a>
Version 19.2.7 (<a
href="https://github.com/react/react/tree/HEAD/packages/react/issues/36591">#36591</a>)</li>
<li><a
href="https://github.com/react/react/commit/eaf3e95ca92be7a23d3c9cc8ffd6f199a40be401"><code>eaf3e95</code></a>
Version 19.2.6</li>
<li><a
href="https://github.com/react/react/commit/23f4f9f30da9e9af2108c18bb197bae75ab584ea"><code>23f4f9f</code></a>
19.2.5</li>
<li>See full diff in <a
href="https://github.com/react/react/commits/v19.2.8/packages/react">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for react since your current version.</p>
</details>
<br />

Updates `@types/react` from 19.2.14 to 19.2.17
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react">compare
view</a></li>
</ul>
</details>
<br />

Updates `react-dom` from 19.2.4 to 19.2.8
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/react/react/releases">react-dom's
releases</a>.</em></p>
<blockquote>
<h2>19.2.8 (July 21st, 2026)</h2>
<h2>React Server Components</h2>
<ul>
<li>Performance improvements when decoding
(<a
href="https://redirect.github.com/facebook/react/pull/37087">#37087</a>
by <a href="https://github.com/eps1lon"><code>@​eps1lon</code></a>)</li>
</ul>
<h2>19.2.7 (June 1st, 2026)</h2>
<h2>React Server Components</h2>
<ul>
<li>Fixed missing <code>FormData</code> entries in Server Actions which
regressed in 19.2.6
(<a
href="https://redirect.github.com/facebook/react/pull/36566">#36566</a>
by <a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a>)</li>
</ul>
<h2>19.2.6 (May 6th, 2026)</h2>
<h2>React Server Components</h2>
<ul>
<li>Type hardening and performance improvements
(<a
href="https://redirect.github.com/facebook/react/pull/36425">#36425</a>
by <a href="https://github.com/eps1lon"><code>@​eps1lon</code></a> and
<a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a>)</li>
</ul>
<h2>19.2.5 (April 8th, 2026)</h2>
<h2>React Server Components</h2>
<ul>
<li>Add more cycle protections (<a
href="https://redirect.github.com/facebook/react/pull/36236">#36236</a>
by <a href="https://github.com/eps1lon"><code>@​eps1lon</code></a> and
<a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/react/react/blob/main/CHANGELOG.md">react-dom's
changelog</a>.</em></p>
<blockquote>
<h2>19.2.7 (June 1, 2026)</h2>
<h3>React Server Components</h3>
<ul>
<li>Fixed missing <code>FormData</code> entries in Server Actions which
regressed in 19.2.6 (<a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a> <a
href="https://redirect.github.com/facebook/react/pull/36566">#36566</a>)</li>
</ul>
<h2>19.2.6 (May 6, 2026)</h2>
<h3>React Server Components</h3>
<ul>
<li>Type hardening and performance improvements (<a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>, <a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a> <a
href="https://redirect.github.com/facebook/react/pull/36425">#36425</a>)</li>
</ul>
<h2>19.2.5 (March 18, 2026)</h2>
<h3>React Server Components</h3>
<ul>
<li>Add more cycle protections (<a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>, <a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a> <a
href="https://redirect.github.com/facebook/react/pull/36236">#36236</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/react/react/commit/1dd4ecbdabf826f527fc9a58c05ea70375b7d170"><code>1dd4ecb</code></a>
[FlightReply] Performance improvements when decoding (<a
href="https://github.com/react/react/tree/HEAD/packages/react-dom/issues/37087">#37087</a>)</li>
<li><a
href="https://github.com/react/react/commit/b0d2fdb78bdfae075a7fa02ddcebbf25f90952c2"><code>b0d2fdb</code></a>
[19.2.x] Update required references to GitHub repo (<a
href="https://github.com/react/react/tree/HEAD/packages/react-dom/issues/36753">#36753</a>)</li>
<li><a
href="https://github.com/react/react/commit/6117d7cca4906492c51fe6a03381e35adfd86e7d"><code>6117d7c</code></a>
Version 19.2.7 (<a
href="https://github.com/react/react/tree/HEAD/packages/react-dom/issues/36591">#36591</a>)</li>
<li><a
href="https://github.com/react/react/commit/eaf3e95ca92be7a23d3c9cc8ffd6f199a40be401"><code>eaf3e95</code></a>
Version 19.2.6</li>
<li><a
href="https://github.com/react/react/commit/23f4f9f30da9e9af2108c18bb197bae75ab584ea"><code>23f4f9f</code></a>
19.2.5</li>
<li>See full diff in <a
href="https://github.com/react/react/commits/v19.2.8/packages/react-dom">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for react-dom since your current version.</p>
</details>
<br />

Updates `@types/react` from 19.2.14 to 19.2.17
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:27:06 +00:00
dependabot[bot] 2bc1041443 build(deps-dev): bump the typescript-eslint group across 1 directory with 3 updates (#7252)
Bumps the typescript-eslint group with 3 updates in the /frontend
directory:
[@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin),
[@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser)
and
[typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).

Updates `@typescript-eslint/eslint-plugin` from 8.61.1 to 8.65.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases">@​typescript-eslint/eslint-plugin's
releases</a>.</em></p>
<blockquote>
<h2>v8.65.0</h2>
<h2>8.65.0 (2026-07-20)</h2>
<h3>🚀 Features</h3>
<ul>
<li>add warning when TS 7 is detected (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12529">#12529</a>)</li>
<li><strong>eslint-plugin:</strong> [no-restricted-imports] deprecate
extension rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12527">#12527</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/19562">#19562</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11889">#11889</a>)</li>
<li><strong>eslint-plugin:</strong> [no-shadow] specialized error on
enum declaration and member shadowing (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12578">#12578</a>)</li>
<li><strong>parser:</strong> add onUnsupportedTypeScriptVersion option
to error on unsupported TypeScript versions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12465">#12465</a>)</li>
<li><strong>typescript-estree:</strong> throw for invalid import defer
syntax (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12552">#12552</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [prefer-string-starts-ends-with]
handle escaped $ ending regex literals (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12515">#12515</a>)</li>
<li><strong>eslint-plugin:</strong> [unbound-method] report unbound
methods accessed via member expression on union types (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12448">#12448</a>)</li>
<li><strong>eslint-plugin:</strong>
[no-unnecessary-parameter-property-assignment] don't flag computed
assignments with a variable key (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12568">#12568</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Josh Goldberg </li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
<li>Serhii Leniv <a
href="https://github.com/Serhii-Leniv"><code>@​Serhii-Leniv</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.65.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.64.0</h2>
<h2>8.64.0 (2026-07-13)</h2>
<h3>🚀 Features</h3>
<ul>
<li>support parsing <code>import defer</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12513">#12513</a>)</li>
<li><strong>eslint-plugin:</strong> [no-loop-func] support
<code>using</code> / <code>await using</code> declarations and deprecate
the rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12500">#12500</a>)</li>
<li><strong>typescript-estree:</strong> throw for invalid definite
assignment in class properties (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12543">#12543</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [require-array-sort-compare] handle
constrained arrays (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12512">#12512</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.64.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md">@​typescript-eslint/eslint-plugin's
changelog</a>.</em></p>
<blockquote>
<h2>8.65.0 (2026-07-20)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-shadow] specialized error on
enum declaration and member shadowing (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12578">#12578</a>)</li>
<li>add warning when TS 7 is detected (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12529">#12529</a>)</li>
<li><strong>eslint-plugin:</strong> [no-restricted-imports] deprecate
extension rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12527">#12527</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/19562">#19562</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11889">#11889</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong>
[no-unnecessary-parameter-property-assignment] don't flag computed
assignments with a variable key (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12568">#12568</a>)</li>
<li><strong>eslint-plugin:</strong> [unbound-method] report unbound
methods accessed via member expression on union types (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12448">#12448</a>)</li>
<li><strong>eslint-plugin:</strong> [prefer-string-starts-ends-with]
handle escaped $ ending regex literals (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12515">#12515</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Josh Goldberg </li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
<li>Serhii Leniv <a
href="https://github.com/Serhii-Leniv"><code>@​Serhii-Leniv</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.65.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.64.0 (2026-07-13)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-loop-func] support
<code>using</code> / <code>await using</code> declarations and deprecate
the rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12500">#12500</a>)</li>
<li><strong>typescript-estree:</strong> throw for invalid definite
assignment in class properties (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12543">#12543</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [require-array-sort-compare] handle
constrained arrays (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12512">#12512</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.64.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.63.0 (2026-07-06)</h2>
<h3>🚀 Features</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/63ba81b6acfa0d663c29aa0013d4672bf3b0426c"><code>63ba81b</code></a>
chore(release): publish 8.65.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/aa602bdf3f2dd460069da4f82d8acf41a7f938b8"><code>aa602bd</code></a>
fix(eslint-plugin): [no-unnecessary-parameter-property-assignment] don't
flag...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/1e90d6733210f550697a062b1e79cb49ce2880e6"><code>1e90d67</code></a>
feat(eslint-plugin): [no-shadow] specialized error on enum declaration
and me...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/b32fb34305f685254059b8ceaf8bec15b1f1f77e"><code>b32fb34</code></a>
docs: fix broken code samples in no-extraneous-class and
prefer-function-type...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/eaf457631ac381aadfee747c2d098c8ac4df9d63"><code>eaf4576</code></a>
feat: add warning when TS 7 is detected (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12529">#12529</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/18c01c7049e55aa346d84c06bd03d8e9daf48343"><code>18c01c7</code></a>
feat(eslint-plugin): [no-restricted-imports] deprecate extension rule
(<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12527">#12527</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/96e8fe25587a6e83a7a1cd957132a2e02b451b4b"><code>96e8fe2</code></a>
fix(eslint-plugin): [unbound-method] report unbound methods accessed via
memb...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/0d06406f3181f063041dbd1621d71984127ddae1"><code>0d06406</code></a>
chore: add attw validation to repo (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12437">#12437</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/9d9973bb181a413187468a95f84f86d9998b0658"><code>9d9973b</code></a>
fix(eslint-plugin): [prefer-string-starts-ends-with] handle escaped $
ending ...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/c2386e49ec6347aa92d53a1f32143ca45984cc13"><code>c2386e4</code></a>
chore(deps): update dependency prettier to v3.9.5 (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12486">#12486</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.65.0/packages/eslint-plugin">compare
view</a></li>
</ul>
</details>
<br />

Updates `@typescript-eslint/parser` from 8.61.1 to 8.65.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases">@​typescript-eslint/parser's
releases</a>.</em></p>
<blockquote>
<h2>v8.65.0</h2>
<h2>8.65.0 (2026-07-20)</h2>
<h3>🚀 Features</h3>
<ul>
<li>add warning when TS 7 is detected (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12529">#12529</a>)</li>
<li><strong>eslint-plugin:</strong> [no-restricted-imports] deprecate
extension rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12527">#12527</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/19562">#19562</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11889">#11889</a>)</li>
<li><strong>eslint-plugin:</strong> [no-shadow] specialized error on
enum declaration and member shadowing (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12578">#12578</a>)</li>
<li><strong>parser:</strong> add onUnsupportedTypeScriptVersion option
to error on unsupported TypeScript versions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12465">#12465</a>)</li>
<li><strong>typescript-estree:</strong> throw for invalid import defer
syntax (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12552">#12552</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [prefer-string-starts-ends-with]
handle escaped $ ending regex literals (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12515">#12515</a>)</li>
<li><strong>eslint-plugin:</strong> [unbound-method] report unbound
methods accessed via member expression on union types (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12448">#12448</a>)</li>
<li><strong>eslint-plugin:</strong>
[no-unnecessary-parameter-property-assignment] don't flag computed
assignments with a variable key (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12568">#12568</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Josh Goldberg </li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
<li>Serhii Leniv <a
href="https://github.com/Serhii-Leniv"><code>@​Serhii-Leniv</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.65.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.64.0</h2>
<h2>8.64.0 (2026-07-13)</h2>
<h3>🚀 Features</h3>
<ul>
<li>support parsing <code>import defer</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12513">#12513</a>)</li>
<li><strong>eslint-plugin:</strong> [no-loop-func] support
<code>using</code> / <code>await using</code> declarations and deprecate
the rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12500">#12500</a>)</li>
<li><strong>typescript-estree:</strong> throw for invalid definite
assignment in class properties (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12543">#12543</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [require-array-sort-compare] handle
constrained arrays (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12512">#12512</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.64.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md">@​typescript-eslint/parser's
changelog</a>.</em></p>
<blockquote>
<h2>8.65.0 (2026-07-20)</h2>
<h3>🚀 Features</h3>
<ul>
<li>add warning when TS 7 is detected (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12529">#12529</a>)</li>
<li><strong>parser:</strong> add onUnsupportedTypeScriptVersion option
to error on unsupported TypeScript versions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12465">#12465</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Josh Goldberg </li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.65.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.64.0 (2026-07-13)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.64.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.63.0 (2026-07-06)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.63.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.62.1 (2026-06-29)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.1">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.62.0 (2026-06-22)</h2>
<h3>🚀 Features</h3>
<ul>
<li>remove redundant package.json &quot;files&quot; (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12444">#12444</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/63ba81b6acfa0d663c29aa0013d4672bf3b0426c"><code>63ba81b</code></a>
chore(release): publish 8.65.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/eaf457631ac381aadfee747c2d098c8ac4df9d63"><code>eaf4576</code></a>
feat: add warning when TS 7 is detected (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser/issues/12529">#12529</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/d8f1044702e3257ee92c0af6681c1455563009db"><code>d8f1044</code></a>
feat(parser): add onUnsupportedTypeScriptVersion option to error on
unsupport...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/0d06406f3181f063041dbd1621d71984127ddae1"><code>0d06406</code></a>
chore: add attw validation to repo (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser/issues/12437">#12437</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/c2386e49ec6347aa92d53a1f32143ca45984cc13"><code>c2386e4</code></a>
chore(deps): update dependency prettier to v3.9.5 (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser/issues/12486">#12486</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/414d9abbf66f77796ab12ec7e75b07722e592832"><code>414d9ab</code></a>
chore(release): publish 8.64.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/290cf6cdcc5ffb00c5b8f3e1e0e9f2fd8cc96374"><code>290cf6c</code></a>
chore(release): publish 8.63.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/3ea32f4ba5e196c08c6da1095619d7f65ba4905e"><code>3ea32f4</code></a>
chore(release): publish 8.62.1</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/54e285728e5d8cb83fadb8041189f0c3b4ab436a"><code>54e2857</code></a>
chore(release): publish 8.62.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/81e4c2654c3f4d923766a888691add2c45b5d64a"><code>81e4c26</code></a>
feat: remove redundant package.json &quot;files&quot; (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser/issues/12444">#12444</a>)</li>
<li>See full diff in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.65.0/packages/parser">compare
view</a></li>
</ul>
</details>
<br />

Updates `typescript-eslint` from 8.61.1 to 8.65.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases">typescript-eslint's
releases</a>.</em></p>
<blockquote>
<h2>v8.65.0</h2>
<h2>8.65.0 (2026-07-20)</h2>
<h3>🚀 Features</h3>
<ul>
<li>add warning when TS 7 is detected (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12529">#12529</a>)</li>
<li><strong>eslint-plugin:</strong> [no-restricted-imports] deprecate
extension rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12527">#12527</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/19562">#19562</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11889">#11889</a>)</li>
<li><strong>eslint-plugin:</strong> [no-shadow] specialized error on
enum declaration and member shadowing (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12578">#12578</a>)</li>
<li><strong>parser:</strong> add onUnsupportedTypeScriptVersion option
to error on unsupported TypeScript versions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12465">#12465</a>)</li>
<li><strong>typescript-estree:</strong> throw for invalid import defer
syntax (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12552">#12552</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [prefer-string-starts-ends-with]
handle escaped $ ending regex literals (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12515">#12515</a>)</li>
<li><strong>eslint-plugin:</strong> [unbound-method] report unbound
methods accessed via member expression on union types (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12448">#12448</a>)</li>
<li><strong>eslint-plugin:</strong>
[no-unnecessary-parameter-property-assignment] don't flag computed
assignments with a variable key (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12568">#12568</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>Josh Goldberg </li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
<li>Serhii Leniv <a
href="https://github.com/Serhii-Leniv"><code>@​Serhii-Leniv</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.65.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.64.0</h2>
<h2>8.64.0 (2026-07-13)</h2>
<h3>🚀 Features</h3>
<ul>
<li>support parsing <code>import defer</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12513">#12513</a>)</li>
<li><strong>eslint-plugin:</strong> [no-loop-func] support
<code>using</code> / <code>await using</code> declarations and deprecate
the rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12500">#12500</a>)</li>
<li><strong>typescript-estree:</strong> throw for invalid definite
assignment in class properties (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12543">#12543</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [require-array-sort-compare] handle
constrained arrays (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12512">#12512</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Evyatar Daud <a
href="https://github.com/StyleShit"><code>@​StyleShit</code></a></li>
<li>송재욱</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.64.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md">typescript-eslint's
changelog</a>.</em></p>
<blockquote>
<h2>8.65.0 (2026-07-20)</h2>
<h3>🚀 Features</h3>
<ul>
<li>add warning when TS 7 is detected (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12529">#12529</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Josh Goldberg </li>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.65.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.64.0 (2026-07-13)</h2>
<p>This was a version bump only for typescript-eslint to align it with
other projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.64.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.63.0 (2026-07-06)</h2>
<p>This was a version bump only for typescript-eslint to align it with
other projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.63.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.62.1 (2026-06-29)</h2>
<p>This was a version bump only for typescript-eslint to align it with
other projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.1">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.62.0 (2026-06-22)</h2>
<h3>🚀 Features</h3>
<ul>
<li>remove redundant package.json &quot;files&quot; (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12444">#12444</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Kirk Waiblinger <a
href="https://github.com/kirkwaiblinger"><code>@​kirkwaiblinger</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.62.0">GitHub
Releases</a> for more information.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/63ba81b6acfa0d663c29aa0013d4672bf3b0426c"><code>63ba81b</code></a>
chore(release): publish 8.65.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/eaf457631ac381aadfee747c2d098c8ac4df9d63"><code>eaf4576</code></a>
feat: add warning when TS 7 is detected (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint/issues/12529">#12529</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/0d06406f3181f063041dbd1621d71984127ddae1"><code>0d06406</code></a>
chore: add attw validation to repo (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint/issues/12437">#12437</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/c2386e49ec6347aa92d53a1f32143ca45984cc13"><code>c2386e4</code></a>
chore(deps): update dependency prettier to v3.9.5 (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint/issues/12486">#12486</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/414d9abbf66f77796ab12ec7e75b07722e592832"><code>414d9ab</code></a>
chore(release): publish 8.64.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/290cf6cdcc5ffb00c5b8f3e1e0e9f2fd8cc96374"><code>290cf6c</code></a>
chore(release): publish 8.63.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/3ea32f4ba5e196c08c6da1095619d7f65ba4905e"><code>3ea32f4</code></a>
chore(release): publish 8.62.1</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/54e285728e5d8cb83fadb8041189f0c3b4ab436a"><code>54e2857</code></a>
chore(release): publish 8.62.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/81e4c2654c3f4d923766a888691add2c45b5d64a"><code>81e4c26</code></a>
feat: remove redundant package.json &quot;files&quot; (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint/issues/12444">#12444</a>)</li>
<li>See full diff in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.65.0/packages/typescript-eslint">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:26:15 +00:00
dependabot[bot] 98fa03caeb build(deps): bump github/codeql-action/upload-sarif from 4.35.5 to 4.37.3 (#7251)
Bumps
[github/codeql-action/upload-sarif](https://github.com/github/codeql-action)
from 4.35.5 to 4.37.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action/upload-sarif's
releases</a>.</em></p>
<blockquote>
<h2>v4.37.3</h2>
<p>No user facing changes.</p>
<h2>v4.37.2</h2>
<ul>
<li>The new address format for the <code>config-file</code> input that
was introduced in CodeQL Action 4.37.0 is now enabled by default. In
addition to the format described there, the <code>remote=</code> prefix
can now be used to explicitly indicate that the input refers to a remote
file. All previous input formats continue to be accepted as well. <a
href="https://redirect.github.com/github/codeql-action/pull/4023">#4023</a></li>
<li>The CodeQL Action can now make use of <a
href="https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries">configured
private registries</a> in Default Setup to retrieve CodeQL configuration
files from remote repositories that require authentication. This will
allow customers to store their CodeQL configuration in a single
repository that can then be referenced by Default Setup workflows in
other repositories. We expect to roll this and other, related changes
out to everyone in July. <a
href="https://redirect.github.com/github/codeql-action/pull/4007">#4007</a></li>
</ul>
<h2>v4.37.1</h2>
<ul>
<li><em>Upcoming breaking change</em>: Add a deprecation warning for
customers using CodeQL version 2.20.6 and earlier. These versions of
CodeQL were discontinued on 1 July 2026 alongside GitHub Enterprise
Server 3.16, and will be unsupported by the next minor release of the
CodeQL Action. <a
href="https://redirect.github.com/github/codeql-action/pull/3956">#3956</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.1">2.26.1</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4019">#4019</a></li>
</ul>
<h2>v4.37.0</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.0">2.26.0</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3995">#3995</a></li>
<li>In addition to the existing input format, the
<code>config-file</code> input for the <code>codeql-action/init</code>
step will soon support a new <code>[owner/]repo[@ref][:path]</code>
format. All components except the repository name are optional. If
omitted, <code>owner</code> defaults to the same owner as the repository
the analysis is running for, <code>ref</code> to <code>main</code>, and
<code>path</code> to <code>.github/codeql-action.yaml</code>. Support
for this format ships in this version of the CodeQL Action, but will
only be enabled over the coming weeks. <a
href="https://redirect.github.com/github/codeql-action/pull/3973">#3973</a></li>
</ul>
<h2>v4.36.3</h2>
<p>No user facing changes.</p>
<h2>v4.36.2</h2>
<ul>
<li>Cache CodeQL CLI version information across Actions steps. <a
href="https://redirect.github.com/github/codeql-action/pull/3943">#3943</a></li>
<li>Reduce requests while waiting for analysis processing by using
exponential backoff when polling SARIF processing status. <a
href="https://redirect.github.com/github/codeql-action/pull/3937">#3937</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6">2.25.6</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3948">#3948</a></li>
</ul>
<h2>v4.36.1</h2>
<p>No user facing changes.</p>
<h2>v4.36.0</h2>
<ul>
<li><em>Breaking change</em>: Bump the minimum required CodeQL bundle
version to 2.19.4. <a
href="https://redirect.github.com/github/codeql-action/pull/3894">#3894</a></li>
<li>Add support for SHA-256 Git object IDs. <a
href="https://redirect.github.com/github/codeql-action/pull/3893">#3893</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.5">2.25.5</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3926">#3926</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action/upload-sarif's
changelog</a>.</em></p>
<blockquote>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>[UNRELEASED]</h2>
<ul>
<li>Fixed a bug where a network error while streaming the download of
the CodeQL bundle could terminate the <code>init</code> Action instead
of falling back to downloading the bundle before extracting it. <a
href="https://redirect.github.com/github/codeql-action/pull/4061">#4061</a></li>
</ul>
<h2>4.37.4 - 29 Jul 2026</h2>
<ul>
<li>This version of the CodeQL Action adds support for the
<code>tools</code> input for the <code>codeql-action/init</code> step to
be specified using a <code>github-codeql-tools</code> <a
href="https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization">repository
property</a>. This feature will gradually be rolled out following the
release of this version. Once rolled out, this allows for the CodeQL CLI
version that is used in GitHub-managed workflows, such as Default Setup,
to be set to a custom value. For example, customers who run into issues
with rate limits when a new CodeQL CLI version is released can set the
value to <code>toolcache</code> to always use the CodeQL CLI version
that is available in the runner toolcache. For Advanced Setup workflows,
the value provided for <code>tools</code> in the workflow definition
always takes precedence unless the value of the repository property
starts with <code>!</code>. <a
href="https://redirect.github.com/github/codeql-action/pull/4037">#4037</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.2">2.26.2</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4051">#4051</a></li>
</ul>
<h2>4.37.3 - 22 Jul 2026</h2>
<p>No user facing changes.</p>
<h2>4.37.2 - 21 Jul 2026</h2>
<ul>
<li>The new address format for the <code>config-file</code> input that
was introduced in CodeQL Action 4.37.0 is now enabled by default. In
addition to the format described there, the <code>remote=</code> prefix
can now be used to explicitly indicate that the input refers to a remote
file. All previous input formats continue to be accepted as well. <a
href="https://redirect.github.com/github/codeql-action/pull/4023">#4023</a></li>
<li>The CodeQL Action can now make use of <a
href="https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries">configured
private registries</a> in Default Setup to retrieve CodeQL configuration
files from remote repositories that require authentication. This will
allow customers to store their CodeQL configuration in a single
repository that can then be referenced by Default Setup workflows in
other repositories. We expect to roll this and other, related changes
out to everyone in July. <a
href="https://redirect.github.com/github/codeql-action/pull/4007">#4007</a></li>
</ul>
<h2>4.37.1 - 16 Jul 2026</h2>
<ul>
<li><em>Upcoming breaking change</em>: Add a deprecation warning for
customers using CodeQL version 2.20.6 and earlier. These versions of
CodeQL were discontinued on 1 July 2026 alongside GitHub Enterprise
Server 3.16, and will be unsupported by the next minor release of the
CodeQL Action. <a
href="https://redirect.github.com/github/codeql-action/pull/3956">#3956</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.1">2.26.1</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/4019">#4019</a></li>
</ul>
<h2>4.37.0 - 08 Jul 2026</h2>
<ul>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.0">2.26.0</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3995">#3995</a></li>
<li>In addition to the existing input format, the
<code>config-file</code> input for the <code>codeql-action/init</code>
step will soon support a new <code>[owner/]repo[@ref][:path]</code>
format. All components except the repository name are optional. If
omitted, <code>owner</code> defaults to the same owner as the repository
the analysis is running for, <code>ref</code> to <code>main</code>, and
<code>path</code> to <code>.github/codeql-action.yaml</code>. Support
for this format ships in this version of the CodeQL Action, but will
only be enabled over the coming weeks. <a
href="https://redirect.github.com/github/codeql-action/pull/3973">#3973</a></li>
</ul>
<h2>4.36.3 - 01 Jul 2026</h2>
<p>No user facing changes.</p>
<h2>4.36.2 - 04 Jun 2026</h2>
<ul>
<li>Cache CodeQL CLI version information across Actions steps. <a
href="https://redirect.github.com/github/codeql-action/pull/3943">#3943</a></li>
<li>Reduce requests while waiting for analysis processing by using
exponential backoff when polling SARIF processing status. <a
href="https://redirect.github.com/github/codeql-action/pull/3937">#3937</a></li>
<li>Update default CodeQL bundle version to <a
href="https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6">2.25.6</a>.
<a
href="https://redirect.github.com/github/codeql-action/pull/3948">#3948</a></li>
</ul>
<h2>4.36.1 - 02 Jun 2026</h2>
<p>No user facing changes.</p>
<h2>4.36.0 - 22 May 2026</h2>
<ul>
<li><em>Breaking change</em>: Bump the minimum required CodeQL bundle
version to 2.19.4. <a
href="https://redirect.github.com/github/codeql-action/pull/3894">#3894</a></li>
<li>Add support for SHA-256 Git object IDs. <a
href="https://redirect.github.com/github/codeql-action/pull/3893">#3893</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/github/codeql-action/commit/e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81"><code>e4fba86</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4031">#4031</a>
from github/update-v4.37.3-72f6a9da0</li>
<li><a
href="https://github.com/github/codeql-action/commit/fb50ab5d62a274adf3ef3e22cfe750ae87a0ede7"><code>fb50ab5</code></a>
Update changelog for v4.37.3</li>
<li><a
href="https://github.com/github/codeql-action/commit/72f6a9da0def52d9193d6a758f0378b65091f8d1"><code>72f6a9d</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4030">#4030</a>
from github/mbg/fix/no-proxy</li>
<li><a
href="https://github.com/github/codeql-action/commit/3b5ee58597653d9cc6785f3f1277f796d81f3646"><code>3b5ee58</code></a>
Use default <code>request</code> options instead of
<code>undefined</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/bfb6be4b5ecd3650f02f530571453e8c64ef0778"><code>bfb6be4</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4028">#4028</a>
from github/mergeback/v4.37.2-to-main-e0647621</li>
<li><a
href="https://github.com/github/codeql-action/commit/526ab84f9858816d9cf5f7b9df4dd5e2235f0eba"><code>526ab84</code></a>
Rebuild</li>
<li><a
href="https://github.com/github/codeql-action/commit/d6217b9b8c14166e4851db94c11155d03bd13c07"><code>d6217b9</code></a>
Update changelog and version after v4.37.2</li>
<li><a
href="https://github.com/github/codeql-action/commit/e0647621c2984b5ed2f768cb892365bf2a616ad1"><code>e064762</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/4027">#4027</a>
from github/update-v4.37.2-385bcdc5a</li>
<li><a
href="https://github.com/github/codeql-action/commit/e0faed839190caa67a5cd42f1cc16246028ca3df"><code>e0faed8</code></a>
Add a couple of change notes</li>
<li><a
href="https://github.com/github/codeql-action/commit/73aad0eaa9df172668665a150d17b8bc5a650c20"><code>73aad0e</code></a>
Update changelog for v4.37.2</li>
<li>Additional commits viewable in <a
href="https://github.com/github/codeql-action/compare/9e0d7b8d25671d64c341c19c0152d693099fb5ba...e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action/upload-sarif&package-manager=github_actions&previous-version=4.35.5&new-version=4.37.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:25:33 +00:00
dependabot[bot] 66369fd609 build(deps): bump log from 0.4.29 to 0.4.33 in /frontend/editor/src-tauri (#7244)
Bumps [log](https://github.com/rust-lang/log) from 0.4.29 to 0.4.33.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/log/releases">log's
releases</a>.</em></p>
<blockquote>
<h2>0.4.32</h2>
<h2>What's Changed</h2>
<ul>
<li>Support <code>Value</code> -&gt; string conversions with
<code>kv</code> + <code>std</code> features instead of
<code>kv_std</code> by <a
href="https://github.com/tisonkun"><code>@​tisonkun</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/729">rust-lang/log#729</a></li>
<li>Prepare for 0.4.32 release by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/730">rust-lang/log#730</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rust-lang/log/compare/0.4.31...0.4.32">https://github.com/rust-lang/log/compare/0.4.31...0.4.32</a></p>
<h2>0.4.31</h2>
<h2>What's Changed</h2>
<ul>
<li>fix typos in kv compile errors and log documentation by <a
href="https://github.com/Isvane"><code>@​Isvane</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/726">rust-lang/log#726</a></li>
<li>Leverage static str key when possible by <a
href="https://github.com/tisonkun"><code>@​tisonkun</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/727">rust-lang/log#727</a></li>
<li>Prepare for 0.4.31 release by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/728">rust-lang/log#728</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Isvane"><code>@​Isvane</code></a> made
their first contribution in <a
href="https://redirect.github.com/rust-lang/log/pull/726">rust-lang/log#726</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rust-lang/log/compare/0.4.30...0.4.31">https://github.com/rust-lang/log/compare/0.4.30...0.4.31</a></p>
<h2>0.4.30</h2>
<h3>What's Changed</h3>
<ul>
<li>Support capturing of <code>std::net</code> types by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/724">rust-lang/log#724</a></li>
</ul>
<h3>New Contributors</h3>
<ul>
<li><a href="https://github.com/V0ldek"><code>@​V0ldek</code></a> made
their first contribution in <a
href="https://redirect.github.com/rust-lang/log/pull/720">rust-lang/log#720</a></li>
<li><a href="https://github.com/woodruffw"><code>@​woodruffw</code></a>
made their first contribution in <a
href="https://redirect.github.com/rust-lang/log/pull/723">rust-lang/log#723</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rust-lang/log/compare/0.4.29...0.4.30">https://github.com/rust-lang/log/compare/0.4.29...0.4.30</a></p>
<h3>Notable Changes</h3>
<ul>
<li>MSRV is bumped to 1.71.0 in <a
href="https://redirect.github.com/rust-lang/log/pull/723">rust-lang/log#723</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/log/blob/master/CHANGELOG.md">log's
changelog</a>.</em></p>
<blockquote>
<h2>[0.4.33] - 2026-06-20</h2>
<h2>What's Changed</h2>
<ul>
<li>Fixed key comparison by <a
href="https://github.com/matteo-zeggiotti-ok"><code>@​matteo-zeggiotti-ok</code></a>
in <a
href="https://redirect.github.com/rust-lang/log/pull/732">rust-lang/log#732</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/matteo-zeggiotti-ok"><code>@​matteo-zeggiotti-ok</code></a>
made their first contribution in <a
href="https://redirect.github.com/rust-lang/log/pull/732">rust-lang/log#732</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rust-lang/log/compare/0.4.32...0.4.33">https://github.com/rust-lang/log/compare/0.4.32...0.4.33</a></p>
<h2>[0.4.32] - 2026-06-04</h2>
<h3>What's Changed</h3>
<ul>
<li>Support <code>Value</code> -&gt; string conversions with
<code>kv</code> + <code>std</code> features instead of
<code>kv_std</code> by <a
href="https://github.com/tisonkun"><code>@​tisonkun</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/729">rust-lang/log#729</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rust-lang/log/compare/0.4.31...0.4.32">https://github.com/rust-lang/log/compare/0.4.31...0.4.32</a></p>
<h2>[0.4.31] - 2026-06-02</h2>
<h3>What's Changed</h3>
<ul>
<li>Leverage static str key when possible by <a
href="https://github.com/tisonkun"><code>@​tisonkun</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/727">rust-lang/log#727</a></li>
</ul>
<h3>New Contributors</h3>
<ul>
<li><a href="https://github.com/Isvane"><code>@​Isvane</code></a> made
their first contribution in <a
href="https://redirect.github.com/rust-lang/log/pull/726">rust-lang/log#726</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rust-lang/log/compare/0.4.30...0.4.31">https://github.com/rust-lang/log/compare/0.4.30...0.4.31</a></p>
<h2>[0.4.30] - 2026-05-21</h2>
<h3>What's Changed</h3>
<ul>
<li>Support capturing of <code>std::net</code> types by <a
href="https://github.com/KodrAus"><code>@​KodrAus</code></a> in <a
href="https://redirect.github.com/rust-lang/log/pull/724">rust-lang/log#724</a></li>
</ul>
<h3>New Contributors</h3>
<ul>
<li><a href="https://github.com/V0ldek"><code>@​V0ldek</code></a> made
their first contribution in <a
href="https://redirect.github.com/rust-lang/log/pull/720">rust-lang/log#720</a></li>
<li><a href="https://github.com/woodruffw"><code>@​woodruffw</code></a>
made their first contribution in <a
href="https://redirect.github.com/rust-lang/log/pull/723">rust-lang/log#723</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rust-lang/log/compare/0.4.29...0.4.30">https://github.com/rust-lang/log/compare/0.4.29...0.4.30</a></p>
<h3>Notable Changes</h3>
<ul>
<li>MSRV is bumped to 1.71.0 in <a
href="https://redirect.github.com/rust-lang/log/pull/723">rust-lang/log#723</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rust-lang/log/commit/f405739f3a15a3f00680c793e1e1fa7e57d26ba4"><code>f405739</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/734">#734</a>
from rust-lang/cargo/0.4.33</li>
<li><a
href="https://github.com/rust-lang/log/commit/6a24abf0835cef62e3d882287c97307dd3ecb403"><code>6a24abf</code></a>
prepare for 0.4.33 release</li>
<li><a
href="https://github.com/rust-lang/log/commit/87e062162e051d54bb553aacae3f0c6c4c213e59"><code>87e0621</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/732">#732</a>
from matteo-zeggiotti-ok/fix-key-comparison</li>
<li><a
href="https://github.com/rust-lang/log/commit/a9b57119a631249fc8e881c7ef78e2028aacb823"><code>a9b5711</code></a>
Review: fallback to the &amp;str hash</li>
<li><a
href="https://github.com/rust-lang/log/commit/cc89cc6e41190de36892e33fff48e5f48cf57fa9"><code>cc89cc6</code></a>
Review: fixed other comparisons</li>
<li><a
href="https://github.com/rust-lang/log/commit/920e7dc2811c18a228bf78e818196de950659d85"><code>920e7dc</code></a>
Review: fixed comparison on <code>MaybeStaticStr</code></li>
<li><a
href="https://github.com/rust-lang/log/commit/0d71d3c685f2e23b1ad209b48408efe1205b18b0"><code>0d71d3c</code></a>
Fixed key comparison</li>
<li><a
href="https://github.com/rust-lang/log/commit/a5b5b2113e2767801250af184d6c3971e689ae3b"><code>a5b5b21</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/730">#730</a>
from rust-lang/cargo/0.4.32</li>
<li><a
href="https://github.com/rust-lang/log/commit/c8d3b125c6216b3667e05544591f4fb34f53ff78"><code>c8d3b12</code></a>
prepare for 0.4.32 release</li>
<li><a
href="https://github.com/rust-lang/log/commit/ce6cd9fef14084207f2b6758999af062f89f9d87"><code>ce6cd9f</code></a>
Merge pull request <a
href="https://redirect.github.com/rust-lang/log/issues/729">#729</a>
from tisonkun/kv-std-support</li>
<li>Additional commits viewable in <a
href="https://github.com/rust-lang/log/compare/0.4.29...0.4.33">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=log&package-manager=cargo&previous-version=0.4.29&new-version=0.4.33)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:25:19 +00:00
dependabot[bot] 88cdfb3a43 build(deps): bump org.postgresql:postgresql from 42.7.11 to 42.7.13 (#7243)
Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from
42.7.11 to 42.7.13.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pgjdbc/pgjdbc/releases">org.postgresql:postgresql's
releases</a>.</em></p>
<blockquote>
<h2>v42.7.13</h2>
<h2>Changes</h2>
<ul>
<li>docs: add 42.7.13 release changelog <a
href="https://github.com/davecramer"><code>@​davecramer</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4270">#4270</a>)</li>
<li>Adjust EditorConfig für Makefile <a
href="https://github.com/BaumiCoder"><code>@​BaumiCoder</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4279">#4279</a>)</li>
<li>fix(scram): fail closed on channel-binding downgrade (no scram bump)
<a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4272">#4272</a>)</li>
<li>Bump pgjdbc version from 42.7.12 to 42.7.13 <a
href="https://github.com/davecramer"><code>@​davecramer</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4269">#4269</a>)</li>
<li>chore: remove test-anorm-sbt module and its disabled CI wiring <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4261">#4261</a>)</li>
<li>refactor(test-gss): convert to Java/JUnit 5 submodule of the main
build <a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4166">#4166</a>)</li>
<li>ci: derive PG test versions from a Renovate-managed maxPgVersion <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4218">#4218</a>)</li>
<li>feat(insert): cap reWriteBatchedInserts by the protocol limit, not
128 <a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4207">#4207</a>)</li>
<li>refactor(metadata): derive getPrimaryKeys from pg_constraint.conkey
<a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4202">#4202</a>)</li>
<li>fix(protocol): defer flushes until response processing <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4196">#4196</a>)</li>
<li>fix(build): resolve the Temurin 8 test toolchain by vendor <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4257">#4257</a>)</li>
<li>build: include multi-release source sets in the JaCoCo coverage
report <a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4256">#4256</a>)</li>
<li>fix(ci): read java_vendor before overwriting java_distribution <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4255">#4255</a>)</li>
<li>ci: generate the whole matrix in one batch, coverage job included <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4253">#4253</a>)</li>
<li>ci: pass CODECOV_TOKEN so protected-branch coverage uploads succeed
<a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4254">#4254</a>)</li>
<li>ci: collect coverage on one pinned job <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4245">#4245</a>)</li>
<li>ci: apply -DqueryTimeout from the matrix query_timeout axis <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4246">#4246</a>)</li>
<li>ci: make Codecov project and patch statuses informational <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4244">#4244</a>)</li>
<li>fix(build): restore JaCoCo XML report so Codecov receives coverage
<a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4240">#4240</a>)</li>
<li>test(replication): shrink big-transaction inserts to avoid CI
timeouts <a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4243">#4243</a>)</li>
<li>update maintainers <a
href="https://github.com/davecramer"><code>@​davecramer</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4222">#4222</a>)</li>
<li>test: add hermetic test for localSocketAddress <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4224">#4224</a>)</li>
<li>docs(translation): clean up leftover German header in ja.po <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4206">#4206</a>)</li>
<li>Update ja.po <a
href="https://github.com/davecramer"><code>@​davecramer</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/2004">#2004</a>)</li>
<li>test: add PostgreSQL 18 to the CI test matrix <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4198">#4198</a>)</li>
<li>test: silence expected SSPI warning stack trace in
SSPIClientWaffleTest <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4197">#4197</a>)</li>
<li>fix(ssl): build PKIX trust anchors without a KeyStore so FIPS-mode
JVMs can load sslrootcert <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4193">#4193</a>)</li>
<li>test: fix flaky sentLocationEqualToLastReceiveLSN replication test
<a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4175">#4175</a>)</li>
<li>build: promote MethodCanBeStatic to error level <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4172">#4172</a>)</li>
<li>Fix PGInterval.setSeconds to reject out of range and NaN values <a
href="https://github.com/sehrope"><code>@​sehrope</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4194">#4194</a>)</li>
<li>Replace connectThreadFactory with connectExecutor <a
href="https://github.com/sehrope"><code>@​sehrope</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4165">#4165</a>)</li>
<li>Fix deleting temp file when spooling large stream to disk in
StreamWrapper <a
href="https://github.com/sehrope"><code>@​sehrope</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4190">#4190</a>)</li>
<li>chore: Add top level /scratch to gitignore <a
href="https://github.com/sehrope"><code>@​sehrope</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4164">#4164</a>)</li>
<li>refactor: favour composition over inheritance for Driver.ConnectTask
<a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4160">#4160</a>)</li>
<li>Fix NumberParser.getFastLong(...) handling of overlong values <a
href="https://github.com/sehrope"><code>@​sehrope</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4163">#4163</a>)</li>
<li>build: produce a multi-release jar from reduced-pom.xml on Java 11+
<a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4157">#4157</a>)</li>
<li>Add connectThreadFactory and refactor Driver to use FutureTask for
loginTimeout connection attempts <a
href="https://github.com/sehrope"><code>@​sehrope</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4120">#4120</a>)</li>
<li>test: verify custom properties reach socket factory <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4125">#4125</a>)</li>
<li>test: fix LazyCleanerTest timeouts for the lingering Java 8 cleanup
thread <a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4122">#4122</a>)</li>
<li>test: stabilise StatementTest.fastCloses on Windows <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4121">#4121</a>)</li>
<li>fix: append default non-proxy hosts when socksNonProxyHosts is set
<a href="https://github.com/davecramer"><code>@​davecramer</code></a>
(<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4045">#4045</a>)</li>
<li>test: budget terminating Sync in BatchDeadlockTest small-RETURNING
branch <a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4116">#4116</a>)</li>
<li>test: make message assertions locale-independent <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4113">#4113</a>)</li>
<li>build: drop xgettext default keywords; regenerate translations <a
href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4100">#4100</a>)</li>
<li>ci: opt-in scheduled workflows via ENABLE_SCHEDULED_JOBS repo
variable <a href="https://github.com/vlsi"><code>@​vlsi</code></a> (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4085">#4085</a>)</li>
<li>Avoid direct java.lang.management dependency in maxResultBuffer
parser <a
href="https://github.com/mblakley-casana"><code>@​mblakley-casana</code></a>
(<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4069">#4069</a>)</li>
<li>fix: restore pre-describe for generated-key batches <a
href="https://github.com/bilalshehata"><code>@​bilalshehata</code></a>
(<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4014">#4014</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md">org.postgresql:postgresql's
changelog</a>.</em></p>
<blockquote>
<h2>[42.7.13] (2026-07-06)</h2>
<h3>Added</h3>
<ul>
<li>feat: invalidate the prepared-statement cache when the server
reports a <code>search_path</code> change via GUC_REPORT (PostgreSQL
18+), so cached plans are no longer used against the wrong schema [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4259">#4259</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4259">pgjdbc/pgjdbc#4259</a>)</li>
<li>feat: <code>reWriteBatchedInserts</code> now merges up to 32768 rows
into one multi-values <code>INSERT</code> (bounded by the 65535
bind-parameter limit on the extended protocol) instead of capping at
128, which speeds up batches of few-column rows. The new
<code>reWriteBatchedInsertsSize</code> connection property lowers that
cap when set; the default of <code>0</code> uses that maximum. [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4207">#4207</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4207">pgjdbc/pgjdbc#4207</a>)</li>
<li>feat: invalidate the prepared-statement cache after
CREATE/DROP/ALTER so callers no longer trip on &quot;cached plan must
not change result type&quot; without opting into
<code>autosave=ALWAYS</code>. Controlled by the new
<code>flushCacheOnDdl</code> connection property (default
<code>true</code>); set to <code>false</code> for the prior behaviour.
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4067">#4067</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4067">pgjdbc/pgjdbc#4067</a>)</li>
<li>feat: add <code>connectExecutor</code> connection property to
customize the <code>Executor</code> used to run the worker task that
performs the connection attempt when <code>loginTimeout</code> is in
effect. The value is the fully qualified name of a class implementing
<code>java.util.concurrent.Executor</code>. With a null value, the
default, the driver retains the prior behavior of running the connection
attempt on a daemon thread named <code>&quot;PostgreSQL JDBC driver
connection thread&quot;</code>. The executor must run the task on a
thread other than the caller's. Running the attempt on a named thread
lets applications that monitor driver-created threads identify it. [PR
<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4165">#4165</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4165">pgjdbc/pgjdbc#4165</a>)</li>
<li>feat: add <code>classLoaderStrategy</code> connection property to
control which classloaders the driver searches when loading a class
named by a connection property, for example <code>socketFactory</code>.
The default <code>driver-first</code> now falls back to the thread
context classloader when the driver's classloader cannot resolve the
class, which fixes class loading in non-flat class paths such as Quarkus
and OSGi. Set <code>driver</code> to keep the previous
driver-classloader-only behaviour, or <code>context-first</code> to
prefer the thread context classloader [Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/2112">#2112</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/2112">pgjdbc/pgjdbc#2112</a>)
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4167">#4167</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4167">pgjdbc/pgjdbc#4167</a>)</li>
<li>feat: add OID constants for geometric arrays, <code>RECORD</code>,
and <code>refcursor</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4220">#4220</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4220">pgjdbc/pgjdbc#4220</a>)</li>
<li>feat: <code>LargeObject</code> <code>BlobInputStream</code> now
skips by seeking instead of reading, and the driver exposes the server
version so it can select the 64-bit large-object API where available [PR
<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4204">#4204</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4204">pgjdbc/pgjdbc#4204</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>refactor: the worker that runs the connection attempt under
<code>loginTimeout</code> is now a <code>FutureTask</code>
(<code>ConnectTask</code>) instead of the hand-rolled
<code>ConnectThread</code>. When the caller hits the timeout, the task
is now cancelled with <code>cancel(true)</code>, which interrupts the
worker thread rather than letting it run to completion. This makes the
connection attempt interruptible, so <code>loginTimeout</code> can stop
a slow connection attempt instead of leaking a thread. As before, a
connection that the worker still manages to establish after the caller
gives up is closed by the worker so that it does not leak. There are no
public API changes and this should only lead to faster background
resource cleanup for connections that time out. [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4120">#4120</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4120">pgjdbc/pgjdbc#4120</a>)</li>
<li>chore: <code>PGXAConnection.ConnectionHandler</code> now rejects
<code>setAutoCommit(false)</code> and <code>setSavepoint(...)</code>
during an active XA branch, in addition to the long-rejected
<code>setAutoCommit(true)</code> / <code>commit()</code> /
<code>rollback()</code>. The <code>setSavepoint</code> rejection was
already meant to be in place but the guard misspelled the method name as
<code>setSavePoint</code>, so savepoints silently went through. Both
changes bring the proxy in line with JTA 1.2 §3.4. [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4114">#4114</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4114">pgjdbc/pgjdbc#4114</a>)</li>
<li>chore: <code>commitPrepared</code> /
<code>rollback</code>-of-prepared now return <code>XAER_RMFAIL</code>
instead of <code>XAER_RMERR</code> when the underlying connection is
left in a non-idle <code>TransactionState</code>. Transaction managers
(Geronimo, Narayana, Atomikos) treat <code>XAER_RMFAIL</code> as
retryable on a fresh <code>XAResource</code>; the prepared transaction
is no longer abandoned. [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4114">#4114</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4114">pgjdbc/pgjdbc#4114</a>)</li>
<li>refactor: derive <code>getPrimaryKeys</code> from
<code>pg_constraint.conkey</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4202">#4202</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4202">pgjdbc/pgjdbc#4202</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>fix: the published GitHub release now ships the released
<code>postgresql-&lt;version&gt;.jar</code> and its detached PGP
signature, taken from the same signed build that is uploaded to Maven
Central, instead of a leftover SNAPSHOT jar [Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3812">#3812</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3812">pgjdbc/pgjdbc#3812</a>)
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3814">#3814</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/3814">pgjdbc/pgjdbc#3814</a>)</li>
<li>fix: simplify the <code>Statement#cancel</code> state machine by
dropping the redundant <code>CANCELLED</code> state.
<code>killTimerTask</code> now waits for the state to return to
<code>IDLE</code> directly, which removes a spin-forever case when more
than one thread observes the cancel completing [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/1827">#1827</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/1827">pgjdbc/pgjdbc#1827</a>).</li>
<li>perf: defer simple-query flushes until the driver reads the
response, allowing <code>BEGIN</code> and the following query to share a
network flush [Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3894">#3894</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3894">pgjdbc/pgjdbc#3894</a>)
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4196">#4196</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4196">pgjdbc/pgjdbc#4196</a>)</li>
<li>fix: <code>reWriteBatchedInserts</code> no longer throws
<code>IllegalArgumentException</code> when batching a parameterless
<code>INSERT</code> (for example <code>INSERT INTO t VALUES (1,
2)</code>) of 256 rows or more [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4207">#4207</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4207">pgjdbc/pgjdbc#4207</a>)</li>
<li>fix: a comment before <code>CALL</code> in a
<code>CallableStatement</code> no longer hides the native call, so OUT
parameter registration works for <code>/* comment */ call proc(?,
?)</code> and similar. <code>Parser.modifyJdbcCall</code> now skips
leading whitespace and SQL comments (both <code>--</code> and <code>/*
*/</code>) before the call, tolerates a trailing comment after a <code>{
... }</code> escape, and no longer adds a spurious comma when moving an
OUT parameter into a call whose arguments are only a comment [Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/2538">#2538</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/2538">pgjdbc/pgjdbc#2538</a>)
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4209">#4209</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4209">pgjdbc/pgjdbc#4209</a>)</li>
<li>fix: <code>PreparedStatement.toString()</code> no longer throws for
a <code>bytea</code> value supplied as text via <code>PGobject</code>.
Hex-format values (<code>\x...</code>) are validated and rendered as a
<code>bytea</code> literal, and escape-format values are quoted and cast
like any other literal [Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3757">#3757</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3757">pgjdbc/pgjdbc#3757</a>)
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4201">#4201</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4201">pgjdbc/pgjdbc#4201</a>)</li>
<li>fix: the driver no longer nulls the <code>contextClassLoader</code>
of shared <code>ForkJoinPool.commonPool()</code> worker threads, which
previously left unrelated tasks on those threads running with a
<code>null</code> classloader [Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4155">#4155</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4155">pgjdbc/pgjdbc#4155</a>)
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4156">#4156</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4156">pgjdbc/pgjdbc#4156</a>)</li>
<li>fix: <code>PgResultSet#getCharacterStream</code> wraps
<code>String</code> in a <code>StringReader</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4063">#4063</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4063">pgjdbc/pgjdbc#4063</a>)</li>
<li>fix: <code>PGXAConnection</code> no longer saves and restores the
underlying connection's JDBC <code>autoCommit</code> flag. All
XA-protocol SQL (<code>BEGIN</code>, <code>PREPARE TRANSACTION</code>,
<code>COMMIT</code>, <code>ROLLBACK</code>, <code>COMMIT
PREPARED</code>, <code>ROLLBACK PREPARED</code>, the
<code>recover()</code> SELECT) is sent through
<code>QUERY_SUPPRESS_BEGIN</code>, so the caller's
<code>autoCommit</code> value is invariant across every
<code>XAResource</code> call. Fixes the &quot;2nd phase commit must be
issued using an idle connection&quot; failure during recovery on managed
datasources that pool connections with <code>autoCommit=false</code>
(TomEE, WildFly, WebSphere Liberty) [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4114">#4114</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4114">pgjdbc/pgjdbc#4114</a>)</li>
<li>fix: <code>PGXAConnection.prepare()</code> now mutates XA state only
after <code>PREPARE TRANSACTION</code> succeeds. A failed
<code>PREPARE</code> previously left the driver thinking the branch was
already prepared, so the follow-up <code>rollback(xid)</code> tried
<code>ROLLBACK PREPARED</code> against a non-existent gid and returned
<code>XAER_RMERR</code>. Transaction managers (Narayana) escalated this
to <code>HeuristicMixedException</code>. With the fix,
<code>rollback(xid)</code> takes the active-branch path and issues a
plain <code>ROLLBACK</code>, which the server accepts cleanly. Fixes
[Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3153">#3153</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3153">pgjdbc/pgjdbc#3153</a>),
[Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3123">#3123</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3123">pgjdbc/pgjdbc#3123</a>).
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4114">#4114</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4114">pgjdbc/pgjdbc#4114</a>)</li>
<li>fix: an updatable result set over an unqualified table name is now
classified using only the table visible through
<code>search_path</code>. When two schemas held a table with the same
name and the same primary or unique index name but a different set of
key columns, the driver took the union of both schemas' columns, so the
result set could be wrongly rejected as not updatable [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4214">#4214</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4214">pgjdbc/pgjdbc#4214</a>).
Supersedes [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3400">#3400</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/3400">pgjdbc/pgjdbc#3400</a>).</li>
<li>fix: <code>LargeObject.close()</code> now flushes a buffered output
stream before marking the object closed, so closing a large object
without an explicit <code>flush()</code> no longer drops buffered
writes. The flush runs while the object is still open (it calls back
into <code>LargeObject.write()</code>), and <code>lo_close</code> always
runs afterward; a failure from <code>lo_close</code> no longer masks an
earlier flush error, and the transaction is not committed when the flush
failed [Issue <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4247">#4247</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4247">pgjdbc/pgjdbc#4247</a>)
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4248">#4248</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4248">pgjdbc/pgjdbc#4248</a>).</li>
<li>fix: reject empty <code>timestamp</code>, <code>timestamptz</code>,
and <code>date</code> text with a clear <code>SQLException</code>
(SQLState <code>22007</code>) instead of an
<code>ArrayIndexOutOfBoundsException</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4278">#4278</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4278">pgjdbc/pgjdbc#4278</a>)</li>
<li>fix: return null <code>CHAR_OCTET_LENGTH</code> for non-character
columns [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4231">#4231</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4231">pgjdbc/pgjdbc#4231</a>)</li>
<li>fix: honor scale in <code>ResultSet.getBigDecimal(int, int)</code>
[PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4211">#4211</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4211">pgjdbc/pgjdbc#4211</a>)</li>
<li>fix: support <code>java.time</code> values in an updatable
<code>ResultSet</code> <code>updateRow()</code> /
<code>insertRow()</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3848">#3848</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/3848">pgjdbc/pgjdbc#3848</a>)</li>
<li>fix: improve batching when the <code>RETURNING</code> clause
contains <code>varchar</code> or <code>numeric</code> types [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4014">#4014</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4014">pgjdbc/pgjdbc#4014</a>)</li>
<li>fix: correct <code>estimatedReceiveBufferBytes</code> accounting
after a forced <code>Sync</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4014">#4014</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4014">pgjdbc/pgjdbc#4014</a>)</li>
<li>fix: avoid creating a transient <code>ResultSet</code> for
describe-statement purposes, and restore the pre-describe path for
generated-key batches [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4014">#4014</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4014">pgjdbc/pgjdbc#4014</a>)</li>
<li>fix: add an explicit failure message when a multi-statement command
executes in a batch [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4014">#4014</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4014">pgjdbc/pgjdbc#4014</a>)</li>
<li>fix: detect <code>search_path</code> changes case-insensitively [PR
<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4216">#4216</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4216">pgjdbc/pgjdbc#4216</a>)</li>
<li>fix: auto-detect the SSL key format instead of relying on the
<code>.key</code> extension [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/3946">#3946</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/3946">pgjdbc/pgjdbc#3946</a>)</li>
<li>fix: build PKIX trust anchors without a <code>KeyStore</code> so
FIPS JVMs work [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4193">#4193</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4193">pgjdbc/pgjdbc#4193</a>)</li>
<li>fix: use <code>gssResponseTimeout</code> rather than
<code>sslResponseTimeout</code> for GSS connections [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4076">#4076</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4076">pgjdbc/pgjdbc#4076</a>)</li>
<li>fix: skip the autosave savepoint for <code>SET LOCAL</code> /
<code>SET SESSION TRANSACTION</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4203">#4203</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4203">pgjdbc/pgjdbc#4203</a>)</li>
<li>fix: do not throw <code>AssertionError</code> from
<code>BatchResultHandler</code> on a closed connection [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4187">#4187</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4187">pgjdbc/pgjdbc#4187</a>)</li>
<li>fix: reject <code>SQL_TSI_FRAC_SECOND</code> with an explicit,
explained error [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4229">#4229</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4229">pgjdbc/pgjdbc#4229</a>)</li>
<li>fix: reject a null URL in <code>Driver.acceptsURL</code> with a
clear <code>NullPointerException</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4205">#4205</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4205">pgjdbc/pgjdbc#4205</a>)</li>
<li>fix: reject overlong inputs in <code>NumberParser.getFastLong</code>
instead of silently wrapping [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4163">#4163</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4163">pgjdbc/pgjdbc#4163</a>)</li>
<li>fix: reject out-of-range and NaN values in
<code>PGInterval.setSeconds</code> [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4194">#4194</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4194">pgjdbc/pgjdbc#4194</a>)</li>
<li>fix: close the socket when <code>PgConnection</code> setup fails
after connect [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4161">#4161</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4161">pgjdbc/pgjdbc#4161</a>)</li>
<li>fix: keep the <code>LazyCleanerImpl</code> cleanup task alive across
a transient empty queue [PR <a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4038">#4038</a>](<a
href="https://redirect.github.com/pgjdbc/pgjdbc/pull/4038">pgjdbc/pgjdbc#4038</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/3297557c6a8059d0d6e3522c79f0bd9a6f82ee07"><code>3297557</code></a>
docs: add 42.7.13 release changelog (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4270">#4270</a>)</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/d93d370984fbbccd099fc6466e4075ba46d8ec59"><code>d93d370</code></a>
style: apply Autostyle to docs/ and .github/</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/2e05ff9e3ea9e8249f25dcb7017984285f1f76b1"><code>2e05ff9</code></a>
build: check docs/ and .github/ formatting with Autostyle</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/b4a6087d2f07b578923a5272fa0155602ade9d40"><code>b4a6087</code></a>
Adjust EditorConfig für Makefiles</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/725cebbb4e13be777483bd916b19dfcd428b5f26"><code>725cebb</code></a>
fix(jdbc): reject empty timestamp/timestamptz text with a clear
error</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/23a1b0dac5a8fc633cc163e883eb21f0219ea521"><code>23a1b0d</code></a>
fix(scram): fail closed on channel-binding downgrade (no scram
bump)</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/0b4077a529b2448cc55a6ca87b2be8667243c9ab"><code>0b4077a</code></a>
Bump pgjdbc version from 42.7.12 to 42.7.13 (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4269">#4269</a>)</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/394800a38aebf54f9f293f6198e1fc5c8b19f10f"><code>394800a</code></a>
fix: flush LargeObject output stream before marking closed (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4248">#4248</a>)</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/83780f130e0c83a77bb67350603f3cca8d4b9bb2"><code>83780f1</code></a>
Maintain consistency with the use of the word maintainer vs comitter (<a
href="https://redirect.github.com/pgjdbc/pgjdbc/issues/4234">#4234</a>)</li>
<li><a
href="https://github.com/pgjdbc/pgjdbc/commit/d42cad5cd12a13197e68aa53f09a7721336dce7a"><code>d42cad5</code></a>
fix(jdbc): classify updatable result set by search_path visibility</li>
<li>Additional commits viewable in <a
href="https://github.com/pgjdbc/pgjdbc/compare/REL42.7.11...REL42.7.13">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.postgresql:postgresql&package-manager=gradle&previous-version=42.7.11&new-version=42.7.13)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 12:25:01 +00:00
James Brunton 4191d347ff Fix Java tests not running headless on Mac (#7260)
# Description of Changes
The `task backend:test` command automatically spawns new Java processes
in the dock on Mac as it runs, which takes the focus away from whatever
the developer is doing at the time. This is because there's missing a
missing `headless` tag in the `build.gradle` file (the tests don't spawn
or require any windows, so they run fine headless).

Also adds a `task backend:test:force` rule to run the tests without
cache because the cache was getting in the way of testing this.

<img width="175" height="98" alt="image"
src="https://github.com/user-attachments/assets/d4524959-9c25-4513-bf34-9fd48310c4d3"
/>
2026-08-03 11:11:13 +00:00
dependabot[bot] 6270fe6d67 build(deps): bump org.apache.pdfbox:jbig2-imageio from 3.0.4 to 3.0.5 (#7249)
Bumps org.apache.pdfbox:jbig2-imageio from 3.0.4 to 3.0.5.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.apache.pdfbox:jbig2-imageio&package-manager=gradle&previous-version=3.0.4&new-version=3.0.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 09:41:17 +00:00
dependabot[bot] 98bdacc706 build(deps): bump org.apache.pdfbox:jbig2-imageio from 3.0.4 to 3.0.5 in /app/core (#7253)
Bumps org.apache.pdfbox:jbig2-imageio from 3.0.4 to 3.0.5.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.apache.pdfbox:jbig2-imageio&package-manager=gradle&previous-version=3.0.4&new-version=3.0.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 09:40:57 +00:00
dependabot[bot]andAnthony Stirling 5bbe26072f build(deps): bump dompurify from 3.4.11 to 3.4.12 in /frontend (#7133)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.11 to
3.4.12.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cure53/DOMPurify/releases">dompurify's
releases</a>.</em></p>
<blockquote>
<h2>DOMPurify 3.4.12</h2>
<ul>
<li>Fixed an issue where a hook would not get called for custom
elements, thanks <a
href="https://github.com/Rikuxx0"><code>@​Rikuxx0</code></a></li>
<li>Hardened the handling of hooks removing elements, <a
href="https://github.com/mkrause-bee360"><code>@​mkrause-bee360</code></a></li>
<li>Added support for a few new SVG attributes, thanks <a
href="https://github.com/cbn-falias"><code>@​cbn-falias</code></a> &amp;
<a
href="https://github.com/Develop-KIM"><code>@​Develop-KIM</code></a></li>
<li>Hardened the handling of declarative partial updates</li>
<li>Updated the documentation is several spots, README, wiki, etc.</li>
<li>Bumped several dependencies where possible</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/cure53/DOMPurify/commit/a9ca1e537422319a557a9a2aa61f003b23b4a197"><code>a9ca1e5</code></a>
release: 3.4.12 (<a
href="https://redirect.github.com/cure53/DOMPurify/issues/1537">#1537</a>)</li>
<li>See full diff in <a
href="https://github.com/cure53/DOMPurify/compare/3.4.11...3.4.12">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dompurify&package-manager=npm_and_yarn&previous-version=3.4.11&new-version=3.4.12)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 23:55:27 +01:00
dependabot[bot] efc6b91648 build(deps): bump docker/login-action from 4.1.0 to 4.5.1 (#7241)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps [docker/login-action](https://github.com/docker/login-action) from
4.1.0 to 4.5.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/login-action/releases">docker/login-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.5.1</h2>
<ul>
<li>Support <code>dhi.io</code> as Docker Hub OIDC registry by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/login-action/pull/1054">docker/login-action#1054</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/login-action/compare/v4.5.0...v4.5.1">https://github.com/docker/login-action/compare/v4.5.0...v4.5.1</a></p>
<h2>v4.5.0</h2>
<ul>
<li><a href="https://github.com/docker/login-action#docker-hub">Docker
Hub OIDC</a> login support by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/login-action/pull/1048">docker/login-action#1048</a></li>
<li>Bump <code>@​aws-sdk/client-ecr</code> and
<code>@​aws-sdk/client-ecr-public</code> to 3.1091.0 in <a
href="https://redirect.github.com/docker/login-action/pull/1037">docker/login-action#1037</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.92.0 to 0.94.0 in
<a
href="https://redirect.github.com/docker/login-action/pull/1044">docker/login-action#1044</a>
<a
href="https://redirect.github.com/docker/login-action/pull/1050">docker/login-action#1050</a></li>
<li>Bump brace-expansion from 1.1.13 to 1.1.16 in <a
href="https://redirect.github.com/docker/login-action/pull/1046">docker/login-action#1046</a></li>
<li>Bump js-yaml from 5.2.0 to 5.2.1 in <a
href="https://redirect.github.com/docker/login-action/pull/1038">docker/login-action#1038</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/login-action/compare/v4.4.0...v4.5.0">https://github.com/docker/login-action/compare/v4.4.0...v4.5.0</a></p>
<h2>v4.4.0</h2>
<ul>
<li>Skip empty <code>registry-auth</code> secret mask by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/login-action/pull/1035">docker/login-action#1035</a></li>
<li>Bump <code>@​aws-sdk/client-ecr</code> and
<code>@​aws-sdk/client-ecr-public</code> to 3.1077.0 <a
href="https://redirect.github.com/docker/login-action/pull/1034">docker/login-action#1034</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/login-action/compare/v4.3.0...v4.4.0">https://github.com/docker/login-action/compare/v4.3.0...v4.4.0</a></p>
<h2>v4.3.0</h2>
<ul>
<li>Preserve names in esbuild bundle by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/login-action/pull/1022">docker/login-action#1022</a></li>
<li>Bump <code>@​aws-sdk/client-ecr</code> and
<code>@​aws-sdk/client-ecr-public</code> to 3.1076.0 <a
href="https://redirect.github.com/docker/login-action/pull/999">docker/login-action#999</a>
<a
href="https://redirect.github.com/docker/login-action/pull/1030">docker/login-action#1030</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.90.0 to 0.92.0 in
<a
href="https://redirect.github.com/docker/login-action/pull/1004">docker/login-action#1004</a>
<a
href="https://redirect.github.com/docker/login-action/pull/1027">docker/login-action#1027</a></li>
<li>Bump <code>@​sigstore/core</code> from 3.1.0 to 3.2.1 in <a
href="https://redirect.github.com/docker/login-action/pull/1023">docker/login-action#1023</a></li>
<li>Bump <code>@​sigstore/verify</code> from 3.1.0 to 3.1.1 in <a
href="https://redirect.github.com/docker/login-action/pull/1029">docker/login-action#1029</a></li>
<li>Bump http-proxy-agent and https-proxy-agent to 9.1.0 in <a
href="https://redirect.github.com/docker/login-action/pull/1017">docker/login-action#1017</a></li>
<li>Bump js-yaml from 4.1.1 to 5.2.0 in <a
href="https://redirect.github.com/docker/login-action/pull/1028">docker/login-action#1028</a></li>
<li>Bump sigstore from 4.1.0 to 4.1.1 in <a
href="https://redirect.github.com/docker/login-action/pull/1031">docker/login-action#1031</a></li>
<li>Bump tmp from 0.2.5 to 0.2.7 in <a
href="https://redirect.github.com/docker/login-action/pull/1002">docker/login-action#1002</a></li>
<li>Bump undici from 6.24.1 to 6.27.0 in <a
href="https://redirect.github.com/docker/login-action/pull/1020">docker/login-action#1020</a></li>
<li>Bump vite from 7.3.3 to 7.3.6 in <a
href="https://redirect.github.com/docker/login-action/pull/1019">docker/login-action#1019</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/login-action/compare/v4.2.0...v4.3.0">https://github.com/docker/login-action/compare/v4.2.0...v4.3.0</a></p>
<h2>v4.2.0</h2>
<ul>
<li>Bump <code>@​actions/core</code> from 3.0.0 to 3.0.1 in <a
href="https://redirect.github.com/docker/login-action/pull/976">docker/login-action#976</a></li>
<li>Bump <code>@​aws-sdk/client-ecr</code> and
<code>@​aws-sdk/client-ecr-public</code> to 3.1050.0 in <a
href="https://redirect.github.com/docker/login-action/pull/960">docker/login-action#960</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.86.0 to 0.90.0 in
<a
href="https://redirect.github.com/docker/login-action/pull/970">docker/login-action#970</a></li>
<li>Bump brace-expansion from 2.0.1 to 5.0.6 in <a
href="https://redirect.github.com/docker/login-action/pull/993">docker/login-action#993</a></li>
<li>Bump fast-xml-builder from 1.1.4 to 1.2.0 in <a
href="https://redirect.github.com/docker/login-action/pull/985">docker/login-action#985</a></li>
<li>Bump fast-xml-parser from 5.3.6 to 5.8.0 in <a
href="https://redirect.github.com/docker/login-action/pull/963">docker/login-action#963</a></li>
<li>Bump http-proxy-agent and https-proxy-agent to 9.0.0 in <a
href="https://redirect.github.com/docker/login-action/pull/961">docker/login-action#961</a></li>
<li>Bump postcss from 8.5.6 to 8.5.10 in <a
href="https://redirect.github.com/docker/login-action/pull/979">docker/login-action#979</a></li>
<li>Bump tar from 6.2.1 to 7.5.15 in <a
href="https://redirect.github.com/docker/login-action/pull/991">docker/login-action#991</a></li>
<li>Bump vite from 7.3.1 to 7.3.3 in <a
href="https://redirect.github.com/docker/login-action/pull/986">docker/login-action#986</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/login-action/compare/v4.1.0...v4.2.0">https://github.com/docker/login-action/compare/v4.1.0...v4.2.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/docker/login-action/commit/abd2ef45e78c5afb21d64d4ca52ee8550d9572c7"><code>abd2ef4</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1055">#1055</a>
from crazy-max/test-registry-auth-oidc</li>
<li><a
href="https://github.com/docker/login-action/commit/d49d3a9839fef51322fa44989a44fdc43fccfc22"><code>d49d3a9</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1054">#1054</a>
from crazy-max/oidc-missing-dhi</li>
<li><a
href="https://github.com/docker/login-action/commit/b58b17c30b4db92a4ed049b213cae512b12e460b"><code>b58b17c</code></a>
test: cover Docker Hub OIDC with registry-auth</li>
<li><a
href="https://github.com/docker/login-action/commit/be646c21cec26cea303e29290d5f6ba6fde8e606"><code>be646c2</code></a>
chore: update generated content</li>
<li><a
href="https://github.com/docker/login-action/commit/d77c059cb9956cedaa427dc022d89f39acba678f"><code>d77c059</code></a>
support dhi.io as Docker Hub OIDC registry</li>
<li><a
href="https://github.com/docker/login-action/commit/06fb636fac595d6fb4b28a5dfcb21a6f5091859c"><code>06fb636</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1037">#1037</a>
from docker/dependabot/npm_and_yarn/aws-sdk-dependen...</li>
<li><a
href="https://github.com/docker/login-action/commit/a8bc9539118a762b0e5788b53a50907977cc1b8d"><code>a8bc953</code></a>
[dependabot skip] chore: update generated content</li>
<li><a
href="https://github.com/docker/login-action/commit/f54b9019bf5074f6e3480a3ac4b834f5f4b90aab"><code>f54b901</code></a>
build(deps): bump the aws-sdk-dependencies group across 1 directory with
2 up...</li>
<li><a
href="https://github.com/docker/login-action/commit/77f18f6713512f90ac35aaf21db0d3710f1b85a6"><code>77f18f6</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1049">#1049</a>
from docker/dependabot/github_actions/codeql-actions...</li>
<li><a
href="https://github.com/docker/login-action/commit/ec0bf287fb1e2e051c56b2f6e6a3eed487b9fe52"><code>ec0bf28</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/login-action/issues/1050">#1050</a>
from docker/dependabot/npm_and_yarn/docker/actions-t...</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/login-action/compare/4907a6ddec9925e35a0a9e82d7399ccc52663121...abd2ef45e78c5afb21d64d4ca52ee8550d9572c7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/login-action&package-manager=github_actions&previous-version=4.1.0&new-version=4.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 23:42:34 +01:00
dependabot[bot] 0661f90267 build(deps): bump docker/setup-buildx-action from 4.0.0 to 4.2.0 (#7239)
Bumps
[docker/setup-buildx-action](https://github.com/docker/setup-buildx-action)
from 4.0.0 to 4.2.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/setup-buildx-action/releases">docker/setup-buildx-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.2.0</h2>
<ul>
<li>Preserve names in esbuild bundle by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/572">docker/setup-buildx-action#572</a></li>
<li>Bump <code>@​actions/core</code> from 3.0.0 to 3.0.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/551">docker/setup-buildx-action#551</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.90.0 to 0.92.0 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/557">docker/setup-buildx-action#557</a>
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/580">docker/setup-buildx-action#580</a></li>
<li>Bump <code>@​sigstore/core</code> from 3.1.0 to 3.2.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/573">docker/setup-buildx-action#573</a></li>
<li>Bump <code>@​sigstore/verify</code> from 3.1.0 to 3.1.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/576">docker/setup-buildx-action#576</a></li>
<li>Bump js-yaml from 4.1.1 to 5.2.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/562">docker/setup-buildx-action#562</a></li>
<li>Bump sigstore from 4.1.0 to 4.1.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/577">docker/setup-buildx-action#577</a></li>
<li>Bump tmp from 0.2.5 to 0.2.7 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/556">docker/setup-buildx-action#556</a></li>
<li>Bump undici from 6.25.0 to 6.27.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/570">docker/setup-buildx-action#570</a></li>
<li>Bump vite from 7.3.2 to 7.3.6 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/569">docker/setup-buildx-action#569</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v4.1.0...v4.2.0">https://github.com/docker/setup-buildx-action/compare/v4.1.0...v4.2.0</a></p>
<h2>v4.1.0</h2>
<ul>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.79.0 to 0.90.0 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/489">docker/setup-buildx-action#489</a></li>
<li>Bump brace-expansion from 1.1.12 to 5.0.6 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/547">docker/setup-buildx-action#547</a>
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/508">docker/setup-buildx-action#508</a></li>
<li>Bump fast-xml-builder from 1.0.0 to 1.2.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/540">docker/setup-buildx-action#540</a></li>
<li>Bump fast-xml-parser from 5.4.2 to 5.8.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/496">docker/setup-buildx-action#496</a></li>
<li>Bump flatted from 3.3.3 to 3.4.2 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/499">docker/setup-buildx-action#499</a></li>
<li>Bump glob from 10.3.12 to 13.0.6 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/495">docker/setup-buildx-action#495</a></li>
<li>Bump handlebars from 4.7.8 to 4.7.9 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/504">docker/setup-buildx-action#504</a></li>
<li>Bump lodash from 4.17.23 to 4.18.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/523">docker/setup-buildx-action#523</a></li>
<li>Bump picomatch from 4.0.3 to 4.0.4 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/503">docker/setup-buildx-action#503</a></li>
<li>Bump postcss from 8.5.6 to 8.5.10 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/537">docker/setup-buildx-action#537</a></li>
<li>Bump tar from 6.2.1 to 7.5.15 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/545">docker/setup-buildx-action#545</a></li>
<li>Bump undici from 6.23.0 to 6.25.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/492">docker/setup-buildx-action#492</a></li>
<li>Bump vite from 7.3.1 to 7.3.2 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/520">docker/setup-buildx-action#520</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v4.0.0...v4.1.0">https://github.com/docker/setup-buildx-action/compare/v4.0.0...v4.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/bb05f3f5519dd87d3ba754cc423b652a5edd6d2c"><code>bb05f3f</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/580">#580</a>
from docker/dependabot/npm_and_yarn/docker/actions-to...</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/321c814cb51fbe4af8eca00249525cc0973ea66f"><code>321c814</code></a>
[dependabot skip] chore: update generated content</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/b9a36ef79ba42cfc611885a1e8c388fbf8b8cb3f"><code>b9a36ef</code></a>
build(deps): bump <code>@​docker/actions-toolkit</code> from 0.91.0 to
0.92.0</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/ebeab241289497cd564ac98b3cfc9e64607bb276"><code>ebeab24</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/570">#570</a>
from docker/dependabot/npm_and_yarn/undici-6.27.0</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/5c7b8ae78cec97a3215d4d86679b1d072eaa80cb"><code>5c7b8ae</code></a>
[dependabot skip] chore: update generated content</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/037e618cd98e95e81525b15ff0e9c96f507e6a0e"><code>037e618</code></a>
build(deps): bump undici from 6.25.0 to 6.27.0</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/66080e5802281ec2e72b7f3108915643e702db85"><code>66080e5</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/577">#577</a>
from docker/dependabot/npm_and_yarn/sigstore-4.1.1</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/409aef0aa3f48f0a742e7dec4e0e04ab19afe93c"><code>409aef0</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/562">#562</a>
from docker/dependabot/npm_and_yarn/js-yaml-4.2.0</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/49c6e42949280fa0d70fb327633591be54efbfb6"><code>49c6e42</code></a>
build(deps): bump sigstore from 4.1.0 to 4.1.1</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/2211273e8121ecf9ecb7d6c7c0fcd55526d530c7"><code>2211273</code></a>
[dependabot skip] chore: update generated content</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/setup-buildx-action/compare/4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd...bb05f3f5519dd87d3ba754cc423b652a5edd6d2c">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=docker/setup-buildx-action&package-manager=github_actions&previous-version=4.0.0&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 23:41:14 +01:00
dependabot[bot] 02a7db0f1e build(deps): bump pdfboxVersion from 3.0.7 to 3.0.8 (#7237)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps `pdfboxVersion` from 3.0.7 to 3.0.8.
Updates `org.apache.pdfbox:preflight` from 3.0.7 to 3.0.8

Updates `org.apache.pdfbox:xmpbox` from 3.0.7 to 3.0.8

Updates `org.apache.pdfbox:pdfbox` from 3.0.7 to 3.0.8

Updates `org.apache.pdfbox:pdfbox-io` from 3.0.7 to 3.0.8


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 23:40:47 +01:00
dependabot[bot]andAnthony Stirling 2533baaeb3 build(deps): bump rand from 0.9.2 to 0.10.2 in /frontend/editor/src-tauri (#7065)
Bumps [rand](https://github.com/rust-random/rand) from 0.9.2 to 0.10.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-random/rand/blob/master/CHANGELOG.md">rand's
changelog</a>.</em></p>
<blockquote>
<h2>[0.10.2] — 2026-07-02</h2>
<h3>Fixes</h3>
<ul>
<li>Fix possible memory safety violation due to deserialization of
<code>UniformChar</code> from bad source (<a
href="https://redirect.github.com/rust-random/rand/issues/1790">#1790</a>)</li>
</ul>
<h3>Changes</h3>
<ul>
<li>Document required output order of fn <code>partial_shuffle</code>
and apply <code>#[must_use]</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1769">#1769</a>)</li>
<li>Avoid usage of <code>unsafe</code> in contexts where non-local
memory corruption could invalidate contract (<a
href="https://redirect.github.com/rust-random/rand/issues/1791">#1791</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/rust-random/rand/issues/1769">#1769</a>:
<a
href="https://redirect.github.com/rust-random/rand/pull/1769">rust-random/rand#1769</a>
<a
href="https://redirect.github.com/rust-random/rand/issues/1790">#1790</a>:
<a
href="https://redirect.github.com/rust-random/rand/pull/1790">rust-random/rand#1790</a>
<a
href="https://redirect.github.com/rust-random/rand/issues/1791">#1791</a>:
<a
href="https://redirect.github.com/rust-random/rand/pull/1791">rust-random/rand#1791</a></p>
<h2>[0.10.1] — 2026-02-11</h2>
<p>This release includes a fix for a soundness bug; see <a
href="https://redirect.github.com/rust-random/rand/issues/1763">#1763</a>.</p>
<h3>Changes</h3>
<ul>
<li>Document panic behavior of <code>make_rng</code> and add
<code>#[track_caller]</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1761">#1761</a>)</li>
<li>Deprecate feature <code>log</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1763">#1763</a>)</li>
</ul>
<p><a
href="https://redirect.github.com/rust-random/rand/issues/1761">#1761</a>:
<a
href="https://redirect.github.com/rust-random/rand/pull/1761">rust-random/rand#1761</a>
<a
href="https://redirect.github.com/rust-random/rand/issues/1763">#1763</a>:
<a
href="https://redirect.github.com/rust-random/rand/pull/1763">rust-random/rand#1763</a></p>
<h2>[0.10.0] - 2026-02-08</h2>
<h3>Changes</h3>
<ul>
<li>The dependency on <code>rand_chacha</code> has been replaced with a
dependency on <code>chacha20</code>. This changes the implementation
behind <code>StdRng</code>, but the output remains the same. There may
be some API breakage when using the ChaCha-types directly as these are
now the ones in <code>chacha20</code> instead of
<code>rand_chacha</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1642">#1642</a>).</li>
<li>Rename fns <code>IndexedRandom::choose_multiple</code> -&gt;
<code>sample</code>, <code>choose_multiple_array</code> -&gt;
<code>sample_array</code>, <code>choose_multiple_weighted</code> -&gt;
<code>sample_weighted</code>, struct <code>SliceChooseIter</code> -&gt;
<code>IndexedSamples</code> and fns
<code>IteratorRandom::choose_multiple</code> -&gt; <code>sample</code>,
<code>choose_multiple_fill</code> -&gt; <code>sample_fill</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1632">#1632</a>)</li>
<li>Use Edition 2024 and MSRV 1.85 (<a
href="https://redirect.github.com/rust-random/rand/issues/1653">#1653</a>)</li>
<li>Let <code>Fill</code> be implemented for element types, not
sliceable types (<a
href="https://redirect.github.com/rust-random/rand/issues/1652">#1652</a>)</li>
<li>Fix <code>OsError::raw_os_error</code> on UEFI targets by returning
<code>Option&lt;usize&gt;</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1665">#1665</a>)</li>
<li>Replace fn <code>TryRngCore::read_adapter(..) -&gt;
RngReadAdapter</code> with simpler struct <code>RngReader</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1669">#1669</a>)</li>
<li>Remove fns <code>SeedableRng::from_os_rng</code>,
<code>try_from_os_rng</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1674">#1674</a>)</li>
<li>Remove <code>Clone</code> support for <code>StdRng</code>,
<code>ReseedingRng</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1677">#1677</a>)</li>
<li>Use <code>postcard</code> instead of <code>bincode</code> to test
the serde feature (<a
href="https://redirect.github.com/rust-random/rand/issues/1693">#1693</a>)</li>
<li>Avoid excessive allocation in <code>IteratorRandom::sample</code>
when <code>amount</code> is much larger than iterator size (<a
href="https://redirect.github.com/rust-random/rand/issues/1695">#1695</a>)</li>
<li>Rename <code>os_rng</code> -&gt; <code>sys_rng</code>,
<code>OsRng</code> -&gt; <code>SysRng</code>, <code>OsError</code> -&gt;
<code>SysError</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1697">#1697</a>)</li>
<li>Rename <code>Rng</code> -&gt; <code>RngExt</code> as upstream
<code>rand_core</code> has renamed <code>RngCore</code> -&gt;
<code>Rng</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1717">#1717</a>)</li>
</ul>
<h3>Additions</h3>
<ul>
<li>Add fns <code>IndexedRandom::choose_iter</code>,
<code>choose_weighted_iter</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1632">#1632</a>)</li>
<li>Pub export <code>Xoshiro128PlusPlus</code>,
<code>Xoshiro256PlusPlus</code> prngs (<a
href="https://redirect.github.com/rust-random/rand/issues/1649">#1649</a>)</li>
<li>Pub export <code>ChaCha8Rng</code>, <code>ChaCha12Rng</code>,
<code>ChaCha20Rng</code> behind <code>chacha</code> feature (<a
href="https://redirect.github.com/rust-random/rand/issues/1659">#1659</a>)</li>
<li>Fn <code>rand::make_rng() -&gt; R where R: SeedableRng</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1734">#1734</a>)</li>
</ul>
<h3>Removals</h3>
<ul>
<li>Removed <code>ReseedingRng</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1722">#1722</a>)</li>
<li>Removed unused feature &quot;nightly&quot; (<a
href="https://redirect.github.com/rust-random/rand/issues/1732">#1732</a>)</li>
<li>Removed feature <code>small_rng</code> (<a
href="https://redirect.github.com/rust-random/rand/issues/1732">#1732</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rust-random/rand/commit/1540ea327e8beaf0694ea64f6d9eb8eaadd47bd5"><code>1540ea3</code></a>
Prepare rand 0.10.2 (<a
href="https://redirect.github.com/rust-random/rand/issues/1800">#1800</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/a29964ad94b54c25b3865626de6964ce0f796a29"><code>a29964a</code></a>
Bump chacha20 from 0.10.0 to 0.10.1 in the all-deps group (<a
href="https://redirect.github.com/rust-random/rand/issues/1801">#1801</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/ced94914cb75c93a1f19140a966a466345185fff"><code>ced9491</code></a>
Tweak docs for RngExt::random_range and SampleRange (<a
href="https://redirect.github.com/rust-random/rand/issues/1798">#1798</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/db146647afaf002b866420d34e4501b0dd872163"><code>db14664</code></a>
Check UniformChar validity on deser (<a
href="https://redirect.github.com/rust-random/rand/issues/1790">#1790</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/bea8620204c7aeecdefc132b5cb0dec8134add4b"><code>bea8620</code></a>
Bump the all-deps group with 2 updates (<a
href="https://redirect.github.com/rust-random/rand/issues/1796">#1796</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/4f449322825498e4ec1f486119e5fd251ba97f8a"><code>4f44932</code></a>
Bump actions/cache from 5 to 6 (<a
href="https://redirect.github.com/rust-random/rand/issues/1795">#1795</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/b999a130a990b30af01743021e8ea97f3b09a17e"><code>b999a13</code></a>
Bump actions/checkout from 6 to 7 (<a
href="https://redirect.github.com/rust-random/rand/issues/1794">#1794</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/aeab810bd9704a3b7666ba0a78e1ad5d1d5ad1ae"><code>aeab810</code></a>
Avoid unsafe where safety depends on non-local values (<a
href="https://redirect.github.com/rust-random/rand/issues/1791">#1791</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/1896d7c660524a022b3dbc3a1e044e162d766b25"><code>1896d7c</code></a>
Add typos CI job (<a
href="https://redirect.github.com/rust-random/rand/issues/1789">#1789</a>)</li>
<li><a
href="https://github.com/rust-random/rand/commit/43eddee18c8cca2cebee929be3899cf183afe801"><code>43eddee</code></a>
Bump the all-deps group with 2 updates (<a
href="https://redirect.github.com/rust-random/rand/issues/1788">#1788</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/rust-random/rand/compare/rand_core-0.9.2...0.10.2">compare
view</a></li>
</ul>
</details>
<br />

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 23:40:30 +01:00
dependabot[bot]andAnthony Stirling ced8e5e52c build(deps): bump eclipse-temurin from b27ca47 to f9bd881 in /docker/embedded (#6556)
Bumps eclipse-temurin from `b27ca47` to `f9bd881`.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=eclipse-temurin&package-manager=docker&previous-version=25-jre-alpine&new-version=25-jre-alpine)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

You can trigger a rebase of this PR by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 23:39:36 +01:00
dependabot[bot]andAnthony Stirling e4c9b0410c build(deps): bump org.verapdf:validation-model from 1.28.2 to 1.30.2 in /app/core (#6836)
Bumps
[org.verapdf:validation-model](https://github.com/veraPDF/veraPDF-validation)
from 1.28.2 to 1.30.2.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/94caa46c1a594512247fbd46c808edae39469542"><code>94caa46</code></a>
Improve security of the DocumentBuilder</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/ae243fc06775ef79495accd2165e5262e31dcf67"><code>ae243fc</code></a>
Fix typo</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/f89130de3b97f19ef4030e5fc84345c4463cd867"><code>f89130d</code></a>
Fix getAlt in GFPDAnnot</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/11ad0c577853a658d11370277196c12e34b5fd81"><code>11ad0c5</code></a>
Proposed SECURITY.md file for veraPDF projects</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/59f9cd4c97799dd87d738ce847c066530bcf2ed1"><code>59f9cd4</code></a>
Use non static isCircularMappingExist</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/7494455aa44fd322fa7bd900456a3cb8f0602f18"><code>7494455</code></a>
REL - v1.30</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/ecd191d3d796dfdfa13970a114920530627a25bb"><code>ecd191d</code></a>
Fix glyph name detection for symbolic TrueType font</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/32e21ce19a478a4e8e47c4a090674cbb2cb58026"><code>32e21ce</code></a>
Update fixRevProperty method (<a
href="https://redirect.github.com/veraPDF/veraPDF-validation/issues/726">#726</a>)</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/ddfee10116d45cc37750a988ff4385dad0c8510a"><code>ddfee10</code></a>
PDF/UA. Fix Table validation</li>
<li><a
href="https://github.com/veraPDF/veraPDF-validation/commit/22ea95799bb98b50a2063c542de50de4aeb4ce9e"><code>22ea957</code></a>
RC - v1.30</li>
<li>Additional commits viewable in <a
href="https://github.com/veraPDF/veraPDF-validation/compare/v1.28.2...v1.30.2">compare
view</a></li>
</ul>
</details>
<br />


> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 23:39:20 +01:00
dependabot[bot] 53086a12c2 build(deps): bump serde_with from 3.17.0 to 3.21.0 in /frontend/editor/src-tauri (#7053)
Bumps [serde_with](https://github.com/jonasbb/serde_with) from 3.17.0 to
3.21.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jonasbb/serde_with/releases">serde_with's
releases</a>.</em></p>
<blockquote>
<h2>serde_with v3.21.0</h2>
<h3>Security</h3>
<ul>
<li>
<p><a
href="https://github.com/jonasbb/serde_with/security/advisories/GHSA-7gcf-g7xr-8hxj">GHSA-7gcf-g7xr-8hxj</a>:
KeyValueMap serialization panics on empty sequence or map entries
Bad or attacker controlled values could cause a panic while allocating
too large values.
Fixed in <a
href="https://redirect.github.com/jonasbb/serde_with/issues/966">#966</a>
by setting a maximum allocation size during the creation of collections
like <code>Vec</code> or sets.</p>
<p>Thanks to <a
href="https://github.com/7thParkk"><code>@​7thParkk</code></a> for
reporting the issue.</p>
</li>
</ul>
<h3>Added</h3>
<ul>
<li>Add <code>NoneAsZero</code> adapter that maps
<code>Option&lt;NonZero*&gt;</code> to a plain integer, encoding
<code>None</code> as <code>0</code> by <a
href="https://github.com/SAY-5"><code>@​SAY-5</code></a> (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/486">#486</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Re-enable link-to-definition on docs.rs (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/964">#964</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Fix some doc links to point to the correct types (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/963">#963</a>)</li>
<li>Re-enable <code>unused_qualifications</code> and fix the resulting
findings by <a
href="https://github.com/lms0806"><code>@​lms0806</code></a> (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/962">#962</a>)</li>
</ul>
<h2>serde_with v3.20.0</h2>
<h3>Added</h3>
<ul>
<li>Add support for <code>base58</code> encoding, similar to the
existing <code>base64</code> setup by <a
href="https://github.com/mitinarseny"><code>@​mitinarseny</code></a> (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/943">#943</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Extend <code>base64</code> with <code>schemars</code> support by <a
href="https://github.com/mitinarseny"><code>@​mitinarseny</code></a> (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/9949">#9949</a>)</li>
</ul>
<h2>serde_with v3.19.0</h2>
<h3>Added</h3>
<ul>
<li>
<p>Add support for <code>hashbrown</code> v0.17 (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/940">#940</a>)</p>
<p>This extends the existing support for <code>hashbrown</code> to the
newly released version.</p>
</li>
</ul>
<h2>serde_with v3.18.0</h2>
<h3>Added</h3>
<ul>
<li>Support <code>OneOrMany</code> with more sequence and set types (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/929">#929</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Bump MSRV to 1.88 due to the <code>darling</code> dependency</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jonasbb/serde_with/commit/0f4ca67e1f8fc4679e850f3a566d454fb30953c1"><code>0f4ca67</code></a>
Update changelog for 3.21.0 (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/967">#967</a>)</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/7654841be1d1702a65afc0f839c67c36563c8188"><code>7654841</code></a>
Update changelog for 3.21.0</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/c8a1d820ea25df01692b367058d587343e199389"><code>c8a1d82</code></a>
Protect all collection creations against capacity overflow by using
`size_hin...</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/6ad5fa5b474270f50016b4cc983e37f25f097ba4"><code>6ad5fa5</code></a>
Properly feature gate the <code>vec_with_capacity_cautious</code>
function</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/ef7d1417e3eacd0077f029763109368ee05c1c22"><code>ef7d141</code></a>
Protect all collection creations against capacity overflow by using
`size_hin...</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/a348da35fe808852a1b7e6fa890b425ad001d3f1"><code>a348da3</code></a>
Add serde_as deserialize_as explain (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/958">#958</a>)</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/2e5bc20e29e1d42eb9c85ab503964130eb1ea62e"><code>2e5bc20</code></a>
Bump the github-actions group with 3 updates (<a
href="https://redirect.github.com/jonasbb/serde_with/issues/965">#965</a>)</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/927a3d69c3cecdf415f7d7662a0521894d313261"><code>927a3d6</code></a>
Bump the github-actions group with 3 updates</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/62d14ec637834259e0fab59ea84b87ca329e81c1"><code>62d14ec</code></a>
Enable link-to-definition on docs.rs again, after the upstream issue was
reso...</li>
<li><a
href="https://github.com/jonasbb/serde_with/commit/4584d94f685b66b96bdcf07bffe76e5df0819ea2"><code>4584d94</code></a>
Enable link-to-definition on docs.rs again, after the upstream issue was
reso...</li>
<li>Additional commits viewable in <a
href="https://github.com/jonasbb/serde_with/compare/v3.17.0...v3.21.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 22:42:31 +01:00
dependabot[bot]andAnthony Stirling 4d6c8341c8 build(deps): bump quinn-proto from 0.11.14 to 0.11.16 in /frontend/editor/src-tauri (#7179)
Bumps [quinn-proto](https://github.com/quinn-rs/quinn) from 0.11.14 to
0.11.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/quinn-rs/quinn/releases">quinn-proto's
releases</a>.</em></p>
<blockquote>
<h2>quinn-proto-0.11.16</h2>
<h2>What's Changed</h2>
<ul>
<li>0.11.x: upgrade dependencies by <a
href="https://github.com/djc"><code>@​djc</code></a> in <a
href="https://redirect.github.com/quinn-rs/quinn/pull/2707">quinn-rs/quinn#2707</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/quinn-rs/quinn/commit/a96949f6cd257c665f544626af4e8ce668a40b30"><code>a96949f</code></a>
Take semver-compatible update for anyhow</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/5429f60d0ee9971770e60f0407d992d3b912d274"><code>5429f60</code></a>
udp: bump version to 0.5.15</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/262a493629acdc979070cd36d801464a2b8dd3e2"><code>262a493</code></a>
proto: bump version to 0.11.16</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/c19b63a04c6eff60684a845fce29fee6d74b1acd"><code>c19b63a</code></a>
Upgrade rustls-platform-verifier to 0.7</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/aff3652c43be3491908ef553fac16610c9ad3e6a"><code>aff3652</code></a>
Disable default features for fastbloom</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/01b2eee2c68b1d73ad09485b440fbfa8f6d3e290"><code>01b2eee</code></a>
Upgrade fastbloom to 0.17</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/2c82013a8cd502f3dd0bba0a4c38a51e564d29cc"><code>2c82013</code></a>
Switch BBR RNG to PCG</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/544dd9ebabf18639cb2041f849ea406100dd3d6d"><code>544dd9e</code></a>
Upgrade to rand 0.10.1</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/a7499b8439e393a6299330111d9c8564cd96c464"><code>a7499b8</code></a>
Bump versions for release</li>
<li><a
href="https://github.com/quinn-rs/quinn/commit/7c1970f19b24280af86b1a0a1c2d06d59fc453f0"><code>7c1970f</code></a>
proto: yield error on too many gaps in assembler</li>
<li>Additional commits viewable in <a
href="https://github.com/quinn-rs/quinn/compare/quinn-proto-0.11.14...quinn-proto-0.11.16">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=quinn-proto&package-manager=cargo&previous-version=0.11.14&new-version=0.11.16)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 22:42:14 +01:00
dependabot[bot]andAnthony Stirling 113a5c7372 build(deps): bump the serde group across 2 directories with 2 updates (#7182)
Bumps the serde group with 2 updates in the /frontend/editor/src-tauri
directory: [serde_json](https://github.com/serde-rs/json) and
[serde](https://github.com/serde-rs/serde).
Bumps the serde group with 2 updates in the
/frontend/editor/src-tauri/provisioner directory:
[serde_json](https://github.com/serde-rs/json) and
[serde](https://github.com/serde-rs/serde).

Updates `serde_json` from 1.0.149 to 1.0.151
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/json/releases">serde_json's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.151</h2>
<ul>
<li>Add RawValue::from_string_unchecked (<a
href="https://redirect.github.com/serde-rs/json/issues/1331">#1331</a>,
thanks <a
href="https://github.com/WonderLawrence"><code>@​WonderLawrence</code></a>)</li>
</ul>
<h2>v1.0.150</h2>
<ul>
<li>Reject non-string enum object keys (<a
href="https://redirect.github.com/serde-rs/json/issues/1324">#1324</a>,
thanks <a
href="https://github.com/puneetdixit200"><code>@​puneetdixit200</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/serde-rs/json/commit/de8500740cdcabffb9734f503e4889def823cf10"><code>de85007</code></a>
Release 1.0.151</li>
<li><a
href="https://github.com/serde-rs/json/commit/3b2b3c5f28c20ed988bd081a4147c535e7e65c74"><code>3b2b3c5</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1331">#1331</a>
from WonderLawrence/rawvalue-from-string-unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/0406d96860e9d8b9252e2002fa3e626ae48ca1b0"><code>0406d96</code></a>
Debug-assert well-formedness and no-whitespace in
from_string_unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/cf16f75d81e28c723323bfc60a68fc02d2994fff"><code>cf16f75</code></a>
Add RawValue::from_string_unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/827a315bf2198558f0325b07bcc1e2cd973aba2f"><code>827a315</code></a>
Update actions/upload-artifact@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/json/commit/cea36a5c017ebffdeb95d0cd0f1aad473bfab758"><code>cea36a5</code></a>
Update actions/checkout@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/json/commit/a1ae73ac6a6940a4a57c673aebaa13ed4dfe3e8c"><code>a1ae73a</code></a>
Release 1.0.150</li>
<li><a
href="https://github.com/serde-rs/json/commit/1a360b0a6c003912afc3503c834b0edd798bca28"><code>1a360b0</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1324">#1324</a>
from puneetdixit200/reject-non-string-enum-keys</li>
<li><a
href="https://github.com/serde-rs/json/commit/2037b634f9dccbddc11cff189ebeb5854fa0e01c"><code>2037b63</code></a>
Reject non-string enum object keys</li>
<li><a
href="https://github.com/serde-rs/json/commit/5d30df60e916e9b8fc46c74794007ff271fdfbbf"><code>5d30df6</code></a>
Resolve manual_assert_eq pedantic clippy lint</li>
<li>Additional commits viewable in <a
href="https://github.com/serde-rs/json/compare/v1.0.149...v1.0.151">compare
view</a></li>
</ul>
</details>
<br />

Updates `serde` from 1.0.228 to 1.0.229
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/serde/releases">serde's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.229</h2>
<ul>
<li>Update to syn 3</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/serde-rs/serde/commit/7fc3b4c30c94f73a96ebd1553f2b090d928fc3a8"><code>7fc3b4c</code></a>
Release 1.0.229</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6d6e9a11101354ce769a3438a088b6b9305c1863"><code>6d6e9a1</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/serde/issues/3085">#3085</a>
from dtolnay/syn3</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6dec3b751126c8338cac0fe8085612d695e4ecf3"><code>6dec3b7</code></a>
Update to syn 3</li>
<li><a
href="https://github.com/serde-rs/serde/commit/cfe669241065984177ff63af8b45058e6e9b499d"><code>cfe6692</code></a>
Resolve mut_mut pedantic clippy lint</li>
<li><a
href="https://github.com/serde-rs/serde/commit/1023d077510b4aef36a41ef56fdb7798568a2654"><code>1023d07</code></a>
Update actions/upload-artifact@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/serde/commit/dd682c2c86aa7629e77c1ccd93212d3729f4c66d"><code>dd682c2</code></a>
Update actions/checkout@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/serde/commit/5f0f18b9211732f2d82f73b5a43e4f5ff3701251"><code>5f0f18b</code></a>
Update ui test suite to nightly-2026-06-01</li>
<li><a
href="https://github.com/serde-rs/serde/commit/63a1498f0e7be991ffac5939bdd202ca16e9a23f"><code>63a1498</code></a>
Regenerate stderr with trybuild normalization fixes</li>
<li><a
href="https://github.com/serde-rs/serde/commit/fa7da4a93567ed347ad0735c28e439fca688ef26"><code>fa7da4a</code></a>
Fix unused_features warning</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6b1a17851ea3d86a56aa116ca1cbf428f8d5f22d"><code>6b1a178</code></a>
Unpin CI miri toolchain</li>
<li>Additional commits viewable in <a
href="https://github.com/serde-rs/serde/compare/v1.0.228...v1.0.229">compare
view</a></li>
</ul>
</details>
<br />

Updates `serde` from 1.0.228 to 1.0.229
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/serde/releases">serde's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.229</h2>
<ul>
<li>Update to syn 3</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/serde-rs/serde/commit/7fc3b4c30c94f73a96ebd1553f2b090d928fc3a8"><code>7fc3b4c</code></a>
Release 1.0.229</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6d6e9a11101354ce769a3438a088b6b9305c1863"><code>6d6e9a1</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/serde/issues/3085">#3085</a>
from dtolnay/syn3</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6dec3b751126c8338cac0fe8085612d695e4ecf3"><code>6dec3b7</code></a>
Update to syn 3</li>
<li><a
href="https://github.com/serde-rs/serde/commit/cfe669241065984177ff63af8b45058e6e9b499d"><code>cfe6692</code></a>
Resolve mut_mut pedantic clippy lint</li>
<li><a
href="https://github.com/serde-rs/serde/commit/1023d077510b4aef36a41ef56fdb7798568a2654"><code>1023d07</code></a>
Update actions/upload-artifact@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/serde/commit/dd682c2c86aa7629e77c1ccd93212d3729f4c66d"><code>dd682c2</code></a>
Update actions/checkout@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/serde/commit/5f0f18b9211732f2d82f73b5a43e4f5ff3701251"><code>5f0f18b</code></a>
Update ui test suite to nightly-2026-06-01</li>
<li><a
href="https://github.com/serde-rs/serde/commit/63a1498f0e7be991ffac5939bdd202ca16e9a23f"><code>63a1498</code></a>
Regenerate stderr with trybuild normalization fixes</li>
<li><a
href="https://github.com/serde-rs/serde/commit/fa7da4a93567ed347ad0735c28e439fca688ef26"><code>fa7da4a</code></a>
Fix unused_features warning</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6b1a17851ea3d86a56aa116ca1cbf428f8d5f22d"><code>6b1a178</code></a>
Unpin CI miri toolchain</li>
<li>Additional commits viewable in <a
href="https://github.com/serde-rs/serde/compare/v1.0.228...v1.0.229">compare
view</a></li>
</ul>
</details>
<br />

Updates `serde_json` from 1.0.149 to 1.0.151
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/json/releases">serde_json's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.151</h2>
<ul>
<li>Add RawValue::from_string_unchecked (<a
href="https://redirect.github.com/serde-rs/json/issues/1331">#1331</a>,
thanks <a
href="https://github.com/WonderLawrence"><code>@​WonderLawrence</code></a>)</li>
</ul>
<h2>v1.0.150</h2>
<ul>
<li>Reject non-string enum object keys (<a
href="https://redirect.github.com/serde-rs/json/issues/1324">#1324</a>,
thanks <a
href="https://github.com/puneetdixit200"><code>@​puneetdixit200</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/serde-rs/json/commit/de8500740cdcabffb9734f503e4889def823cf10"><code>de85007</code></a>
Release 1.0.151</li>
<li><a
href="https://github.com/serde-rs/json/commit/3b2b3c5f28c20ed988bd081a4147c535e7e65c74"><code>3b2b3c5</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1331">#1331</a>
from WonderLawrence/rawvalue-from-string-unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/0406d96860e9d8b9252e2002fa3e626ae48ca1b0"><code>0406d96</code></a>
Debug-assert well-formedness and no-whitespace in
from_string_unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/cf16f75d81e28c723323bfc60a68fc02d2994fff"><code>cf16f75</code></a>
Add RawValue::from_string_unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/827a315bf2198558f0325b07bcc1e2cd973aba2f"><code>827a315</code></a>
Update actions/upload-artifact@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/json/commit/cea36a5c017ebffdeb95d0cd0f1aad473bfab758"><code>cea36a5</code></a>
Update actions/checkout@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/json/commit/a1ae73ac6a6940a4a57c673aebaa13ed4dfe3e8c"><code>a1ae73a</code></a>
Release 1.0.150</li>
<li><a
href="https://github.com/serde-rs/json/commit/1a360b0a6c003912afc3503c834b0edd798bca28"><code>1a360b0</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1324">#1324</a>
from puneetdixit200/reject-non-string-enum-keys</li>
<li><a
href="https://github.com/serde-rs/json/commit/2037b634f9dccbddc11cff189ebeb5854fa0e01c"><code>2037b63</code></a>
Reject non-string enum object keys</li>
<li><a
href="https://github.com/serde-rs/json/commit/5d30df60e916e9b8fc46c74794007ff271fdfbbf"><code>5d30df6</code></a>
Resolve manual_assert_eq pedantic clippy lint</li>
<li>Additional commits viewable in <a
href="https://github.com/serde-rs/json/compare/v1.0.149...v1.0.151">compare
view</a></li>
</ul>
</details>
<br />

Updates `serde_json` from 1.0.149 to 1.0.151
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/json/releases">serde_json's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.151</h2>
<ul>
<li>Add RawValue::from_string_unchecked (<a
href="https://redirect.github.com/serde-rs/json/issues/1331">#1331</a>,
thanks <a
href="https://github.com/WonderLawrence"><code>@​WonderLawrence</code></a>)</li>
</ul>
<h2>v1.0.150</h2>
<ul>
<li>Reject non-string enum object keys (<a
href="https://redirect.github.com/serde-rs/json/issues/1324">#1324</a>,
thanks <a
href="https://github.com/puneetdixit200"><code>@​puneetdixit200</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/serde-rs/json/commit/de8500740cdcabffb9734f503e4889def823cf10"><code>de85007</code></a>
Release 1.0.151</li>
<li><a
href="https://github.com/serde-rs/json/commit/3b2b3c5f28c20ed988bd081a4147c535e7e65c74"><code>3b2b3c5</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1331">#1331</a>
from WonderLawrence/rawvalue-from-string-unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/0406d96860e9d8b9252e2002fa3e626ae48ca1b0"><code>0406d96</code></a>
Debug-assert well-formedness and no-whitespace in
from_string_unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/cf16f75d81e28c723323bfc60a68fc02d2994fff"><code>cf16f75</code></a>
Add RawValue::from_string_unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/827a315bf2198558f0325b07bcc1e2cd973aba2f"><code>827a315</code></a>
Update actions/upload-artifact@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/json/commit/cea36a5c017ebffdeb95d0cd0f1aad473bfab758"><code>cea36a5</code></a>
Update actions/checkout@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/json/commit/a1ae73ac6a6940a4a57c673aebaa13ed4dfe3e8c"><code>a1ae73a</code></a>
Release 1.0.150</li>
<li><a
href="https://github.com/serde-rs/json/commit/1a360b0a6c003912afc3503c834b0edd798bca28"><code>1a360b0</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1324">#1324</a>
from puneetdixit200/reject-non-string-enum-keys</li>
<li><a
href="https://github.com/serde-rs/json/commit/2037b634f9dccbddc11cff189ebeb5854fa0e01c"><code>2037b63</code></a>
Reject non-string enum object keys</li>
<li><a
href="https://github.com/serde-rs/json/commit/5d30df60e916e9b8fc46c74794007ff271fdfbbf"><code>5d30df6</code></a>
Resolve manual_assert_eq pedantic clippy lint</li>
<li>Additional commits viewable in <a
href="https://github.com/serde-rs/json/compare/v1.0.149...v1.0.151">compare
view</a></li>
</ul>
</details>
<br />

Updates `serde` from 1.0.228 to 1.0.229
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/serde/releases">serde's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.229</h2>
<ul>
<li>Update to syn 3</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/serde-rs/serde/commit/7fc3b4c30c94f73a96ebd1553f2b090d928fc3a8"><code>7fc3b4c</code></a>
Release 1.0.229</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6d6e9a11101354ce769a3438a088b6b9305c1863"><code>6d6e9a1</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/serde/issues/3085">#3085</a>
from dtolnay/syn3</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6dec3b751126c8338cac0fe8085612d695e4ecf3"><code>6dec3b7</code></a>
Update to syn 3</li>
<li><a
href="https://github.com/serde-rs/serde/commit/cfe669241065984177ff63af8b45058e6e9b499d"><code>cfe6692</code></a>
Resolve mut_mut pedantic clippy lint</li>
<li><a
href="https://github.com/serde-rs/serde/commit/1023d077510b4aef36a41ef56fdb7798568a2654"><code>1023d07</code></a>
Update actions/upload-artifact@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/serde/commit/dd682c2c86aa7629e77c1ccd93212d3729f4c66d"><code>dd682c2</code></a>
Update actions/checkout@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/serde/commit/5f0f18b9211732f2d82f73b5a43e4f5ff3701251"><code>5f0f18b</code></a>
Update ui test suite to nightly-2026-06-01</li>
<li><a
href="https://github.com/serde-rs/serde/commit/63a1498f0e7be991ffac5939bdd202ca16e9a23f"><code>63a1498</code></a>
Regenerate stderr with trybuild normalization fixes</li>
<li><a
href="https://github.com/serde-rs/serde/commit/fa7da4a93567ed347ad0735c28e439fca688ef26"><code>fa7da4a</code></a>
Fix unused_features warning</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6b1a17851ea3d86a56aa116ca1cbf428f8d5f22d"><code>6b1a178</code></a>
Unpin CI miri toolchain</li>
<li>Additional commits viewable in <a
href="https://github.com/serde-rs/serde/compare/v1.0.228...v1.0.229">compare
view</a></li>
</ul>
</details>
<br />

Updates `serde` from 1.0.228 to 1.0.229
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/serde/releases">serde's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.229</h2>
<ul>
<li>Update to syn 3</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/serde-rs/serde/commit/7fc3b4c30c94f73a96ebd1553f2b090d928fc3a8"><code>7fc3b4c</code></a>
Release 1.0.229</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6d6e9a11101354ce769a3438a088b6b9305c1863"><code>6d6e9a1</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/serde/issues/3085">#3085</a>
from dtolnay/syn3</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6dec3b751126c8338cac0fe8085612d695e4ecf3"><code>6dec3b7</code></a>
Update to syn 3</li>
<li><a
href="https://github.com/serde-rs/serde/commit/cfe669241065984177ff63af8b45058e6e9b499d"><code>cfe6692</code></a>
Resolve mut_mut pedantic clippy lint</li>
<li><a
href="https://github.com/serde-rs/serde/commit/1023d077510b4aef36a41ef56fdb7798568a2654"><code>1023d07</code></a>
Update actions/upload-artifact@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/serde/commit/dd682c2c86aa7629e77c1ccd93212d3729f4c66d"><code>dd682c2</code></a>
Update actions/checkout@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/serde/commit/5f0f18b9211732f2d82f73b5a43e4f5ff3701251"><code>5f0f18b</code></a>
Update ui test suite to nightly-2026-06-01</li>
<li><a
href="https://github.com/serde-rs/serde/commit/63a1498f0e7be991ffac5939bdd202ca16e9a23f"><code>63a1498</code></a>
Regenerate stderr with trybuild normalization fixes</li>
<li><a
href="https://github.com/serde-rs/serde/commit/fa7da4a93567ed347ad0735c28e439fca688ef26"><code>fa7da4a</code></a>
Fix unused_features warning</li>
<li><a
href="https://github.com/serde-rs/serde/commit/6b1a17851ea3d86a56aa116ca1cbf428f8d5f22d"><code>6b1a178</code></a>
Unpin CI miri toolchain</li>
<li>Additional commits viewable in <a
href="https://github.com/serde-rs/serde/compare/v1.0.228...v1.0.229">compare
view</a></li>
</ul>
</details>
<br />

Updates `serde_json` from 1.0.149 to 1.0.151
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/serde-rs/json/releases">serde_json's
releases</a>.</em></p>
<blockquote>
<h2>v1.0.151</h2>
<ul>
<li>Add RawValue::from_string_unchecked (<a
href="https://redirect.github.com/serde-rs/json/issues/1331">#1331</a>,
thanks <a
href="https://github.com/WonderLawrence"><code>@​WonderLawrence</code></a>)</li>
</ul>
<h2>v1.0.150</h2>
<ul>
<li>Reject non-string enum object keys (<a
href="https://redirect.github.com/serde-rs/json/issues/1324">#1324</a>,
thanks <a
href="https://github.com/puneetdixit200"><code>@​puneetdixit200</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/serde-rs/json/commit/de8500740cdcabffb9734f503e4889def823cf10"><code>de85007</code></a>
Release 1.0.151</li>
<li><a
href="https://github.com/serde-rs/json/commit/3b2b3c5f28c20ed988bd081a4147c535e7e65c74"><code>3b2b3c5</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1331">#1331</a>
from WonderLawrence/rawvalue-from-string-unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/0406d96860e9d8b9252e2002fa3e626ae48ca1b0"><code>0406d96</code></a>
Debug-assert well-formedness and no-whitespace in
from_string_unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/cf16f75d81e28c723323bfc60a68fc02d2994fff"><code>cf16f75</code></a>
Add RawValue::from_string_unchecked</li>
<li><a
href="https://github.com/serde-rs/json/commit/827a315bf2198558f0325b07bcc1e2cd973aba2f"><code>827a315</code></a>
Update actions/upload-artifact@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/json/commit/cea36a5c017ebffdeb95d0cd0f1aad473bfab758"><code>cea36a5</code></a>
Update actions/checkout@v6 -&gt; v7</li>
<li><a
href="https://github.com/serde-rs/json/commit/a1ae73ac6a6940a4a57c673aebaa13ed4dfe3e8c"><code>a1ae73a</code></a>
Release 1.0.150</li>
<li><a
href="https://github.com/serde-rs/json/commit/1a360b0a6c003912afc3503c834b0edd798bca28"><code>1a360b0</code></a>
Merge pull request <a
href="https://redirect.github.com/serde-rs/json/issues/1324">#1324</a>
from puneetdixit200/reject-non-string-enum-keys</li>
<li><a
href="https://github.com/serde-rs/json/commit/2037b634f9dccbddc11cff189ebeb5854fa0e01c"><code>2037b63</code></a>
Reject non-string enum object keys</li>
<li><a
href="https://github.com/serde-rs/json/commit/5d30df60e916e9b8fc46c74794007ff271fdfbbf"><code>5d30df6</code></a>
Resolve manual_assert_eq pedantic clippy lint</li>
<li>Additional commits viewable in <a
href="https://github.com/serde-rs/json/compare/v1.0.149...v1.0.151">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 22:41:56 +01:00
dependabot[bot]andAnthony Stirling 5f2001c708 build(deps-dev): bump brace-expansion from 1.1.14 to 1.1.16 in /frontend (#7149)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion)
from 1.1.14 to 1.1.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/juliangruber/brace-expansion/releases">brace-expansion's
releases</a>.</em></p>
<blockquote>
<h2>v1.1.15</h2>
<ul>
<li>Backport v5.0.6 change to v1 (<a
href="https://redirect.github.com/juliangruber/brace-expansion/issues/111">#111</a>)
0b09384</li>
</ul>
<hr />
<p><a
href="https://github.com/juliangruber/brace-expansion/compare/v1.1.14...v1.1.15">https://github.com/juliangruber/brace-expansion/compare/v1.1.14...v1.1.15</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/447763a91a613cfa67ac73096cbc1de9a2304f97"><code>447763a</code></a>
1.1.16</li>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/d74e63030c012e3b7ae81657b8d665619cd51b95"><code>d74e630</code></a>
fix: v1 backport for CVE-2026-13149 (<a
href="https://redirect.github.com/juliangruber/brace-expansion/issues/122">#122</a>)</li>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/2203f4f4895eba16c4d408b4219ce1b8e5f6ff24"><code>2203f4f</code></a>
1.1.15</li>
<li><a
href="https://github.com/juliangruber/brace-expansion/commit/0b0938410732370559704230724ca4a44d1b29fd"><code>0b09384</code></a>
Backport v5.0.6 change to v1 (<a
href="https://redirect.github.com/juliangruber/brace-expansion/issues/111">#111</a>)</li>
<li>See full diff in <a
href="https://github.com/juliangruber/brace-expansion/compare/v1.1.14...v1.1.16">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=brace-expansion&package-manager=npm_and_yarn&previous-version=1.1.14&new-version=1.1.16)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 22:41:39 +01:00
dependabot[bot]andAnthony Stirling 18fb663b4d build(deps): bump bouncycastleVersion from 1.84 to 1.85 (#7132)
Bumps `bouncycastleVersion` from 1.84 to 1.85.
Updates `org.bouncycastle:bcprov-jdk18on` from 1.84 to 1.85
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html">org.bouncycastle:bcprov-jdk18on's
changelog</a>.</em></p>
<blockquote>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p><!-- raw HTML omitted --><!-- raw HTML omitted -->2.2.1 Version<!--
raw HTML omitted --><!-- raw HTML omitted -->
Release: 1.85, 1.85.1<!-- raw HTML omitted -->
Date:      2026, July 12th</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/bcgit/bc-java/commits">compare view</a></li>
</ul>
</details>
<br />

Updates `org.bouncycastle:bcpkix-jdk18on` from 1.84 to 1.85
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html">org.bouncycastle:bcpkix-jdk18on's
changelog</a>.</em></p>
<blockquote>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p><!-- raw HTML omitted --><!-- raw HTML omitted -->2.2.1 Version<!--
raw HTML omitted --><!-- raw HTML omitted -->
Release: 1.85, 1.85.1<!-- raw HTML omitted -->
Date:      2026, July 12th</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/bcgit/bc-java/commits">compare view</a></li>
</ul>
</details>
<br />

Updates `org.bouncycastle:bcutil-jdk18on` from 1.84 to 1.85
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/bcgit/bc-java/blob/main/docs/releasenotes.html">org.bouncycastle:bcutil-jdk18on's
changelog</a>.</em></p>
<blockquote>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p><!-- raw HTML omitted --><!-- raw HTML omitted -->2.2.1 Version<!--
raw HTML omitted --><!-- raw HTML omitted -->
Release: 1.85, 1.85.1<!-- raw HTML omitted -->
Date:      2026, July 12th</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/bcgit/bc-java/commits">compare view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 22:41:26 +01:00
dependabot[bot]andLudy 73668bcae8 build(deps): bump the mui group across 1 directory with 2 updates (#6497)
Bumps the mui group with 1 update in the /frontend directory:
[@mui/icons-material](https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material).

Updates `@mui/icons-material` from 9.0.0 to 9.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/mui/material-ui/releases">@​mui/icons-material's
releases</a>.</em></p>
<blockquote>
<h2>v9.2.0</h2>
<p>A big thanks to the 9 contributors who made this release
possible.</p>
<ul>
<li>⚙️ Add support for <a
href="https://mui.com/material-ui/guides/typescript/#allowing-data-attributes-on-slotprops"><code>data-*</code>
attributes on <code>slotProps</code></a>.</li>
</ul>
<h3><code>@mui/material@9.1.3</code></h3>
<ul>
<li>[l10n] Add missing MuiPagination localization to zh-CN locale (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48741">#48741</a>)
<a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a></li>
<li>[select] Guard display ref during mouse down (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48744">#48744</a>)
<a
href="https://github.com/michelengelen"><code>@​michelengelen</code></a></li>
</ul>
<h3><code>@mui/utils@9.1.3</code></h3>
<ul>
<li>[utils] Add opt-in <code>DataAttributesOverrides</code> augmentation
for slot props (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48554">#48554</a>)
<a href="https://github.com/LukasTy"><code>@​LukasTy</code></a></li>
</ul>
<h3>Docs</h3>
<ul>
<li>[docs] Improve Icon Dialog responsiveness on small screens (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48639">#48639</a>)
<a
href="https://github.com/Prakash1185"><code>@​Prakash1185</code></a></li>
<li>[docs] Fix invalid UTF-8 in skill references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48739">#48739</a>)
<a href="https://github.com/mturac"><code>@​mturac</code></a></li>
</ul>
<h3>Core</h3>
<ul>
<li>[code-infra] Resolve Renovate dashboard warnings (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48700">#48700</a>)
<a
href="https://github.com/Sushantplive"><code>@​Sushantplive</code></a></li>
<li>[code-infra] Validate npm publishing through dry run (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48691">#48691</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>[code-infra] Run prettier after renovate update (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48754">#48754</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[code-infra] Fix 'A11y results committed?' check on react-pinned
nightly jobs (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48740">#48740</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[core] Remove leftover Joy UI references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48719">#48719</a>)
<a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a></li>
<li>[code-infra] Bump react-router to 7.15.1 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48725">#48725</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[docs-infra] Drive docs analytics IDs via ANALYTICS_ENV (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48694">#48694</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[docs-infra] Pre-render API page descriptions (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48693">#48693</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>[code-infra][icons-material] Build lib/package.json with code-infra
--no-expand (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48689">#48689</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[code-infra] Fix react@18/next nightly workflow (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48635">#48635</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
</ul>
<p>All contributors of this release in alphabetical order: <a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a>, <a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a>, <a
href="https://github.com/Janpot"><code>@​Janpot</code></a>, <a
href="https://github.com/LukasTy"><code>@​LukasTy</code></a>, <a
href="https://github.com/michelengelen"><code>@​michelengelen</code></a>,
<a href="https://github.com/mturac"><code>@​mturac</code></a>, <a
href="https://github.com/Prakash1185"><code>@​Prakash1185</code></a>, <a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a>, <a
href="https://github.com/Sushantplive"><code>@​Sushantplive</code></a></p>
<h2>v9.1.2</h2>
<p>A big thanks to the 5 contributors who made this release
possible.</p>
<h3><code>@mui/material@9.1.2</code></h3>
<ul>
<li>[autocomplete] Don't submit forms when committing
<code>freeSolo</code> value with Enter key (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48679">#48679</a>)
<a
href="https://github.com/mj12albert"><code>@​mj12albert</code></a></li>
<li>[transitions] Fix RTG import in ESM (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48645">#48645</a>)
<a
href="https://github.com/mj12albert"><code>@​mj12albert</code></a></li>
</ul>
<h3><code>@mui/system@9.1.2</code></h3>
<ul>
<li>[InitColorSchemeScript] Fix script tag warning in Next.js 16 dev
mode (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48671">#48671</a>)
<a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a></li>
</ul>
<h3>Docs</h3>
<ul>
<li>Fix typos in release instructions (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48687">#48687</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>Update <code>@​mui/x</code>-* packages to latest (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48661">#48661</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/mui/material-ui/blob/master/CHANGELOG.md">@​mui/icons-material's
changelog</a>.</em></p>
<blockquote>
<h2>9.2.0</h2>
<!-- raw HTML omitted -->
<p><em>Jul 3, 2026</em></p>
<p>A big thanks to the 9 contributors who made this release
possible.</p>
<ul>
<li>⚙️ Add support for <a
href="https://mui.com/material-ui/guides/typescript/#allowing-data-attributes-on-slotprops"><code>data-*</code>
attributes on <code>slotProps</code></a>.</li>
</ul>
<h3><code>@mui/material@9.2.0</code></h3>
<ul>
<li>[l10n] Add missing MuiPagination localization to zh-CN locale (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48741">#48741</a>)
<a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a></li>
<li>[select] Guard display ref during mouse down (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48744">#48744</a>)
<a
href="https://github.com/michelengelen"><code>@​michelengelen</code></a></li>
</ul>
<h3><code>@mui/utils@9.2.0</code></h3>
<ul>
<li>[utils] Add opt-in <code>DataAttributesOverrides</code> augmentation
for slot props (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48554">#48554</a>)
<a href="https://github.com/LukasTy"><code>@​LukasTy</code></a></li>
</ul>
<h3>Docs</h3>
<ul>
<li>[docs] Improve Icon Dialog responsiveness on small screens (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48639">#48639</a>)
<a
href="https://github.com/Prakash1185"><code>@​Prakash1185</code></a></li>
<li>[docs] Fix invalid UTF-8 in skill references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48739">#48739</a>)
<a href="https://github.com/mturac"><code>@​mturac</code></a></li>
</ul>
<h3>Core</h3>
<ul>
<li>[code-infra] Resolve Renovate dashboard warnings (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48700">#48700</a>)
<a
href="https://github.com/Sushantplive"><code>@​Sushantplive</code></a></li>
<li>[code-infra] Validate npm publishing through dry run (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48691">#48691</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>[code-infra] Run prettier after renovate update (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48754">#48754</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[code-infra] Fix 'A11y results committed?' check on react-pinned
nightly jobs (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48740">#48740</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[core] Remove leftover Joy UI references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48719">#48719</a>)
<a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a></li>
<li>[code-infra] Bump react-router to 7.15.1 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48725">#48725</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[docs-infra] Drive docs analytics IDs via ANALYTICS_ENV (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48694">#48694</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[docs-infra] Pre-render API page descriptions (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48693">#48693</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>[code-infra][icons-material] Build lib/package.json with code-infra
--no-expand (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48689">#48689</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[code-infra] Fix react@18/next nightly workflow (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48635">#48635</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
</ul>
<p>All contributors of this release in alphabetical order: <a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a>, <a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a>, <a
href="https://github.com/Janpot"><code>@​Janpot</code></a>, <a
href="https://github.com/LukasTy"><code>@​LukasTy</code></a>, <a
href="https://github.com/michelengelen"><code>@​michelengelen</code></a>,
<a href="https://github.com/mturac"><code>@​mturac</code></a>, <a
href="https://github.com/Prakash1185"><code>@​Prakash1185</code></a>, <a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a>, <a
href="https://github.com/Sushantplive"><code>@​Sushantplive</code></a></p>
<h2>9.1.2</h2>
<!-- raw HTML omitted -->
<p><em>Jun 23, 2026</em></p>
<p>A big thanks to the 5 contributors who made this release
possible.</p>
<h3><code>@mui/material@9.1.2</code></h3>
<ul>
<li>[autocomplete] Don't submit forms when committing
<code>freeSolo</code> value with Enter key (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48679">#48679</a>)
<a
href="https://github.com/mj12albert"><code>@​mj12albert</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/mui/material-ui/commit/cb77df2fdf6b070cd3958af0ffba11e11454bf98"><code>cb77df2</code></a>
[release] v9.2.0 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48755">#48755</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/4206a995e11373a82f0fa29211434f910fa62d98"><code>4206a99</code></a>
[icons-material] Build lib/package.json with code-infra --no-expand (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48689">#48689</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/0f9b43f4e001102e9aa94f10c3882e15277908a5"><code>0f9b43f</code></a>
[release] v9.1.1 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48656">#48656</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/ef607d7d9254fb3bebbf739f9e9217b086381440"><code>ef607d7</code></a>
[code-infra] Port codebase to use tsgo (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48616">#48616</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/a389a2d9bc2a89c6c86c4d98aca51c3fa809a753"><code>a389a2d</code></a>
[release] v9.1.0 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48620">#48620</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/a34a94d094338213d7e3aba73ee85c9deaf2dafa"><code>a34a94d</code></a>
[docs] Use the standard license header preferred by OSI and GitHub</li>
<li><a
href="https://github.com/mui/material-ui/commit/a11407d18d3c241657e623e9f626bdd803e4ec79"><code>a11407d</code></a>
Bump react monorepo to 19.2.6 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48511">#48511</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/ea0f8b93c7936c057c17d4c648a59920f5382090"><code>ea0f8b9</code></a>
Bump code-infra:devDependencies (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48401">#48401</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/35b5b62f1861ec14b0a4b4c7aed8a9304f3e30e4"><code>35b5b62</code></a>
Bump react monorepo to 19.2.5 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48406">#48406</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/933bdf67f2405b9bfd4a115b957bc60fd2abaccf"><code>933bdf6</code></a>
v9.0.1 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-icons-material/issues/48479">#48479</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/mui/material-ui/commits/v9.2.0/packages/mui-icons-material">compare
view</a></li>
</ul>
</details>
<br />

Updates `@mui/material` from 9.0.0 to 9.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/mui/material-ui/releases">@​mui/material's
releases</a>.</em></p>
<blockquote>
<h2>v9.2.0</h2>
<p>A big thanks to the 9 contributors who made this release
possible.</p>
<ul>
<li>⚙️ Add support for <a
href="https://mui.com/material-ui/guides/typescript/#allowing-data-attributes-on-slotprops"><code>data-*</code>
attributes on <code>slotProps</code></a>.</li>
</ul>
<h3><code>@mui/material@9.1.3</code></h3>
<ul>
<li>[l10n] Add missing MuiPagination localization to zh-CN locale (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48741">#48741</a>)
<a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a></li>
<li>[select] Guard display ref during mouse down (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48744">#48744</a>)
<a
href="https://github.com/michelengelen"><code>@​michelengelen</code></a></li>
</ul>
<h3><code>@mui/utils@9.1.3</code></h3>
<ul>
<li>[utils] Add opt-in <code>DataAttributesOverrides</code> augmentation
for slot props (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48554">#48554</a>)
<a href="https://github.com/LukasTy"><code>@​LukasTy</code></a></li>
</ul>
<h3>Docs</h3>
<ul>
<li>[docs] Improve Icon Dialog responsiveness on small screens (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48639">#48639</a>)
<a
href="https://github.com/Prakash1185"><code>@​Prakash1185</code></a></li>
<li>[docs] Fix invalid UTF-8 in skill references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48739">#48739</a>)
<a href="https://github.com/mturac"><code>@​mturac</code></a></li>
</ul>
<h3>Core</h3>
<ul>
<li>[code-infra] Resolve Renovate dashboard warnings (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48700">#48700</a>)
<a
href="https://github.com/Sushantplive"><code>@​Sushantplive</code></a></li>
<li>[code-infra] Validate npm publishing through dry run (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48691">#48691</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>[code-infra] Run prettier after renovate update (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48754">#48754</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[code-infra] Fix 'A11y results committed?' check on react-pinned
nightly jobs (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48740">#48740</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[core] Remove leftover Joy UI references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48719">#48719</a>)
<a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a></li>
<li>[code-infra] Bump react-router to 7.15.1 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48725">#48725</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[docs-infra] Drive docs analytics IDs via ANALYTICS_ENV (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48694">#48694</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[docs-infra] Pre-render API page descriptions (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48693">#48693</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>[code-infra][icons-material] Build lib/package.json with code-infra
--no-expand (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48689">#48689</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[code-infra] Fix react@18/next nightly workflow (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48635">#48635</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
</ul>
<p>All contributors of this release in alphabetical order: <a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a>, <a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a>, <a
href="https://github.com/Janpot"><code>@​Janpot</code></a>, <a
href="https://github.com/LukasTy"><code>@​LukasTy</code></a>, <a
href="https://github.com/michelengelen"><code>@​michelengelen</code></a>,
<a href="https://github.com/mturac"><code>@​mturac</code></a>, <a
href="https://github.com/Prakash1185"><code>@​Prakash1185</code></a>, <a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a>, <a
href="https://github.com/Sushantplive"><code>@​Sushantplive</code></a></p>
<h2>v9.1.2</h2>
<p>A big thanks to the 5 contributors who made this release
possible.</p>
<h3><code>@mui/material@9.1.2</code></h3>
<ul>
<li>[autocomplete] Don't submit forms when committing
<code>freeSolo</code> value with Enter key (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48679">#48679</a>)
<a
href="https://github.com/mj12albert"><code>@​mj12albert</code></a></li>
<li>[transitions] Fix RTG import in ESM (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48645">#48645</a>)
<a
href="https://github.com/mj12albert"><code>@​mj12albert</code></a></li>
</ul>
<h3><code>@mui/system@9.1.2</code></h3>
<ul>
<li>[InitColorSchemeScript] Fix script tag warning in Next.js 16 dev
mode (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48671">#48671</a>)
<a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a></li>
</ul>
<h3>Docs</h3>
<ul>
<li>Fix typos in release instructions (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48687">#48687</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>Update <code>@​mui/x</code>-* packages to latest (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48661">#48661</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/mui/material-ui/blob/master/CHANGELOG.md">@​mui/material's
changelog</a>.</em></p>
<blockquote>
<h2>9.2.0</h2>
<!-- raw HTML omitted -->
<p><em>Jul 3, 2026</em></p>
<p>A big thanks to the 9 contributors who made this release
possible.</p>
<ul>
<li>⚙️ Add support for <a
href="https://mui.com/material-ui/guides/typescript/#allowing-data-attributes-on-slotprops"><code>data-*</code>
attributes on <code>slotProps</code></a>.</li>
</ul>
<h3><code>@mui/material@9.2.0</code></h3>
<ul>
<li>[l10n] Add missing MuiPagination localization to zh-CN locale (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48741">#48741</a>)
<a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a></li>
<li>[select] Guard display ref during mouse down (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48744">#48744</a>)
<a
href="https://github.com/michelengelen"><code>@​michelengelen</code></a></li>
</ul>
<h3><code>@mui/utils@9.2.0</code></h3>
<ul>
<li>[utils] Add opt-in <code>DataAttributesOverrides</code> augmentation
for slot props (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48554">#48554</a>)
<a href="https://github.com/LukasTy"><code>@​LukasTy</code></a></li>
</ul>
<h3>Docs</h3>
<ul>
<li>[docs] Improve Icon Dialog responsiveness on small screens (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48639">#48639</a>)
<a
href="https://github.com/Prakash1185"><code>@​Prakash1185</code></a></li>
<li>[docs] Fix invalid UTF-8 in skill references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48739">#48739</a>)
<a href="https://github.com/mturac"><code>@​mturac</code></a></li>
</ul>
<h3>Core</h3>
<ul>
<li>[code-infra] Resolve Renovate dashboard warnings (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48700">#48700</a>)
<a
href="https://github.com/Sushantplive"><code>@​Sushantplive</code></a></li>
<li>[code-infra] Validate npm publishing through dry run (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48691">#48691</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>[code-infra] Run prettier after renovate update (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48754">#48754</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[code-infra] Fix 'A11y results committed?' check on react-pinned
nightly jobs (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48740">#48740</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[core] Remove leftover Joy UI references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48719">#48719</a>)
<a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a></li>
<li>[code-infra] Bump react-router to 7.15.1 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48725">#48725</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[docs-infra] Drive docs analytics IDs via ANALYTICS_ENV (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48694">#48694</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[docs-infra] Pre-render API page descriptions (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48693">#48693</a>)
<a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a></li>
<li>[code-infra][icons-material] Build lib/package.json with code-infra
--no-expand (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48689">#48689</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
<li>[code-infra] Fix react@18/next nightly workflow (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48635">#48635</a>)
<a href="https://github.com/Janpot"><code>@​Janpot</code></a></li>
</ul>
<p>All contributors of this release in alphabetical order: <a
href="https://github.com/brijeshb42"><code>@​brijeshb42</code></a>, <a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a>, <a
href="https://github.com/Janpot"><code>@​Janpot</code></a>, <a
href="https://github.com/LukasTy"><code>@​LukasTy</code></a>, <a
href="https://github.com/michelengelen"><code>@​michelengelen</code></a>,
<a href="https://github.com/mturac"><code>@​mturac</code></a>, <a
href="https://github.com/Prakash1185"><code>@​Prakash1185</code></a>, <a
href="https://github.com/siriwatknp"><code>@​siriwatknp</code></a>, <a
href="https://github.com/Sushantplive"><code>@​Sushantplive</code></a></p>
<h2>9.1.2</h2>
<!-- raw HTML omitted -->
<p><em>Jun 23, 2026</em></p>
<p>A big thanks to the 5 contributors who made this release
possible.</p>
<h3><code>@mui/material@9.1.2</code></h3>
<ul>
<li>[autocomplete] Don't submit forms when committing
<code>freeSolo</code> value with Enter key (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48679">#48679</a>)
<a
href="https://github.com/mj12albert"><code>@​mj12albert</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/mui/material-ui/commit/cb77df2fdf6b070cd3958af0ffba11e11454bf98"><code>cb77df2</code></a>
[release] v9.2.0 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48755">#48755</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/ff92ccd23f7dde356a6f17e52f18747647e9a359"><code>ff92ccd</code></a>
[l10n] Add missing MuiPagination localization to zh-CN locale (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48741">#48741</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/71f1a967fa83054ef2c8ef05201ac92ff78af860"><code>71f1a96</code></a>
[Select] Guard display ref during mouse down (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48744">#48744</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/3ccff759bd1cd8c39c5ee1599a42d9ca682eed7f"><code>3ccff75</code></a>
[internal] Fix outdated links to the React repository</li>
<li><a
href="https://github.com/mui/material-ui/commit/33be3ca2326a1043cdc19b7dce4bd07827555533"><code>33be3ca</code></a>
[test] Fix react@18/next nightly workflow (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48635">#48635</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/48a4f98e257c00772fd8de194ec546daff8b5db9"><code>48a4f98</code></a>
[utils] Add opt-in <code>DataAttributesOverrides</code> augmentation for
slot props (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48">#48</a>...</li>
<li><a
href="https://github.com/mui/material-ui/commit/0cc3e24327ab6ef1aab39687cdb074dd692cfef3"><code>0cc3e24</code></a>
[core] Remove leftover Joy UI references (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48719">#48719</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/f33d58f7b86d78458216427b91682b3e7bcc5c6a"><code>f33d58f</code></a>
[core] Bump react-router to 7.15.1 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48725">#48725</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/a1ea5d8bb0fedc4dfe26886ab4012771b8f9aae7"><code>a1ea5d8</code></a>
[release] v9.1.2 (<a
href="https://github.com/mui/material-ui/tree/HEAD/packages/mui-material/issues/48713">#48713</a>)</li>
<li><a
href="https://github.com/mui/material-ui/commit/e6a054d39fe8c1f8f877b993aa3f2d88bf1b2d51"><code>e6a054d</code></a>
[autocomplete] Don't submit forms when committing <code>freeSolo</code>
value with Enter...</li>
<li>Additional commits viewable in <a
href="https://github.com/mui/material-ui/commits/v9.2.0/packages/mui-material">compare
view</a></li>
</ul>
</details>
<br />


> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ludy <Ludy87@users.noreply.github.com>
2026-08-01 18:52:48 +01:00
dependabot[bot]andAnthony Stirling 80501e599c build(deps): bump windows from 0.61.3 to 0.62.2 in /frontend/editor/src-tauri (#6419)
Bumps [windows](https://github.com/microsoft/windows-rs) from 0.61.3 to
0.62.2.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/microsoft/windows-rs/commits">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=windows&package-manager=cargo&previous-version=0.61.3&new-version=0.62.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 18:52:32 +01:00
dependabot[bot] a2ff8f8c8c build(deps): bump step-security/harden-runner from 2.19.3 to 2.20.0 (#7066)
Bumps
[step-security/harden-runner](https://github.com/step-security/harden-runner)
from 2.19.3 to 2.20.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/step-security/harden-runner/releases">step-security/harden-runner's
releases</a>.</em></p>
<blockquote>
<h2>v2.20.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Support for block policy for MacOS and Windows GitHub-hosted
runners</li>
<li>Support for Bitrise MacOS GitHub Actions runners</li>
<li>HTTPS monitoring support for Bun for Linux runners (enterprise
tier)</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/step-security/harden-runner/compare/v2.19.4...v2.20.0">https://github.com/step-security/harden-runner/compare/v2.19.4...v2.20.0</a></p>
<h2>v2.19.4</h2>
<h2>What's Changed</h2>
<ul>
<li>Improvements for HTTPS Monitoring for the Enterprise tier of Harden
Runner</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/step-security/harden-runner/compare/v2.19.3...v2.19.4">https://github.com/step-security/harden-runner/compare/v2.19.3...v2.19.4</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/step-security/harden-runner/commit/bf7454d06d71f1098171f2acdf0cd4708d7b5920"><code>bf7454d</code></a>
Merge pull request <a
href="https://redirect.github.com/step-security/harden-runner/issues/673">#673</a>
from step-security/fix/aggregate-error-startup-hang</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/1188420976b49762617c32cc010cba50a9fd7a71"><code>1188420</code></a>
Update non-TLS agent to v0.16.2</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/162cfeac170141192dc6d57ade86ddf59448ad96"><code>162cfea</code></a>
Update non-TLS agent to v0.16.1</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/eb9e1f4943b602b6f338f6f79468e812c2c6b320"><code>eb9e1f4</code></a>
Bring macOS runner updates from PR 674</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/1a10b01783c147498a6dee4fa4e7122325762720"><code>1a10b01</code></a>
Update Windows agent to v1.0.7</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/8b4a105ef5119b20c97c1566b0275b9399ae188d"><code>8b4a105</code></a>
Apply npm audit fixes with release-age cooldown</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/3626e0327723bef1c4e6b01750518eccd380a5df"><code>3626e03</code></a>
Default TLS status check failures to enabled</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/100e08b39cfd419c292df7becc379b0305ac0628"><code>100e08b</code></a>
Update agent-ebpf to v1.8.12</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/774f75f2c6334606d2d3d910a663f93c9ea49b3b"><code>774f75f</code></a>
Update agent to v1.8.9</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/f312657a64c745fae39c2c66cc7c7f7bc4c804d8"><code>f312657</code></a>
Extend missing-agent-dir guard to Linux and macOS cleanup paths</li>
<li>Additional commits viewable in <a
href="https://github.com/step-security/harden-runner/compare/ab7a9404c0f3da075243ca237b5fac12c98deaa5...bf7454d06d71f1098171f2acdf0cd4708d7b5920">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 18:52:12 +01:00
Anthony Stirling 547dce4cf3 Add multi-node cluster regression suite (compose stack + behave e2e) (#7026)
# Description of Changes

- The multi-node compose stack + behave suite (11 features)
- The nightly multinode-e2e job in build-enterprise.yml


cuke features are

cluster_health - both nodes boot healthy and join the Valkey backplane
load_balancing - traffic spreads across nodes; no spurious 401 when
bounced
cross_node_auth - a token from one node validates on all nodes (shared
DB keys)
shared_state - teams/sources/org visible from every node
policy_management - create/rename/delete a policy on any node, reflected
everywhere
source_management - source CRUD cross-node; referenced source can't be
deleted anywhere
connections - S3 connection resolves (secret masked) and deletes
cluster-wide
processor_ledger - files processed exactly once even when both nodes
trigger together
policy_run_coordination - a run on one node is visible from every node
rate_limiting - rate-limit counters shared via Valkey, not per node
failover - LB keeps serving when a node dies; recovered node accepts
existing tokens


can now start a full node system with 
export PREMIUM_KEY=<your licence key> ./start-multinode-test.sh
starts a 40 person org DB install with multi node and database
(--no-seed to have without DB on startup)
4 teams
1 s3 connection
1 policy

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-01 17:09:11 +01:00
dependabot[bot] aba9275ea7 build(deps): bump postcss from 8.5.12 to 8.5.25 in /devTools (#7232)
Bumps [postcss](https://github.com/postcss/postcss) from 8.5.12 to
8.5.25.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/releases">postcss's
releases</a>.</em></p>
<blockquote>
<h2>8.5.25</h2>
<ul>
<li>Fixed 8.5.17 visitor regression.</li>
<li>Fixed <code>list.split()</code> for non-string values (by <a
href="https://github.com/amir-rezaei"><code>@​amir-rezaei</code></a>).</li>
</ul>
<h2>8.5.24</h2>
<ul>
<li>Preserve the BOM after the processing (by <a
href="https://github.com/hdimer"><code>@​hdimer</code></a>).</li>
</ul>
<h2>8.5.23</h2>
<ul>
<li>Do not load source map without <code>opts.from</code> for security
reasons.</li>
</ul>
<h2>8.5.22</h2>
<ul>
<li>Fixed custom property losing semicolon before a comment (by <a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
</ul>
<h2>8.5.21</h2>
<ul>
<li>Fixed childless at-rule losing semicolon before comment (by <a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
<li>Fixed docs (by <a
href="https://github.com/isker"><code>@​isker</code></a>).</li>
</ul>
<h2>8.5.20</h2>
<ul>
<li>Fixed missing space if <code>AtRule#params</code> is set after (by
<a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
<li>Fixed mixing AST error on warnings (by <a
href="https://github.com/MahinAnowar"><code>@​MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.19</h2>
<ul>
<li>Fixed cleaning <code>before</code> for new nodes inserted to
<code>Root</code> (by <a
href="https://github.com/MahinAnowar"><code>@​MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.18</h2>
<ul>
<li>Restricted loading previous source maps file to the
<code>opts.from</code> folder for security reasons (use <code>unsafeMap:
true</code> to disable the check).</li>
</ul>
<h2>8.5.17</h2>
<ul>
<li>Fixed <code>Maximum call stack size exceeded</code> error.</li>
<li>Fixed Prototype hijacking for <code>postcss.fromJSON()</code>.</li>
<li>Fixed <code>Input#origin()</code> for unmapped end position (by <a
href="https://github.com/chatman-media"><code>@​chatman-media</code></a>).</li>
</ul>
<h2>8.5.16</h2>
<ul>
<li>Fixed <code>Input#origin()</code> position (by <a
href="https://github.com/mizdra"><code>@​mizdra</code></a>).</li>
<li>Fixed <code>raws</code> after rehydrating a JSON AST (by <a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
<li>Fixed putting parent-less node in <code>nodes</code> of new node (by
<a
href="https://github.com/MahinAnowar"><code>@​MahinAnowar</code></a>).</li>
<li>Fixed computing <code>offset</code> in <code>positionBy()</code> (by
<a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a>).</li>
<li>Fixed <code>rangeBy()</code> on <code>index: 0</code> (by <a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
</ul>
<h2>8.5.15</h2>
<ul>
<li>Fixed declaration parsing performance (by <a
href="https://github.com/homanp"><code>@​homanp</code></a>).</li>
</ul>
<h2>8.5.14</h2>
<ul>
<li>Fixed custom syntax regression (by <a
href="https://github.com/43081j"><code>@​43081j</code></a>).</li>
</ul>
<h2>8.5.13</h2>
<ul>
<li>Fixed <code>postcss-scss</code> commend regression.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/postcss/blob/main/CHANGELOG.md">postcss's
changelog</a>.</em></p>
<blockquote>
<h2>8.5.25</h2>
<ul>
<li>Fixed 8.5.17 visitor regression.</li>
<li>Fixed <code>list.split()</code> for non-string values (by <a
href="https://github.com/amir-rezaei"><code>@​amir-rezaei</code></a>).</li>
</ul>
<h2>8.5.24</h2>
<ul>
<li>Preserve the BOM after the processing (by <a
href="https://github.com/hdimer"><code>@​hdimer</code></a>).</li>
</ul>
<h2>8.5.23</h2>
<ul>
<li>Do not load source map without <code>opts.from</code> for security
reasons.</li>
</ul>
<h2>8.5.22</h2>
<ul>
<li>Fixed custom property losing semicolon before a comment (by <a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
</ul>
<h2>8.5.21</h2>
<ul>
<li>Fixed childless at-rule losing semicolon before comment (by <a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
<li>Fixed docs (by <a
href="https://github.com/isker"><code>@​isker</code></a>).</li>
</ul>
<h2>8.5.20</h2>
<ul>
<li>Fixed missing space if <code>AtRule#params</code> is set after (by
<a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
<li>Fixed mixing AST error on warnings (by <a
href="https://github.com/MahinAnowar"><code>@​MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.19</h2>
<ul>
<li>Fixed cleaning <code>before</code> for new nodes inserted to
<code>Root</code> (by <a
href="https://github.com/MahinAnowar"><code>@​MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.18</h2>
<ul>
<li>Restricted loading previous source maps file to the
<code>opts.from</code> folder for security reasons (use <code>unsafeMap:
true</code> to disable the check).</li>
</ul>
<h2>8.5.17</h2>
<ul>
<li>Fixed <code>Maximum call stack size exceeded</code> error.</li>
<li>Fixed Prototype hijacking for <code>postcss.fromJSON()</code>.</li>
<li>Fixed <code>Input#origin()</code> for unmapped end position (by <a
href="https://github.com/chatman-media"><code>@​chatman-media</code></a>).</li>
</ul>
<h2>8.5.16</h2>
<ul>
<li>Fixed <code>Input#origin()</code> position (by <a
href="https://github.com/mizdra"><code>@​mizdra</code></a>).</li>
<li>Fixed <code>raws</code> after rehydrating a JSON AST (by <a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
<li>Fixed putting parent-less node in <code>nodes</code> of new node (by
<a
href="https://github.com/MahinAnowar"><code>@​MahinAnowar</code></a>).</li>
<li>Fixed computing <code>offset</code> in <code>positionBy()</code> (by
<a
href="https://github.com/greymoth-jp"><code>@​greymoth-jp</code></a>).</li>
<li>Fixed <code>rangeBy()</code> on <code>index: 0</code> (by <a
href="https://github.com/sarathfrancis90"><code>@​sarathfrancis90</code></a>).</li>
</ul>
<h2>8.5.15</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/postcss/postcss/commit/08c989c43cc87edb1ed71408c2f5164c54fc21df"><code>08c989c</code></a>
Release 8.5.25 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/24f681471645cd960ee760ab7f9e348fbabfd42c"><code>24f6814</code></a>
Fix 8.5.17 visitor regression</li>
<li><a
href="https://github.com/postcss/postcss/commit/f2fa53f11daab3a16c7eb8bcaf5a945142341df3"><code>f2fa53f</code></a>
Add supply chain security requirement to PostCSS plugin guide</li>
<li><a
href="https://github.com/postcss/postcss/commit/10edf0b0606f97b1510e040c27bfd078c48d6ea7"><code>10edf0b</code></a>
fix: return empty array for empty string in list.split (<a
href="https://redirect.github.com/postcss/postcss/issues/2121">#2121</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/0ebe8ad591621ab4e48311da47a76974617571f9"><code>0ebe8ad</code></a>
Release 8.5.24 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/73218c64245be53e25d58150e0cc7e984f1d162d"><code>73218c6</code></a>
Update dependencies</li>
<li><a
href="https://github.com/postcss/postcss/commit/9a114f62b0deb37be859102f93b414b49385805a"><code>9a114f6</code></a>
Preserve the BOM when stringifying (<a
href="https://redirect.github.com/postcss/postcss/issues/2119">#2119</a>)</li>
<li><a
href="https://github.com/postcss/postcss/commit/90692619125cb9424f5eafd8c64bc76b2da23db1"><code>9069261</code></a>
Fix types check</li>
<li><a
href="https://github.com/postcss/postcss/commit/eb9e1fe793740bb3280bdf5bf98147f857f011bd"><code>eb9e1fe</code></a>
Release 8.5.23 version</li>
<li><a
href="https://github.com/postcss/postcss/commit/9d19c78ac91108b3f7d7130e55c6fa806c0efb84"><code>9d19c78</code></a>
Update dependencies</li>
<li>Additional commits viewable in <a
href="https://github.com/postcss/postcss/compare/8.5.12...8.5.25">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for postcss since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=postcss&package-manager=npm_and_yarn&previous-version=8.5.12&new-version=8.5.25)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 17:08:03 +01:00
dependabot[bot] 71957d5da5 build(deps): bump fast-uri from 3.1.2 to 3.1.5 in /devTools (#7231)
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.2 to
3.1.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/fastify/fast-uri/releases">fast-uri's
releases</a>.</em></p>
<blockquote>
<h2>v3.1.5</h2>
<h2>⚠️ Security Warning</h2>
<p>Fix for <a
href="https://github.com/fastify/fast-uri/security/advisories/GHSA-7p8r-x3mc-p8w7">https://github.com/fastify/fast-uri/security/advisories/GHSA-7p8r-x3mc-p8w7</a></p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/fastify/fast-uri/compare/v3.1.4...v3.1.5">https://github.com/fastify/fast-uri/compare/v3.1.4...v3.1.5</a></p>
<h2>v3.1.4</h2>
<h2>⚠️ Security Release</h2>
<p>Fix for <a
href="https://github.com/fastify/fast-uri/security/advisories/GHSA-v2hh-gcrm-f6hx">https://github.com/fastify/fast-uri/security/advisories/GHSA-v2hh-gcrm-f6hx</a></p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/fastify/fast-uri/compare/v3.1.3...v3.1.4">https://github.com/fastify/fast-uri/compare/v3.1.3...v3.1.4</a></p>
<h2>v3.1.3</h2>
<h2>⚠️ Security Release</h2>
<ul>
<li>Fixes: <a
href="https://github.com/fastify/fast-uri/security/advisories/GHSA-4c8g-83qw-93j6">https://github.com/fastify/fast-uri/security/advisories/GHSA-4c8g-83qw-93j6</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.3">https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/fastify/fast-uri/commit/5e179cbb4636d5f773ed21126e5bd3068e87e94e"><code>5e179cb</code></a>
Bumped v3.1.5</li>
<li><a
href="https://github.com/fastify/fast-uri/commit/2cad02d6ed428a720499bb7a3c3d6c3d41f10f5a"><code>2cad02d</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/fastify/fast-uri/commit/6aeece669e4166b2446a89f17c07a3b15dfb7ed4"><code>6aeece6</code></a>
Bumped v3.1.4</li>
<li><a
href="https://github.com/fastify/fast-uri/commit/2d50fbabc80e4d0884fe0f6a98fe118ce6faa353"><code>2d50fba</code></a>
fix: reject literal backslash in URI authority</li>
<li><a
href="https://github.com/fastify/fast-uri/commit/0549fe35b0d482233f3be2816439f3ec803603fa"><code>0549fe3</code></a>
Bumped v3.1.3</li>
<li><a
href="https://github.com/fastify/fast-uri/commit/2a6d357a18a68e6d812824379fd3388a1ae50d05"><code>2a6d357</code></a>
Merge commit from fork</li>
<li>See full diff in <a
href="https://github.com/fastify/fast-uri/compare/v3.1.2...v3.1.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=fast-uri&package-manager=npm_and_yarn&previous-version=3.1.2&new-version=3.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 17:07:56 +01:00
dependabot[bot] 536a9ebaa7 build(deps): bump actions/ai-inference from 2.1.0 to 2.1.1 (#6832)
Bumps [actions/ai-inference](https://github.com/actions/ai-inference)
from 2.1.0 to 2.1.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/ai-inference/releases">actions/ai-inference's
releases</a>.</em></p>
<blockquote>
<h2>v2.1.1</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: delay process.exit on Windows to dodge libuv UV_HANDLE_CLOSING
crash by <a
href="https://github.com/mickey-mikey"><code>@​mickey-mikey</code></a>
in <a
href="https://redirect.github.com/actions/ai-inference/pull/228">actions/ai-inference#228</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/mickey-mikey"><code>@​mickey-mikey</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/ai-inference/pull/228">actions/ai-inference#228</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/ai-inference/compare/v2...v2.1.1">https://github.com/actions/ai-inference/compare/v2...v2.1.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/ai-inference/commit/a7805884c80886efc241e94a5351df715968a0ad"><code>a780588</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/ai-inference/issues/228">#228</a>
from mickey-mikey/fix/libuv-windows-exit</li>
<li><a
href="https://github.com/actions/ai-inference/commit/99b696214c2205c9bdca442acae4307252da5067"><code>99b6962</code></a>
chore: npm audit fix — clear 17 transitive-dep CVEs</li>
<li><a
href="https://github.com/actions/ai-inference/commit/200ca3a4231fb2fbf71affa629d3af65e17e3a70"><code>200ca3a</code></a>
ci: disable redundant Biome validators and add dependabot cooldown</li>
<li><a
href="https://github.com/actions/ai-inference/commit/0e2c6977336b824b8dbb490be15874fe6f589e43"><code>0e2c697</code></a>
chore: refresh .licenses cache</li>
<li><a
href="https://github.com/actions/ai-inference/commit/0bb3dae7d8aab92acdb63a4595aa693f6ebc21f8"><code>0bb3dae</code></a>
fix: delay process.exit on Windows to dodge libuv UV_HANDLE_CLOSING
crash</li>
<li>See full diff in <a
href="https://github.com/actions/ai-inference/compare/17ff458cb182449bbb2e43701fcd98f6af8f6570...a7805884c80886efc241e94a5351df715968a0ad">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/ai-inference&package-manager=github_actions&previous-version=2.1.0&new-version=2.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

You can trigger a rebase of this PR by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 17:07:32 +01:00
dependabot[bot] c8db0a912e build(deps): bump ubuntu from c4a8d55 to 4fbb8e6 in /docker/unoserver (#6557)
Bumps ubuntu from `c4a8d55` to `4fbb8e6`.


> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 17:07:21 +01:00
dependabot[bot] 88012c6861 build(deps): bump jackson2Version from 2.21.4 to 2.22.1 (#7131)
Bumps `jackson2Version` from 2.21.4 to 2.22.1.
Updates `com.fasterxml.jackson.core:jackson-core` from 2.21.4 to 2.22.1
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/2451603e1931dac6f28ebdbcf308eb24b0f84b26"><code>2451603</code></a>
[maven-release-plugin] prepare release jackson-core-2.22.1</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/d3180c0827e45e39c0ca38dc6d650f19aff572ef"><code>d3180c0</code></a>
Prep for 2.22.1 release</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/6c5bae8184485c9def18ef98951840830bcdca60"><code>6c5bae8</code></a>
Merge branch '2.21' into 2.22</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/fda71aa915d4637c2e8377725eeee9039b740500"><code>fda71aa</code></a>
Post-release dep version bump</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/4ad623584c272a8b7de89ea6fd2bb40af1911b4a"><code>4ad6235</code></a>
[maven-release-plugin] prepare for next development iteration</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/b5f62dd8cf4b6897bb18a43565495355e45b4e65"><code>b5f62dd</code></a>
[maven-release-plugin] prepare release jackson-core-2.21.5</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/11f8b8c2730c48c8da188372af98b1b7a8219172"><code>11f8b8c</code></a>
Prep for 2.21.5 release</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/492000443fcfc30bd97ae6a46d924120f39ce21c"><code>4920004</code></a>
Post-release version bump</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/2bb55e8634c7fa1c197f995cdd4566ae7b7f4e0f"><code>2bb55e8</code></a>
[maven-release-plugin] prepare for next development iteration</li>
<li><a
href="https://github.com/FasterXML/jackson-core/commit/d763562443cc9d6e224a6265ca3710195c813cf5"><code>d763562</code></a>
[maven-release-plugin] prepare release jackson-core-2.22.0</li>
<li>Additional commits viewable in <a
href="https://github.com/FasterXML/jackson-core/compare/jackson-core-2.21.4...jackson-core-2.22.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `com.fasterxml.jackson.core:jackson-databind` from 2.21.4 to
2.22.1
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/FasterXML/jackson/commits">compare
view</a></li>
</ul>
</details>
<br />

Updates `com.fasterxml.jackson.dataformat:jackson-dataformat-yaml` from
2.21.4 to 2.22.1
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/681f699ec98fec4202245384e46fb781ee92e747"><code>681f699</code></a>
[maven-release-plugin] prepare release
jackson-dataformats-text-2.22.1</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/8e2585234fecca6599e75b060f913495d12b418b"><code>8e25852</code></a>
Prep for 2.22.1 release</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/e1ed4d2cb6cebf7e657ee5b91732a20c60baf932"><code>e1ed4d2</code></a>
Merge branch '2.21' into 2.22</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/3f3257ce1b8f367ec024adff3145819f9f168c21"><code>3f3257c</code></a>
Post-release dep version bump</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/3348a1aac8d06a14d787ce69022241581f2bf409"><code>3348a1a</code></a>
[maven-release-plugin] prepare for next development iteration</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/687ad4f318cd633eb0000f888bbb936c328dddde"><code>687ad4f</code></a>
[maven-release-plugin] prepare release
jackson-dataformats-text-2.21.5</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/955c59fae23292e389a13715fde664f7d3484eb9"><code>955c59f</code></a>
Prep for 2.21.5 release</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/588933e4c87ea2ef7669d4659c770fbff04fc108"><code>588933e</code></a>
Post-release dep version bump</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/38f3683f4c7793dad8111cf823c17243541a74df"><code>38f3683</code></a>
[maven-release-plugin] prepare for next development iteration</li>
<li><a
href="https://github.com/FasterXML/jackson-dataformats-text/commit/23d487c5e2740c74668b67d9a0a98992248ce91f"><code>23d487c</code></a>
[maven-release-plugin] prepare release
jackson-dataformats-text-2.22.0</li>
<li>Additional commits viewable in <a
href="https://github.com/FasterXML/jackson-dataformats-text/compare/jackson-dataformats-text-2.21.4...jackson-dataformats-text-2.22.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jdk8` from
2.21.4 to 2.22.1

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from
2.21.4 to 2.22.1


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 17:07:02 +01:00
e76a22e520 fix(desktop): persist default-app banner dismiss and fix Linux detection (#7112)
# Description of Changes

Fixes the desktop default-PDF banner that kept returning every launch
after users dismissed it or already set Stirling as default
([#6743](https://github.com/Stirling-Tools/Stirling-PDF/issues/6743),
also tracked in
[#5772](https://github.com/Stirling-Tools/Stirling-PDF/issues/5772) /
[#6270](https://github.com/Stirling-Tools/Stirling-PDF/issues/6270)).

### What changed
- **Persist dismiss:** X closes the banner for the current session only;
**Don't remind me again** (muted secondary action) permanently opts out
via the existing `localStorage` helpers that were never wired.
- **Settings:** General → Default PDF editor includes a **Remind me to
set as default** toggle (on by default), shown only when Stirling is not
already the default, so users can undo a permanent dismiss.
- **Linux detection:** Treat `Stirling-PDF.desktop` / case-insensitive
`*stirling*.desktop` as default, and resolve the real desktop file when
setting the association (fixes “already default but banner still
shows”).
- **InfoBanner:** optional secondary button support for the muted “Don't
remind me again” action.

### macOS quirk (Gatekeeper false positive)
One-click **Set Default** on macOS still uses
`LSSetDefaultRoleHandlerForContentType` — Apple has no public
replacement for document UTIs, so this remains the only single-button
path.

After setting Stirling as default, if a user later switches away with
Finder **Open With → Always Open With** on a *quarantined* (typically
downloaded) PDF, macOS can show:

> Apple could not verify “…pdf” is free of malware…

That is a known Gatekeeper/`LSRiskCategoryHasRedirectedBinding`
behaviour ([Apple Developer Forums
thread](https://developer.apple.com/forums/thread/795994)), not malware
and not something we can suppress from the app. **Safe way to switch
away:** select a PDF → File → Get Info → Open With → choose the app →
**Change All** (avoid Open With → Always on downloaded PDFs).

Closes #6743

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [x] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)
- New strings added in **en-US only** (`defaultApp.prompt.dontRemind`,
`settings.general.defaultPdfEditorRemind` / `RemindDescription`); other
locales handled separately.

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
- Banner: session dismiss (X) + muted **Don't remind me again**;
settings toggle only when not already default.

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

#### Test runs
- `task pre-commit:fix` (including toml-sort / locale hygiene)
- `task backend:test` — passed (incl. JaCoCo coverage targets)
- `task frontend:check` — lint, typecheck, format, tests
- `task frontend:test` — **166 files / 1353 tests passed**
- `task engine:check` — typecheck, lint, format; **335 pytest tests
passed**
- Re-ran `unusedTranslations` / `missingTranslations` after new en-US
keys — passed
- Manual: permanent dismiss persists across relaunch; settings remind
toggle restores banner; Linux desktop-file name mismatch addressed in
Rust

Co-authored-by: Wesley <wesley@awka.dev>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-08-01 16:30:53 +01:00
Ludy e565251991 ci(tauri): disable updater signing for unsigned builds (#7181)
# Description of Changes

This change updates the Tauri CI workflow to:

- Disable Tauri updater artifact generation for unsigned builds.
- Prevent unsigned builds from requiring updater signing secrets.
- Skip PR artifact comments for fork and Dependabot pull requests, where
the GitHub token is read-only.
- Preserve signed release builds and their updater artifacts unchanged.

The change prevents unsigned CI builds from failing because of
unavailable or invalid updater signing credentials. It also prevents
expected GitHub API permission errors from failing the workflow.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-08-01 14:28:47 +01:00
dependabot[bot] 47c68af068 build(deps): bump pyasn1 from 0.6.3 to 0.6.4 in /engine in the uv group across 1 directory (#7190)
Bumps the uv group with 1 update in the /engine directory:
[pyasn1](https://github.com/pyasn1/pyasn1).

Updates `pyasn1` from 0.6.3 to 0.6.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pyasn1/pyasn1/releases">pyasn1's
releases</a>.</em></p>
<blockquote>
<h2>Release 0.6.4</h2>
<p>This is a security release.</p>
<ul>
<li>CVE-2026-59885 (GHSA-8ppf-4f7h-5ppj): Fixed quadratic time
complexity in the OBJECT IDENTIFIER and RELATIVE-OID decoders. A small
crafted substrate encoding many arcs could consume excessive CPU.</li>
<li>CVE-2026-59884 (GHSA-m4p7-r5rc-7g4j): Limited BER long-form tag IDs
to 20 octets (140 bits). Unbounded tag IDs allowed a crafted substrate
to consume excessive CPU and memory.</li>
<li>CVE-2026-59886 (GHSA-hm4w-wwcw-mr6r): Fixed excessive memory and CPU
consumption in <code>Real.__float__()</code> for values with large
base-10 exponents.</li>
<li>Pinned PyPI publish GitHub Action to an immutable commit.</li>
</ul>
<p>All changes are noted in the <a
href="https://github.com/pyasn1/pyasn1/blob/main/CHANGES.rst">CHANGELOG</a>.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pyasn1/pyasn1/blob/main/CHANGES.rst">pyasn1's
changelog</a>.</em></p>
<blockquote>
<h2>Revision 0.6.4, released 08-07-2026</h2>
<ul>
<li>CVE-2026-59885 (GHSA-8ppf-4f7h-5ppj): Fixed quadratic time
complexity in the OBJECT IDENTIFIER and RELATIVE-OID decoders.
A small crafted substrate encoding many arcs could consume
excessive CPU. Arcs are now accumulated in linear time; decoded
values are unchanged (thanks for reporting, tynus2)</li>
<li>CVE-2026-59884 (GHSA-m4p7-r5rc-7g4j): Limited BER long-form tag
IDs to 20 octets (140 bits), matching the OID arc limit introduced
in 0.6.2. Unbounded tag IDs allowed a crafted substrate to consume
excessive CPU and memory; longer tag IDs are now rejected with
PyAsn1Error. Also fixed Tag and TagSet repr() failing on huge tag
(thanks for reporting, mikeappsec)
IDs due to the integer-to-string conversion limit (Python 3.11+)</li>
<li>CVE-2026-59886 (GHSA-hm4w-wwcw-mr6r): Fixed excessive memory and
CPU consumption in Real.<strong>float</strong>() for values with large
base-10
exponents. Conversion no longer materializes huge intermediate
integers; values too large to represent as a Python float raise
OverflowError promptly, and prettyPrint() renders them as
'<!-- raw HTML omitted -->' as before. Also fixed base-10 mantissa
normalization
to use exact integer arithmetic; mantissas larger than 2**53
could previously lose precision through float division
(thanks for reporting, gvozdila)</li>
<li>Pinned PyPI publish GitHub Action to an immutable commit
[pr <a
href="https://redirect.github.com/pyasn1/pyasn1/issues/113">#113</a>](<a
href="https://redirect.github.com/pyasn1/pyasn1/pull/113">pyasn1/pyasn1#113</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pyasn1/pyasn1/commit/72e4803405816c371ed3b2cb4be181c47f038406"><code>72e4803</code></a>
Prepare release 0.6.4</li>
<li><a
href="https://github.com/pyasn1/pyasn1/commit/0c19eeb853731db1c717ff125ea001a1e558332d"><code>0c19eeb</code></a>
Pin PyPI publish action to immutable commit (<a
href="https://redirect.github.com/pyasn1/pyasn1/issues/113">#113</a>)</li>
<li><a
href="https://github.com/pyasn1/pyasn1/commit/45bdb19eb7df4b3780fe9c912c63e99bffc39dd9"><code>45bdb19</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/pyasn1/pyasn1/commit/628e36ecbb5277a3f01572ce418ef54271b165a5"><code>628e36e</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/pyasn1/pyasn1/commit/e60c691cb91addb8fcefa2f537e85ede6fb1e886"><code>e60c691</code></a>
Merge commit from fork</li>
<li>See full diff in <a
href="https://github.com/pyasn1/pyasn1/compare/v0.6.3...v0.6.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pyasn1&package-manager=uv&previous-version=0.6.3&new-version=0.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 10:55:16 +00:00
dependabot[bot] 5412dd4d4f build(deps): bump dorny/paths-filter from 4.0.1 to 4.0.2 (#6987)
Bumps [dorny/paths-filter](https://github.com/dorny/paths-filter) from
4.0.1 to 4.0.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dorny/paths-filter/releases">dorny/paths-filter's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.2</h2>
<h2>What's Changed</h2>
<ul>
<li>fix warning message by <a
href="https://github.com/cgundy"><code>@​cgundy</code></a> in <a
href="https://redirect.github.com/dorny/paths-filter/pull/282">dorny/paths-filter#282</a></li>
<li>chore: fix GitHub spelling in logs by <a
href="https://github.com/squat"><code>@​squat</code></a> in <a
href="https://redirect.github.com/dorny/paths-filter/pull/278">dorny/paths-filter#278</a></li>
<li>fix: use rev-parse instead of branch --show-current for older git
compat by <a
href="https://github.com/saschabratton"><code>@​saschabratton</code></a>
in <a
href="https://redirect.github.com/dorny/paths-filter/pull/303">dorny/paths-filter#303</a></li>
<li>fix: work around git dubious ownership errors in container jobs by
<a
href="https://github.com/saschabratton"><code>@​saschabratton</code></a>
in <a
href="https://redirect.github.com/dorny/paths-filter/pull/317">dorny/paths-filter#317</a></li>
<li>docs: update changelog for v4.0.2 by <a
href="https://github.com/saschabratton"><code>@​saschabratton</code></a>
in <a
href="https://redirect.github.com/dorny/paths-filter/pull/318">dorny/paths-filter#318</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/cgundy"><code>@​cgundy</code></a> made
their first contribution in <a
href="https://redirect.github.com/dorny/paths-filter/pull/282">dorny/paths-filter#282</a></li>
<li><a href="https://github.com/squat"><code>@​squat</code></a> made
their first contribution in <a
href="https://redirect.github.com/dorny/paths-filter/pull/278">dorny/paths-filter#278</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/dorny/paths-filter/compare/v4.0.1...v4.0.2">https://github.com/dorny/paths-filter/compare/v4.0.1...v4.0.2</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md">dorny/paths-filter's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>v4.0.2</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/317">Work
around git dubious ownership errors in container jobs</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/303">Use
rev-parse instead of branch --show-current for older git compat</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/282">Fix
warning message</a></li>
</ul>
<h2>v4.0.1</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/255">Support
merge queue</a></li>
</ul>
<h2>v4.0.0</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/294">Update
action runtime to node24</a></li>
</ul>
<h2>v3.0.3</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/279">Add
missing predicate-quantifier</a></li>
</ul>
<h2>v3.0.2</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/224">Add
config parameter for predicate quantifier</a></li>
</ul>
<h2>v3.0.1</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/133">Compare
base and ref when token is empty</a></li>
</ul>
<h2>v3.0.0</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/210">Update to
Node.js 20</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/215">Update
all dependencies</a></li>
</ul>
<h2>v2.11.1</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/167">Update
@​actions/core to v1.10.0 - Fixes warning about deprecated
set-output</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/168">Document
need for pull-requests: read permission</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/164">Updating
to actions/checkout@v3</a></li>
</ul>
<h2>v2.11.0</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/157">Set
list-files input parameter as not required</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/161">Update
Node.js</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/162">Fix
incorrect handling of Unicode characters in exec()</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/163">Use
Octokit pagination</a></li>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/160">Updates
real world links</a></li>
</ul>
<h2>v2.10.2</h2>
<ul>
<li><a href="https://redirect.github.com/dorny/paths-filter/pull/91">Fix
getLocalRef() returns wrong ref</a></li>
</ul>
<h2>v2.10.1</h2>
<ul>
<li><a
href="https://redirect.github.com/dorny/paths-filter/pull/85">Improve
robustness of change detection</a></li>
</ul>
<h2>v2.10.0</h2>
<ul>
<li><a href="https://redirect.github.com/dorny/paths-filter/pull/82">Add
ref input parameter</a></li>
<li><a href="https://redirect.github.com/dorny/paths-filter/pull/83">Fix
change detection in PR when pullRequest.changed_files is
incorrect</a></li>
</ul>
<h2>v2.9.3</h2>
<ul>
<li><a href="https://redirect.github.com/dorny/paths-filter/pull/78">Fix
change detection when base is a tag</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/dorny/paths-filter/commit/7b450fff21473bca461d4b92ce414b9d0420d706"><code>7b450ff</code></a>
docs: update changelog for v4.0.2 (<a
href="https://redirect.github.com/dorny/paths-filter/issues/318">#318</a>)</li>
<li><a
href="https://github.com/dorny/paths-filter/commit/928037783a71f24983ea250c6e55290c1b2de54f"><code>9280377</code></a>
fix: work around git dubious ownership errors in container jobs (<a
href="https://redirect.github.com/dorny/paths-filter/issues/317">#317</a>)</li>
<li><a
href="https://github.com/dorny/paths-filter/commit/f3ceefdc7ef57bc2d8560787d4b6c33e44044cec"><code>f3ceefd</code></a>
fix: use rev-parse instead of branch --show-current for older git compat
(<a
href="https://redirect.github.com/dorny/paths-filter/issues/303">#303</a>)</li>
<li><a
href="https://github.com/dorny/paths-filter/commit/61f87a10cd2c304679af17bb73ef192addf33c1c"><code>61f87a1</code></a>
chore: fix GitHub spelling in logs (<a
href="https://redirect.github.com/dorny/paths-filter/issues/278">#278</a>)</li>
<li><a
href="https://github.com/dorny/paths-filter/commit/b82ff81ffbe6fb4b636bb5b47e37fd8d12b32632"><code>b82ff81</code></a>
fix warning message (<a
href="https://redirect.github.com/dorny/paths-filter/issues/282">#282</a>)</li>
<li>See full diff in <a
href="https://github.com/dorny/paths-filter/compare/fbd0ab8f3e69293af611ebaee6363fc25e6d187d...7b450fff21473bca461d4b92ce414b9d0420d706">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dorny/paths-filter&package-manager=github_actions&previous-version=4.0.1&new-version=4.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 10:55:10 +00:00
dependabot[bot] d8c6af2e7a build(deps): bump eclipse-temurin from b27ca47 to 2f1da10 in /docker/base (#6555)
Bumps eclipse-temurin from `b27ca47` to `2f1da10`.


> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 10:55:05 +00:00
EthanHealy01 9d473fb435 Resolve duplicate CSS selectors reported by Stylelint (#7212)
Fixes #7189

Consolidates all 29 `no-duplicate-selectors` violations across 18
stylesheets by merging later duplicate rule blocks into the first
occurrence. Where duplicates had conflicting values, the cascade-winning
(later) value was kept, so computed styles are unchanged.

Also:
- Adds `frontend/stylelint.config.mjs` with only
`no-duplicate-selectors` enabled (Prettier and the theme linter own
everything else).
- Adds a `frontend:lint:css` task, wired into `task frontend:lint` as a
blocking check so regressions can't creep back in.
- Lints all first-party CSS (`editor/**/*.css`, so `public/css` and any
future non-`src` stylesheets are covered too), excluding only the
vendored `cookieconsent.css` and build output via `ignoreFiles`. This
surfaced and fixed 5 additional duplicate selectors in
`cookieconsentCustomisation.css` that weren't in the original issue
report.

Note: `portal/views/Sources.css` goes beyond dedup — the whole
`.portal-sources__connections*` block is deleted as dead code
(unreferenced since the S3 connections redesign in #6965; only
`-actions` in it was an actual duplicate).

🤖 Generated with [Claude Code](https://claude.ai/code)
2026-07-31 16:46:31 +00:00
James Brunton 041b6a4b5f Move parameter validation to config-accessible function (#7224)
# Description of Changes
Move the logic for validating params into global exported functions and
attach them to the operation config so that we can access them elsewhere
so things like Pipelines know whether the tool has been configured and
provide a warning if not.

<img width="1264" height="503" alt="image"
src="https://github.com/user-attachments/assets/f320579c-6c08-4c66-a999-015d46df1b33"
/>
2026-07-31 15:59:16 +00:00
ConnorYoh 8990f55e50 feat(storage): encryption at rest for stored files (per-team envelope encryption) (#7155)
# Description of Changes

PR1 of the encrypt-at-rest initiative: user files stored by Stirling (My
Files, workflow files) are now AES-256 encrypted at rest across all
three storage backends, with keys that never leave the deployment.

**What was changed**

- New `EncryptingStorageProvider` decorator wraps whichever
`StorageProvider` backend is configured (local / database / S3). It
encrypts on `store` (Tink AES-256-GCM streaming AEAD, 1 MiB segments)
and transparently decrypts on `load`; legacy plaintext blobs are
detected by magic sniff and pass through untouched, so mixed state is
safe and no migration is required to enable.
- Envelope-encryption key hierarchy: each blob gets a random per-file
DEK, wrapped by a per-team KEK stored (master-key-wrapped) in a new
`file_encryption_keys` registry table; the master key resolves like the
existing credential key — `stirling.security.fileEncryptionKey`
property, `STIRLING_FILE_ENCRYPTION_KEY` env var, or an auto-generated
owner-only `file-encryption.key` in the config dir (cluster mode
requires an explicit shared key, fail-fast).
- Self-describing blob format (`SPDFEAR1` header) carrying the key id,
plaintext length, and the wrapped DEK; the header prefix is bound as GCM
associated data to both the DEK wrap and the payload, so headers cannot
be transplanted between blobs.
- Enabled via `storage.encryption.enabled=true`, gated on a
Pro/Enterprise licence — **write side only**: decryption activates
whenever key rows exist, so switching the flag off or a lapsed licence
can never make previously encrypted files unreadable.
- Key status lifecycle (`ACTIVE`/`RETIRED`/`DISABLED`): `DISABLED` is a
reversible per-team kill switch that fails closed on read; no API path
deletes key material. A revoked download surfaces as **403 Forbidden**
("access revoked"), not a 500, since it is a deliberate policy state
rather than a fault.
- Startup self-check: a master key that cannot unwrap existing key rows
refuses to boot rather than silently starting a second key hierarchy.
- S3 presigned download URLs are suppressed for decorated storage (they
would serve ciphertext); the controller already falls back to
app-streamed downloads.
- `StoredFile`/`StoredObject` gain a nullable `encryption_key_id`
(ddl-auto, no migration); persisted sizes remain plaintext sizes so
quotas and UI are unchanged.

**Why**

Enterprise security questionnaires (and HIPAA/GDPR/CMMC buyers) require
encryption at rest with documented key management; files were previously
plaintext in every backend. Design doc and vendor/standards research
(Purview, Box KeySafe, Google CSE, ISO 32000-2) informed the approach.

## Manually tested end-to-end

Beyond the automated suite, the full flow was exercised against a
running backend (local provider, `storage.encryption.enabled=true`,
login enabled) via the storage API:

1. **Startup** — master key auto-generated with the "back this up"
warning; logs `master key initialised (AES-256-GCM, fingerprint …)` and
`Storage encryption at rest active (writes encrypted)`.
2. **Encrypted at rest** — uploaded a PDF containing a known marker
string; the blob on disk (371 B vs 219 B plaintext) began with the
`SPDFEAR1` header + key id + ciphertext, contained **no `%PDF` signature
and no marker** — not openable as a PDF straight off disk.
3. **Transparent access** — downloading the file through the API
returned it **byte-identical** to the original, marker intact; stored
`sizeBytes` stayed the plaintext size.
4. **Kill switch + reversibility** — set the team key's status directly
in the DB and restarted:
- `DISABLED` → download **failed closed** (`403`, "access to this
content is revoked"), zero plaintext served.
- `ACTIVE` again → file **fully recovered, byte-identical**. Disabling
is a reversible switch on a preserved key row, not destruction.

(The 403 mapping in step 4 was added in this PR after the manual run
first surfaced it as a generic 500.)

## Coming in later PRs

- **PR2 — ops & lifecycle:** audit events for
encrypt/decrypt/key-lifecycle; admin endpoints for the kill switch
(disable/enable) and key status; a background "encrypt existing files"
migration job for turning the feature on over pre-existing plaintext;
master-key rotation (re-wrap KEK rows). Also plans a
key-backup/fingerprint verification command.
- **PR3 — admin UI:** settings section (status, per-team key list with
disable/enable), encrypted-file badge in My Files, i18n.
- **Later:** per-**source** encryption for the Processor pipeline (the
`SOURCE` key scope is already reserved in the schema); pluggable
external KMS / BYOK master-key backends (Vault, AWS/Azure/GCP KMS);
optional FIPS-validated crypto module build for CMMC; and encrypted
egress (PDF-native AES-256) for files leaving the platform.

**Reviewer notes**

- New dependency: `com.google.crypto.tink:tink:1.23.0` (Apache-2.0, pure
Java — bundled in the boot jar, no Docker changes). Pulls protobuf-java
4.33.6, which clears the Aikido-flagged CVE-2024-7254. `./gradlew
checkLicense --no-parallel` passes.
- The `file-encryption.key` file is generated in the config dir on first
use and must be backed up; losing it makes encrypted files unrecoverable
(loud log warning + fingerprint exposed for backup verification).
- Tests cover round-trips on re-openable and one-shot (S3-style)
backends, multi-segment files, legacy passthrough, decrypt-only mode,
disabled-key fail-closed (now asserting the 403 mapping), header/payload
tamper rejection, key-creation races, and presigned-URL suppression.

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-31 14:57:19 +00:00
ConnorYoh d5e3c3e6e1 Remove dead frontend exports and their orphaned translation keys (#7226)
## Why

Spotted while working on #7222. `PIPELINE_OPERATIONS` reads like the
list that decides which tools the pipeline composer offers — its doc
comment literally said *"the operation catalogue the composer builds a
pipeline from"* and *"adding an operation needs no translation work"*.
Nothing has imported it since #6905 replaced it with
`getExecutableTools` over the tool registry.

That makes it worse than dead weight: I added an entry to it to expose
Auto Rotate, and the entry did nothing. The next person will do the
same.

So I swept the editor frontend for the same shape — exported values with
no reference anywhere, including inside their own file — and removed the
confirmed ones.

## What went

**6 wholly dead files**
- `core/components/tooltips/useCertSignTooltips.ts`
- `core/components/tooltips/useCertificateChoiceTips.ts`
- `core/components/tooltips/useSessionManagementTips.ts`
- `core/components/tooltips/useWetSignatureTips.ts`
- `desktop/config/planFeatures.ts`
- `core/hooks/tools/shared/useOperationResults.ts`

**Dead consts and helpers** across core, portal and desktop:
`PIPELINE_OPERATIONS` + `PipelineOperationDef`, `FILE_ORIGINS`,
`DATE_GROUP_ORDER`, `toRgba`, `isSplitMethod`, `useSignatureMode`,
`getCategoryLabel`, `useCommonTranslations`, `useSignatureDetection`,
two `Z_INDEX_*` tokens, `getFontStatusIcon`, `buildUpdatedDocument`,
`INFO_PDF_FILENAME`, `useCustomMetadataTips`, `PORTAL_ACCESS_TONE`,
`MEMBER_STATUS_TONE`, `ASSIGNABLE_ROLES`, `TIER_INFO`, `VIEW_LABELS`,
`lookupVertical`, `lookupEndpoint`, `lookupAgent`, `lookupSource`,
`lookupDestination`, `docsSource`.

`fileProcessingService.ts` keeps only `ProcessedFileMetadata`, which
four files still import. Removing the dead service instance orphaned the
`FileProcessingService` class and its result type, so those went with
it.

**103 en-US translation keys** that only the deleted tooltip hooks and
helpers referenced — the unused-translation audit flags these as soon as
their callers go, so the cleanup isn't complete without them. Only
`en-US` is touched, since that is what the audit gates.

## Kept deliberately

Three things look unused in `core` but are not, and a naive sweep would
have deleted them:

- `Z_ANALYTICS_MODAL` and `DEV_TESTING_ENABLED` — the `saas` and
`proprietary` layers shadow those modules and reference them
- `CLOUD_LAYER_PROBE` — exists to prove layer resolution

## Testing

Deletions only, so the type checker and the suites are the proof:

- `typecheck:all` + `typecheck:portal` — all eight build variants clean
- full `eslint` (zero warnings) and `theme-lint`
- `prettier --check` across the frontend
- full editor suite: **1651 tests, 186 files, all passing**

Three incomplete removals and two orphaned imports were caught by
exactly those gates and fixed before pushing.

## Note

The same 103 keys still exist in the other ~40 locale files. The audit
only gates `en-US`, and translations are usually synced separately, so I
left them — worth a follow-up if you want them pruned too.
2026-07-31 14:55:46 +00:00
ConnorYoh 6094040e0a Make Auto Rotate's settings editable in the pipeline composer (#7222)
Follow-up to #7152.

## Why

Auto Rotate was already selectable as a pipeline step —
`getExecutableTools` lists any registry tool with an `operationConfig`
and an endpoint resolvable from defaults, which it has. But once added,
the settings pane showed *"Displaying these tool params for editing is
not supported yet"* and the step card read *"Runs with default
settings"*.

Both come from the same cause. `classifyToolStepSupport` keys off the
operation config's mappers:

```js
const hasMappers = Boolean(config?.toApiParams && config?.fromApiParams);
if (!hasMappers) return "unsupported";
return entry.automationSettings ? "editable" : "noSettings";
```

Auto Rotate had `automationSettings` but no mappers, because its custom
processor builds its own FormData and never needed them — so it
classified as `unsupported`.

The more consequential half is `serializeToolStep`, which emits
`parameters: {}` for a mapper-less tool. A composed pipeline therefore
ran Auto Rotate on server defaults with no way to change that. "Runs
with default settings" was literal.

## What

Declares `toApiParams` / `fromApiParams` on `autoRotateOperationConfig`,
mapping `detectionMode`, `confidenceThreshold` and `inferUndetected`.

That flips the step to `editable`, so the composer reuses the existing
`AutoRotateAutomationSettings` panel, and the chosen settings now reach
the backend.

**No backend change.** Policy steps already serialise `parameters` as
form fields and the endpoint already accepts these three — verified
against a running server while working on #7152.

## Testing

- New round-trip test in `toolAutomation.test.ts`: the step serialises
to `{detectionMode, confidenceThreshold, inferUndetected}` and
deserialises back with `support: "editable"`, using the real operation
config.
- `core/hooks/tools/shared` + `portal/components/pipelines` suites: 63
tests pass.
- Typecheck across build variants, ESLint, Prettier.

The composer UI itself was not clicked: the portal is not served by the
editor dev server locally, so the verification is the unit test plus the
render path (`PipelineStepSettings` renders `entry.automationSettings`
when support is `editable`, and the registry entry supplies it). Worth a
click-through on the preview deploy.

## Note for maintainers

While tracing this I found `PIPELINE_OPERATIONS` in
`portal/components/pipelines/pipelineOperations.ts` is exported but
never imported — the composer builds its list from the tool registry
instead. `humanizeOperation` in the same file *is* still used as a label
fallback. Left alone here as it is out of scope, but it looks like dead
code worth deleting separately.

Generated with [Claude Code](https://claude.com/claude-code)
2026-07-31 13:52:44 +00:00
James Brunton 6933d11bce Type-check Storybook files (#7223)
# Description of Changes
Storybook files aren't currently being type-checked, but they should be.
A bunch of them had a dodgy import in them (which didn't affect anything
because it was just an `import type` but still worth fixing).
2026-07-31 13:20:07 +00:00
ConnorYoh 46865cd154 Add Auto Rotate tool that detects and fixes page orientation (#7152)
## What

New **Auto Rotate** tool: give it any PDF and it detects each page's
correct orientation and sets `/Rotate` so every page displays upright.
Lossless — only the page rotation metadata changes, content is never
re-rendered.

New endpoint: `POST /api/v1/misc/auto-rotate-pdf`, plus an editor tool
registered next to Rotate.

## How it works

Two-tier detection, per page, both expressed as an additive clockwise
`/Rotate` correction:

1. **Embedded-text fast path** (`AutoRotateDetection`): dominant glyph
direction via `PDFTextStripper`/`TextPosition.getDir()`. Trusted only
with >= 30 glyphs at >= 95% agreement. Near-instant for born-digital
PDFs and needs no external tools. Correction = `(glyphDir -
pageRotation) mod 360` — the sign conventions are pinned by
parameterized fixture tests covering all text-angle x `/Rotate`
combinations.
2. **Tesseract OSD fallback**: pages the text path can't decide are
rendered at 300 DPI grayscale and run through `tesseract --psm 0`.
Corrections apply only above a confidence threshold (default 14.0,
matching OCRmyPDF's `--rotate-pages-threshold`). Rendering honours the
existing `/Rotate`, so the verdict is always additive.

**Conservative by default**: blank pages, mixed-direction pages, and
low-confidence verdicts are skipped, never guessed — the failure mode to
avoid is making a correct page wrong.

### API surface

- `detectionMode`: `auto` (default) | `text` | `osd` — forcing one
method is useful for testing
- `confidenceThreshold`: minimum OSD confidence to apply a correction
- `dryRun=true`: returns a JSON per-page report instead of the PDF
- `pageRotations={"1":90,...}`: applies precomputed corrections without
detection

The frontend uses analyze-then-apply (dryRun, then pageRotations) so
detection runs exactly once per file, and the analysis report can be
shown in the UI.

### UI

The tool's results panel shows a **detection report** for
debugging/tuning: per page — method badge (Text / OCR / Skipped),
confidence score (glyph-dominance % for text, raw OSD score for OCR),
applied rotation, and a skip reason (too little text, mixed directions,
below threshold, OCR not installed...). Settings expose detection mode
and the OSD threshold.

### Dependency handling

Registered in `PageOps` only — deliberately **not** gated on the
`tesseract` group, because the text path works without Tesseract. The
controller checks `isGroupEnabled("tesseract")` at runtime; when it's
missing, scanned pages are skipped with a visible `tesseractUnavailable`
note instead of the whole tool disappearing.

## Testing

- 14 detection unit tests: all text-angle x `/Rotate` fixture
combinations (pins the direction conventions), dominance/glyph-count
guards, OSD output parsing
- 6 controller tests: dryRun report, correction application, explicit
pageRotations, tesseract-unavailable reporting, input validation
- Frontend: typecheck (core/desktop/proprietary), ESLint, Prettier, all
i18n audit tests
- **Live, text path**: fixture with pages at `/Rotate` 0/90/180/270 ->
all pages return upright; report UI verified in the browser
- **Live, OSD path**: image-only "scan" fixture (no text layer) with
pages upright/180/90 -> all detected by OSD at conf ~15-17 and
corrected; closed-loop re-analysis of the output reports 0 pages to
rotate with *higher* confidence than the input

Out of scope: skew correction (that's the OCR tool's `--deskew`); this
fixes 90-degree-multiple orientation only.
2026-07-31 11:27:12 +00:00
James Brunton 3bee6d212e Change pipelines to have 1 input and 1 output (#7121)
# Description of Changes

Change pipelines so that sources and triggers are grouped into a list of
inputs, so you can have a different trigger for each source in the list.
This is necessary because triggers are not universally supported by all
source types. If you wanted to have a pipeline pull from both a folder
and an S3 bucket, the current system allows you to choose "Folder Watch"
as the trigger, which will either do nothing or crash when it's paired
with the S3 bucket.

I've got reservations about actually allowing different triggers for
every source because it allows for user workflows that I don't believe
exist, like "I want this folder to be polled every minute and this other
one to be polled every hour, but they should run the same tools and
should output to the same place". Because of this (with agreement from
Connor, Anthony and Matt) I've changed this PR to artificially limit
pipelines to having 1 input & output at this stage. The backend is still
shaped to support multiple inputs & outputs so it should be trivial to
re-add support for them in the future if we decide we want to, but the
UI can be much simpler and easier to understand with just 1 input and
output.

<img width="1262" height="521" alt="image"
src="https://github.com/user-attachments/assets/809e6803-9f99-436d-9aeb-52dddf0906ff"
/>
2026-07-31 08:53:01 +00:00
James Brunton 9d01866c83 Set PRs to build Mac and Windows binaries when building desktop code (#7203)
# Description of Changes
Currently, desktop PRs only build on Linux, which none of the core
maintainers currently use. Change it so that desktop PRs build Mac and
Windows, so core maintainers can test the built version.
2026-07-30 14:08:04 +00:00
Reece Browne b35329c8f5 a11y scan: generate required assets, and fail when a story file can't load (#7201)
## What

Two related bugs found while looking at why #7187's a11y check behaves
differently on CI than locally.

### 21 stories were never being scanned on CI

The scan tasks only depended on `install`, not `prepare`. On a fresh
checkout that means the generated icon set
(`editor/src/assets/material-symbols-icons.json`, gitignored) doesn't
exist, so every story that reaches `LocalIcon` fails to import:

```
Failed to resolve import "../../../assets/material-symbols-icons.json"
from "editor/src/core/components/shared/LocalIcon.tsx"
```

On CI that was four story files / 21 stories, every run. It works
locally only because our trees already have the file from a previous
build. The scan tasks now depend on `prepare`, like the `build:*` tasks
do.

### The gate reported those runs as clean

Worse than the missing stories: a file that fails to import produces a
**failed suite with no assertions**. Every check in `a11y-check.mjs`
reads assertions, so the file satisfied the manifest, contributed
nothing to compare, and the run printed `✓ no a11y regressions`.

An assertion-less failed suite now fails the gate and points at the scan
log for the underlying resolve error. `--record` refuses in the same
situation, so a baseline can't be written that quietly drops those
stories.

Also switched the affected-story emptiness test to single quotes, since
that list now carries its own per-path quoting (it was producing `[ -z
""a" "b"" ]`).

## Testing

- Deleted the generated asset to reproduce a fresh checkout: the gate
**fails** with the file named and the cause explained, where before it
printed `✓ no a11y regressions` and exited 0.
- With the `prepare` dependency the task regenerates the asset itself
and the previously-invisible files scan: 21 stories, 35 story-rule
pairs, all already baselined.
2026-07-30 08:13:41 +00:00
Reece Browne 4dc0927104 a11y job: emit the affected-story list on one line (#7196)
## What

Fixes the a11y check failing with `permission denied` on any PR that
touches more than one story (currently hitting #7163).

The script that lists which stories to scan printed one path per line.
That list gets pasted into a shell command, so everything after the
first line fell out of the command — the shell treated the second path
as a command of its own and failed.

One-line fix: print the list on a single line.

## Testing

Changed two components and ran the task from both git-bash and
PowerShell — both stories scanned, check passes. #7163's red check
should go green on re-run once this is in.
2026-07-29 17:08:08 +00:00
ConnorYoh b4a264239c fix(saas): provision a new user and their personal team atomically (#7193)
New SaaS accounts were landing with `team_id = null`. That state is
unrecoverable: portal access derives from leading a team, and signup is
the only place one is assigned.

Five things had to be fixed, all on the signup path. Only the last is a
behaviour change you'd notice.

### 1. Shared-PK entity was routed to `merge()`
`SaasUserExtensions` pre-sets its `@MapsId` id in the constructor, so
Spring Data's id-nullness check treated a brand-new row as existing and
`save()` failed with `AssertionFailure: null identifier`. Now implements
`Persistable` and decides on the creation timestamp — the idiom already
used by `ProcessedFileEntity` and `SourceDocCountEntity`.

This was the blocker. It threw on every signup, and because the failure
was swallowed (see 3) every new account was stranded.

### 2. User and team were committed separately
`createUser()` is annotated `@Transactional` but is called as
`this.createUser(...)`, and self-invocation bypasses the proxy — so the
annotation did nothing. `saveUser()` and `ensurePersonalTeam()` each
committed in their own transaction, leaving a window where a **committed
user was visible with `team_id = null`**. Parallel requests entering
that window each provisioned a team, producing duplicates (observed:
teams 160/161 and 162/163 for one user).

Both writes now happen in one transaction via
`SaasTeamService.saveUserWithPersonalTeam()`. The window is gone, so
there is nothing left to race over.

### 3. A failed team create was swallowed
The old code logged at WARN and committed the user anyway. It now
propagates: the shared transaction rolls the user back, the request
401s, and a retry starts clean. Nothing half-built is committed.

This is the deliberate trade — a transient failure now surfaces instead
of silently producing an account that can never reach the portal.

### 4. Per-request healing removed
`recoverMissingTeam` (added in #7180) ran on **every authenticated
request** whose user had no team, with no mutual exclusion. Under a
burst of parallel requests it was itself a source of concurrent
provisioning. Provisioning belongs to signup alone.

### 5. Policy seeding could not run
`@TransactionalEventListener(AFTER_COMMIT)` leaves the *completed*
transaction bound to the thread, so `JpaPolicyStore.save`'s
`@Transactional` joined it instead of opening a live one — and its `FOR
UPDATE` lock threw `TransactionRequiredException`. Now seeded in
`BEFORE_COMMIT`: the lock has a live transaction, rollback safety is
unchanged (a rolled-back team still leaves no policy), and it stays on a
single pooled connection.

## Verified

`:saas:test` green, both spotless gates green, on top of current `main`.

Manually on a live signup: **one** team per user, and the
concurrent-signup race resolves correctly through the pre-existing
unique-constraint catch (`users_supabase_auth_id_key` violation →
refetch the winner).

12 filter tests needed updating. Two of them asserted behaviour this PR
deliberately removes (`personalTeamFailureSwallowed`,
`assignsTeamWhenMissing`), so they were rewritten to assert the new
contract rather than re-stubbed into passing.

## Not in scope

- **Existing stranded accounts** are not repaired — with the healer
gone, nothing fixes them on the request path. They need a one-off
backfill or deletion.
- **A DB-level invariant.** A partial unique index
(`UNIQUE(created_by_user_id) WHERE is_personal`) would make duplicate
personal teams impossible rather than merely unreachable. Wanted, but it
is a Supabase migration in the SaaS repo, so it is deliberately
separate.
- **Per-request auth cost.** The filter still does two remote-Postgres
round-trips per authenticated request; a frontend request storm makes
that expensive. Being handled separately.
2026-07-29 15:15:49 +00:00
James Brunton bbd4d2c3ac Redesign toml sorting to speed up from ~40s to ~2s (#7192)
# Description of Changes
The `pre-commit` tool to sort the translations is really slow. It took
~40 seconds to run because it's using a parser which attempts to save
all of the formatting data from the Toml. Our translations toml is
pretty much entirely formatted anyway, so there's no point in trying to
preserve any of that data. The only thing we lose is 5 comments, none of
which are needed anyway and only appear in the US translation file. By
switching to Python stdlib `tomllib` reading and `tomli-w` for writing,
we can make the Toml formatting job take 2.11 seconds, where it used to
take 39.78s. The whole pre-commit job now takes 4.58 seconds.
2026-07-29 14:33:34 +00:00
Reece Browne 4d207f0c3f a11y job: scan stories when their component changes; fix cold-start false failures (#7191)
## What

Two fixes to the pull-request a11y job (#7086 follow-up), both found on
its first day live.

### It now scans a component's stories when the component changes

The job picked its scan set from changed **story files** alone. But a
story renders the live component — editing `Button.tsx` changes what
every Button story shows without touching a story file, and the job
scanned nothing. That's the common way a11y regressions arrive, and it
was exactly the case the job missed.

The scan set now also includes stories whose **same-named sibling source
file changed**: edit `Button.tsx` or `Button.css` and
`Button.stories.tsx` is scanned. Changes that ripple further than a
component's own stories (shared UI, theme tokens) remain the nightly
sweep's job.

### It no longer fails on cold-start infrastructure noise

The job's first real run (#7163) flagged a story as "failed to render".
The story was fine — on a cold dependency cache (**every** CI run), Vite
discovered the preview's own dependency graph mid-run and reloaded the
page, killing whichever story happened to be loading with `Failed to
fetch dynamically imported module`. Reproduced on a cold cache, passes
on a warm one.

- The preview's deps are named in `optimizeDeps.include`, which removes
the mid-run reload (verified cold).
- A batch whose report contains crash-class failures (failures carrying
no axe rule) is retried once — a one-off infrastructure death passes the
retry, a story that genuinely can't render fails both attempts and is
still reported.

Also: the scan-report artifacts were never actually uploading — they
live in a dot-directory, which `upload-artifact` silently skips as
hidden by default. `include-hidden-files: true` fixes that for the PR
job and the nightly, so a red run finally has its evidence attached.

### The glue is Node now, so tasks work from any shell

Raised in review: the pipeline leaned on `bash`, `sed`, `grep`, `sort`
and `tr`. Task runs its commands in an embedded POSIX interpreter, but
those are external binaries it has to find on PATH — and a Windows dev
calling tasks from **PowerShell** has none of them (`sed`/`tr` missing
outright, `sort` resolves to Windows' own, and `bash` resolves to
*WSL's*). Confirmed broken by running the task from PowerShell before
the change.

The batch runner and affected-story detection are now small Node scripts
(`a11y-scan.mjs`, `a11y-changed.mjs`) — the repo already requires Node,
so one implementation serves PowerShell, git-bash and CI alike, instead
of maintaining `.sh`/`.ps1` twins.

## Testing

- Sibling detection: editing `Tabs.tsx` (component only) pulls
`Tabs.stories.tsx` into the scan set; editing a `.css` sibling does the
same; nothing unrelated leaks in.
- **From PowerShell**: `task frontend:storybook:a11y:changed`
early-exits cleanly with no changes, and with a component edit it
detects the sibling, runs the browser scan and passes the gate — same
result from git-bash.
- Cold cache end-to-end: cleared both Vite caches, ran the scan — no
re-optimize, no reload, stories fail only on their (baselined) axe
results.
- Crash classifier: 1 on a synthetic crash report, 0 on axe-only
failures, 0 on a real report — so the retry can't be triggered by
legitimate violations.
- Full scan + gate run green end-to-end; taskfile parses, workflows are
valid YAML, Prettier/ESLint pass.

#7163's red check needs no action from that PR's author — it should go
green on re-run once this lands.
2026-07-29 14:18:55 +00:00
Reece Browne 8a5470dd01 Add an accessibility regression gate for Storybook (#7086)
## What

Follow-up to #7073. Turns the story scan into an accessibility gate:
stories run axe in a real browser, and CI flags a change that adds a
**new** violation.

The app has plenty of existing a11y problems (mostly theme-level colour
contrast), so rather than block everything on those, they're recorded in
`.storybook/a11y-baseline.json` and grandfathered. The gate cares about
three things:

- a story breaking a rule it wasn't already breaking
- a story that fails to render at all
- a scan that didn't cover everything it was asked to

Starting point: 839 stories carry a known violation, 1058 story-rule
pairs.

## Where it runs

- **Pull requests** scan only the stories the branch touches — usually
seconds. A full sweep is ~30 minutes, too slow to sit in front of every
merge, and the `frontend` path filter is broad enough that unrelated
changes would pay for it.
- **Nightly** scans every story, so a violation introduced somewhere
other than the story itself — a shared component, a theme token — still
surfaces within a day.
- Both upload their scan reports as artifacts; the reports carry the
offending selector and help text, without which a red run can only be
understood by reproducing it locally.
- **Advisory to start with.** It is deliberately not in
`all-checks-passed`, so it reports without blocking. Worth promoting
once a few weeks of runs show the pass/fail is stable.

## Using it

- **Fixed some violations?** `task frontend:storybook:a11y:record`
re-records so the gate locks the improvement in.
- **Locally:** `task frontend:storybook:a11y:changed` for your branch,
`task frontend:storybook:a11y` for everything.
- **New component?** Its story is picked up automatically.

## Testing

- Every story — 526 files, ~1,450 stories — runs in a real browser with
no render failures, and the gate reports no regressions against the
baseline.
- Running the gate over a single changed story takes seconds, which is
the pull-request path.
- The gate's own behaviour is covered against synthetic scan reports: a
new rule fails, the same rule on more nodes does not, a crashed story
fails, an incomplete scan refuses to report, and re-recording refuses
while anything is crashing.
- Typecheck (all build variants), ESLint and Prettier pass.

## Notes for reviewers

Some of this PR is making the mechanism trustworthy rather than adding
features, so it's worth knowing what changed and why:

- Rule ids come from the axe docs URL in each violation, not a
hand-maintained list of rule names — the old list silently ignored 39 of
axe's 104 rules, including `object-alt`, `target-size` and the table
rules.
- The baseline records **which** rules a story breaks, not how many
nodes break them. Node counts drift between runs because stories fetch
asynchronously and axe samples whatever has rendered, which made
unrelated changes look like regressions. For the same reason the
baseline is the union of repeated scans, so a run can only be a subset
of it.
- A story that fails for a non-a11y reason used to yield no rule id and
was recorded as clean, which hid crashes and could mask real violations.
Those now fail, and re-recording refuses to run while any story is
crashing.
- The scan writes a manifest of every story file it intends to cover and
the check fails unless all of them reported, so a dropped batch can't
read as "no violations".
- Vite was pre-bundling the JSX runtime mid-run and reloading the page,
which crashed whichever stories were loading; those deps are now named
up front and the per-story timeout is above the 5s default.

Colour contrast dominates the baseline and is theme-level, tracked
separately from this.
2026-07-29 11:28:24 +00:00
James Brunton 999b5e5995 Add persistent outputs to Processor (#7071)
# Description of Changes
<img width="1270" height="487" alt="image"
src="https://github.com/user-attachments/assets/64894e2b-aab9-42ab-96c2-2c11ba427b52"
/>

Change policies to point towards a source for its output instead of a
dynamically defined output location for the pipeline. This allows for
easy reuse of outputs in different pipelines and makes it impossible to
break complex pipelines by accidentally updating the source but not the
output and vice versa. Also makes outputs a list to match the inputs, so
it's possible for a pipeline to output to multiple locations.

We should consider whether we want to continue calling these Sources
since they're now being used as both inputs and outputs, but that
decision is beyond the scope of this PR.

Also updates the existing S3 DB migration script and adds a new one to
migrate to the new schema. Neither of these scripts are possible with
SQL since it involves parsing and restructuring JSON. I've updated them
so that they only ever run once on startup and mark themselves as
completed.
2026-07-29 11:22:47 +00:00
ConnorYoh 66b80a80c0 fix(saas): personal teams must be allowed to share a name (new signups get no team) (#7180)
## The bug

Every SaaS signup after the very first one is created with `team_id =
NULL`, no team membership and no `home_team_id`. A brand-new account:

```
user_id | username               | team_id | authenticationtype | home_team_id | memberships
    952 | hedewot627@candaba.com | null    | web                | null         | null
```

Since #7070 derives Processor access from leading a team, these accounts
are silently redirected out of the Processor and back to the editor.

## Cause

`SaasTeamService.createPersonalTeam` names every personal team the
literal `"My Team"`, and `stirling_pdf.teams.name` was unique — so the
insert throws a duplicate-key error for the second account onwards. Team
creation is best-effort (caught, logged at WARN), so the account is
created anyway, permanently team-less.

Migration `20251211000000` had already dropped that constraint for
exactly this reason, but it dropped it **by name** while the entity
still declared `@Column(unique = true)`. With Flyway retired for `:saas`
(#7100), `ddl-auto=update` reconciles the schema — so Hibernate
re-created the constraint on the next boot under a generated name the
old `DROP` could never match.

The data bug predates #7070; that PR only made it visible.

## Changes

- **`Team.name` no longer unique.** `TeamController` already enforces
uniqueness for admin-created teams (`existsByNameIgnoreCase` on create
and rename, 409), so nothing user-facing changes. `findByName` is only
used for the `Default`/`Internal` system teams.
- **Existing team-less accounts recover on authentication.** Signup is
the only other place a team is assigned and nothing back-fills
`team_id`, so without this they stay locked out. Guests excluded by
design; healthy accounts short-circuit on a null check (`team` is
`EAGER`).
- **Tests:** team recovered, existing team untouched, guest stays
team-less.

## Deploy order

Needs `20260806000000_teams_name_drop_unique` (SaaS repo, `v3`) to drop
the constraint from the live schema — **deployed after this**, or
Hibernate re-adds it on the next boot.

## Verification

`:saas:compileJava`, `:proprietary:compileJava`, spotless on both, and
the `:saas` team/auth-filter tests (`TeamRecovery`: 3 tests, 0
failures).
2026-07-29 09:31:47 +00:00
dependabot[bot] e05b7f12da build(deps): bump madrapps/jacoco-report from 1.7.2 to 1.8.0 (#6750)
Bumps
[madrapps/jacoco-report](https://github.com/madrapps/jacoco-report) from
1.7.2 to 1.8.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/madrapps/jacoco-report/releases">madrapps/jacoco-report's
releases</a>.</em></p>
<blockquote>
<h2>v1.8.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump <code>@​tsconfig/node20</code> from 20.1.4 to 20.1.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/289">Madrapps/jacoco-report#289</a></li>
<li>Bump eslint-plugin-n from 17.15.1 to 18.0.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/290">Madrapps/jacoco-report#290</a></li>
<li>Bump webpack from 5.95.0 to 5.107.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/291">Madrapps/jacoco-report#291</a></li>
<li>Bump eslint-plugin-import from 2.31.0 to 2.32.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/292">Madrapps/jacoco-report#292</a></li>
<li>Bump picomatch from 2.3.1 to 2.3.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/301">Madrapps/jacoco-report#301</a></li>
<li>Bump brace-expansion by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/300">Madrapps/jacoco-report#300</a></li>
<li>Bump <code>@​eslint/eslintrc</code> from 3.1.0 to 3.3.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/295">Madrapps/jacoco-report#295</a></li>
<li>Bump flatted from 3.2.7 to 3.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/298">Madrapps/jacoco-report#298</a></li>
<li>Bump ts-jest from 29.2.5 to 29.4.11 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/296">Madrapps/jacoco-report#296</a></li>
<li>Bump eslint-plugin-jest from 28.8.3 to 29.15.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/297">Madrapps/jacoco-report#297</a></li>
<li>Bump typescript-eslint from 8.32.0 to 8.60.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/303">Madrapps/jacoco-report#303</a></li>
<li>Bump prettier from 3.3.3 to 3.8.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/306">Madrapps/jacoco-report#306</a></li>
<li>Bump <code>@​types/node</code> from 22.10.2 to 25.9.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/307">Madrapps/jacoco-report#307</a></li>
<li>Bump webpack-cli from 5.1.4 to 7.0.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/308">Madrapps/jacoco-report#308</a></li>
<li>Bump <code>@​octokit/plugin-paginate-rest</code> by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/311">Madrapps/jacoco-report#311</a></li>
<li>Bump <code>@​octokit/request</code> by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/312">Madrapps/jacoco-report#312</a></li>
<li>Bump octokit from 4.0.2 to 5.0.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/309">Madrapps/jacoco-report#309</a></li>
<li>Bump globals from 15.14.0 to 17.6.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/317">Madrapps/jacoco-report#317</a></li>
<li>Bump <code>@​octokit/request-error</code> from 5.1.0 to 5.1.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/319">Madrapps/jacoco-report#319</a></li>
<li>Bump eslint-plugin-promise from 7.1.0 to 7.3.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/314">Madrapps/jacoco-report#314</a></li>
<li>Update dependencies - Node 24 by <a
href="https://github.com/thsaravana"><code>@​thsaravana</code></a> in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/320">Madrapps/jacoco-report#320</a></li>
<li>Release 1.8.0 by <a
href="https://github.com/thsaravana"><code>@​thsaravana</code></a> in <a
href="https://redirect.github.com/Madrapps/jacoco-report/pull/321">Madrapps/jacoco-report#321</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Madrapps/jacoco-report/compare/v1.7.2...v1.8.0">https://github.com/Madrapps/jacoco-report/compare/v1.7.2...v1.8.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/e51ce1f46f7f8b5331593f935e59cbaf44b84920"><code>e51ce1f</code></a>
Release 1.8.0 (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/321">#321</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/6e277c5e84a92823f9f2bedb98bcfc654f853b5d"><code>6e277c5</code></a>
Update dependencies - Node 24 (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/320">#320</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/8cd82edaad1cb66dce2fff04423d033d155731aa"><code>8cd82ed</code></a>
Bump eslint-plugin-promise from 7.1.0 to 7.3.0 (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/314">#314</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/fe40aed5b33ed6a74a74baf1b971ae8902dd4c80"><code>fe40aed</code></a>
Bump <code>@​octokit/request-error</code> from 5.1.0 to 5.1.1 (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/319">#319</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/fcffed9b340a2cb027a7491558945cb355e1389b"><code>fcffed9</code></a>
Bump globals from 15.14.0 to 17.6.0 (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/317">#317</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/97271b3031bbbea3c5b1708491a31c42c306f27d"><code>97271b3</code></a>
Bump octokit from 4.0.2 to 5.0.5 (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/309">#309</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/775c401329b49ebb8d018ca14e863ef4523ffc5f"><code>775c401</code></a>
Bump <code>@​octokit/request</code> (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/312">#312</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/a4d5c6ab9c2794fd73f6e9511b18d3d9978c0a7b"><code>a4d5c6a</code></a>
Bump <code>@​octokit/plugin-paginate-rest</code> (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/311">#311</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/566870688b61542ffbf72a8a55b9f72b61c9212f"><code>5668706</code></a>
Bump webpack-cli from 5.1.4 to 7.0.3 (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/308">#308</a>)</li>
<li><a
href="https://github.com/Madrapps/jacoco-report/commit/7783a4ed10087d6b5dda9f32211ff2d2db9896fa"><code>7783a4e</code></a>
Bump <code>@​types/node</code> from 22.10.2 to 25.9.1 (<a
href="https://redirect.github.com/madrapps/jacoco-report/issues/307">#307</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/madrapps/jacoco-report/compare/50d3aff4548aa991e6753342d9ba291084e63848...e51ce1f46f7f8b5331593f935e59cbaf44b84920">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=madrapps/jacoco-report&package-manager=github_actions&previous-version=1.7.2&new-version=1.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

You can trigger a rebase of this PR by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 09:13:30 +00:00
dependabot[bot] dff3101ca7 build(deps): bump pillow from 12.2.0 to 12.3.0 in /engine in the uv group across 1 directory (#7119)
Bumps the uv group with 1 update in the /engine directory:
[pillow](https://github.com/python-pillow/Pillow).

Updates `pillow` from 12.2.0 to 12.3.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/python-pillow/Pillow/releases">pillow's
releases</a>.</em></p>
<blockquote>
<h2>12.3.0</h2>
<p><a
href="https://pillow.readthedocs.io/en/stable/releasenotes/12.3.0.html">https://pillow.readthedocs.io/en/stable/releasenotes/12.3.0.html</a></p>
<h2>Removals</h2>
<ul>
<li>Remove non-image ImageCms modes <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9697">#9697</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
</ul>
<h2>Documentation</h2>
<ul>
<li>Add release notes for SBOM and performance improvements <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9747">#9747</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Add security release notes <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9741">#9741</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Add release notes for Python 3.15 beta wheels <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9696">#9696</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>ImageFont can also be used with ImageText <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9597">#9597</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Additional guidelines for security reports <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9659">#9659</a>
[<a
href="https://github.com/wiredfool"><code>@​wiredfool</code></a>]</li>
<li>Fixed typo <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9636">#9636</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Added CVEs to 12.2.0 release notes <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9591">#9591</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Revise development support information in README <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9583">#9583</a>
[<a
href="https://github.com/aclark4life"><code>@​aclark4life</code></a>]</li>
<li>Add INCIDENT_RESPONSE.md <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9555">#9555</a>
[<a
href="https://github.com/aclark4life"><code>@​aclark4life</code></a>]</li>
<li>Add STRIDE threat model to security docs <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9562">#9562</a>
[<a
href="https://github.com/aclark4life"><code>@​aclark4life</code></a>]</li>
<li>Add CVEs to 12.2.0 release notes <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9556">#9556</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update README with revised security policy <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9553">#9553</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update security policy <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9552">#9552</a>
[<a
href="https://github.com/aclark4life"><code>@​aclark4life</code></a>]</li>
<li>Update macOS tested Python versions <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9534">#9534</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
</ul>
<h2>Dependencies</h2>
<ul>
<li>Update dependency harfbuzz to v14.2.1 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9720">#9720</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency mypy to v2 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9653">#9653</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency cibuildwheel to v4 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9665">#9665</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update github-actions <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9655">#9655</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency libavif to v1.4.2 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9652">#9652</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency lcms2 to v2.19.1 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9651">#9651</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency check-jsonschema to v0.37.2 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9650">#9650</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update google/oss-fuzz digest to d872252 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9614">#9614</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency lcms2 to v2.19 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9609">#9609</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency libpng to v1.6.58 - autoclosed <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9608">#9608</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency harfbuzz to v14 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9610">#9610</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency mypy to v1.20.2 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9599">#9599</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update github-actions <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9611">#9611</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Update dependency cibuildwheel to v3.4.1 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9607">#9607</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
<li>Move dependency versions to single JSON and enable Renovate <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9559">#9559</a>
[<a href="https://github.com/hugovk"><code>@​hugovk</code></a>]</li>
<li>Updated raqm to 0.10.5 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9557">#9557</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Update dependency cibuildwheel to v3.4.0 <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9532">#9532</a>
[@<a href="https://github.com/apps/renovate">renovate[bot]</a>]</li>
</ul>
<h2>Testing</h2>
<ul>
<li>Remove matrix.os from benchmark <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9735">#9735</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Remove references to libavif patch <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9734">#9734</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
<li>Add benchmark tests <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9654">#9654</a>
[<a href="https://github.com/akx"><code>@​akx</code></a>]</li>
<li>Use reshape() instead of setting NumPy array shape directly <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9728">#9728</a>
[<a
href="https://github.com/radarhere"><code>@​radarhere</code></a>]</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python-pillow/Pillow/commit/bb1d8e8ab8d29048624d96e3ee53cecf7c13d13d"><code>bb1d8e8</code></a>
12.3.0 version bump</li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/e63fc481dc2e07e21d5403deafb8f1ed98a513af"><code>e63fc48</code></a>
Add release notes for SBOM and performance improvements (<a
href="https://redirect.github.com/python-pillow/Pillow/issues/9747">#9747</a>)</li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/13b701bbab291eec4bc87ea17ba06c94e5fe3054"><code>13b701b</code></a>
Add release notes for <a
href="https://redirect.github.com/python-pillow/Pillow/issues/9679">#9679</a></li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/5564ca72fcd59d040e270af5dcf17a0d7161c364"><code>5564ca7</code></a>
List methods</li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/a0920fd384f800b5d0ba3dd29ecdeae4f1d4043b"><code>a0920fd</code></a>
Speed up ImageChops operations (<a
href="https://redirect.github.com/python-pillow/Pillow/issues/9738">#9738</a>)</li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/07e9a6cd5336dc6cf8cae9165cd70cdd2b3e42fc"><code>07e9a6c</code></a>
Speed up <code>Image.filter()</code> (<a
href="https://redirect.github.com/python-pillow/Pillow/issues/9736">#9736</a>)</li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/a94578cf9649ea13e426cf7fb2b71b39ffc0dd50"><code>a94578c</code></a>
Speed up <code>Image.getchannel()</code>, <code>Image.merge()</code>,
<code>Image.putalpha()</code> and `Image...</li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/53e02c43c919d149b2a154a5180079f9df18fbbb"><code>53e02c4</code></a>
Speed up <code>Image.fill()</code>, <code>Image.linear_gradient()</code>
and `Image.radial_gradient...</li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/af037475be8634ba739744243164ba9e2c8346a6"><code>af03747</code></a>
Speed up <code>Image.resample()</code> (<a
href="https://redirect.github.com/python-pillow/Pillow/issues/9739">#9739</a>)</li>
<li><a
href="https://github.com/python-pillow/Pillow/commit/5c9ca56c3e5fba52b647809fbb0986c87e73a571"><code>5c9ca56</code></a>
Speed up <code>alpha_composite</code>, <code>matrix</code>,
<code>negative</code>, <code>quantize</code> (<a
href="https://redirect.github.com/python-pillow/Pillow/issues/9740">#9740</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/python-pillow/Pillow/compare/12.2.0...12.3.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pillow&package-manager=uv&previous-version=12.2.0&new-version=12.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 09:13:22 +00:00
dependabot[bot] af1acb68d5 build(deps): bump actions/setup-python from 6.2.0 to 7.0.0 (#7185)
Bumps [actions/setup-python](https://github.com/actions/setup-python)
from 6.2.0 to 7.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-python/releases">actions/setup-python's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>What's Changed</h2>
<h3>Enhancements</h3>
<ul>
<li>Migrate to ESM and upgrade dependencies by <a
href="https://github.com/priyagupta108"><code>@​priyagupta108</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/1330">actions/setup-python#1330</a></li>
<li>Pin SHA commits and update docs with latest versions by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/1338">actions/setup-python#1338</a></li>
<li>Remove the pip-install input by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-python/pull/1336">actions/setup-python#1336</a></li>
</ul>
<h3>Bug Fix</h3>
<ul>
<li>Fix to Classify stderr warning messages as warnings instead of
errors in annotations by <a
href="https://github.com/lmvysakh"><code>@​lmvysakh</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/1335">actions/setup-python#1335</a></li>
<li>Validate and retry manifest fetch to prevent silent failures by <a
href="https://github.com/priyagupta108"><code>@​priyagupta108</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/1332">actions/setup-python#1332</a></li>
</ul>
<h3>Dependency Upgrade</h3>
<ul>
<li>Bump certifi from 2020.6.20 to 2024.7.4 in
/<strong>tests</strong>/data by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/1328">actions/setup-python#1328</a></li>
<li>Remove EOL Python versions and Bumps numpy text fixture by <a
href="https://github.com/priya-kinthali"><code>@​priya-kinthali</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/1333">actions/setup-python#1333</a></li>
<li>Upgrade <code>@​actions/cache</code> to 6.2.0 by <a
href="https://github.com/philip-gai"><code>@​philip-gai</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/1337">actions/setup-python#1337</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/lmvysakh"><code>@​lmvysakh</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-python/pull/1335">actions/setup-python#1335</a></li>
<li><a
href="https://github.com/philip-gai"><code>@​philip-gai</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-python/pull/1337">actions/setup-python#1337</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-python/compare/v6...v7.0.0">https://github.com/actions/setup-python/compare/v6...v7.0.0</a></p>
<h2>v6.3.0</h2>
<h2>What's Changed</h2>
<h3>Enhancement</h3>
<ul>
<li>Add RHEL support and include Linux distro in cache keys by <a
href="https://github.com/priyagupta108"><code>@​priyagupta108</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/1323">actions/setup-python#1323</a></li>
<li>Fix pip cache error handling on Windows by <a
href="https://github.com/priyagupta108"><code>@​priyagupta108</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/1040">actions/setup-python#1040</a></li>
</ul>
<h3>Dependency update</h3>
<ul>
<li>Upgrade minimatch from 3.1.2 to 3.1.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/1281">actions/setup-python#1281</a></li>
<li>Upgrade actions dependencies by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a>
with <a href="https://github.com/Copilot"><code>@​Copilot</code></a> in
<a
href="https://redirect.github.com/actions/setup-python/pull/1303">actions/setup-python#1303</a></li>
<li>Upgrade <code>@​actions/cache</code> to 5.1.0, log cache write
denied by <a
href="https://github.com/jasongin"><code>@​jasongin</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/1324">actions/setup-python#1324</a></li>
<li>Upgrade dependency versions and test workflow configuration by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-python/pull/1322">actions/setup-python#1322</a></li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Update advanced-usage.md by <a
href="https://github.com/Dunky-Z"><code>@​Dunky-Z</code></a> in <a
href="https://redirect.github.com/actions/setup-python/pull/811">actions/setup-python#811</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a>
with <a href="https://github.com/Copilot"><code>@​Copilot</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-python/pull/1303">actions/setup-python#1303</a></li>
<li><a href="https://github.com/jasongin"><code>@​jasongin</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-python/pull/1324">actions/setup-python#1324</a></li>
<li><a href="https://github.com/Dunky-Z"><code>@​Dunky-Z</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-python/pull/811">actions/setup-python#811</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-python/compare/v6.2.0...v6.3.0">https://github.com/actions/setup-python/compare/v6.2.0...v6.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/setup-python/commit/5fda3b95a4ea91299a34e894583c3862153e4b97"><code>5fda3b9</code></a>
Pin SHA commits and update docs with latest versions (<a
href="https://redirect.github.com/actions/setup-python/issues/1338">#1338</a>)</li>
<li><a
href="https://github.com/actions/setup-python/commit/4ab7e95f05e168b4356aebde89dd84f59c283d8e"><code>4ab7e95</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/setup-python/issues/1337">#1337</a>
from actions/philip-gai/bump-actions-cache-6-2-0</li>
<li><a
href="https://github.com/actions/setup-python/commit/0f3a009f475dbea83c0371cd85d099690fee8c5c"><code>0f3a009</code></a>
Remove the pip-install input (<a
href="https://redirect.github.com/actions/setup-python/issues/1336">#1336</a>)</li>
<li><a
href="https://github.com/actions/setup-python/commit/f8cf4291c8b8e273ddd26e569454615c7315d932"><code>f8cf429</code></a>
Migrate to ESM and upgrade dependencies (<a
href="https://redirect.github.com/actions/setup-python/issues/1330">#1330</a>)</li>
<li><a
href="https://github.com/actions/setup-python/commit/54baeea5b34417d10a7479663a23cca53ea209b5"><code>54baeea</code></a>
Validate and retry manifest fetch to prevent silent failures (<a
href="https://redirect.github.com/actions/setup-python/issues/1332">#1332</a>)</li>
<li><a
href="https://github.com/actions/setup-python/commit/c7092773a316760f4ecfe498e4af668a4dafeac5"><code>c709277</code></a>
Annotation code fix (<a
href="https://redirect.github.com/actions/setup-python/issues/1335">#1335</a>)</li>
<li><a
href="https://github.com/actions/setup-python/commit/6849080452e69b330395e8a6d23cf90f56d76a1a"><code>6849080</code></a>
remove EOL Python versions and Bumps numpy text fixture (<a
href="https://redirect.github.com/actions/setup-python/issues/1333">#1333</a>)</li>
<li><a
href="https://github.com/actions/setup-python/commit/0903b469fbf4441aadfe4f4b249dc5b1fba3a73e"><code>0903b46</code></a>
Bump certifi from 2020.6.20 to 2024.7.4 in /<strong>tests</strong>/data
(<a
href="https://redirect.github.com/actions/setup-python/issues/1328">#1328</a>)</li>
<li><a
href="https://github.com/actions/setup-python/commit/ece7cb06caefa5fff74198d8649806c4678c61a1"><code>ece7cb0</code></a>
Fix pip cache error handling on Windows. (<a
href="https://redirect.github.com/actions/setup-python/issues/1040">#1040</a>)</li>
<li><a
href="https://github.com/actions/setup-python/commit/1d18d7af5f767c1259ede05a0a5bcc30f3dcf1cf"><code>1d18d7a</code></a>
Update advanced-usage.md (<a
href="https://redirect.github.com/actions/setup-python/issues/811">#811</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/setup-python/compare/a309ff8b426b58ec0e2a45f0f869d46889d02405...5fda3b95a4ea91299a34e894583c3862153e4b97">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=6.2.0&new-version=7.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-29 09:13:07 +00:00
Reece Browne 22ec0947c9 Storybook coverage: scan harness + stories (#7073)
## What

Gets most of the app's components into Storybook and adds a scan that
runs every story in a real browser, so we have a base to build
accessibility testing on next.

- **~380 new stories**, taking story files from 144 to 526. Components
with a story:

  | Layer | Before | After |
  |---|---|---|
  | core | 41 / 309 (13%) | **183 / 309 (59%)** |
  | portal | 91 / 161 (57%) | **127 / 161 (79%)** |
  | proprietary | 1 / 105 (1%) | **39 / 105 (37%)** |
| cloud / desktop / saas / portal-saas / prototypes | 0 / 84 | 0 / 84
(unchanged) |
  | **Total** | **133 / 659 (20%)** | **349 / 659 (53%)** |

Both columns are counted the same way — every `.tsx` exporting a
component, so the denominator includes things that aren't really visual
units (contexts, providers, barrels). Excluding those it's 22% → 58%.
Either way it's reproducible from the tree rather than a number you have
to take on trust.

- **Scan harness** — the Storybook Vitest addon runs each story in
headless Chromium as a **render/smoke check** (a story must mount
without throwing). New task: `task frontend:storybook:test` (pass a
filter, e.g. `-- Button`). Separate Vitest config so it doesn't touch
the existing jsdom unit tests.

## Scope

- **Stories and Storybook config only, with one exception:** a one-line
fix to `ProviderCard`, which re-rendered forever whenever its optional
`settings` prop was omitted. Called out because it's the only component
source change here.
- The preview gains a `QueryClientProvider` (the portal app has one, so
stories reaching a query hook threw without it), and the scan task now
installs the browser it drives.
- **a11y is report-only** and **nothing runs the scan in CI yet** —
enforcing a11y and wiring it into CI is the follow-up, #7086.
- Components that can't render as an isolated unit are **not** included:
anything needing the full editor runtime (ToolWorkflow / FileManager /
AppConfig / a live PDF engine) or that's headless (providers, gates, API
bridges, config factories). Stories that only rendered by mounting the
whole `AppProviders` tree were dropped for the same reason — that isn't
isolation, and the tree's ErrorBoundary swallowed render failures so
those stories could never fail. A few that need assets the headless
browser can't serve are tagged `!test`, so they still show in the UI but
sit out the scan.

## Testing

Typecheck (all build variants), ESLint, Prettier and the unit suite
pass. Every story in the scanned set mounts without throwing.

## Notes for reviewers

- Stories use the `@app`/`@core`/`@portal`/`@proprietary` aliases (no
deep relative imports) and mock data-fetching components with MSW.
- Running the full suite in one go can flake on the Vite dep-optimizer;
scan in small batches (or by filter) for a stable local run.
2026-07-28 16:06:06 +00:00
ConnorYohandReece Browne ba404d3f90 PAYG bundle: server-authoritative price (inline amount_off coupon) + #7032 review nits (#7156)
## What

Follow-up to #7032. Makes the prepaid-bundle price
**server-authoritative** and removes the percent-coupon rounding drift,
by switching the 12-for-10 discount from a pre-made `percent_off` Stripe
coupon to an **edge-function-computed inline `amount_off` coupon**. Also
folds in Ethan's #7032 review nits.

This is a money-mechanism change, so it was verified against the Deno
tests and is ready for a V2-preview check before rollout.

## SaaS side — already on `v3` (purely additive)

The edge fn + migration were pushed **directly to `v3`** (commit
`4534ff1c1`), since the DB change is purely additive (a
backward-compatible function replacement — no table/column/data
changes):

- `create-payg-bundle-quote`: retrieves the Stripe Price for the bundle,
computes `subtotal = unit_amount x pool_credits` (falls back to
`round(unit_amount_decimal x pool_credits)`), `discount = round(subtotal
x 2 / 12)`, `total = subtotal - discount`; mints a single-use
fixed-amount coupon (`amount_off`, `duration: once`, `max_redemptions:
1`, `redeem_by = valid_until`) and applies it instead of the stored
percent coupon; persists `total` via `p_price_minor`.
- Migration `20260803000000_payg_bundle_quote_stripe_price_minor.sql`:
`payg_set_bundle_quote_stripe` gains `p_price_minor BIGINT DEFAULT NULL`
→ `price_minor = COALESCE(p_price_minor, price_minor)`.

**Deploy choreography (important):** the migration must apply **before**
the edge fn is deployed — the fn now calls the 4-arg
`payg_set_bundle_quote_stripe`. #7032's own Supabase migration is
already on `main`/`v3`.

## This PR (FE)

- **Server-authoritative price:** `bundlePriceMinor` now computes
`subtotal - round(subtotal x (granted-paid)/granted)` (round the
discount, then subtract) — identical to the edge fn — so the pre-mint
estimate matches the `amount_off` charged, and the persisted/frozen
total, to the penny (they previously diverged by a minor unit on
exact-half ties). Tie-case test added.

### Ethan's #7032 review nits

- **1** — comments in `ActivationChoiceModal` / `FreePlanView` no longer
assert the metered subscription is auto-provisioned off the saved card;
they describe it as a known, not-yet-wired follow-up.
- **2** — corrected the price-authority narrative (`stripe.ts`,
`BundleCheckoutModal`): the client-sent `p_price_minor` is a pre-mint
**display estimate only**; the edge fn overwrites `price_minor` with the
server total once the quote is minted. **Verified** the edge fn builds
the Stripe line from `bundle_price_id x pool_credits` with `amount_off`
from the retrieved Price — it never uses the client price.
- **4** — `ensureStripeQuote`'s reuse key now includes the
posture/size/pipeline ids (`buildStripeQuoteSig`), not just pool+PO, so
a same-pool sizing edit re-mints and re-persists instead of leaving
stale sizing on the row.
- **5** — `SpendLimitPicker`: a cleared field (maps to `0`) can no
longer proceed as a `$0` cap — the cap-step Continue is disabled and
`handleContinue` guards on it (empty = incomplete, distinct from the
explicit `null` "No limit").
- **6** — `"prepaid PDFs"` code fallbacks aligned to the `"prepaid
credits"` TOML (`usageMeters`, `PrepaidCapacityCard`).

## Testing

- SaaS Deno: **25/25** (coupon `amount_off == round(subtotal*2/12)`,
`p_price_minor == total` persisted, `unit_amount_decimal` fallback,
exact-half tie, zero-discount path, price/coupon failure paths).
- FE vitest: **50** billing/format tests pass; prettier + eslint clean;
tsc clean for all changed files.
- Pending: manual V2-preview check that the invoice shows a concrete
`-$X.00` discount line (labelled "12 months for the price of 10") equal
to the in-app total.

Closes the residual half of #7032 review finding #2 — once
merged/deployed, the in-app total, the persisted value, and the Stripe
invoice all agree.

---------

Co-authored-by: Reece Browne <74901996+reecebrowne@users.noreply.github.com>
2026-07-28 13:05:20 +00:00
ConnorYoh a380a82234 build: raise Gradle daemon heap to avoid intermittent CI OOM (#7151)
## Problem

The `build (25, saas)` CI job intermittently fails with:

```
The Daemon will expire immediately since the JVM garbage collector is thrashing.
The currently configured max heap space is '512 MiB' and the configured max metaspace is '384 MiB'.
FAILURE: Build failed with an exception.
* What went wrong:
Gradle build daemon has been stopped: since the JVM garbage collector is thrashing
```

`gradle.properties` never set `org.gradle.jvmargs`, so the daemon runs
on Gradle's 512 MiB default heap. The larger builds — the `saas` flavor
in particular, which compiles core + proprietary + saas — exhaust it
under `org.gradle.parallel=true`, and the daemon dies mid-build. It's
flaky (passes on re-run), which makes it a recurring, noisy CI failure.

## Fix

```properties
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=1g
```

2 GiB heap + 1 GiB metaspace gives comfortable headroom on GitHub-hosted
runners and typical dev machines, well clear of the thrash point.
One-line, repo-wide config change.

## Verification

- `./gradlew help` starts the daemon cleanly with the new args (no
malformed-arg failure).
- The real signal is CI: this branch's `build (25, saas)` should stop
OOM-ing.

Split out from #7048 (Plan & Usage) since it's unrelated build
infrastructure.
2026-07-27 10:46:56 +00:00
ConnorYoh 3813ca360e PAYG prepaid usage bundles (#7032)
# Prepaid usage bundles

Teams on pay‑as‑you‑go can **buy a year of PDF processing up front, at a
discount** — *"12 months for the price of 10."* You pre‑buy a pool of
credits; they're spent **before** any metered billing and sit
**outside** the monthly spend limit; unused capacity expires after 12
months.

---

## What this PR delivers

**Buy → quote → invoice → pay (Stripe‑Quotes‑native).**
- A team lead sizes the pool in the calculator (persisted as a quote
row), which doubles as the quote page with a **"Download quote (PDF)"**
— the PDF is **Stripe's own rendered quote** (same mechanism procurement
uses), not an app‑generated document.
- **Finalise** turns the accepted quote into an invoice; the lead can
**download the invoice** or **pay online** (Stripe hosted invoice).
**Card and bank‑transfer / PO** are both supported (payment‑method
fork), on net terms.
- The billing page loads the in‑flight quote/invoice on open, so the CTA
resumes the right step (**View quote** / **Pay invoice to complete**)
and offers **Cancel purchase** (voids the invoice + quote and restarts).

**Prepaid is usable on its own — no subscription required.** The
entitlement gate honours a live prepaid pool in both cases:
- *Unsubscribed*: once the one‑time free grant is spent, a live pool
keeps the team **fully entitled** (all feature gates) rather than
degraded.
- *Subscribed*: a team **at/over its metered cap** but holding a live
pool stays fully entitled — prepaid draws are netted out of metered
spend, so the pool genuinely sits outside the cap.

Only when the free grant **and** the prepaid pool are both empty do
billable categories stop.

**Coordinated SaaS change (ships with this — `Stirling-PDF-SaaS` `v3`
branch):** the `invoice.paid` webhook credits the pool idempotently
(keyed on the invoice id) and settles the quote. Metered‑subscription
provisioning is best‑effort and **classified** — a permanent Stripe 4xx
(the single‑use hosted‑invoice card can't be attached) is a claimed
no‑op (HTTP 200, no retry) so Stripe doesn't redeliver forever; only
transient errors (5xx / connection / rate‑limit) retry. A failed credit
now retries rather than silently dropping a paid bundle.

### Flow

1. Lead sizes the pool and agrees to the terms → the browser sends team
+ capacity + consent, **never a price**.
2. A leader‑gated server function looks up the price and creates a
Stripe **quote** (line quantity = capacity).
3. Lead **finalises** → the quote becomes a Stripe **invoice**; download
it or pay online (card or bank transfer).
4. On `invoice.paid`, the webhook **credits the prepaid pool**
(idempotent) and settles the quote.
5. Usage then draws **free grant → prepaid pool → meter**; the pool is
usable with no subscription.

<img width="1280" height="920" alt="01-activation-fork"
src="https://github.com/user-attachments/assets/e8981dc7-809d-4fc5-bfde-71e619096b7b"
/>
<img width="1280" height="920" alt="02-calculator"
src="https://github.com/user-attachments/assets/81f6b886-1797-4c54-ba18-97d126be78e2"
/>
<img width="1120" height="600" alt="03-free-plan"
src="https://github.com/user-attachments/assets/c4057fde-d965-47dd-93e8-f2f0f612aa73"
/>
<img width="1105" height="1285" alt="04-subscribed-prepaid"
src="https://github.com/user-attachments/assets/9d1d0ef1-29d0-4bd4-9c17-ac5f68f88ca8"
/>


---

## In a follow‑up (not this PR)

1. **Authoritative price via an inline fixed‑amount coupon** *(in
progress in a separate PR).* Replace the percentage 12‑for‑10 coupon
with an edge‑function‑computed **`amount_off`** coupon: the invoice
shows a concrete "−$X.00" discount line, the total is deterministic (no
percentage‑rounding drift), and the persisted price becomes
**server‑authoritative**. Money‑mechanism change — needs validation
against the Stripe test env, so it warrants its own testable PR.
2. **Metered auto‑resume when the pool empties.** Save the paying card
at invoice time (`setup_future_usage`) for card payers → real
`charge_automatically`; a cardless `send_invoice` subscription for
bank‑transfer / PO. This makes the "processing continues at the metered
rate" promise true for everyone.
3. **Provisioning idempotency hardening** (SaaS repo). Idempotency key
on subscription creation + a conditional link RPC, so a webhook
redelivery or link‑RPC failure can't create duplicate or orphaned
subscriptions.
4. **Repo‑wide "credits" copy** across *all* of usage & billing (this PR
only makes its own additions consistent).

---

## Known edges (current state)

- **Cardless teams degrade when the pool empties.** An unsubscribed
bundle team that runs the pool dry hits DEGRADED (metered paused), not
automatic metered continuation — because no metered subscription gets
provisioned off a hosted‑invoice card. The consent copy states
processing "continues at the metered rate"; that promise is
intentionally **ahead of the mechanism** (follow‑up 2), and the 12‑month
term is the runway to deliver it. The prepaid capacity itself stays
fully usable in the meantime.
- **In‑app total vs charge can differ by ≤1¢** until follow‑up 1 lands.
The **shared approval document (the Stripe quote PDF) and the actual
invoice are already Stripe‑authoritative**; the persisted price shown
in‑app is still a front‑end estimate (percentage‑coupon rounding), so it
can differ from Stripe by a rounding cent. Resume‑time drift is fixed
(frozen to persisted); exact‑to‑the‑penny parity arrives with the
authoritative‑price follow‑up.
- **Provisioning idempotency is latent, not live.** The
duplicate/orphan‑subscription window only becomes reachable once
card‑linking (follow‑up 2) makes provisioning actually run; hardening is
tracked as follow‑up 3.
- **One job can overshoot the spend cap via a near‑empty pool.** A
subscribed team that has hit its metered cap but still holds a
*nearly‑exhausted* pool is let through (the pool overrides the cap
gate); if a job needs more than the pool has left, the pool drains to
zero and the **remainder meters**, so that single job's remainder can
bill just past the "never past your spend limit" ceiling. Bounded to one
job's overshoot and only at the pool's tail; the alternative — blocking
the job — would strand paid‑for capacity, so this is a deliberate trade.

---

## Testing

- **Java** — `EntitlementServiceTest` (18) incl.
unsubscribed‑live‑pool‑stays‑FULL,
subscribed‑over‑cap‑with‑pool‑stays‑FULL, and lazy‑read guards.
- **Frontend** — `useBundleFlowState` + `Usage` render tests; portal &
SaaS `tsc`; i18n audit; `lint:colors`; toml‑sort; prettier.
- **SaaS webhook** (`v3`) — Deno tests for terminal‑vs‑transient
provisioning classification (rate‑limit treated as retryable),
credit‑error‑retries, and an end‑to‑end no‑storm assertion on the
unusable‑card path.

*Preview:* the checkout runs in a Supabase function in
`Stirling-PDF-SaaS` (`v3`); a live V2 preview is linked in the
auto‑deploy comment below. Screenshots to be refreshed — the checkout
modal changed since the originals.
2026-07-24 12:53:16 +00:00
Anthony Stirling 1681b5d298 Source and connections changes to integrations (#7068) 2026-07-24 11:50:17 +01:00
Anthony Stirling 831bd4fe94 Remove depot.dev support from GitHub Actions workflows (#7148) 2026-07-24 10:52:26 +01:00
James Brunton 4fbb2fe885 Add PR Quiz skill (#7137)
# Description of Changes
Adds a Claude skill to quiz you about your PR, to help check that you
understand the code in the PR.

<img width="796" height="589" alt="image"
src="https://github.com/user-attachments/assets/0f520a99-9acf-4922-85fe-5f49f8f68823"
/>

<img width="811" height="621" alt="image"
src="https://github.com/user-attachments/assets/e440c775-d901-443b-a213-1cc4ee6303af"
/>
2026-07-24 09:37:10 +00:00
ConnorYoh 54bf32485f feat(portal): adopt TanStack Query with a shared per-resource query layer (#7135)
## Why

The processor/portal loads slowly because every view fetches its data on
mount with no client-side cache — navigating away and back refetches
everything, and shared data (policies, sources, roster, fleet stats) is
fetched repeatedly. This adopts **TanStack Query** so the portal caches,
dedupes, and revalidates instead.

Follows the Users-page proof-of-concept (kept as the reference A/B
example behind a dev flag); DevTools before/after confirmed revisiting a
cached view now costs zero network calls.

## What

**Shared per-resource query layer** (`portal/queries/`) — the mechanism
for both in-view and cross-view sharing:
- `keys.ts` (flavor-agnostic queryKey factory), `adapters.ts`
(`toAsyncState` → the existing `AsyncState` shape, so view bodies barely
change)
- One **base hook per endpoint**; **derived hooks**
(`usePoliciesOverview`, `useProcessorFlow`, `useOnboardingProgress`)
compose them
- The bundle functions (`fetchPolicies`, `fetchProcessorFlow`,
`useOnboardingProgress`) are decomposed into base queries — otherwise
the caches wouldn't dedupe against each other

**Migrated:** Documents, Policies, Pipelines, Sources + all of Home's
fetching cards. Mutations use `invalidateQueries` (Policies' `version`
bump removed; Source/Pipeline builders invalidate-then-navigate;
ConnectionsTab + S3 picker share one cache).

**SaaS `/team/my` collapse:** `resolveTeam()` reads through the shared
cache (`ensureQueryData`), so roster + teams resolve it once (2→1), with
a direct-fetch fallback when no provider is mounted.

`QueryClientProvider` is mounted once at the portal root (`PortalApp`),
above the router, so the cache survives navigation.

## Impact on duplicate fetches

- **In-view:** Home `/policies` ×3, `/policies/runs` ×3, `/sources` ×2,
`/v1/editor/deployment` ×2 → **1× each** per mount
- **Cross-view:** Policies / Sources / Users / EditorAdmin /
Infrastructure reuse Home's warmed cache within `staleTime` (no refetch
on navigation)
- **SaaS Users:** `/team/my` 2× → **1×**

## Testing

- Portal typecheck + SaaS typecheck, ESLint (`--max-warnings=0`),
Prettier — all green
- **224 portal tests pass** (existing component tests wrapped in a
shared `QueryClient` test provider)
- New: `queries/sharing.test.tsx` (in-view: 3 consumers → 1 fetch each;
cross-view: remount → 0 refetch) and a `/team/my` collapse assertion in
`UsersReactQuery.test.tsx`

## Notes for reviewers

- Keys are intentionally flavor-agnostic (local vs SaaS routing lives
inside the api fns), so one key addresses whichever backend the flavor
build resolves.
- `staleTime` 30s / `gcTime` 5m defaults; tier-dependent resources key
on tier.
- Users view keeps its dev flag/legacy path deliberately as the
documented reference.
2026-07-23 14:53:16 +00:00
Anthony Stirling a1b1f974a0 Show brand mark and Stirling name in processor sidebar (#7125)
# Description of Changes
Change logo in top left
<img width="872" height="160" alt="image"
src="https://github.com/user-attachments/assets/69f5366c-8640-41ca-9555-c5d30881678d"
/>

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-23 11:22:46 +00:00
James Brunton 29002d0b82 Improve UX around source folders in Processor (#7101)
# Description of Changes
Adds implicitly defined folders to the list of locations that folder
sources can look in, including the legacy watchedFolder folders, and the
server storage location (if enabled). Also adds a settings UI for
defining the list of allowed folders instead of having to manually edit
`settings.yml` (please excuse the styling, that's the standard styling
of the Processor, hoping it gets fixed by one of the styling PRs).

<img width="888" height="786" alt="image"
src="https://github.com/user-attachments/assets/cf6d0705-adcf-463c-8e80-6901a652068b"
/>

<img width="1103" height="713" alt="image"
src="https://github.com/user-attachments/assets/b7244592-249a-4149-994f-3a2b750f25f9"
/>
2026-07-23 11:19:24 +00:00
Anthony Stirling 1e2895a79f Add external-API integrations plus pipeline steps (#7098)
New Generic API mode with examples and integrations setup around it 

- Adds an integration operations catalogue so external-API connections
(e.g. Microsoft Purview) can be used as policy pipeline steps
- New generic external-API step calls a configured connection during a
policy run, with a verdict gate to pass/fail documents on the response
- Purview sensitivity-labelling step applies labels to processed
documents, gated behind the Purview connection being configured (WIP to
be changed later)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-23 11:18:39 +00:00
EthanHealy01 67e10138b5 Follow-up: colour token migration (compat → --c-*, hardcoded hex) (#7011)
Follow-up to #7009, which built the theme token layer (`primitives` →
`colors` → `compat`). This PR moves the whole app onto it, removes
hardcoded colours, turns on enforcement so they can't come back, and
adds a user-selectable accent.

## What this does
- **Semantic tokens everywhere** — legacy colour aliases and raw hex are
rewritten to `--c-*` tokens (`--c-surface*`, `--c-text*`, `--c-primary`,
…). Straight rename, no visual change. Genuine literals (brand/OAuth,
colour pickers, data-viz) are left as-is.
- **Fixes missing colours** — some tokens the migration referenced were
never defined, so a few surfaces (login button, auth banners, badges,
procurement view) silently lost their colour. All defined now, and they
adapt to light/dark and the accent automatically.
- **Blocking colour lint** — CI now fails on hardcoded colours,
undefined tokens, or unreadable low-contrast status colours.
- **User-selectable accent** — light and dark each get their own accent
from Settings → Appearance, contrast-clamped so text stays legible.
"Default" keeps the standard blue.

## Still to come
Remaining inline-style hex, the legacy token-definition files
(`theme.css`, `tokens.css`), and folding `zIndex.ts` onto the dimension
tokens.

## Testing
`task frontend:check:all` green; light/dark and accent switching
spot-checked.
2026-07-23 09:05:56 +00:00
Anthony Stirling 8de94ff152 Ai customization settings (#7069)
# Description of Changes
AI settings customisation in settings menu, as part of this also tested
and fixed ollama and other 3rd party AI integrations

- Adds an admin AI settings UI for customizing AI behaviour, including
per-provider model and API-key configuration
- Backend pushes AI config changes to the Python engine at runtime via a
config-push bridge, so changes apply without a restart
- Config-push is gated off in SaaS; engine now drains background tasks
on shutdown instead of cancelling them
---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-23 08:29:06 +00:00
Anthony Stirling b3875d3149 Add heuristic classification (#7050)
# Description of Changes

- Adds a non-AI heuristic classification engine that classifies
documents client-side in the browser when AI is disabled
- Classification is billed as a policy run via a fast, non-blocking
meter endpoint; a default Classification policy is seeded per team
- Enables the policy engine by default

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-23 08:28:26 +00:00
Anthony StirlingandEthanHealy01 357eb77f94 Portal: multiple named personal API keys with per-key usage tracking (#6961)
# Description of Changes

Multiple named **personal** API keys per user, replacing the single
opaque per-user key.

- Create (name + one-time secret), list, and revoke named keys from the
portal Infrastructure → API Keys tab. Works self-hosted and SaaS
(`X-API-KEY`).
- Per-key usage stats (today / trailing 30 days / lifetime);
API-processed documents are attributed to the specific key in the
processor's Documents feed.
- The legacy single per-user key keeps working and is lazily represented
as a named key. Rotating it revokes its migrated shadow row so the old
secret stops authenticating.
- Per-user (not per-key) rate limiting plus a per-user active-key cap,
so minting keys can't multiply the daily quota. Name-length cap;
race-safe migration and usage recording.

Keys are strictly personal: one owner, full access, no sharing.
Team-shared / scoped keys and per-key access levels were intentionally
left out of this PR to keep it small and easy to review; they can follow
as a separate, focused change.

> Note: the screenshots from the original revision showed an earlier
team-scoped design and need refreshing.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
2026-07-23 07:52:57 +00:00
EthanHealy01 718277a934 Portal home: trim to onboarding + processor flow, secondary Set up buttons (#7111)
Simplifies the processor home page:

- Removes everything below the processor flow (processing status strip,
recent activity, quick actions, policy summary), leaving just the
onboarding hero and processor flow.
- Changes the policy "Set up" buttons (Security/Classification) from
primary to secondary variant.

<img width="2056" height="1047" alt="Screenshot 2026-07-20 at 7 27
56 PM"
src="https://github.com/user-attachments/assets/8625b274-b52a-47be-9052-80ac3d32dd93"
/>
2026-07-22 20:08:45 +00:00
Anthony Stirling 3bf0019d7c Webhook policy source (#7051)
# Description of Changes
Create custom webhooks as a source, allows file pushes toa custom made
endpoint with custom auth ID

- Adds webhook as a policy source: external systems push documents to a
receiver endpoint, which stages the files locally and triggers the
policy run
- Requests are authenticated with HMAC signatures; receiver hardened
with bounded body reads and server-minted IDs
- Uses the same team-scoped IntegrationConfig connection model as the S3
source, with matching portal UI (source type, icon, wizard)
- Includes a policies-gated Cucumber feature covering the receiver
end-to-end

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-22 12:33:53 +00:00
Anthony Stirling 7e76097ac1 Make processor UI mobile friendly BASIC BASIC impl (#7126)
# Description of Changes

Very basic mobile impl, just makes side bar collapsable and minor other
changes "better than nothing"

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-22 11:10:53 +00:00
Anthony Stirling ce7f74a3c1 Add SaaS OG link-preview cards for app, processor and editor (#7027)
# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-22 09:46:51 +00:00
ConnorYohandJames Brunton 50c0f2bcb5 Fix Calendly scheduler: blank on first open + slow load (#7075)
## What was wrong

Opening the procurement **Schedule a call** modal had two problems:

1. **Blank the first time, works the second time.** The first open
showed nothing; closing and reopening eventually loaded Calendly.
2. **Slow to load** even when it did work.

## Why

1. Our script loader treated a script as "ready" the moment its
`<script>` tag was added to the page — not when it had actually finished
downloading. On the first open, two loads overlap (React re-runs the
effect in dev), and the second one returned "ready" too early, before
Calendly's code existed, so nothing rendered. Reopening worked because
by then the script had finished.
2. Nothing was loaded until you clicked, so the first open waited on a
cold download of Calendly's script and then its booking page.

## The fix

- Make the script loader wait for the script to **actually finish
loading**, and have overlapping loads share the same wait. This fixes
the blank-first-open (and helps every other lazy-loaded script too).
- **Warm up Calendly early**: open the connection and start fetching its
script as soon as the "Schedule a call" button appears, so the modal
opens quickly instead of downloading everything on click.
- If Calendly still can't load (e.g. blocked by an extension), show the
existing "open in a new tab" link instead of an empty modal.

## Testing

Added a unit test proving the loader only reports "ready" after the
script truly loads. Type-check, lint, and formatting all pass.

Note: I couldn't click through the live modal here (needs a linked
procurement deal running locally) — happy to do a manual open/close/open
pass before merge if you'd like.

---------

Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-07-22 09:23:15 +00:00
brios fab00f3fe2 style(sidebar): fix file sidebar button visibility spacing (#7124)
# Description of Changes

<img width="522" height="258" alt="image"
src="https://github.com/user-attachments/assets/f7310ae9-3bdb-460a-a761-d593d6daafe0"
/>


<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-22 09:22:58 +00:00
dependabot[bot]andLudy b5b9cc443f build(deps): bump com.github.junrar:junrar from 7.5.10 to 7.6.0 in /app/common (#7090)
Bumps [com.github.junrar:junrar](https://github.com/junrar/junrar) from
7.5.10 to 7.6.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/junrar/junrar/releases">com.github.junrar:junrar's
releases</a>.</em></p>
<blockquote>
<h2>Release v7.6.0</h2>
<h2>Changelog</h2>
<h2>🚀 Features</h2>
<ul>
<li>support random access for files in solid RAR4 archives (<a
href="https://github.com/junrar/junrar/commits/e0874d2">e0874d2</a>)</li>
</ul>
<h2>🏎 Perf</h2>
<ul>
<li>replace RarCRC.checkCrc with java.util.zip.CRC32 (<a
href="https://github.com/junrar/junrar/commits/5270d23">5270d23</a>)</li>
</ul>
<h2>🛠  Build</h2>
<p><strong>deps</strong></p>
<ul>
<li>bump gradle-wrapper to 9.5.1 (<a
href="https://github.com/junrar/junrar/commits/cb4b7fd">cb4b7fd</a>)</li>
<li>bump com.fasterxml.jackson.core:jackson-databind (<a
href="https://github.com/junrar/junrar/commits/0bb56b3">0bb56b3</a>)</li>
<li>bump com.fasterxml.jackson.datatype:jackson-datatype-jsr310 (<a
href="https://github.com/junrar/junrar/commits/ca621b2">ca621b2</a>)</li>
<li>bump org.jreleaser from 1.23.0 to 1.24.0 (<a
href="https://github.com/junrar/junrar/commits/90f0548">90f0548</a>)</li>
<li>bump commons-io:commons-io from 2.21.0 to 2.22.0 (<a
href="https://github.com/junrar/junrar/commits/83a5d08">83a5d08</a>)</li>
<li>bump com.github.ben-manes.versions from 0.53.0 to 0.54.0 (<a
href="https://github.com/junrar/junrar/commits/d5abcdb">d5abcdb</a>)</li>
</ul>
<p><strong>unscoped</strong></p>
<ul>
<li>replace deprecated action (<a
href="https://github.com/junrar/junrar/commits/338efcb">338efcb</a>)</li>
</ul>
<h2>Contributors</h2>
<p>We'd like to thank the following people for their contributions:
Gauthier, Gauthier Roebroeck, Robin Schimpf</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/junrar/junrar/blob/master/CHANGELOG.md">com.github.junrar:junrar's
changelog</a>.</em></p>
<blockquote>
<h1><a
href="https://github.com/junrar/junrar/compare/v7.5.10...v7.6.0">7.6.0</a>
(2026-05-13)</h1>
<h2>🚀 Features</h2>
<ul>
<li>support random access for files in solid RAR4 archives (<a
href="https://github.com/junrar/junrar/commits/e0874d2">e0874d2</a>)</li>
</ul>
<h2>🏎 Perf</h2>
<ul>
<li>replace RarCRC.checkCrc with java.util.zip.CRC32 (<a
href="https://github.com/junrar/junrar/commits/5270d23">5270d23</a>)</li>
</ul>
<h2>🛠  Build</h2>
<p><strong>deps</strong></p>
<ul>
<li>bump gradle-wrapper to 9.5.1 (<a
href="https://github.com/junrar/junrar/commits/cb4b7fd">cb4b7fd</a>)</li>
<li>bump com.fasterxml.jackson.core:jackson-databind (<a
href="https://github.com/junrar/junrar/commits/0bb56b3">0bb56b3</a>)</li>
<li>bump com.fasterxml.jackson.datatype:jackson-datatype-jsr310 (<a
href="https://github.com/junrar/junrar/commits/ca621b2">ca621b2</a>)</li>
<li>bump org.jreleaser from 1.23.0 to 1.24.0 (<a
href="https://github.com/junrar/junrar/commits/90f0548">90f0548</a>)</li>
<li>bump commons-io:commons-io from 2.21.0 to 2.22.0 (<a
href="https://github.com/junrar/junrar/commits/83a5d08">83a5d08</a>)</li>
<li>bump com.github.ben-manes.versions from 0.53.0 to 0.54.0 (<a
href="https://github.com/junrar/junrar/commits/d5abcdb">d5abcdb</a>)</li>
</ul>
<p><strong>unscoped</strong></p>
<ul>
<li>replace deprecated action (<a
href="https://github.com/junrar/junrar/commits/338efcb">338efcb</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/junrar/junrar/commit/cb4b7fdb84269e95741fa22120e08ceb15a06152"><code>cb4b7fd</code></a>
build(deps): bump gradle-wrapper to 9.5.1</li>
<li><a
href="https://github.com/junrar/junrar/commit/0bb56b3df4e3b6d14f73de92746a2eb47dd2d7a3"><code>0bb56b3</code></a>
build(deps): bump com.fasterxml.jackson.core:jackson-databind</li>
<li><a
href="https://github.com/junrar/junrar/commit/ca621b22421f9e846df23112b32113230610c8d9"><code>ca621b2</code></a>
build(deps): bump
com.fasterxml.jackson.datatype:jackson-datatype-jsr310</li>
<li><a
href="https://github.com/junrar/junrar/commit/e0874d213832bbeaa8eb265c79479b01b5fa7392"><code>e0874d2</code></a>
feat: support random access for files in solid RAR4 archives</li>
<li><a
href="https://github.com/junrar/junrar/commit/90f0548c728b0bf2e94f6e26f9e6396d9d0a7262"><code>90f0548</code></a>
build(deps): bump org.jreleaser from 1.23.0 to 1.24.0</li>
<li><a
href="https://github.com/junrar/junrar/commit/83a5d085dc84991226229fef1515cc902d129241"><code>83a5d08</code></a>
build(deps): bump commons-io:commons-io from 2.21.0 to 2.22.0</li>
<li><a
href="https://github.com/junrar/junrar/commit/338efcb5472be051989fbafd7179d561c71722eb"><code>338efcb</code></a>
ci: replace deprecated action</li>
<li><a
href="https://github.com/junrar/junrar/commit/5270d235ade54d96dfc9958ab06f495fbbd169e7"><code>5270d23</code></a>
perf: replace RarCRC.checkCrc with java.util.zip.CRC32</li>
<li><a
href="https://github.com/junrar/junrar/commit/d5abcdb9af988ddfa76e98d80787e15525488332"><code>d5abcdb</code></a>
build(deps): bump com.github.ben-manes.versions from 0.53.0 to
0.54.0</li>
<li><a
href="https://github.com/junrar/junrar/commit/edadb28896962fdcf754029bafd0994aaff24530"><code>edadb28</code></a>
chore(release): 7.5.10 [skip ci]</li>
<li>See full diff in <a
href="https://github.com/junrar/junrar/compare/v7.5.10...v7.6.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ludy <Ludy87@users.noreply.github.com>
2026-07-22 07:50:24 +00:00
Ludy a4ac034a18 feat(build): centralize Java toolchain language version configuration (#6894)
# Description of Changes

This change centralizes the Java toolchain language version into a
single `buildJavaLanguageVersion` variable and reuses it across all Java
compilation tasks to ensure consistent toolchain selection.

### What was changed

- Introduced a shared `buildJavaLanguageVersion` variable derived from
the optional `javaVersion` project property, defaulting to Java 25.
- Updated the root project's Java toolchain configuration to use the
shared variable.
- Updated all subproject Java toolchain configurations to reference the
same shared variable instead of a hardcoded language version.
- Explicitly configured the `compileRestartHelper` task to use a
`javaCompiler` resolved from the same shared toolchain version.

### Why the change was made

- Eliminate duplicated Java language version definitions.
- Ensure all compilation tasks use the same Java toolchain
configuration.
- Allow the `javaVersion` project property to consistently affect the
root project, subprojects, and the restart helper compilation task.
- Simplify future Java version upgrades by requiring changes in only one
location.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-22 07:10:19 +00:00
brios e24a30828b refactor(api): replace deprecated APIs with their modern equivalents (#6434)
# Description of Changes


This PR resolves deprecation warnings and addresses compiler errors
resulting from the transition to Spring Security 7.x., as well Jackson 3
and general Java.

* Replaced all usages of `asText()`/`isTextual()` with
`asString()`/`isString()` in JSON parsing logic across
`FormPayloadParser.java`, `ApiEndpoint.java`, and
`KeygenLicenseVerifier.java` to ensure consistent and type-safe string
* Updated `CustomSaml2AuthenticatedPrincipal` to implement
`Saml2ResponseAssertionAccessor`, added a `responseValue` field, and
provided additional getter methods and type-safe attribute accessors.
* Switched from constructing `URL` objects directly from strings to
using `URI.create(...).toURL()` in `UIDataTessdataController.java` for
improved URL safety and parsing.

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-21 18:49:59 +00:00
briosandAnthony Stirling e2ea720fc8 refactor(api): replace regex literals with compiled patterns for improved performance and readability (#6511)
# Description of Changes


This pull request refactors several utility classes and controllers to
replace inline regular expression usage with precompiled `Pattern`
constants. This change improves performance, consistency, and
maintainability by ensuring that regex patterns are compiled only once
and reused throughout the codebase. Additionally, it enhances code
clarity and security in filename and SQL content sanitization.

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [X] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-07-21 17:41:44 +00:00
brios a4ffdc7831 fix(viewer): dynamic page number input width based on total page count (#6607)
# Description of Changes


### Before:

<img width="3092" height="468" alt="image"
src="https://github.com/user-attachments/assets/8ed16ac3-9547-4f07-937e-4177c4ed16fd"
/>


### After: 

<img width="1868" height="490" alt="image"
src="https://github.com/user-attachments/assets/8ddf2227-bac4-49f6-973a-90c9f4667dfe"
/>


### Mobile (after):

<img width="842" height="444" alt="image"
src="https://github.com/user-attachments/assets/e601fa94-45a6-46ae-b432-550bb27a98a6"
/>



<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [X] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-21 17:40:16 +00:00
Anthony Stirling 621731bda1 Validate RFC 3161 document timestamps and expose timestamping (#7095)
# Description of Changes

Fixes timestamp issue and adds timestamp to the signing/security policiy
---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-21 17:37:54 +00:00
James Brunton 5e3e89ccb2 Fix existing teams logic (#7070)
# Description of Changes
Paired with https://github.com/Stirling-Tools/Stirling-PDF-SaaS/pull/320

Fixes the following bugs we found when testing the SaaS release:
- Existing users couldn't join teams - this was because they were the
last leader of their team, so it'd be left orphaned). Users now have a
'home team', which can have no members if they join another team, but
they can then go back to it later.
- Existing leaders didn't have unlimited seats - `saas_teams_extensions`
had no row for them, so the app fell back to `max_seats=1`. The
migration script fixes it.
- Members without Processor access could still access the Processor - It
was just checking "Are you the leader of **any** team", instead of the
user's active team.
2026-07-21 13:57:45 +00:00
ConnorYohandJames Brunton f60a75c253 chore(saas): remove unused Flyway migration system (#7100)
## What this PR does

Removes the **Flyway** migration system from the SaaS build:

- drops `flyway-core` + `flyway-database-postgresql` from
`app/saas/build.gradle`
- deletes all `Vxx__*.sql` files under
`app/saas/src/main/resources/db/migration/`
- removes the `spring.flyway.*` config from
`application-saas.properties`
- clears the now-inert `SPRING_FLYWAY_ENABLED` override and stale Flyway
comments in `testing/compose/docker-compose-saas.yml`

`ddl-auto` is **left on `update`** (unchanged) — that's a separate
decision (see "Not in this PR").

## Why — Flyway never actually ran anywhere

From a full schema-management review
(`notes/FLYWAY_MIGRATION_REVIEW.md`), verified against the live
databases:

- **Prod & dev (v3):** no `flyway_schema_history` table exists in any
schema → Flyway has never executed. Schema is authored by the Supabase
migrations in `Stirling-PDF-SaaS` and applied by that repo's **GitHub
integration** (merge to `main` → prod).
- **Tests:** the saas module has zero `@SpringBootTest`; the only
real-DB integration tests (in `proprietary`) use `ddl-auto=create-drop`
and don't have Flyway on the classpath.
- **The mock-DB harness** (`testing/compose/docker-compose-saas.yml`,
PAYG cucumber) *explicitly disabled* Flyway, because the `Vxx`
migrations can't run against a clean Postgres — they assume Supabase has
already provisioned `users`/`teams` (`V2` ALTERs `users`, `V5`
references `teams`).

So Flyway was dead weight, and its 4 duplicate versions
(`V25/V26/V30/V31`) were a latent trap: re-enabling it would crash boot
on the collision. Everything it contained (schema + seeds like the
default pricing policy) is already mirrored by the Supabase migrations,
and by `saas-seed.sql` for the cucumber stack.

## ⚠️ Required follow-up (item #1) — capture the Flyway-only tables into
Supabase migrations

**This is documentation of the next step, not done in this PR.**

Seven tables were defined in Flyway with **no matching Supabase
migration**. They exist in prod today only because `ddl-auto=update`
created them from their entities. Before `ddl-auto` is ever tightened to
`validate` (see #3 below), and so any fresh Supabase branch is complete,
they must be added as Supabase migrations in
`Stirling-PDF-SaaS/supabase/migrations/`.

**Capture (CREATE) — 6 live tables** (definitions are visible in the
deleted files in this PR's diff):

| Table | Source (deleted here) | Backing entity |
|---|---|---|
| `resource_grants` | `V25__resource_grants.sql` | `ResourceGrant` |
| `integration_configs` | `V26__integration_configs.sql` |
`IntegrationConfig` |
| `policy_sources` | `V22__policy_engine_tables.sql` | `SourceEntity` |
| `policy_source_doc_counts` | `V23__policy_source_doc_counts.sql` |
`SourceDocCountEntity` |
| `policy_source_doc_totals` | `V23__policy_source_doc_counts.sql` |
`SourceDocTotalEntity` |
| `saas_user_extensions` | `V9__saas_user_team_extensions.sql` |
`SaasUserExtensions` |

Write them as `CREATE TABLE IF NOT EXISTS stirling_pdf.<name> (...)`
(idempotent — no-op against the existing prod/v3 tables). Preserve
column types/defaults/constraints from the deleted `Vxx` files.

**Drop (do NOT recreate) — 1 orphaned table:**

- `classification_labels` — created by `V30` and dropped by `V39` within
Flyway; its `ClassificationLabel` is now a plain `record`, not a JPA
entity. It lingers in prod only because Flyway's `V39` drop never ran.
The follow-up should emit a `DROP TABLE IF EXISTS
stirling_pdf.classification_labels` (mirroring `V39`'s intent), after
confirming nothing reads it.

## Not in this PR (deliberately)

- **#3 — flip saas `ddl-auto` `update` → `validate`.** Held pending team
confirmation; it has boot-risk and should be gated by a CI
"validate-boot against a fresh Supabase branch" first. Self-hosted stays
on `update` regardless.
- **#4 — `billing_subscriptions` split-brain** (prod `public` has 23,164
rows, `stirling_pdf` has 0, Java reads the empty one). Tracked
separately.

## Verification

- `:saas:compileJava` succeeds with Flyway removed (no code imports
`org.flywaydb.*`).
- No test or ArchUnit rule references Flyway or the migration files.
- No runtime/data impact: Flyway never ran against any live database.

---------

Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-07-21 09:32:56 +00:00
Ludy 401894a065 build(deps): bump gradle/actions/setup-gradle from 6.1.0 to 6.2.0 (#7116)
# Description of Changes

Replies PR: #7113, which ensures that the build tests are executed
correctly.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-21 08:24:31 +00:00
dependabot[bot] 15423c6479 build(deps): bump com.diffplug.spotless from 8.5.0 to 8.8.0 (#7089)
Bumps com.diffplug.spotless from 8.5.0 to 8.8.0.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=com.diffplug.spotless&package-manager=gradle&previous-version=8.5.0&new-version=8.8.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-21 08:24:23 +00:00
albanobattistella f4560cccb9 Update Italian translation (#7087) 2026-07-21 08:17:31 +00:00
dependabot[bot] 43a6ff3066 build(deps): bump mcp from 1.26.0 to 1.28.1 in /engine in the uv group across 1 directory (#7114)
Bumps the uv group with 1 update in the /engine directory:
[mcp](https://github.com/modelcontextprotocol/python-sdk).

Updates `mcp` from 1.26.0 to 1.28.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/modelcontextprotocol/python-sdk/releases">mcp's
releases</a>.</em></p>
<blockquote>
<h2>v1.28.0</h2>
<h2>Deprecations</h2>
<p>Two API surfaces now emit <code>DeprecationWarning</code> ahead of
their removal in v2. Nothing is removed in 1.x, and the warnings fire
only when the deprecated API is <em>called</em> - importing the modules
stays silent.</p>
<ul>
<li><strong>WebSocket transport</strong> -
<code>mcp.client.websocket.websocket_client</code> and
<code>mcp.server.websocket.websocket_server</code><code>modelcontextprotocol/typescript-sdk#1783</code></li>
<li><strong>Experimental tasks API</strong> -
<code>ClientSession.experimental</code>,
<code>Server.experimental</code>,
<code>ServerSession.experimental</code>, and the
<code>experimental_task_handlers=</code> kwarg on
<code>ClientSession</code>. Tasks (SEP-1686) were removed from the MCP
specification and are expected to return as a separate MCP
extension.</li>
</ul>
<p>If your test suite runs with <code>filterwarnings =
[&quot;error&quot;]</code> and exercises these paths, add a scoped
ignore such as <code>ignore:The experimental tasks API is
deprecated:DeprecationWarning</code> or <code>ignore:The WebSocket .*
transport is deprecated:DeprecationWarning</code>.</p>
<p>See <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/issues/2828">#2828</a>
for full details.</p>
<h2>What's Changed</h2>
<ul>
<li>[v1.x] Support Python 3.14 by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2769">modelcontextprotocol/python-sdk#2769</a></li>
<li>fix: omit null optional fields from task result payloads by <a
href="https://github.com/liuzemei"><code>@​liuzemei</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2809">modelcontextprotocol/python-sdk#2809</a></li>
<li>[v1.x] Deprecate the WebSocket transport and the experimental tasks
entry points by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2828">modelcontextprotocol/python-sdk#2828</a></li>
<li>[v1.x] Add a v2 status banner to the README by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2835">modelcontextprotocol/python-sdk#2835</a></li>
<li>[v1.x] Deflake the child process cleanup tests by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2839">modelcontextprotocol/python-sdk#2839</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/liuzemei"><code>@​liuzemei</code></a>
made their first contribution in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2809">modelcontextprotocol/python-sdk#2809</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.2...v1.28.0">https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.2...v1.28.0</a></p>
<h2>v1.27.2</h2>
<h2>What's Changed</h2>
<ul>
<li>[v1.x] ci: deploy docs to py.sdk.modelcontextprotocol.io via Pages
artifact by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2635">modelcontextprotocol/python-sdk#2635</a></li>
<li>[v1.x] Add subject and claims to AccessToken by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2690">modelcontextprotocol/python-sdk#2690</a></li>
<li>[v1.x] Bind transport sessions to the authenticated principal by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2719">modelcontextprotocol/python-sdk#2719</a></li>
<li>[v1.x] Scope experimental tasks to the session that created them by
<a href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2720">modelcontextprotocol/python-sdk#2720</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.1...v1.27.2">https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.1...v1.27.2</a></p>
<h2>v1.27.1</h2>
<h2>What's Changed</h2>
<ul>
<li>[v1.x] fix: catch PydanticUserError when generating output schema
(pydantic 2.13 compat) by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2435">modelcontextprotocol/python-sdk#2435</a></li>
<li>[v1.x] fix(auth): coerce empty-string optional URL fields to None in
OAuthClientMetadata by <a
href="https://github.com/felixweinberger"><code>@​felixweinberger</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2405">modelcontextprotocol/python-sdk#2405</a></li>
<li>[v1.x] build: restrict httpx to &lt;1.0.0 by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2559">modelcontextprotocol/python-sdk#2559</a></li>
<li>[v1.x] refactor: import SSEError from httpx_sse public API by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2561">modelcontextprotocol/python-sdk#2561</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.0...v1.27.1">https://github.com/modelcontextprotocol/python-sdk/compare/v1.27.0...v1.27.1</a></p>
<h2>v1.27.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: remove unused <code>requests</code> dependency from
simple-chatbot example by <a
href="https://github.com/maxisbey"><code>@​maxisbey</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/1959">modelcontextprotocol/python-sdk#1959</a></li>
<li>ci: backport conformance tests from main to v1.x by <a
href="https://github.com/felixweinberger"><code>@​felixweinberger</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/pull/2068">modelcontextprotocol/python-sdk#2068</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/777b8d06710c140e3606b0d4598e2aa48546c266"><code>777b8d0</code></a>
[v1.x] Support TransportSecuritySettings in the WebSocket server
transport (#...</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/47204674fb26185c2cf45f065831f27b8e5d5c65"><code>4720467</code></a>
[v1.x] Set Development Status classifier to Production/Stable (<a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/issues/2976">#2976</a>)</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/6df3d734265eb49bf758a5e5eb420937337184e9"><code>6df3d73</code></a>
[v1.x] Buffer per-request StreamableHTTP streams; store priming event
before ...</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/32d32908feb7b15eddeb46872774bf95869cc5f0"><code>32d3290</code></a>
[v1.x] Pass a list to parametrize in test_docs_examples (pytest 9.1.0
compat)...</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/0dca751056dc87d04893d53af129fd00b56a18da"><code>0dca751</code></a>
[v1.x] Deflake the child process cleanup tests (<a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/issues/2839">#2839</a>)</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/52258a95645c66fccbe925289c3382712b9bc68a"><code>52258a9</code></a>
[v1.x] Add a v2 status banner to the README (<a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/issues/2835">#2835</a>)</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/b8f491724c45dbf89d6569364b58d6e8d25d7e42"><code>b8f4917</code></a>
[v1.x] Deprecate the WebSocket transport and the experimental tasks
entry poi...</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/2309e5ef974062748e0268c396eba73cfdb6f5e3"><code>2309e5e</code></a>
fix: omit null optional fields from task result payloads (<a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/issues/2809">#2809</a>)</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/494eb11d36b4238226cc0551da6015e1c73f7f3b"><code>494eb11</code></a>
[v1.x] Support Python 3.14 (<a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/issues/2769">#2769</a>)</li>
<li><a
href="https://github.com/modelcontextprotocol/python-sdk/commit/62137874ff26dd74d2fea80ff528a7fd9ca7a5e7"><code>6213787</code></a>
[v1.x] Scope experimental tasks to the session that created them (<a
href="https://redirect.github.com/modelcontextprotocol/python-sdk/issues/2720">#2720</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/modelcontextprotocol/python-sdk/compare/v1.26.0...v1.28.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mcp&package-manager=uv&previous-version=1.26.0&new-version=1.28.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/Stirling-Tools/Stirling-PDF/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-21 08:15:15 +00:00
Ludy 14def378bf chore(frontend): update frontend dependencies to latest compatible versions (#6860)
# Description of Changes

This change updates multiple frontend dependencies to their latest
compatible releases by refreshing the `package-lock.json`. The update
includes dependency version bumps across the frontend toolchain and
runtime libraries while removing obsolete transitive dependencies
introduced by newer package versions.

### What was changed

- Updated Babel packages to the latest 7.29.x releases.
- Upgraded Vite from 7.3.2 to 7.3.6.
- Upgraded Vitest packages from 3.2.4 to 3.2.6.
- Updated React Router and React Router DOM from 7.13.2 to 7.18.1.
- Updated Axios from 1.15.0 to 1.18.1.
- Updated PostHog packages to newer releases.
- Updated additional frontend dependencies including Preact, Web Vitals,
FormData, HasOwn, Brace Expansion, and other transitive packages.
- Removed obsolete OpenTelemetry and Protobuf-related transitive
dependencies that are no longer required by the updated dependency
graph.
- Refreshed the lockfile to reflect the new dependency tree.

### Why the change was made

- Keep frontend dependencies up to date.
- Incorporate upstream bug fixes, performance improvements, and security
updates.
- Reduce unnecessary transitive dependencies where newer package
versions no longer require them.
- Maintain compatibility with the current frontend toolchain.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-21 07:05:25 +00:00
dependabot[bot] 49cc3f88f9 build(deps): bump ubuntu from c4a8d55 to 4fbb8e6 in /docker/base (#6554)
Bumps ubuntu from `c4a8d55` to `4fbb8e6`.


> **Note**
> Automatic rebases have been disabled on this pull request as it has
been open for over 30 days.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-20 21:05:10 +00:00
Anthony Stirling 79dc7d5615 Multi node cluster fixes (#7025)
- Exclude DataRedisRepositoriesAutoConfiguration (cluster crash-loop
fix)
- Share JWT signing keys via the DB + require a shared credential key in
cluster mode
- Make policy run status/listing visible across nodes


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 20:51:30 +00:00
EthanHealy01 bda9cebc5c Portal ProcessorFlow: proportional particle emission + Storybook playground (#7105)
## Summary
Follow-up polish to the home **PDF Processor** flow visualiser (base
landed in #7014). Tunes the particle animation to react to real volume
and adds a Storybook playground to tune it live.

## Changes
### Particle emission — `useFlowParticles.ts`, `flowTypes.ts`
- Emission rate now scales ~linearly with a source's 24h volume (**2×
volume ≈ 2× dots**) instead of the flat `rate / 86400 × SPEED`, capped
at **one dot / 250ms** (`MAX_EMIT_PER_SEC`) for busy sources (~≥
800/24h).
- Bounded the spread so the busiest source emits at most **5×** the
quietest (`EMIT_SPREAD_CAP`) — a dominant source can't starve the
others.
- Wider departure jitter (`[0.4×–1.7×]` the mean, still floored at the
per-source min-gap) and ~**2× faster travel** so the flow reads
livelier.
- Replaced the single `SPEED` constant with `EMIT_DIVISOR` /
`MAX_EMIT_PER_SEC` / `EMIT_SPREAD_CAP`. Weighted round-robin outcome
split is unchanged (e.g. 3 failed / 30 delivered → ~1 red dot in 11).

### Storybook Playground — `ProcessorFlow.stories.tsx`,
`ProcessorFlow.tsx`
- New **Playground** story with live controls: per-input rate sliders,
the delivered/failed split (drives the red-dot ratio), and a
Classification-active toggle.
- Added an optional `dataOverride` prop (prod-inert testing seam) so the
story renders a supplied flow model instead of fetching — changes apply
instantly.

### Housekeeping
- Condensed authored comments across the feature to ≤ 2 lines.

## Testing
- `task frontend:check` green — lint, typecheck, 1353 tests.
- Verified emission numerically (proportionality, 250ms ceiling, 5×
spread cap) and confirmed live animation in a focused Storybook tab.
2026-07-20 15:29:46 +00:00
James BruntonandEthanHealy01 0fc2958daa Add explicit length to member column to avoid ddl resizing (#7109)
# Description of Changes
There's currently a column size inconsistency between the SaaS v3 DB and
the main Java code which causes the backend to fail to start up when
connected to a fresh DB. This is because the column previously was width
255, but now it's officially width 50, but the Java type is still
implicitly `varchar(255)` because there's no length attribute. If it's a
fresh DB, Postgres throws an error that it can't expand the column (this
doesn't error on an existing DB because the column is already wide
enough behind the scenes).

Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
2026-07-20 15:23:11 +00:00
ConnorYoh c19d56de22 PAYG usage card: review follow-ups (avg/PDF, empty-state, unique wording) (#6967)
Small follow-up to #6957 addressing the three non-blocker findings from
its review. **Draft / stacked on #6957** — the diff shows #6957's
changes until it merges, then auto-narrows to just these 5 files. Mark
ready + rebase onto `main` once #6957 lands.

### 1. avg-per-PDF no longer blends unsynced units over synced-only docs
`avgCostMinor` now divides **synced** units (`spendUnitsThisPeriod`) by
synced docs, so numerator and denominator cover the same population.
Combined-billing `pendingUnits` (units-only, no doc count) previously
inflated the average for linked-instance teams. The "meter units" figure
still shows synced+pending (total current usage) — only the *average* is
synced-only.

### 2. Empty-state: unsynced-only reads cleanly
When `docs == 0` but there are pending meter units (combined-billing,
nothing synced yet), the card showed a bare **"0 PDFs"** headline with a
count-less summary and no split. It now shows a **"{n} meter units
pending sync from linked instances"** note instead. New `unitsPending`
i18n key + a `UnsyncedOnly` story. (Only reachable on the
combined-billing path; pure-SaaS teams are unaffected.)

### 3. uniquePdfs wording is now accurate
`document_fingerprint` is a hash of a charge's whole **input set**, so
the same file reused across *different* groupings (standalone, then
later in a merge `{A,B}`) counts per grouping — a close approximation of
"unique PDFs", exact for the single-input common case. Softened the FE
type doc + the `WalletLedgerEntry.document_fingerprint` javadoc to say
so (no behaviour change; counting model unchanged).

### Verification
FE typecheck / test / lint / format all clean; `:saas:compileJava`
green. No behaviour change beyond #1 (avg) and #2 (empty-state copy); #3
is doc-only.
2026-07-20 13:51:55 +00:00
Ludy 1954d20910 refactor(frontend): decouple signature status logic from PDF color palette (#6992)
# Description of Changes

- Moved the signature status-to-color mapping from `signatureStatus.ts`
to `pdfPalette.ts`.
- Removed the PDF palette dependency from the pure signature status
calculation module.
- Updated the PDF signature report to import the color mapping from the
palette module.
- Prevented signature status unit tests from initializing
browser-dependent CSS colors unnecessarily.
- Eliminated fallback warnings caused by unavailable theme CSS variables
in the Vitest environment.
- Preserved the existing signature status calculation and PDF report
color behavior.

```sh
[frontend:test:editor] stderr | src/core/hooks/tools/validateSignature/utils/signatureStatus.test.ts
[frontend:test:editor] CSS variable --pdf-light-header-bg not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-accent not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-text-primary not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-text-muted not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-box-bg not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-box-border not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-warning not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-danger not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-success not found, using fallback
[frontend:test:editor] CSS variable --pdf-light-neutral not found, using fallback
```

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:11:51 +00:00
Ludy b6b5077467 deps: update vulnerable dependencies to address GitHub Security Advisories (#7064)
# Description of Changes

This pull request updates project dependencies to versions that resolve
the following GitHub Security Advisories:

- GHSA-wf93-45jw-7689
- GHSA-58qw-9mgm-455v
- GHSA-jp4c-xjxw-mgf9

### What was changed

- Updated affected dependencies to patched versions.
- Removed known vulnerable dependency versions reported by GitHub
Security Advisories.
- Ensured dependency versions remain compatible with the existing
project configuration.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:10:38 +00:00
Ludy a63ab2db7b Add PR conflict labeler workflow (#7061)
### Motivation
- Automatically detect and mark pull requests that have merge conflicts
so maintainers can triage them quickly.
- Ensure both new and existing open PRs are covered by running on PR
events, a schedule, and manual dispatch.

### Description
- Add workflow `: .github/workflows/pr-conflict-labeler.yml` that
triggers on `pull_request_target`, a recurring `schedule`, and
`workflow_dispatch` for manual runs.
- The job uses the repository `stirling-bot`
(`.github/actions/setup-bot`) and `actions/github-script` to poll
`pull.mergeable` until GitHub computes mergeability and then add or
remove the `has conflicts` label when `mergeable === false &&
mergeable_state === 'dirty'`.
- The workflow idempotently ensures the `has conflicts` label exists
(creates it if missing) and the repository label config `
.github/labels.yml` is updated to include `has conflicts` with an
appropriate color and description.

### Testing
- Parsed both ` .github/workflows/pr-conflict-labeler.yml` and `
.github/labels.yml` with Ruby `YAML.load_file`, which succeeded.
- Installed and ran `actionlint` via `go install
github.com/rhysd/actionlint/cmd/actionlint@latest` and validated the new
workflow file with `actionlint`, which succeeded.

------
[Codex
Task](https://chatgpt.com/codex/cloud/tasks/task_e_6a58b7061c2c8325b024980a4af8f632)
2026-07-20 12:10:07 +00:00
Ludy 1ba9092999 chore: upgrade Gradle to 9.6.1 across CI, Docker, and wrapper (#6892)
# Description of Changes

This change upgrades the project from Gradle **9.6.0** to **9.6.1**
across all build environments to keep the toolchain consistent and
aligned.

### What was changed

- Updated the Gradle Wrapper to **9.6.1**.
- Updated all GitHub Actions workflows using
`gradle/actions/setup-gradle` to install Gradle **9.6.1**.
- Updated all Docker build stages to use the `gradle:9.6.1-jdk25` image
with the corresponding pinned image digest.
- Regenerated the Windows Gradle wrapper script, resulting in minor
comment updates (`Gradle` → `gradlew`).

### Why the change was made

- Keep the project up to date with the latest Gradle patch release.
- Ensure all local, CI, and Docker build environments use the same
Gradle version.
- Benefit from the latest bug fixes and maintenance improvements
included in Gradle 9.6.1.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:08:27 +00:00
LudyandAnthony Stirling 99887f77a6 deps(frontend): upgrade @embedpdf packages to v2.14.4 (#6989)
# Description of Changes

- Updated all `@embedpdf/*` packages from earlier releases to `v2.14.4`.
- Upgraded `@embedpdf/engines` from `2.8.0` to `2.14.4`.
- Upgraded `@embedpdf/plugin-selection` from `2.8.0` to `2.14.4`.
- Aligned every EmbedPDF package to the same version to avoid version
mismatches.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-07-20 12:07:51 +00:00
Ludy 1b3e757686 build(docker): use Node.js 22 for embedded frontend builds (#7076)
# Description of Changes

Updated the NodeSource setup from Node.js 20 to Node.js 22 in all
embedded frontend Docker build variants:

- Standard image
- Fat image
- Ultra-lite image

This aligns the Docker builds with the Node.js version used by the
frontend CI workflows and satisfies the `node >=22` engine requirement
of `rollup-plugin-visualizer@7.0.1`
https://github.com/btd/rollup-plugin-visualizer/commit/2caae97a061c752b9ec0fc5b820d10f0777b4c01
. It removes the `EBADENGINE` warning emitted during `frontend:install`
in the Docker Compose test workflow.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:06:23 +00:00
LudyandCopilot bb830e5711 build: upgrade google-java-format and restore strict Spotless validation (#7091)
# Description of Changes

- Upgraded google-java-format from 1.28.0 to 1.35.0.
- Removed the broad `suppressLintsFor` workaround for the
`google-java-format` step.
- Ensured the shared `gradle/spotless.gradle` configuration is
recognized by the relevant CI path filters and repository automation.
- Kept the shared formatter configuration available to all backend
modules.
- Verified that google-java-format 1.35.0 runs successfully on JDK 25
for the Common, Core, and SaaS modules.
- Confirmed that the previous claim about a general Guava 32.x crash on
JDK 24/25 no longer justifies suppressing all formatter lint failures.

### Verification

Verified with Temurin JDK 25.0.3 and google-java-format 1.35.0. The
formatter still depends on Guava 32.1.3-jre, and no `suppressLintsFor`
configuration is present.

```bash
./gradlew \
  :common:spotlessJavaCheck \
  :stirling-pdf:spotlessJavaCheck \
  --rerun-tasks
```

Result:

```text
> Task :common:spotlessJava
> Task :common:spotlessJavaCheck
> Task :stirling-pdf:spotlessJava
> Task :stirling-pdf:spotlessJavaCheck

BUILD SUCCESSFUL in 26s
4 actionable tasks: 4 executed
```

Using `--rerun-tasks` ensured that the formatter was executed and that
the result did not come from the Gradle task cache.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-20 12:05:53 +00:00
Ludy f4d760b139 fix(sign): preserve PNG signature placement and page content (#7093)
# Description of Changes

This PR fixes PNG signature application issues in the PDF signing
workflow.

## What was changed

- Reworked signature application to create locked and printable PDFium
stamp annotations with dedicated appearance streams.
- Removed the use of `FPDFPage_GenerateContent()` from the signature
workflow.
- Preserved the signature's original position and dimensions when
converting from the viewer's top-left coordinate system to PDF
coordinates.
- Added CropBox-aware coordinate conversion for PDFs whose visible page
origin differs from the MediaBox origin.
- Improved signature image extraction to handle internal EmbedPDF asset
references and nested image data.
- Refactored PDFium bitmap creation so image objects can safely be
transferred to annotations.
- Corrected PDFium bitmap ownership and cleanup to prevent duplicate
destruction.
- Added a PDFium WASM integration test covering:
  - Existing page-content preservation
  - Stamp appearance generation
  - Signature coordinates and dimensions
  - Printable, read-only, and locked annotation flags
- Persisted image data taking precedence over internal asset references

## Why the change was made

Applying a PNG signature previously regenerated the complete page
content through PDFium. This could corrupt existing vector or font-based
page elements, including the university logo reported in the linked
issue.

The previous coordinate conversion also relied only on the page height
and did not account for CropBox offsets, allowing the applied signature
to move from its preview position.

Creating a PDFium stamp annotation with its own appearance stream avoids
regenerating existing page content while retaining the selected
signature position and size.


Closes #7083

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:05:01 +00:00
Ludy 4cfe29139a chore(labels): add missing label metadata and remove duplicate entry (#7096)
# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:04:35 +00:00
Ludy 0be0c0839b build(docker): pin container base images by digest for reproducible builds (#6797)
# Description of Changes

### What was changed

- Updated `BASE_VERSION` references in:
  - `docker/backend/Dockerfile`
  - `docker/embedded/Dockerfile`
  - `docker/embedded/Dockerfile.fat`
- Pinned `stirlingtools/stirling-pdf-base:1.0.2` to a specific SHA256
digest.
- Pinned the `eclipse-temurin:25-jre-noble` image used in the
`jar-extract` stage to a specific SHA256 digest.
- Pinned the `ghcr.io/astral-sh/uv:python3.13-bookworm-slim` image in
`engine/Dockerfile.dev` to a specific SHA256 digest.
- Removed reliance on mutable image tags alone for these build stages.

### Why the change was made

- Ensure deterministic and reproducible Docker builds.
- Prevent unexpected changes caused by upstream image tag updates.
- Improve supply chain integrity by explicitly defining the exact image
artifacts used during builds.
- Align container build practices with security and compliance
recommendations.

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:02:16 +00:00
Ludy c6e84a2124 fix(admin-settings): correctly mask Telegram bot tokens in settings output (#6822)
# Description of Changes

- What was changed
- Fixed the sensitive-field detection logic in `AdminSettingsController`
so `botToken` is matched correctly after lowercasing the field name.
- This ensures Telegram bot tokens are masked consistently in admin
settings responses.
- Why the change was made
- The previous check used `lowerField.contains("botToken")`, which could
never match after converting the field name to lowercase.
- As a result, `botToken` values could remain visible in masked settings
output.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:01:59 +00:00
Ludy 72e8ba2951 fix(admin-settings): prevent hydration error in the Admin General section (#6823)
# Description of Changes

- What was changed
- Fixed an invalid HTML nesting issue in `AdminGeneralSection` by
changing the affected Mantine `Text` wrapper from the default `<p>`
element to `component="div"`.
- This prevents a `<div>` from being rendered inside a `<p>` when the
`Group` for the "Logo Style" label is displayed.
- Why the change was made
- Firefox reported a hydration error in the settings modal because the
rendered DOM was invalid.
- The warning was triggered in the Admin General settings section and
affected the settings modal experience.


Firefox 152.0.3 (64-Bit)

```
In HTML, <div> cannot be a descendant of <p>.
This will cause a hydration error.

  ...
    <AdminGeneralSection>
      <div className="settings-s...">
        <@mantine/core/Stack gap="lg" className="settings-s...">
          <@mantine/core/Box ref={null} className="settings-s..." style={{...}} variant={undefined}>
            <div ref={null} style={{...}} className="settings-s..." data-variant={undefined} data-size={undefined} ...>
              <LoginRequiredBanner>
              <div>
              <@mantine/core/Paper withBorder={true} p="md" radius="md">
                <@mantine/core/Box ref={null} mod={[...]} className="m_1b7284a3..." style={{...}} variant={undefined} ...>
                  <div ref={null} style={{...}} className="m_1b7284a3..." data-variant={undefined} data-size={undefined} ...>
                    <@mantine/core/Stack gap="md">
                      <@mantine/core/Box ref={null} className="m_6d731127..." style={{...}} variant={undefined}>
                        <div ref={null} style={{...}} className="m_6d731127..." data-variant={undefined} ...>
                          <@mantine/core/Text>
                          <div>
                          <div>
                            <@mantine/core/Text size="sm" fw={500} mb={4}>
                              <@mantine/core/Box className="mantine-fo..." style={{...}} ref={null} component="p" ...>
>                               <p
>                                 ref={null}
>                                 style={{--text-fz:"var(--mant...",--text-lh:"var(--mant...",marginBottom:"calc(0.25r...", ...}}
>                                 className="mantine-focus-auto m_b6d8b162 mantine-Text-root"
>                                 data-variant={undefined}
>                                 data-size="sm"
>                                 size={undefined}
>                               >
                                  <@mantine/core/Group gap="xs">
                                    <@mantine/core/Box className="m_4081bf90..." style={{...}} ref={null} ...>
>                                     <div
>                                       ref={null}
>                                       style={{--group-gap:"var(--mant...",--group-align:"center",--group-justify:"flex-start", ...}}
>                                       className="m_4081bf90 mantine-Group-root"
>                                       data-variant={undefined}
>                                       data-size={undefined}
>                                       size={undefined}
>                                     >
                            ...
                          ...
              ...
        ...
react-dom-client.development.js:2605:19
```


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:01:40 +00:00
Ludy 4230d2902b fix(editor): respect no-login settings visibility in config navigation (#6807)
# Description of Changes

This change fixes the editor configuration navigation for issue #6800 by
passing the `showSettingsWhenNoLogin` configuration flag through all
config navigation section hooks.

- Added `config?.showSettingsWhenNoLogin ?? true` when building the app
config modal navigation.
- Extended shared, desktop, and proprietary `useConfigNavSections`
signatures to accept the `showSettingsWhenNoLogin` flag.
- Forwarded the flag from desktop and proprietary config navigation
wrappers into the shared navigation logic.
- Updated proprietary admin section visibility so read-only admin
previews are only shown when login is disabled and
`system.showSettingsWhenNoLogin` allows it.

The change was made to ensure deployments with login disabled can still
control whether settings/admin configuration entries are visible,
matching the existing `showSettingsWhenNoLogin` behavior.

Closes #6800

<img width="1920" height="1032" alt="image"
src="https://github.com/user-attachments/assets/193f083b-3c87-4466-8e91-81a13a27cec3"
/>

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [x] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [x] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [x] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 12:01:15 +00:00
Ludy 2c1a666889 fix(frontend): make development label detection cross-platform (#6988)
# Description of Changes

This PR makes the frontend development label detection compatible with
both Windows and Unix-based environments.

- Added platform-specific handling to the `STIRLING_DEV_LABEL` Taskfile
variable.
- Uses PowerShell and `Split-Path` on Windows.
- Retains the existing `basename` implementation on Linux and macOS.
- Preserves the fallback to the current working directory when the Git
repository root cannot be determined.
- Fixes `task frontend:dev` and `task dev:all` failing on Windows
because `basename` was unavailable.
- Handles shell quoting explicitly so PowerShell variables are not
expanded by the intermediate command shell.

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 11:59:55 +00:00
Ludy 47fe4a1d06 fix(licenses): fall back to license URL for backend dependency links (#7046)
# Description of Changes

This change improves link handling in the third-party licenses section.

- Added a shared `getModuleUrl` helper that returns `moduleUrl` when
available and falls back to `moduleLicenseUrl`.
- Updated backend license entries to render as clickable links when only
a license URL is provided.
- Preserved the existing link behavior, including opening URLs in a new
tab with appropriate security attributes.
- Fixed inconsistent rendering where some dependency names appeared as
plain text despite having an available license URL.

The change was made to ensure backend dependency entries consistently
provide a usable external link, even when dependency metadata does not
include a dedicated module URL.


before:
<img width="1920" height="1080" alt="image"
src="https://github.com/user-attachments/assets/aafee561-43e0-4924-923f-eb4ecf00c873"
/>

after:
<img width="1920" height="1080" alt="image"
src="https://github.com/user-attachments/assets/10a6f76a-6852-49af-a987-e0a864ec0b91"
/>


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-20 11:59:27 +00:00
Anthony Stirling b509fae0c8 Split processor sidebar into PDF Processor and PDF Platform sections (#7072) 2026-07-19 18:42:43 +01:00
Reece BrowneandJames Brunton 8b179fbc55 Support translations in Storybook: locale toolbar (#6843)
## What

Adds a globe toolbar to Storybook so any story can be previewed in all
42 supported languages (the i18n init already on `main` was
English-only).

## How

Bundles every locale's `translation.toml` via a `?raw` glob into i18next
resources, and switches language on toolbar change. RTL locales (`ar`,
`fa`) flip `document.dir`.

---------

Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-07-17 15:01:58 +00:00
James Brunton ecddce9944 Remove agent builder from processor (#7063)
# Description of Changes
Remove agent builder from processor because we don't intend to implement
it any time soon.
2026-07-17 13:15:35 +00:00
Ludy 398f473316 Clarify portal SaaS licensing (#7074)
### Motivation
* The repository uses per-layer licensing and the
`frontend/editor/src/portal-saas/` layer existed without an explicit
license entry in the root `LICENSE`, so the layered licensing reference
needed to be added for clarity.

### Description
* Add a new `frontend/editor/src/portal-saas/LICENSE` containing the
same "Stirling PDF User License" used by adjacent non-MIT layers and
update the top-level `LICENSE` to list
`frontend/editor/src/portal-saas/` as covered by that file.

### Testing
* Verified with `diff -u frontend/editor/src/portal/LICENSE
frontend/editor/src/portal-saas/LICENSE` and `test -f
frontend/editor/src/portal-saas/LICENSE`, and attempted `task
frontend:check` which could not run in this environment because `task`
is not installed.

------
[Codex
Task](https://chatgpt.com/codex/cloud/tasks/task_e_6a59f78f2f8483258cbe914b84126346)
2026-07-17 10:16:06 +00:00
Anthony Stirling bc96eed040 Portal Policies: table layout with colour-matched icons (#6994)
# Description of Changes

Reworks the Policies catalogue from blocky cards into a clean table with
tinted category icons and tone-matched "enforces" chips, so it matches
the styling used elsewhere in the portal.

Part of a portal (processor) UI-consistency pass, split into small
focused PRs.

## Before / after

<img width="2816" height="1318" alt="after-policies-light"
src="https://github.com/user-attachments/assets/af7586f7-8d23-47eb-ae2e-90630d09929b"
/>
<img width="2816" height="1438" alt="before-policies-dark"
src="https://github.com/user-attachments/assets/efcc63d9-5f2d-4dca-944d-d470aa689304"
/>
<img width="2816" height="1438" alt="before-policies-light"
src="https://github.com/user-attachments/assets/2398df15-0632-439f-9f23-0a6ddc496083"
/>
<img width="2816" height="1318" alt="after-policies-dark"
src="https://github.com/user-attachments/assets/9a3726ac-1637-4c7c-ad7a-dcdaf141d89d"
/>


---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [x] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-17 07:07:09 +00:00
EthanHealy01 d271b8f357 Slim down login/signup to a single centered form (#7033)
Replaces the two-column carousel login/signup with a single clean
centered form, uniform across proprietary, saas, desktop, and the portal
(all now route through the shared single-column `AuthShell`). Adds a
Storybook playground under **Auth → Auth Screens** (provider /
login-method controls) to iterate on it.

## Before / After

<img width="1600" height="920" alt="image"
src="https://github.com/user-attachments/assets/6e3f166f-40df-468e-825a-bc4c7880406c"
/>

<img width="2056" height="1000" alt="Screenshot 2026-07-14 at 6 11
11 PM"
src="https://github.com/user-attachments/assets/e015efc9-71e5-4b9b-b64a-5ba1dbf2fcec"
/>
2026-07-16 23:02:49 +00:00
EthanHealy01 6b2ab5a743 The flow chart for policies running (#7014) 2026-07-16 15:32:08 +00:00
Anthony Stirling 275d70242e Portal Editor admin: replace glyph icons with SVGs (#6999)
# Description of Changes

Swaps the emoji and box glyphs in the editor deployment, pairing and
storage panels for tinted icons consistent with the rest of the portal.

Part of a portal (processor) UI-consistency pass, split into small
focused PRs.


---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [x] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-16 14:01:11 +00:00
Ludy 1835e6fe6b Avoid uv cache reservation collisions in CI by adding per-workflow cache-suffix (#7060)
### Motivation
- Prevent concurrent GitHub Actions jobs from attempting to reserve the
same `setup-uv` cache key and failing with "Unable to reserve cache ...
another job may be creating this cache" when multiple workflows run at
once.
- Target workflows that enable `setup-uv` caching and have run
concurrently in CI: pre-commit, check-generated-models, ai-engine, and
sync_files_v2.

### Description
- Added a `cache-suffix` value to the `astral-sh/setup-uv` step in
`.github/workflows/pre_commit.yml`,
`.github/workflows/check-generated-models.yml`,
`.github/workflows/ai-engine.yml`, and
`.github/workflows/sync_files_v2.yml` to create unique cache keys
(`pre-commit`, `generated-models`, `ai-engine`, `sync-files`).
- No behavior changes beyond isolating the uv cache keys per-workflow
and no other workflow steps were modified.

### Testing
- Ran `git diff --check` which completed with no reported whitespace or
index issues.
- Verified each modified workflow is valid YAML by loading them with a
Ruby YAML parser which succeeded for all four files.
- Attempted to run `task --list` to exercise the Taskfile locally but
`task` is not installed in this environment so that check could not be
executed.

------
[Codex
Task](https://chatgpt.com/codex/cloud/tasks/task_e_6a58b399a33083259d65e0614fcc35d2)
2026-07-16 12:43:11 +00:00
Anthony Stirling 939afef14f perf(portal): collapse admin-roster N+1 + session indexes (#7008)
# Description of Changes

Collapses the portal admin-roster endpoint (`getAdminSettingsData`,
`/api/v1/proprietary/ui-data/admin-settings`) from a per-user N+1 into a
constant set of queries, and adds the missing
session/user/team-membership indexes.

**Verified on H2 and real Postgres 16, 2,000-user roster:** 10,601 → 7
SQL statements, 600 → 0 writes-during-a-GET, O(N) → O(1). Portal-access
resolution is proven equivalent to the per-user check (parity test), and
a scaling guard fails the build if the endpoint ever regresses.

Also in scope (same controller / session subsystem): `getLoginData`
counts instead of loading the whole user table; `getTeamDetailsData`
fetch-joins authorities; `SessionScheduled` uses one bulk expire + a
bounded purge.

Behaviour note: the roster "active" flag now reflects *any* live session
(a strict superset of the old "newest session only") — no user who was
active is ever shown inactive.

---

## Checklist

### General

- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Testing

- [x] I have run backend `task check` (spotless + full backend test
suite) — all green
- [x] I have tested my changes locally (before/after benchmark on H2 +
Postgres)
2026-07-16 12:00:02 +00:00
ConnorYoh 2118de0bb7 Open processor "Open in browser" CTAs in a new tab (#7045)
## Description

The processor home-hero and download-editor modal "Open in browser"
buttons were meant to open the editor in a new tab, but they used
`window.location.href = EDITOR_URL`, which replaces the current tab.

This switches both to `window.open(EDITOR_URL, "_blank",
"noopener,noreferrer")`, matching the existing behaviour of the "Open"
button in `EditorStatusCard.tsx`. The `noopener,noreferrer` flags mirror
that same call and prevent the new tab from getting a `window.opener`
reference.

## Changes

- `WelcomeBanner.tsx` — home-hero "Open in browser" CTA
- `DownloadEditorModal.tsx` — download modal "Open in browser" CTA

## Notes

`EDITOR_URL` can resolve to a same-origin path when the editor is the
same SPA, so opening in a new tab triggers a full page load of the
editor app. This is the expected behaviour for "Open in browser".
2026-07-16 10:20:49 +00:00
Anthony Stirling 963fe6c0cf Portal: add docs + auto-synced with full-text search (#6985)
# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
2026-07-16 10:12:36 +00:00
4085 changed files with 144638 additions and 40382 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ vs `main`. Flags: `--html` (also emit a rendered HTML twin), `--no-screens`.
- Read the PR description / commit messages for stated intent. Do **not** invent
history or motivation that isn't evidenced (state current behavior in present tense).
- Classify touched files by layer:
- **Frontend**: tools (`frontend/editor/src/core/components/tools/*` or `.../core/tools/*`),
- **Frontend**: tools (`frontend/src/editor/core/components/tools/*` or `.../core/tools/*`),
hooks (`core/hooks/tools/*`, `useToolOperation`), contexts, routes, i18n
(`public/locales/en-US`).
- **Java backend**: controllers (`.../controller/api/...`), services, models, config.
+137
View File
@@ -0,0 +1,137 @@
---
name: pr-quiz
description: >-
Quiz the PR author on their own branch before they request review, to prove they
actually understand the change - especially code an AI wrote for them. Scopes the
branch diff vs its base, reads the changed code, then asks graded questions about
what changed, why, how it works, what it could break, and which edge cases it must
handle. Presents all questions first, waits for the author's answers, then grades
each honestly against the real code (Correct / Partial / Incorrect with the true
answer and file:line), scores it, and gives a readiness verdict that names the
areas to re-study before asking humans to review. Use when asked to quiz me on my
PR/branch, "test my understanding before review", a self-check gate before opening
a PR, or before requesting reviewers. Administered as an interactive
multiple-choice quiz (clickable options) by default; pass --free-text for
written answers, --questions N to set count, --save to write a scorecard.
argument-hint: "[branch-or-base-ref] [--questions N] [--free-text] [--save]"
allowed-tools: Bash, Read, Grep, Glob, Write, AskUserQuestion
---
# PR Quiz
Test whether the **author** genuinely understands their own branch before they ask
other people to spend time reviewing it. This is a self-check gate: the point is to
catch changes - often AI-written - that the author would not be able to explain or
defend in review. Be a fair but honest examiner, not a pushover.
`$ARGUMENTS` may name a base ref or branch to diff against; default is this branch
vs where it forked from the main line. Flags:
- `--questions N` - target N questions (else scale to diff size, see below).
- `--free-text` - administer as a written numbered list instead of the default
interactive multiple-choice.
- `--save` - also write a scorecard file after grading.
## Integrity rules (read first - the whole skill depends on these)
1. **Present every question before revealing any answer.** Ask, then wait. Never
show the answer key alongside the questions.
2. **Do not give hints or the answer while the quiz is open.** If the author asks
"what's the answer?" or "is it X?" before committing, decline warmly and tell
them to give their best answer first - guessing is part of the signal.
3. **Grade truthfully.** Vague, hand-wavy, or "the AI did it" non-answers are
Partial or Incorrect, not Correct. Do not inflate the score to be nice; a false
pass defeats the entire purpose.
4. **Ground everything in code you actually read.** Every question and every model
answer must trace to a real line in the diff. Cite `path:line`. No trivia
("how many lines?"), no invented behavior.
5. **Credit real understanding.** If the author explains it correctly in their own
words, mark it Correct even if worded differently than your key.
## Process
### 1. Scope the change (silently)
- Find the base. Prefer the fork point off the main line so the quiz covers only
this branch's work:
```bash
git fetch -q origin 2>/dev/null; \
BASE=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main); \
git diff --stat "$BASE"...HEAD
```
If `$ARGUMENTS` names a ref, diff against that instead.
- If the diff is empty, stop and say there's nothing to quiz on.
- Read commit messages / PR description for the *stated* intent, but verify it
against the actual diff - a mismatch is itself a good question.
### 2. Understand the code well enough to examine on it
Read the full diff plus enough surrounding context and related files to answer
every question you plan to ask. You cannot grade understanding you don't have.
Note the non-obvious parts: the design decisions, the risky lines, the edge cases,
the cross-file ripples, and anything that violates or upholds repo conventions
(for this repo e.g. `@app/*` import layering, all file ops via FileContext,
Jackson 3 / Spring Boot 4 APIs, engine typed-contract boundaries).
### 3. Build the question set
Scale count to the change unless `--questions N` is given:
small (< ~50 changed lines) 3-4, medium 5-8, large 9-12. Cap at 12.
Draw from these categories - weight toward the ones the diff actually exercises:
- **Intent** - what problem this solves; why it was needed now.
- **Mechanism** - how a specific non-trivial piece actually works ("walk me
through what `foo()` does when called with X").
- **Decisions & alternatives** - why this approach over an obvious alternative;
what a reviewer would reasonably push back on.
- **Blast radius** - what else this touches or could break; what you'd retest.
- **Edge cases** - inputs/states the change must handle (null, empty, large,
concurrent, error paths).
- **Conventions & correctness** - does it follow the repo's rules; is there a
latent bug the author should be able to spot.
Prefer questions the author can only answer if they read and understood the code.
Keep a private answer key with `path:line` for each - do **not** show it yet.
### 4. Administer the quiz
- **Default (multiple choice):** use the `AskUserQuestion` tool. Per question write
3-4 options where **every** option is independently plausible - each distractor a
real-but-wrong reading of the code, not filler. Two hard rules so the answer
can't be spotted by shape rather than knowledge:
- **Randomise the correct option's position** across questions - never default
it to first. Spread it roughly evenly over the slots.
- **Keep all options the same depth and length.** Do not describe the correct
one more fully than the distractors - a longer or more-detailed option is a
dead giveaway. Trim the right answer or flesh out the wrong ones until a
reader can't tell them apart by size.
The tool caps a call at 4 questions, so ask in batches of 4 - but run them as
one continuous flow: fire the next batch immediately after the previous
returns, with no narration ("Round 2 of 3") and no grading between batches.
The author always has an "Other" free-text escape, which is fine.
- **`--free-text`:** present all questions in one numbered list, then say
"Answer in one reply; number your answers. I won't grade until you're done."
Wait for the author's answers.
- Do not proceed to grading until every answer is in.
### 5. Grade
For each question, in order:
- Verdict: **Correct** / **Partial** / **Incorrect**.
- The model answer in one or two sentences, citing the real `path:line`.
- One line on the gap when Partial/Incorrect - what they missed and where to look.
Then a **Score** (e.g. 6/8, counting Partial as half) and a one-line summary of
the pattern (e.g. "solid on intent, shaky on the error paths").
### 6. Readiness verdict
End with a clear call:
- **Ready for review** - understanding is sound; note anything to mention to
reviewers proactively.
- **Study first** - list the specific files/concepts to re-read before requesting
review, each as a clickable `path:line`. Be concrete: "re-read the null handling
in X before you send this out."
Keep it honest - if they'd get grilled in review on something, say so now.
### 7. If `--save`
Write `pr-quiz/<branch>-scorecard.md`: the questions, their answers, your grades
and model answers, the score, and the verdict. Don't commit it unless asked.
## Principles
- **The author is the examinee, not the collaborator.** During the quiz you withhold
answers; you're measuring them, not helping them pass.
- **A failed quiz is a successful outcome** - it caught a gap before a human's time
was spent. Frame it that way, not as a scolding.
- **True to the code.** Every question, answer, and grade traces to a line you read.
- **Terse and direct** in chat - the questions and the verdict, minimal preamble.
+5 -5
View File
@@ -53,11 +53,11 @@ gh pr diff <pr> --name-only # or: git diff --name-only <base>...HEAD
Map changed frontend files to URLs generically:
- **Tools**: a changed `components/tools/<toolDir>/…` or `hooks/tools/<tool>/…`
toolId → URL via the repo's own rule `getToolUrlPath` in
[toolsTaxonomy.ts:200](frontend/editor/src/core/data/toolsTaxonomy.ts): `/` + the
[toolsTaxonomy.ts:200](frontend/src/editor/core/data/toolsTaxonomy.ts): `/` + the
id kebab-cased (`addPageNumbers``/add-page-numbers`).
- **Pages/routes**: changed `filesPage/*``/files`, etc.
- `--all`: enumerate every tool in the registry instead of just changed ones.
Write `frontend/editor/screenshots/ui-diff/targets.json` =
Write `frontend/screenshots/ui-diff/targets.json` =
`[{ "id":"compress", "url":"/compress", "name":"Compress" }]`. This is what makes
it generic - the spec never names a tool.
@@ -69,12 +69,12 @@ the full viewport - or the `--scope` container if given). Ensure the harness is
(node_modules + icons).
```
# after = current head
cd frontend/editor && PR_SHOT_SIDE=after PR_SHOT_THEME=light \
cd frontend && PR_SHOT_SIDE=after PR_SHOT_THEME=light \
npx playwright test --project=stubbed ui-before-after.spec.ts
# before = base, in an isolated worktree (copy the spec + targets.json in)
git worktree add ../ba-base origin/<baseRefName> # or the merge-base
# set up its frontend, copy spec + screenshots/ui-diff/targets.json across, then:
cd ../ba-base/frontend/editor && PR_SHOT_SIDE=before PR_SHOT_THEME=light \
cd ../ba-base/frontend && PR_SHOT_SIDE=before PR_SHOT_THEME=light \
npx playwright test --project=stubbed ui-before-after.spec.ts
# copy its screenshots/ui-diff/before/ back next to after/. Repeat with
# PR_SHOT_THEME=dark if --theme includes dark. Remove worktree when done.
@@ -82,7 +82,7 @@ cd ../ba-base/frontend/editor && PR_SHOT_SIDE=before PR_SHOT_THEME=light \
### 4. Auto-diff (surface what changed)
```
cd frontend/editor && node <skill>/diff-shots.mjs \
cd frontend && node <skill>/diff-shots.mjs \
screenshots/ui-diff/before screenshots/ui-diff/after screenshots/ui-diff
```
Produces `diff-report.json` classifying each view `unchanged | changed | added |
@@ -2,7 +2,7 @@
// unchanged | changed | added | removed, and CROP each changed pair to the
// affected region (bounding box of differing pixels + padding) - unless the
// change spans most of the page, in which case the full frame is kept.
// Run from frontend/editor (so deps resolve):
// Run from frontend (so deps resolve):
// node <skill>/diff-shots.mjs <beforeDir> <afterDir> [outDir]
// Env:
// DIFF_THRESHOLD min fraction of differing pixels to count as changed (default 0.001)
@@ -1,5 +1,5 @@
// Render each .tab-section of a montage HTML into its own PNG (the PR-ready image).
// Run from frontend/editor (so @playwright/test resolves):
// Run from frontend (so @playwright/test resolves):
// node <skill>/shoot-sections.mjs <montage.html> <outDir>
import path from "node:path";
import { pathToFileURL } from "node:url";
+6 -6
View File
@@ -28,13 +28,13 @@ current branch diff. Flags: `--fix`, `--theme light|dark|both` (default both),
## What this repo gives you (use it, don't reinvent)
- **Stubbed Playwright project** = backend-free screenshots via `page.route()` mocks.
Reference implementation: `frontend/editor/src/core/tests/stubbed/files-page-screenshots.spec.ts`.
Reference implementation: `frontend/src/editor/core/tests/stubbed/files-page-screenshots.spec.ts`.
It already shows the light / **dark** / **RTL** passes, JWT seeding, IndexedDB
seeding, and dumping PNGs to a `screenshots/<area>/` folder. Copy its shape.
- Helpers: `frontend/editor/src/core/tests/helpers/ui-helpers.ts`
- Helpers: `frontend/src/editor/core/tests/helpers/ui-helpers.ts`
(`uploadFiles`, `openSettings`, `waitForModalOpen`, `dismissTourTooltip`, …)
and the `stub-test-base` fixtures (`autoGoto`, `seedJwt`, `viewport`).
- Config: `frontend/editor/playwright.config.ts` (run from `frontend/editor/`).
- Config: `frontend/playwright.config.ts` (run from `frontend/`).
- Report template: [report-template.html](report-template.html) - self-contained,
one big image at a time, a global light/dark slider that flips every shot,
thumbnail rail, prev/next + arrow keys, and a Findings tab.
@@ -54,13 +54,13 @@ current branch diff. Flags: `--fix`, `--theme light|dark|both` (default both),
Worktrees have no `node_modules` and no generated icons. From repo root:
```
cd frontend && npm ci # or junction main's node_modules (see memory)
cd frontend/editor && node scripts/generate-icons.js
cd frontend && node scripts/generate-icons.js
```
Kill any stale dev server first (it serves old modules):
`Get-NetTCPConnection -LocalPort 5173 -State Listen | %{ Stop-Process -Id $_.OwningProcess -Force }`
### 3. Write the capture spec
Create `frontend/editor/src/core/tests/stubbed/<feature>-walkthrough.spec.ts`,
Create `frontend/src/editor/core/tests/stubbed/<feature>-walkthrough.spec.ts`,
modeled on `files-page-screenshots.spec.ts`. For each enumerated view:
- stub the APIs it needs, drive the UI to that state, wait on a real locator
(not a fixed sleep), `await settle(page)` for Mantine portals, then
@@ -71,7 +71,7 @@ modeled on `files-page-screenshots.spec.ts`. For each enumerated view:
- Name shots `NN_<view>_<theme>.png` so light/dark pair up by suffix.
- Prefer **stable test-ids** over translated accessible names (RTL/i18n breaks text locators).
Run it: `cd frontend/editor && npx playwright test --project=stubbed <feature>-walkthrough.spec.ts`.
Run it: `cd frontend && npx playwright test --project=stubbed <feature>-walkthrough.spec.ts`.
Add `--project=stubbed-firefox`/`-webkit` only if cross-browser layout matters.
### 4. Build the report
+4 -4
View File
@@ -26,16 +26,16 @@ version_builds/
node_modules/
**/node_modules/
frontend/node_modules/
frontend/editor/dist/
frontend/editor/playwright-report/
frontend/dist/
frontend/playwright-report/
.npm/
.yarn/
# Tauri/desktop builds
src-tauri/target/
src-tauri/dist/
frontend/editor/src-tauri/target/
frontend/editor/src-tauri/dist/
frontend/src-tauri/target/
frontend/src-tauri/dist/
# IDE and editor
.idea/
+14 -9
View File
@@ -9,6 +9,7 @@ ci: &ci
build: &build
- *ci
- build.gradle
- gradle/spotless.gradle
- app/(common|core|proprietary|saas)/build.gradle
- Taskfile.yml
- .taskfiles/backend.yml
@@ -83,6 +84,7 @@ frontend: &frontend
- .taskfiles/frontend.yml
- .taskfiles/e2e.yml
- .github/workflows/frontend-validation.yml
- .github/workflows/frontend-a11y.yml
- .github/workflows/e2e-stubbed.yml
- .github/workflows/e2e-live.yml
@@ -90,12 +92,12 @@ frontend: &frontend
# job on changes to any of these.
tauri: &tauri
- *ci
- frontend/editor/src-tauri/**
- frontend/editor/src/desktop/**
- frontend/editor/tsconfig.desktop.vite.json
- frontend/src-tauri/**
- frontend/src/editor/desktop/**
- frontend/tsconfig.desktop.vite.json
- frontend/package.json
- frontend/package-lock.json
- frontend/editor/vite.config.ts
- frontend/vite.config.ts
- .github/workflows/tauri-build.yml
- Taskfile.yml
- .taskfiles/desktop.yml
@@ -119,10 +121,12 @@ engine: &engine
generated-models: &generated-models
- *ci
- *openapi
- frontend/editor/scripts/generate-tool-api-types.mts
- frontend/editor/src/core/types/toolApiTypes.ts
- frontend/scripts/generate-tool-api-types.mts
- frontend/src/editor/core/types/toolApiTypes.ts
- frontend/src/editor/core/types/toolIO.ts
- engine/scripts/generate_tool_models.py
- engine/src/stirling/models/tool_models.py
- engine/src/stirling/models/tool_io.py
- .taskfiles/frontend.yml
- .taskfiles/engine.yml
- .github/workflows/check-generated-models.yml
@@ -131,7 +135,7 @@ licenses-frontend: &licenses-frontend
- ".github/workflows/frontend-backend-licenses-update.yml"
- "frontend/package.json"
- "frontend/package-lock.json"
- "frontend/editor/scripts/generate-licenses.js"
- "frontend/scripts/generate-licenses.js"
licenses-backend: &licenses-backend
- ".github/workflows/frontend-backend-licenses-update.yml"
@@ -142,8 +146,8 @@ licenses-backend: &licenses-backend
proprietary: &proprietary
- *ci
- app/proprietary/**
- frontend/editor/src/proprietary/**
- frontend/editor/src/core/tests/enterprise/**
- frontend/src/editor/proprietary/**
- frontend/src/editor/core/tests/enterprise/**
- testing/compose/docker-compose-keycloak-oauth.yml
- testing/compose/docker-compose-keycloak-saml.yml
- testing/compose/keycloak-realm-oauth.json
@@ -155,4 +159,5 @@ proprietary: &proprietary
- configs/settings.yml.template
- build.gradle
- app/proprietary/build.gradle
- gradle/spotless.gradle
- .github/workflows/build-enterprise.yml
+3 -3
View File
@@ -128,9 +128,9 @@ updates:
- package-ecosystem: cargo
directories:
- /frontend/editor/src-tauri
- /frontend/editor/src-tauri/thumbnail-handler
- /frontend/editor/src-tauri/provisioner
- /frontend/src-tauri
- /frontend/src-tauri/thumbnail-handler
- /frontend/src-tauri/provisioner
schedule:
interval: "weekly"
cooldown:
+4 -4
View File
@@ -51,7 +51,7 @@ labels:
- label: 'Translation'
files:
- 'frontend/editor/public/locales/[a-zA-Z]{2}-[a-zA-Z\-]{2,7}/translation.toml'
- 'frontend/public/locales/[a-zA-Z]{2}-[a-zA-Z\-]{2,7}/translation.toml'
- 'scripts/ignore_translation.toml'
- 'scripts/remove_translation_keys.sh'
- 'scripts/replace_translation_line.sh'
@@ -70,8 +70,8 @@ labels:
- label: 'Tauri'
files:
- 'frontend/editor/src-tauri/**'
- 'frontend/editor/src-tauri/.*'
- 'frontend/src-tauri/**'
- 'frontend/src-tauri/.*'
- label: 'engine'
files:
@@ -163,7 +163,7 @@ labels:
- '.github/workflows/scorecards.yml'
- 'exampleYmlFiles/test_cicd.yml'
- label: 'Github'
- label: 'GitHub'
files:
- '.github/.*'
+11 -7
View File
@@ -5,6 +5,7 @@
# the GitHub Action https://github.com/marketplace/actions/github-labeler.
- name: "Licenses"
color: "EDEDED"
description: "Issues or pull requests related to licenses"
from_name: "licenses"
- name: "Back End"
color: "20CE6C"
@@ -146,21 +147,21 @@
description: "Changes that do not affect the meaning of the code (formatting, etc.)"
- name: "admin"
color: "195055"
- name: "codex"
color: "ededed"
description: null
- name: "Github"
- name: "GitHub"
color: "0052CC"
- name: "github_actions"
color: "000000"
description: "Pull requests that update GitHub Actions code"
description: "Issues or pull requests related to GitHub configuration and integrations"
from_name: "Github"
- name: "needs-changes"
color: "A65A86"
description: "Pull requests that require changes before they can be merged"
- name: "on-hold"
color: "2526F9"
- name: "python"
color: "2b67c6"
description: "Pull requests that update Python code"
- name: "engine"
color: "2b67c6"
description: "Issues or pull requests related to the engine"
- name: "size:L"
color: "eb9500"
description: "This PR changes 100-499 lines ignoring generated files."
@@ -201,3 +202,6 @@
- name: "license-review-required"
color: "EDEDED"
description: "This PR requires a license review"
- name: "has conflicts"
color: "D93F0B"
description: "Pull request has merge conflicts with the base branch"
+2 -2
View File
@@ -13,7 +13,7 @@ Usage:
"""
# Sample for Windows:
# python .github/scripts/check_language_toml.py --reference-file frontend/editor/public/locales/en-US/translation.toml --branch "" --files frontend/editor/public/locales/de-DE/translation.toml frontend/editor/public/locales/fr-FR/translation.toml
# python .github/scripts/check_language_toml.py --reference-file frontend/public/locales/en-US/translation.toml --branch "" --files frontend/public/locales/de-DE/translation.toml frontend/public/locales/fr-FR/translation.toml
import argparse
import glob
@@ -308,7 +308,7 @@ def check_for_differences(reference_file, file_list, branch, actor):
report.append("## ❌ Overall Check Status: **_Failed_**")
report.append("")
report.append(
f"@{actor} please check your translation if it conforms to the standard. Follow the format of [en-US/translation.toml](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/editor/public/locales/en-US/translation.toml)"
f"@{actor} please check your translation if it conforms to the standard. Follow the format of [en-US/translation.toml](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/frontend/public/locales/en-US/translation.toml)"
)
else:
report.append("## ✅ Overall Check Status: **_Success_**")
+365 -352
View File
@@ -1,101 +1,116 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile --allow-unsafe --generate-hashes --output-file='.github\scripts\requirements_dev.txt' --strip-extras '.github\scripts\requirements_dev.in'
#
# WARNING: pip install will require the following package to be hashed.
# Consider using a hashable URL like https://github.com/jazzband/pip-tools/archive/SOMECOMMIT.zip
# CVE-2025-6176 mitigation: pin brotli to a specific commit
brotli @ git+https://github.com/google/brotli.git@028fb5a23661f123017c060daa546b55cf4bde29
# via
# -r .github/scripts/requirements_dev.in
# fonttools
cffi==2.0.0 \
--hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \
--hash=sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b \
--hash=sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f \
--hash=sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9 \
--hash=sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44 \
--hash=sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2 \
--hash=sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c \
--hash=sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75 \
--hash=sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65 \
--hash=sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e \
--hash=sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a \
--hash=sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e \
--hash=sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25 \
--hash=sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a \
--hash=sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe \
--hash=sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b \
--hash=sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91 \
--hash=sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592 \
--hash=sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187 \
--hash=sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c \
--hash=sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1 \
--hash=sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94 \
--hash=sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba \
--hash=sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb \
--hash=sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165 \
--hash=sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529 \
--hash=sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca \
--hash=sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c \
--hash=sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6 \
--hash=sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c \
--hash=sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0 \
--hash=sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743 \
--hash=sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63 \
--hash=sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5 \
--hash=sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5 \
--hash=sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4 \
--hash=sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d \
--hash=sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b \
--hash=sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93 \
--hash=sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205 \
--hash=sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27 \
--hash=sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512 \
--hash=sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d \
--hash=sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c \
--hash=sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037 \
--hash=sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26 \
--hash=sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322 \
--hash=sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb \
--hash=sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c \
--hash=sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8 \
--hash=sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4 \
--hash=sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414 \
--hash=sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9 \
--hash=sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664 \
--hash=sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9 \
--hash=sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775 \
--hash=sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739 \
--hash=sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc \
--hash=sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062 \
--hash=sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe \
--hash=sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9 \
--hash=sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92 \
--hash=sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5 \
--hash=sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13 \
--hash=sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d \
--hash=sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26 \
--hash=sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f \
--hash=sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495 \
--hash=sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b \
--hash=sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6 \
--hash=sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c \
--hash=sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef \
--hash=sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5 \
--hash=sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18 \
--hash=sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad \
--hash=sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3 \
--hash=sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7 \
--hash=sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5 \
--hash=sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534 \
--hash=sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49 \
--hash=sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2 \
--hash=sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5 \
--hash=sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453 \
--hash=sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf
cffi==2.1.0 \
--hash=sha256:02cb7ff33ded4f1532476731f89ede53e2e488a8e6205515a82144246ffa7dcc \
--hash=sha256:03e9810d18c646077e501f661b682fbf5dee4676048527ca3cffe66faa9960dd \
--hash=sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d \
--hash=sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5 \
--hash=sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f \
--hash=sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6 \
--hash=sha256:0a96b74cda968eebbad56d973efe5098974f0a9fb323865bf99ea1fd24e3e64c \
--hash=sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda \
--hash=sha256:11b3fb55f4f8ad92274ed26705f65d8f91457de71f5380061eb6d125a768fecd \
--hash=sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a \
--hash=sha256:164bff1657b2a74f0b6d54e11c9b375bc97b931f2ca9c43fcf875838da1570dd \
--hash=sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd \
--hash=sha256:19c54ac121cad98450b4896fa9a43ee0180d57bc4bc911a33db6cab1efab6cd3 \
--hash=sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb \
--hash=sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66 \
--hash=sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d \
--hash=sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f \
--hash=sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6 \
--hash=sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0 \
--hash=sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c \
--hash=sha256:30b65779d598c370374fefabf138d456fd6f3216bfa7bedfab1ba82025b0cd93 \
--hash=sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d \
--hash=sha256:35aaea0c7ee0e58a5cd8c2fd1a48fdf7ece0d2699b7ecdda08194e9ce5dd9b3d \
--hash=sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8 \
--hash=sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b \
--hash=sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001 \
--hash=sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d \
--hash=sha256:3d7f118b5adbfdfead90c25822690b02bc8074fba949bb7858bec4ebd55adb43 \
--hash=sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b \
--hash=sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0 \
--hash=sha256:4d433a51f1870e43a13b6732f92aaf540ff77c2015097c78556f75a2d6c030e0 \
--hash=sha256:4f26194e3d95e06501b942642855aed4f953d55e95d7d01b7c4483db3ecff458 \
--hash=sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8 \
--hash=sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d \
--hash=sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94 \
--hash=sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022 \
--hash=sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db \
--hash=sha256:64c753a0f87a256020004f37a1c8c02c480e725f910f0b2a0f3f07debd1b2479 \
--hash=sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376 \
--hash=sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d \
--hash=sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6 \
--hash=sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3 \
--hash=sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea \
--hash=sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd \
--hash=sha256:7762faa47e8ff7eb80bd261d9a7d8eea2d8baa69de5e95b70c1f338bbe712f02 \
--hash=sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde \
--hash=sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224 \
--hash=sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76 \
--hash=sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804 \
--hash=sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1 \
--hash=sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913 \
--hash=sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714 \
--hash=sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc \
--hash=sha256:88023dfe18799507b73f1dbb0d14326a17465de1bc9c9c7655c22845e9ddc3a2 \
--hash=sha256:89095c1968b4ba8285840e131bf2891b09ae137fe2146905acae0354fbce1b5e \
--hash=sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda \
--hash=sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512 \
--hash=sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28 \
--hash=sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699 \
--hash=sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3 \
--hash=sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c \
--hash=sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe \
--hash=sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a \
--hash=sha256:9d72af0cf10a76a600a9690078fe31c63b9588c8e86bf9fd353f713c84b5db0f \
--hash=sha256:9d8272c0e483b024e1b9ad029821470ed8ec65631dbd90217469da0e7cd89f1c \
--hash=sha256:a016194dbe13d14ee9556e734b772d8d67b947092b268d757fd4290e3ba2dfc2 \
--hash=sha256:a5781494d4d400a3f47f8f1da94b324f6e6b440a53387774002890a2a2f4b50f \
--hash=sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b \
--hash=sha256:aa7a1b53a2a4452ada2d1b5dade9960b2522f1e61293a811a077439e39029565 \
--hash=sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056 \
--hash=sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629 \
--hash=sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7 \
--hash=sha256:b65f590ef2a44640f9a05dbb548a429b4ade77913ce683ac8b1480777658a6c0 \
--hash=sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9 \
--hash=sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853 \
--hash=sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13 \
--hash=sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a \
--hash=sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4 \
--hash=sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce \
--hash=sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac \
--hash=sha256:c5f5df567f6eb216de69be06ce55c8b714090fae02b18a3b40da8163b8c5fa9c \
--hash=sha256:c941bb58d5a6e1c3892d86e42927ed6c180302f07e6d395d08c416e594b98b46 \
--hash=sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384 \
--hash=sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b \
--hash=sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210 \
--hash=sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc \
--hash=sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a \
--hash=sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5 \
--hash=sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7 \
--hash=sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2 \
--hash=sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326 \
--hash=sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f \
--hash=sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca \
--hash=sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98 \
--hash=sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9 \
--hash=sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5 \
--hash=sha256:f5bce581e6b8c235e566a14768a943b172ada3ed73537bb0c0be1edee312d4e7 \
--hash=sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc \
--hash=sha256:fb62edb5bb52cca65fab91a63afa7561607120d26090a7e8fda6fb9f064726da \
--hash=sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f
# via weasyprint
cfgv==3.5.0 \
--hash=sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0 \
@@ -105,67 +120,67 @@ cssselect2==0.9.0 \
--hash=sha256:6a99e5f91f9a016a304dd929b0966ca464bcfda15177b6fb4a118fc0fb5d9563 \
--hash=sha256:759aa22c216326356f65e62e791d66160a0f9c91d1424e8d8adc5e74dddfc6fb
# via weasyprint
distlib==0.4.0 \
--hash=sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16 \
--hash=sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d
distlib==0.4.3 \
--hash=sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b \
--hash=sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed
# via virtualenv
filelock==3.29.0 \
--hash=sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90 \
--hash=sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258
filelock==3.30.0 \
--hash=sha256:1774e682dbe443bd60f9609162fc596e2c80dc84ffc2957068953406d0520090 \
--hash=sha256:40632998f0772e64183bb819f086a1b9def6be1090cf1dcb9d45f46806ef279b
# via
# python-discovery
# virtualenv
fonttools==4.62.1 \
--hash=sha256:0aa72c43a601cfa9273bb1ae0518f1acadc01ee181a6fc60cd758d7fdadffc04 \
--hash=sha256:0b3ae47e8636156a9accff64c02c0924cbebad62854c4a6dbdc110cd5b4b341a \
--hash=sha256:12859ff0b47dd20f110804c3e0d0970f7b832f561630cd879969011541a464a9 \
--hash=sha256:149f7d84afca659d1a97e39a4778794a2f83bf344c5ee5134e09995086cc2392 \
--hash=sha256:1596aeaddf7f78e21e68293c011316a25267b3effdaccaf4d59bc9159d681b82 \
--hash=sha256:19177c8d96c7c36359266e571c5173bcee9157b59cfc8cb0153c5673dc5a3a7d \
--hash=sha256:1c5c25671ce8805e0d080e2ffdeca7f1e86778c5cbfbeae86d7f866d8830517b \
--hash=sha256:1eecc128c86c552fb963fe846ca4e011b1be053728f798185a1687502f6d398e \
--hash=sha256:268abb1cb221e66c014acc234e872b7870d8b5d4657a83a8f4205094c32d2416 \
--hash=sha256:2d850f66830a27b0d498ee05adb13a3781637b1826982cd7e2b3789ef0cc71ae \
--hash=sha256:2e7abd2b1e11736f58c1de27819e1955a53267c21732e78243fa2fa2e5c1e069 \
--hash=sha256:403d28ce06ebfc547fbcb0cb8b7f7cc2f7a2d3e1a67ba9a34b14632df9e080f9 \
--hash=sha256:40975849bac44fb0b9253d77420c6d8b523ac4dcdcefeff6e4d706838a5b80f7 \
--hash=sha256:486f32c8047ccd05652aba17e4a8819a3a9d78570eb8a0e3b4503142947880ed \
--hash=sha256:49a445d2f544ce4a69338694cad575ba97b9a75fff02720da0882d1a73f12800 \
--hash=sha256:59b372b4f0e113d3746b88985f1c796e7bf830dd54b28374cd85c2b8acd7583e \
--hash=sha256:5a648bde915fba9da05ae98856987ca91ba832949a9e2888b48c47ef8b96c5a9 \
--hash=sha256:5f37df1cac61d906e7b836abe356bc2f34c99d4477467755c216b72aa3dc748b \
--hash=sha256:6706d1cb1d5e6251a97ad3c1b9347505c5615c112e66047abbef0f8545fa30d1 \
--hash=sha256:68959f5fc58ed4599b44aad161c2837477d7f35f5f79402d97439974faebfebe \
--hash=sha256:6acb4109f8bee00fec985c8c7afb02299e35e9c94b57287f3ea542f28bd0b0a7 \
--hash=sha256:7487782e2113861f4ddcc07c3436450659e3caa5e470b27dc2177cade2d8e7fd \
--hash=sha256:7aa21ff53e28a9c2157acbc44e5b401149d3c9178107130e82d74ceb500e5056 \
--hash=sha256:7bca7a1c1faf235ffe25d4f2e555246b4750220b38de8261d94ebc5ce8a23c23 \
--hash=sha256:8d337fdd49a79b0d51c4da87bc38169d21c3abbf0c1aa9367eff5c6656fb6dae \
--hash=sha256:8f8fca95d3bb3208f59626a4b0ea6e526ee51f5a8ad5d91821c165903e8d9260 \
--hash=sha256:90365821debbd7db678809c7491ca4acd1e0779b9624cdc6ddaf1f31992bf974 \
--hash=sha256:92bb00a947e666169c99b43753c4305fc95a890a60ef3aeb2a6963e07902cc87 \
--hash=sha256:93c316e0f5301b2adbe6a5f658634307c096fd5aae60a5b3412e4f3e1728ab24 \
--hash=sha256:942b03094d7edbb99bdf1ae7e9090898cad7bf9030b3d21f33d7072dbcb51a53 \
--hash=sha256:9c125ffa00c3d9003cdaaf7f2c79e6e535628093e14b5de1dccb08859b680936 \
--hash=sha256:9dde91633f77fa576879a0c76b1d89de373cae751a98ddf0109d54e173b40f14 \
--hash=sha256:9e7863e10b3de72376280b515d35b14f5eeed639d1aa7824f4cf06779ec65e42 \
--hash=sha256:a24decd24d60744ee8b4679d38e88b8303d86772053afc29b19d23bb8207803c \
--hash=sha256:a5d8825e1140f04e6c99bb7d37a9e31c172f3bc208afbe02175339e699c710e1 \
--hash=sha256:aa69d10ed420d8121118e628ad47d86e4caa79ba37f968597b958f6cceab7eca \
--hash=sha256:ad5cca75776cd453b1b035b530e943334957ae152a36a88a320e779d61fc980c \
--hash=sha256:b4e0fcf265ad26e487c56cb12a42dffe7162de708762db951e1b3f755319507d \
--hash=sha256:b820fcb92d4655513d8402d5b219f94481c4443d825b4372c75a2072aa4b357a \
--hash=sha256:bd13b7999d59c5eb1c2b442eb2d0c427cb517a0b7a1f5798fc5c9e003f5ff782 \
--hash=sha256:bdfe592802ef939a0e33106ea4a318eeb17822c7ee168c290273cbd5fabd746c \
--hash=sha256:c05557a78f8fa514da0f869556eeda40887a8abc77c76ee3f74cf241778afd5a \
--hash=sha256:c22b1014017111c401469e3acc5433e6acf6ebcc6aa9efb538a533c800971c79 \
--hash=sha256:c9b9e288b4da2f64fd6180644221749de651703e8d0c16bd4b719533a3a7d6e3 \
--hash=sha256:d241cdc4a67b5431c6d7f115fdf63335222414995e3a1df1a41e1182acd4bcc7 \
--hash=sha256:e54c75fd6041f1122476776880f7c3c3295ffa31962dc6ebe2543c00dca58b5d \
--hash=sha256:e8514f4924375f77084e81467e63238b095abda5107620f49421c368a6017ed2 \
--hash=sha256:ee91628c08e76f77b533d65feb3fbe6d9dad699f95be51cf0d022db94089cdc4 \
--hash=sha256:ef46db46c9447103b8f3ff91e8ba009d5fe181b1920a83757a5762551e32bb68 \
--hash=sha256:fa1d16210b6b10a826d71bed68dd9ec24a9e218d5a5e2797f37c573e7ec215ca
fonttools==4.63.0 \
--hash=sha256:032038247a96c1690f9f31e377c389383c902531b085aa4e4dabd6f57f870e69 \
--hash=sha256:063e08bd17bd5a90127a14123de0d6a952dbc847695fd98b63c043d58057f90c \
--hash=sha256:0c18358a155d75034911c5ee397a5b44cd19dd325dbb8b35fb60bf421d6a72ac \
--hash=sha256:0eac00b9118c3c2f87d272e45341871c5b3066baa3c86897fa634a7c3fb59096 \
--hash=sha256:1e874792a8212b44583ea02189d9e693906b2f78b261f372f95d6c563210ac1d \
--hash=sha256:22135da48a348785c5e2d5d2d9d6bec5ed44adacbaeb9db12d9493bf6c6bfa68 \
--hash=sha256:22693918177bd9ceabec4736d338045f357769416fc6b0b2508eefef75b08616 \
--hash=sha256:27fdc65af8da6f88b9c6121c47a464cbe359fcfff7ff6fc2d37a1f395d755b78 \
--hash=sha256:2b8ae05d9eacf6081414d759c0a352769ac28ce31280d6bb8e77b03f9e3c449f \
--hash=sha256:2c14b4fd138c4bafcca294765c547914e1aa431ae1ca94ab99d8db08c958bd3b \
--hash=sha256:308f957cdeaf8abe4e5f2f124902ef405448af92c90f80e302a3b771c2e6116b \
--hash=sha256:37dd23e621e3b0aef1baa70a303b80aaf38449632cfc8fd2a55fb285bbccfc02 \
--hash=sha256:445af2eab030a16b9171ea8bdda7ebf7d96bda2df88ee182a464252f6e05e20d \
--hash=sha256:51394295f1a51de8b5f30bdb1e1b9a4231536c7064ef5c6e211eec19fa36036f \
--hash=sha256:58dc6bb86a78d782f00f9190ca02c119cf5bbe2807536e361e18d42019f877d8 \
--hash=sha256:59ac449f8cca9b4ffa08d2e7bbadad87ce710d69d1eda5c3c1ce579baa987272 \
--hash=sha256:6b2248c5decb223562f7902ff6325077a073f608ee8e33e88ad88db734eb9f49 \
--hash=sha256:6d4741eb179121cab9eea4cb2393d24492373a260d7945006358c08cfbf45419 \
--hash=sha256:6db5140a60a5d731d21ec076745b40a310607731b0a565b50776393188649001 \
--hash=sha256:6e528da43bc3791085f8cb6141b1d13e459226790240340fcbb4625649238b03 \
--hash=sha256:796f27556dbe094c4824f75ca85267e4df776c79036c8441469a4df37038c196 \
--hash=sha256:79cdc9f567aec74a72918fd060283911406750cbc9fd28c1316023deb6ce31a9 \
--hash=sha256:7d76edbff9014094dbf03bd2d074709dfa6ec7aba13d838c937a2b33d2d6a86e \
--hash=sha256:7d782fac32985914c351556f68ac0855391572bcd87de50e05970d3cd4c96fc5 \
--hash=sha256:7dd683fef0663e9f0f45cf541d788d24caa3ec9db50796b588e1757d8b3bc007 \
--hash=sha256:85be818f5506e8a7753153def2c9550178f0ecae6a47b5e0e8dbb23f7cc90380 \
--hash=sha256:948428a275741f0b64b113c955425a953314f4b9ab9997f73a72c83e68e569c8 \
--hash=sha256:9ced0bd02ac751dd6319b0da88aaef24414e3b0dbc32bb4f24944821a3741a27 \
--hash=sha256:9e12f105d2b6342c559c298afb674006bb2893afc7102dcf8a1b55b0486b4e40 \
--hash=sha256:a8b33a82979e0a6a34ff435cc81317be1f95ec1ebb7a3a2d1c8a6a54f02ae44e \
--hash=sha256:a9faff9e0c1f76f9fd55899d2ce785832efebab37eb8ae13995853aef178bef0 \
--hash=sha256:af2fd1664d00a397d75f806985ddb36282091c2131a73a6485c23b4a34722263 \
--hash=sha256:afefc1ed0a59785a7fb06ea7e1678e849c193e1e387db783579bc7b3056fcfcb \
--hash=sha256:b1cd75a03ad8cb5bc40c90bfde68c0c47de423aa19e5c0f362b43520645eea94 \
--hash=sha256:ba04cb5891d4c0c21b6da95eda8d7b090021508a294fff33464fc7d241e0856b \
--hash=sha256:bf00f21eb5fb721dbaf73d1e9da6d02a1af7768f2ebcf9798be98beab8ba90f6 \
--hash=sha256:c0425b277a59cff3d80ca42162a8de360f318438a2ac83570842a678d826d579 \
--hash=sha256:c1aaa4b9c75798400ac043ce04d74e7830376c85095a5a6ed7cba2f17a266bf4 \
--hash=sha256:c2a2a42198b696a6f48fad91709afb55176e66a5e566131219dba372fb7f8c59 \
--hash=sha256:caeb583deeb5168e694b65cda8b4ee62abedfa66cf88488734466f2366b9c4e0 \
--hash=sha256:cb014d58140a38135f16064c74c652ed57aa0b75cbf8bb59cac821f7edb5334e \
--hash=sha256:ccf41f2efdf56994d22d73bef4ced1052161958169428d06ba9724ea9e9a64be \
--hash=sha256:cd7e9857e5e63738b9d9fd707bc1f59c8b09e5177726d23664db393c59bb08bd \
--hash=sha256:d76ac49f929aecaf82d83250b8347e099d7aecba0f4726c1d9b6df3b8bb5fe18 \
--hash=sha256:d7e5c9973aa04c95650c96e5f5ad865fbf42d62079163ecfab1e01cbc2504c22 \
--hash=sha256:dcf076a4474fe0d7367e5bbf5b052c7284fa1feca729c04176ce513521afd8a0 \
--hash=sha256:e3297a6a4059b4acc3a1e9a8b04741f240a80044eef08ebd32e8b5bcdddce75b \
--hash=sha256:ee08ebfa58f6e1aeff5697ab9582105bb620008c1caafb681e4c557e7483027b \
--hash=sha256:ef3048ef05dbb552b89817713d9cac912e00d0fde4a3105c00d29e52e10c89af \
--hash=sha256:fd1e3094f42d806d3d7c79162fc59e5910fcbe3a7360c385b8da969bc4493745
# via weasyprint
identify==2.6.19 \
--hash=sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a \
@@ -175,193 +190,190 @@ nodeenv==1.10.0 \
--hash=sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827 \
--hash=sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb
# via pre-commit
numpy==2.4.4 \
--hash=sha256:07077278157d02f65c43b1b26a3886bce886f95d20aabd11f87932750dfb14ed \
--hash=sha256:08f2e31ed5e6f04b118e49821397f12767934cfdd12a1ce86a058f91e004ee50 \
--hash=sha256:0aec54fd785890ecca25a6003fd9a5aed47ad607bbac5cd64f836ad8666f4959 \
--hash=sha256:0d35aea54ad1d420c812bfa0385c71cd7cc5bcf7c65fed95fc2cd02fe8c79827 \
--hash=sha256:0d4e437e295f18ec29bc79daf55e8a47a9113df44d66f702f02a293d93a2d6dd \
--hash=sha256:0dfd3f9d3adbe2920b68b5cd3d51444e13a10792ec7154cd0a2f6e74d4ab3233 \
--hash=sha256:1378871da56ca8943c2ba674530924bb8ca40cd228358a3b5f302ad60cf875fc \
--hash=sha256:15716cfef24d3a9762e3acdf87e27f58dc823d1348f765bbea6bef8c639bfa1b \
--hash=sha256:19710a9ca9992d7174e9c52f643d4272dcd1558c5f7af7f6f8190f633bd651a7 \
--hash=sha256:23cbfd4c17357c81021f21540da84ee282b9c8fba38a03b7b9d09ba6b951421e \
--hash=sha256:2483e4584a1cb3092da4470b38866634bafb223cbcd551ee047633fd2584599a \
--hash=sha256:27a8d92cd10f1382a67d7cf4db7ce18341b66438bdd9f691d7b0e48d104c2a9d \
--hash=sha256:28a650663f7314afc3e6ec620f44f333c386aad9f6fc472030865dc0ebb26ee3 \
--hash=sha256:2aa0613a5177c264ff5921051a5719d20095ea586ca88cc802c5c218d1c67d3e \
--hash=sha256:2c194dd721e54ecad9ad387c1d35e63dce5c4450c6dc7dd5611283dda239aabb \
--hash=sha256:2d19e6e2095506d1736b7d80595e0f252d76b89f5e715c35e06e937679ea7d7a \
--hash=sha256:2d390634c5182175533585cc89f3608a4682ccb173cc9bb940b2881c8d6f8fa0 \
--hash=sha256:30caa73029a225b2d40d9fae193e008e24b2026b7ee1a867b7ee8d96ca1a448e \
--hash=sha256:42c16925aa5a02362f986765f9ebabf20de75cdefdca827d14315c568dcab113 \
--hash=sha256:45dbed2ab436a9e826e302fcdcbe9133f9b0006e5af7168afb8963a6520da103 \
--hash=sha256:4636de7fd195197b7535f231b5de9e4b36d2c440b6e566d2e4e4746e6af0ca93 \
--hash=sha256:4a19d9dba1a76618dd86b164d608566f393f8ec6ac7c44f0cc879011c45e65af \
--hash=sha256:4bbc7f303d125971f60ec0aaad5e12c62d0d2c925f0ab1273debd0e4ba37aba5 \
--hash=sha256:4d6d57903571f86180eb98f8f0c839fa9ebbfb031356d87f1361be91e433f5b7 \
--hash=sha256:4e874c976154687c1f71715b034739b45c7711bec81db01914770373d125e392 \
--hash=sha256:51fc224f7ca4d92656d5a5eb315f12eb5fe2c97a66249aa7b5f562528a3be38c \
--hash=sha256:58c8b5929fcb8287cbd6f0a3fae19c6e03a5c48402ae792962ac465224a629a4 \
--hash=sha256:5a285b3b96f951841799528cd1f4f01cd70e7e0204b4abebac9463eecfcf2a40 \
--hash=sha256:5c70f1cc1c4efbe316a572e2d8b9b9cc44e89b95f79ca3331553fbb63716e2bf \
--hash=sha256:62d6b0f03b694173f9fcb1fb317f7222fd0b0b103e784c6549f5e53a27718c44 \
--hash=sha256:6a246d5914aa1c820c9443ddcee9c02bec3e203b0c080349533fae17727dfd1b \
--hash=sha256:6aa3236c78803afbcb255045fbef97a9e25a1f6c9888357d205ddc42f4d6eba5 \
--hash=sha256:6bbe4eb67390b0a0265a2c25458f6b90a409d5d069f1041e6aff1e27e3d9a79e \
--hash=sha256:715d1c092715954784bc79e1174fc2a90093dc4dc84ea15eb14dad8abdcdeb74 \
--hash=sha256:72944b19f2324114e9dc86a159787333b77874143efcf89a5167ef83cfee8af0 \
--hash=sha256:81f4a14bee47aec54f883e0cad2d73986640c1590eb9bfaaba7ad17394481e6e \
--hash=sha256:846300f379b5b12cc769334464656bc882e0735d27d9726568bc932fdc49d5ec \
--hash=sha256:86b6f55f5a352b48d7fbfd2dbc3d5b780b2d79f4d3c121f33eb6efb22e9a2015 \
--hash=sha256:874f200b2a981c647340f841730fc3a2b54c9d940566a3c4149099591e2c4c3d \
--hash=sha256:8a87ec22c87be071b6bdbd27920b129b94f2fc964358ce38f3822635a3e2e03d \
--hash=sha256:8b3b60bb7cba2c8c81837661c488637eee696f59a877788a396d33150c35d842 \
--hash=sha256:8e3ed142f2728df44263aaf5fb1f5b0b99f4070c553a0d7f033be65338329150 \
--hash=sha256:93e15038125dc1e5345d9b5b68aa7f996ec33b98118d18c6ca0d0b7d6198b7e8 \
--hash=sha256:989824e9faf85f96ec9c7761cd8d29c531ad857bfa1daa930cba85baaecf1a9a \
--hash=sha256:99d838547ace2c4aace6c4f76e879ddfe02bb58a80c1549928477862b7a6d6ed \
--hash=sha256:9b2aec6af35c113b05695ebb5749a787acd63cafc83086a05771d1e1cd1e555f \
--hash=sha256:9c585a1790d5436a5374bac930dad6ed244c046ed91b2b2a3634eb2971d21008 \
--hash=sha256:a7164afb23be6e37ad90b2f10426149fd75aee07ca55653d2aa41e66c4ef697e \
--hash=sha256:ac6b31e35612a26483e20750126d30d0941f949426974cace8e6b5c58a3657b0 \
--hash=sha256:ad2e2ef14e0b04e544ea2fa0a36463f847f113d314aa02e5b402fdf910ef309e \
--hash=sha256:b268594bccac7d7cf5844c7732e3f20c50921d94e36d7ec9b79e9857694b1b2f \
--hash=sha256:b5f0362dc928a6ecd9db58868fca5e48485205e3855957bdedea308f8672ea4a \
--hash=sha256:ba1f4fc670ed79f876f70082eff4f9583c15fb9a4b89d6188412de4d18ae2f40 \
--hash=sha256:ba203255017337d39f89bdd58417f03c4426f12beed0440cfd933cb15f8669c7 \
--hash=sha256:c901b15172510173f5cb310eae652908340f8dede90fff9e3bf6c0d8dfd92f83 \
--hash=sha256:c9b39d38a9bd2ae1becd7eac1303d031c5c110ad31f2b319c6e7d98b135c934d \
--hash=sha256:d2a8490669bfe99a233298348acc2d824d496dee0e66e31b66a6022c2ad74a5c \
--hash=sha256:dddbbd259598d7240b18c9d87c56a9d2fb3b02fe266f49a7c101532e78c1d871 \
--hash=sha256:df3775294accfdd75f32c74ae39fcba920c9a378a2fc18a12b6820aa8c1fb502 \
--hash=sha256:e44319a2953c738205bf3354537979eaa3998ed673395b964c1176083dd46252 \
--hash=sha256:e4a010c27ff6f210ff4c6ef34394cd61470d01014439b192ec22552ee867f2a8 \
--hash=sha256:e823b8b6edc81e747526f70f71a9c0a07ac4e7ad13020aa736bb7c9d67196115 \
--hash=sha256:e892aff75639bbef0d2a2cfd55535510df26ff92f63c92cd84ef8d4ba5a5557f \
--hash=sha256:eea7ac5d2dce4189771cedb559c738a71512768210dc4e4753b107a2048b3d0e \
--hash=sha256:ef4059d6e5152fa1a39f888e344c73fdc926e1b2dd58c771d67b0acfbf2aa67d \
--hash=sha256:f169b9a863d34f5d11b8698ead99febeaa17a13ca044961aa8e2662a6c7766a0 \
--hash=sha256:f2cf083b324a467e1ab358c105f6cad5ea950f50524668a80c486ff1db24e119 \
--hash=sha256:f8474c4241bc18b750be2abea9d7a9ec84f46ef861dbacf86a4f6e043401f79e \
--hash=sha256:f983334aea213c99992053ede6168500e5f086ce74fbc4acc3f2b00f5762e9db \
--hash=sha256:f9e75681b59ddaa5e659898085ae0eaea229d054f2ac0c7e563a62205a700121 \
--hash=sha256:fbc356aae7adf9e6336d336b9c8111d390a05df88f1805573ebb0807bd06fd1d \
--hash=sha256:fcfe2045fd2e8f3cb0ce9d4ba6dba6333b8fa05bb8a4939c908cd43322d14c7e
numpy==2.4.6 \
--hash=sha256:001fbb8e08d942dd57599e781f2472269ee7f2755fae407b4f67b2f0b17da3f1 \
--hash=sha256:0280e0356c0829a18d9de1cb7eee50ec22ca639878d7240307ca0943d73cd2c4 \
--hash=sha256:043191bfa8eab18c776647b62723ac9dddece59743b13f49b2016094129c2b3f \
--hash=sha256:06ca2f61ec4385a07a6977c55ba998a4466c123642b4a32694d3128fce18c079 \
--hash=sha256:0a041d3d761dc3c35cc56ce0351506a02bcbc25f7b169f652435141a17db9096 \
--hash=sha256:0ab0a9c4ffb1a6d95ef519fe4247dba8eb6b18ad93999f76b7f657039acabd47 \
--hash=sha256:0c9136e14ed34a9e343a31c533d78a9813a69a3148332bce5e9821cb2f996e66 \
--hash=sha256:110f8b71aacb688ec69062bb7f6938a0f8acb01b7c1c4beb453c65b6d234584d \
--hash=sha256:112b06a867b235ef466ed3508ddf0238050df9c727cafb5301ac385b899189a1 \
--hash=sha256:17f9ade344e7d9b464a084d69bcf18fc691cb1db67c62ed80820bf4926d78f0e \
--hash=sha256:1e254a00cdf42b1e4d5b3d68d33af63268d41340d8885df2ab6470f2e1500147 \
--hash=sha256:1e978ec1e8bd0e0e4de6bb75de9d30cbb74db6b6a2bb727618613703ca0167dd \
--hash=sha256:25c692919ac5a01f170a3bfcd62d745b24fd095c353d50812637d6fcab442e75 \
--hash=sha256:260a5d70215b61ab4fadf5c7baacd64821842975eea312125ed3c39a6391b063 \
--hash=sha256:2803abfebfc990042cd494d8ce2d5f82e9d847af6d35ec486923aa19dbad5e73 \
--hash=sha256:29a287e0cf63ff528da061de6b9f64a4618da591ca1046aafc54062e40ca7eab \
--hash=sha256:29cb7f67d10b479ff07c17d33e39f78c07f71c40ef30d63c153d340e96cd3fb4 \
--hash=sha256:3213d622a0283a39a93d188f3cf72b26862df52fbb4ca3697f51705016523d41 \
--hash=sha256:33111801a01c12a8a1e3721f0a9232f8cfc8ae2c6b7098167e6f623c6073f402 \
--hash=sha256:357cc07a6d7b0b182ff02249616a03742827ebb1277546b5c7cd7f7620a45698 \
--hash=sha256:38efbc8de75c7a0fc1ac190162d892787f3f47b57cc291231aafee36b80982b7 \
--hash=sha256:4081eb135ac24158bd51cdfbef16f1c64df7063b1143f24731387137c092bec8 \
--hash=sha256:40fdc1ae7125e518ea98e53e69a4ebc27e1fd50510c47b7ea130cf21e5e1d42b \
--hash=sha256:4cfe66903cc32a9921a6733d96b19bb6abf310397581bbad89c228f5abaf0ee8 \
--hash=sha256:511dbaf848decaaaf4b4ca48032619fb3138710c4bf7da7617765edad1ef96b0 \
--hash=sha256:55cced7c52e981362f708ad635198e97a752dfba412cc03c23bbf3bd8d5cd662 \
--hash=sha256:56b39e5e0622a09a25bf5baf62f4bcf0cb8a41ae6e2819cf49bbc5a74c083f91 \
--hash=sha256:5dbbdb29840ca3d91ee0fece42fc29278886d908280bfec0a5846c6f901a3eb0 \
--hash=sha256:5f9fb9157b4ce2971008323afe46053787b526ef624fea915b261468a8421a0f \
--hash=sha256:6180d8b35af935aed8ece3a85e0a43f87393ae0ac87c8d2c8bd2c993f7270ef3 \
--hash=sha256:68a5124b13fa6cc2086764a20005d30bc0548146f7f5322f02fce212ca14317f \
--hash=sha256:68bb27509ac1b9a3443094260f6326150663b06abe40b73a2f81160623da5b67 \
--hash=sha256:6f41ae150c4e32db4f3310cdaf64b1593a03dbabe29eec77fc9b50fe64061df6 \
--hash=sha256:7265a2f3d436e54ef9f2b52b5c937e6be778781bd97a590319d7348f1c1ca997 \
--hash=sha256:72fbe16c6fac95aedf5937fa873445cec2110be35d8a4e9433d7501fd98dae6b \
--hash=sha256:7d92c3819208a60205a12a245c91ad70cb0a85336659b19b834205573ac8456e \
--hash=sha256:8155154c7c691289fe18f510b5d4657c68c67989f293f0535a91360392ff6538 \
--hash=sha256:81a1cca95ed5bb92aa8b10dd2cdc9a0d3853a50fad926c28b5d7e8ea54389627 \
--hash=sha256:89cd468399cfd2504718f0ba50e410dca55a170b61a02ad92bb18c8a65186e93 \
--hash=sha256:8ad03c0965fb3c692200e74d458ca28c1dbb4ce96f9a479a8aa041ad5fabca02 \
--hash=sha256:90f9849678c75fe7afa2d348ac842c168b0a4d3d61919687216dfc547976d853 \
--hash=sha256:948424b06129ce883307e8cff868c31396d8dc7630a59c61d70d98dbe70f222c \
--hash=sha256:9cd5ffd25db4e7ba6a375693b3fc0fc1791ec636c17db3720da19bde7180ec43 \
--hash=sha256:a0df0043bdb289bde1f62da130d20df23d58b45429f752bc7a8fc5325a225ecd \
--hash=sha256:a2c306dea656c12c68f51f4cea133cbe78ca7435eb28c735eac1d3ebe73be6e8 \
--hash=sha256:a7830bab239b79cda9c08c2da014761cafb48da6150e1da17ac06283f43b6089 \
--hash=sha256:a7c711e21628b52034bb5ab8d1bce291f752fcc5e92accc615778acee1ff4778 \
--hash=sha256:aaf159caa35993cb1f56fb9b8e4610d35758e7ca005412eb1daa856a78c9c4b1 \
--hash=sha256:ae506e6902902557576a26ff33eda8695e7ecb3cb36c3b573a0765dee114ebdb \
--hash=sha256:b507f5c4c1d508876d1819b6bf9a49d365b96320b5d4993426b33a23ca4b8261 \
--hash=sha256:bf162abab1c1a736333192707cef898e735a5ca00f38f27eeedf44b39d9e85eb \
--hash=sha256:c1a2af6c6ef86344a6b0db6b97834208bf598db514f2b155042439b62605601a \
--hash=sha256:c2d37ab77531417474168eb79d6d80b14f821a966818505d03013d0833edb7a8 \
--hash=sha256:c4fc99836233ea196540b17ab0983aff60ed07941751930f5f4d05bc3b3b7359 \
--hash=sha256:d581b735e177fdcdce6fed8e7e8880a3fb6ee4e3653a3ac6af01c6f4c03effc5 \
--hash=sha256:d6da64deb6b8ed903e7560180a92f2d804ee1ba5eeb849ac2748b8c1aba1f6d7 \
--hash=sha256:d8e8286dd7cea7895157318d1b91cdacac64c479f3cbc8dce548331728484751 \
--hash=sha256:ddea102b48f9e339f3948bf22040944184627a30fdf7f858667673b9c5f033c8 \
--hash=sha256:dfa20cc6ca228e6b155b11da03825975ce66aea520985dbbddf0f2a5a495c605 \
--hash=sha256:e3e5193ef5a3dc73bceee50f7fdc2c90dbb76c42df8d8fae3d1067a583df579e \
--hash=sha256:e3eeb0aabd6bd5ce64faae67e9935203a6991b4bc2a485a767fbafb2c5125f45 \
--hash=sha256:e5805d5a22fd19c8ccff10a9561f9df94436b0545619ea579db2d3c35294bce2 \
--hash=sha256:e85b752a1e912b70eaad4fafbd4d1238007ab221de2009b9a2f5ae7461239895 \
--hash=sha256:eaf7fa2de5c0be8ae6ff8e9bea2ccd725e980541244521d8d4b5f3354a27babe \
--hash=sha256:ebfb099f8dcf083deef3ac1ca4c1503f387cf76296fcb3816b66f5ecb5f54fdb \
--hash=sha256:ece3d2cfe132e7d51f44a832b303895e6f2d499c5e74dfbdb06ee246147a304a \
--hash=sha256:ed9749eef4cbd126da3dc1d6bcb3a57f5eb7ac6a6484146bdbf743f552dfc577 \
--hash=sha256:ede83e07a75dd06bc501566c1eca2afc0d61677c1472ac9ad93fdee6e638a48d \
--hash=sha256:ef4aea96ce4d3b074422cb4f2f64e216bf9e213004bb58ecfdf50ea02ea8eb9a \
--hash=sha256:f3a3570c4a2a16746ac2c31a7c7c7b0c186b95ce902e33db6f28094ed7387dda \
--hash=sha256:f407cb6b8e9d6d8c626bc73c945db1706035af8fd632295547bf1c9e46d092d6 \
--hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20
# via opencv-python-headless
opencv-python-headless==4.13.0.92 \
--hash=sha256:0525a3d2c0b46c611e2130b5fdebc94cf404845d8fa64d2f3a3b679572a5bd22 \
--hash=sha256:0bd48544f77c68b2941392fcdf9bcd2b9cdf00e98cb8c29b2455d194763cf99e \
--hash=sha256:1a7d040ac656c11b8c38677cc8cccdc149f98535089dbe5b081e80a4e5903209 \
--hash=sha256:3e0a6f0a37994ec6ce5f59e936be21d5d6384a4556f2d2da9c2f9c5dc948394c \
--hash=sha256:5c8cfc8e87ed452b5cecb9419473ee5560a989859fe1d10d1ce11ae87b09a2cb \
--hash=sha256:77a82fe35ddcec0f62c15f2ba8a12ecc2ed4207c17b0902c7a3151ae29f37fb6 \
--hash=sha256:a7cf08e5b191f4ebb530791acc0825a7986e0d0dee2a3c491184bd8599848a4b \
--hash=sha256:eb60e36b237b1ebd40a912da5384b348df8ed534f6f644d8e0b4f103e272ba7d
opencv-python-headless==5.0.0.93 \
--hash=sha256:030ca5e0837a2963ab36ef896baa9767eb8d2b83353fb28af5a521e40dd8756f \
--hash=sha256:09a872a157c1376ab922a69bbf22f9a95bcc7b658a9d8b436a60212b02b2eeb4 \
--hash=sha256:10818d91510e05c04568ae12b5cd120779c70c01bf897b001a6221fe430df80f \
--hash=sha256:1e55af3abfb462eeeabe5c775f12bdb36216d8a93a3583d69e6bd6e1d6ba7d00 \
--hash=sha256:829717b6a95554f273e49e357cee3b3a2a26b6f4842fbc1bed2b45bdd8f87e0e \
--hash=sha256:840bd717c21e5c11cadadc022a823315ea417f961213d06b4df010e019eb16f4 \
--hash=sha256:b82f9831daab90b725c7c1ee1b36cb5732c367096ac76d119e64e14eb70d5f3c \
--hash=sha256:c6bcd96b185975ea240d22cfdb15a1f6d080cc95264cfbe2621f21bb144d89b9 \
--hash=sha256:ed709fdf9aa0bd1f2ed8549e71d19449b03a675bb581eb292285f6861953be37
# via -r .github/scripts/requirements_dev.in
pdf2image==1.17.0 \
--hash=sha256:eaa959bc116b420dd7ec415fcae49b98100dda3dd18cd2fdfa86d09f112f6d57 \
--hash=sha256:ecdd58d7afb810dffe21ef2b1bbc057ef434dabbac6c33778a38a3f7744a27e2
# via -r .github/scripts/requirements_dev.in
pillow==12.2.0 \
--hash=sha256:00a2865911330191c0b818c59103b58a5e697cae67042366970a6b6f1b20b7f9 \
--hash=sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5 \
--hash=sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987 \
--hash=sha256:03f6fab9219220f041c74aeaa2939ff0062bd5c364ba9ce037197f4c6d498cd9 \
--hash=sha256:042db20a421b9bafecc4b84a8b6e444686bd9d836c7fd24542db3e7df7baad9b \
--hash=sha256:0538bd5e05efec03ae613fd89c4ce0368ecd2ba239cc25b9f9be7ed426b0af1f \
--hash=sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd \
--hash=sha256:0c838a5125cee37e68edec915651521191cef1e6aa336b855f495766e77a366e \
--hash=sha256:144748b3af2d1b358d41286056d0003f47cb339b8c43a9ea42f5fea4d8c66b6e \
--hash=sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe \
--hash=sha256:1e1757442ed87f4912397c6d35a0db6a7b52592156014706f17658ff58bbf795 \
--hash=sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601 \
--hash=sha256:25373b66e0dd5905ed63fa3cae13c82fbddf3079f2c8bf15c6fb6a35586324c1 \
--hash=sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed \
--hash=sha256:2c727a6d53cb0018aadd8018c2b938376af27914a68a492f59dfcaca650d5eea \
--hash=sha256:2d192a155bbcec180f8564f693e6fd9bccff5a7af9b32e2e4bf8c9c69dbad6b5 \
--hash=sha256:2e589959f10d9824d39b350472b92f0ce3b443c0a3442ebf41c40cb8361c5b97 \
--hash=sha256:2e5a76d03a6c6dcef67edabda7a52494afa4035021a79c8558e14af25313d453 \
--hash=sha256:325ca0528c6788d2a6c3d40e3568639398137346c3d6e66bb61db96b96511c98 \
--hash=sha256:34c0d99ecccea270c04882cb3b86e7b57296079c9a4aff88cb3b33563d95afaa \
--hash=sha256:390ede346628ccc626e5730107cde16c42d3836b89662a115a921f28440e6a3b \
--hash=sha256:394167b21da716608eac917c60aa9b969421b5dcbbe02ae7f013e7b85811c69d \
--hash=sha256:3997232e10d2920a68d25191392e3a4487d8183039e1c74c2297f00ed1c50705 \
--hash=sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8 \
--hash=sha256:3e080565d8d7c671db5802eedfb438e5565ffa40115216eabb8cd52d0ecce024 \
--hash=sha256:4a6c9fa44005fa37a91ebfc95d081e8079757d2e904b27103f4f5fa6f0bf78c0 \
--hash=sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286 \
--hash=sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150 \
--hash=sha256:50d8520da2a6ce0af445fa6d648c4273c3eeefbc32d7ce049f22e8b5c3daecc2 \
--hash=sha256:51c4167c34b0d8ba05b547a3bb23578d0ba17b80a5593f93bd8ecb123dd336a3 \
--hash=sha256:56a3f9c60a13133a98ecff6197af34d7824de9b7b38c3654861a725c970c197b \
--hash=sha256:56b25336f502b6ed02e889f4ece894a72612fe885889a6e8c4c80239ff6e5f5f \
--hash=sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463 \
--hash=sha256:58f62cc0f00fd29e64b29f4fd923ffdb3859c9f9e6105bfc37ba1d08994e8940 \
--hash=sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166 \
--hash=sha256:5cdfebd752ec52bf5bb4e35d9c64b40826bc5b40a13df7c3cda20a2c03a0f5ed \
--hash=sha256:5d04bfa02cc2d23b497d1e90a0f927070043f6cbf303e738300532379a4b4e0f \
--hash=sha256:5d2fd0fa6b5d9d1de415060363433f28da8b1526c1c129020435e186794b3795 \
--hash=sha256:62f5409336adb0663b7caa0da5c7d9e7bdbaae9ce761d34669420c2a801b2780 \
--hash=sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7 \
--hash=sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1 \
--hash=sha256:673aa32138f3e7531ccdbca7b3901dba9b70940a19ccecc6a37c77d5fdeb05b5 \
--hash=sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295 \
--hash=sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b \
--hash=sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354 \
--hash=sha256:6e6b2a0c538fc200b38ff9eb6628228b77908c319a005815f2dde585a0664b60 \
--hash=sha256:71cde9a1e1551df7d34a25462fc60325e8a11a82cc2e2f54578e5e9a1e153d65 \
--hash=sha256:7371b48c4fa448d20d2714c9a1f775a81155050d383333e0a6c15b1123dda005 \
--hash=sha256:766cef22385fa1091258ad7e6216792b156dc16d8d3fa607e7545b2b72061f1c \
--hash=sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be \
--hash=sha256:7f84204dee22a783350679a0333981df803dac21a0190d706a50475e361c93f5 \
--hash=sha256:8023abc91fba39036dbce14a7d6535632f99c0b857807cbbbf21ecc9f4717f06 \
--hash=sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae \
--hash=sha256:8297651f5b5679c19968abefd6bb84d95fe30ef712eb1b2d9b2d31ca61267f4c \
--hash=sha256:88d387ff40b3ff7c274947ed3125dedf5262ec6919d83946753b5f3d7c67ea4c \
--hash=sha256:88ddbc66737e277852913bd1e07c150cc7bb124539f94c4e2df5344494e0a612 \
--hash=sha256:8bd7903a5f2a4545f6fd5935c90058b89d30045568985a71c79f5fd6edf9b91e \
--hash=sha256:8be29e59487a79f173507c30ddf57e733a357f67881430449bb32614075a40ab \
--hash=sha256:8c984051042858021a54926eb597d6ee3012393ce9c181814115df4c60b9a808 \
--hash=sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f \
--hash=sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e \
--hash=sha256:90e6f81de50ad6b534cab6e5aef77ff6e37722b2f5d908686f4a5c9eba17a909 \
--hash=sha256:975385f4776fafde056abb318f612ef6285b10a1f12b8570f3647ad0d74b48ec \
--hash=sha256:9a8a34cc89c67a65ea7437ce257cea81a9dad65b29805f3ecee8c8fe8ff25ffe \
--hash=sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50 \
--hash=sha256:9f08483a632889536b8139663db60f6724bfcb443c96f1b18855860d7d5c0fd4 \
--hash=sha256:a4e8f36e677d3336f35089648c8955c51c6d386a13cf6ee9c189c5f5bd713a9f \
--hash=sha256:a52edc8bfff4429aaabdf4d9ee0daadbbf8562364f940937b941f87a4290f5ff \
--hash=sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5 \
--hash=sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb \
--hash=sha256:af73337013e0b3b46f175e79492d96845b16126ddf79c438d7ea7ff27783a414 \
--hash=sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1 \
--hash=sha256:b85f66ae9eb53e860a873b858b789217ba505e5e405a24b85c0464822fe88032 \
--hash=sha256:b86024e52a1b269467a802258c25521e6d742349d760728092e1bc2d135b4d76 \
--hash=sha256:bd9c0c7a0c681a347b3194c500cb1e6ca9cab053ea4d82a5cf45b6b754560136 \
--hash=sha256:bfa9c230d2fe991bed5318a5f119bd6780cda2915cca595393649fc118ab895e \
--hash=sha256:d362d1878f00c142b7e1a16e6e5e780f02be8195123f164edf7eddd911eefe7c \
--hash=sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3 \
--hash=sha256:dac8d77255a37e81a2efcbd1fc05f1c15ee82200e6c240d7e127e25e365c39ea \
--hash=sha256:dd025009355c926a84a612fecf58bb315a3f6814b17ead51a8e48d3823d9087f \
--hash=sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104 \
--hash=sha256:e74473c875d78b8e9d5da2a70f7099549f9eb37ded4e2f6a463e60125bccd176 \
--hash=sha256:ee3120ae9dff32f121610bb08e4313be87e03efeadfc6c0d18f89127e24d0c24 \
--hash=sha256:eedf4b74eda2b5a4b2b2fb4c006d6295df3bf29e459e198c90ea48e130dc75c3 \
--hash=sha256:efd8c21c98c5cc60653bcb311bef2ce0401642b7ce9d09e03a7da87c878289d4 \
--hash=sha256:f1c943e96e85df3d3478f7b691f229887e143f81fedab9b20205349ab04d73ed \
--hash=sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43 \
--hash=sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421 \
--hash=sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7 \
--hash=sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06 \
--hash=sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5
pillow==12.3.0 \
--hash=sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756 \
--hash=sha256:04f01d28a6aaff387bf842a13be313df23ba0597a44f1a976c9feb3c6ff4711a \
--hash=sha256:06ff022112bc9cbf83b60f8e028d94ad87b60621706487e65f673de61610ab59 \
--hash=sha256:0740a512dc522224c77d9aa5a8d70d8b7d73fb91f2c21125d8d025d3b8990e45 \
--hash=sha256:0847a763afefb695bc912d7c131e7e0632d4edc1d8698f58ddabec8e46b8b6d3 \
--hash=sha256:0dd2064cbc55aaec028ef5fbb60fa47bb6c3e7918e07ff17935284b227a9d2df \
--hash=sha256:0feb2e9d6ad6c9e3c06effe9d00f3f1e618a6643273576b016f591e9315a7139 \
--hash=sha256:10e41f0fbf1eec8cfd234b8fe17a4caac7c9d0db4c204d3c173a8f9f6ef3232b \
--hash=sha256:1182d52bc2d5e5d7d0949503aa7e36d12f42205dc287e4883f407b1988820d39 \
--hash=sha256:164b31cd1a0490ab6efae01aa5df49da7061be0af1b30e035b6e9a1bfe34ee6e \
--hash=sha256:1657923d2d45afb66526e5b933e5b3052e6bdea196c90d3abb2424e18c77dae8 \
--hash=sha256:186941b6aef820ad110fb01fb06eb925374dc3a21b17e37ec9a53b250c6fe2d1 \
--hash=sha256:1cca606cd25738df4ed873d5ad46bbdb3d83b5cbca291f6b4ff13a4df6b0bbe8 \
--hash=sha256:21900ce7ba264168cd50defae43cd75d25c833ad4ad6e73ffc5596d12e25ac89 \
--hash=sha256:236ff70b9312fb68943c703aa842ca6a758abfa45ac187a5e7c1452e96ef72b5 \
--hash=sha256:23aceaa007d6172b02c277f0cd359c79492bbb14f7072b4ede9fbcaf20648130 \
--hash=sha256:23d27a3e0307ec2244cc51e7287b919aa68d097504ebe19df4e76a98a3eea5bd \
--hash=sha256:24870b09b224f7ae3c39ed07d10e819d06f8720bc551847b1d623832b5b0e28d \
--hash=sha256:251bf95b67017e27b13d82f5b326234ca62d70f9cf4c2b9032de2358a3b12c7b \
--hash=sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed \
--hash=sha256:28ce87c5ab450a9dd970b52e5aca5fe63ed432d18a2eaddd1979a00a1ba24ace \
--hash=sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb \
--hash=sha256:30f2aa603c41533cc25c05acd0da21636e84a315768feb631c937177db558931 \
--hash=sha256:331b624368d4f1d069149002f25f44bc61c8919ce8ddb3c45bdad8f6e2d89510 \
--hash=sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6 \
--hash=sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1 \
--hash=sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce \
--hash=sha256:3edce1d53195db527e0191f84b71d02022de0540bf43a16ed734ed7537b07385 \
--hash=sha256:446c34dcc4324b084a53b705127dc15717b22c5e140ae0a3c38349d4efec071e \
--hash=sha256:4998562bf62a445225f22e07c896bb04b35b1b1f2eb6d760584c9c51d7a5f78c \
--hash=sha256:4b0a7fe987b14c31ebda6083f74f22b561fd3739bc0ac51e019622e3d72668c7 \
--hash=sha256:4e8c2a84d977f50b9daed6eeaf3baef67d00d5d74d932288f02cb94518ee3ace \
--hash=sha256:4f883547d4b7f0495ebe7056b0cc2aea76094e7a4abc8e933540f3271df27d9c \
--hash=sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f \
--hash=sha256:53aa02d20d10c3d814d536aa4e5ac9b84ca0ff5a88377963b085ad6822f93e64 \
--hash=sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f \
--hash=sha256:571b9fcb07b97ef3a492028fb3d2dc0993ca23a06138b0315286566d29ef718a \
--hash=sha256:57b3d78c95ba9059768b10e28b813002261d3f3dfc55cc48b0c988f625175827 \
--hash=sha256:5afb51d599ea772b8365ae807ae557f18bccfe46ab261fd1c2a9ed700fc6eb17 \
--hash=sha256:6b02afb9b97f65fbca5f31db6a2a3ba21aa93030225f150fa3f249717e938fb4 \
--hash=sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a \
--hash=sha256:71d6097b330eea8fd15097780c8e89cb1a8ce7838669f48c5bacd6f663dd4701 \
--hash=sha256:756c768d0c9c2955feb7a56c37ea24aea2e369f8d36a88da270b6a9f19e62b5e \
--hash=sha256:78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91 \
--hash=sha256:7a743ff716f746fc19a9557f60dab1600d4613255f8a7aeb3cdde4db7eb15a66 \
--hash=sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468 \
--hash=sha256:8728f216dcdb6e6d555cf971cb34076139ad74b31fc2c14da4fafc741c5f6217 \
--hash=sha256:877c3f311ff35410f690861c4409e7ccbf0cd2f878e50628a28e5a0bb689e658 \
--hash=sha256:8cd2f7bdda092d99c9fc2fb7391354f306d01443d22785d0cbfafa2e2c8bb418 \
--hash=sha256:8e95e1385e4998ae9694eeaa4730ba5457ff61185b3a55e2e7bea0880aef452a \
--hash=sha256:962864dc93511324d51ddbb5b9f8731bf71675b93ca612a07441896f4688fb8c \
--hash=sha256:9cf95fe4d0f84c82d282745d9bb08ad9f926efa00be4697e767b814ce40d4330 \
--hash=sha256:9e881fca225083806662a5c43d627d215f258ff43c890f831966c7d7ba9c7402 \
--hash=sha256:a2b55dd6b2a4c4b7d87ffa56bdb33fdc5fdb9a462173861a7bc097f17d91cb09 \
--hash=sha256:a45650e8ce7fafffd731db8550230db6b0d306d181a90b67d3e6bca2f1990930 \
--hash=sha256:a876864214e136f0eb367788dbd7df045f4806801518e2cfe9e13229cfe06d8f \
--hash=sha256:ae26d61dfa7a47befdc7572b521024e8745f3d809bd95ca9505a7bba9ef849ec \
--hash=sha256:af8d94b0db561cf68b88a267c5c44b49e134f525d0dc2cb7ed413a66bc23559a \
--hash=sha256:b343699e8308bdc51978310e1c959c584e7869cc8c40780058c87da7781a1e94 \
--hash=sha256:b3c777e849237620b022f7f297dd67705f9f5cf1685f09f02e46f93e92725468 \
--hash=sha256:b629de27fda84b42cde7edef0d85f13b958b47f6e9bbcbba9b673c562a89bd8b \
--hash=sha256:ba09209fbe443b4acccebe845d8a138b89a8f4fbaeedd44953490b5315d5e965 \
--hash=sha256:ba54cfebe86920a559a7c4d6b9050791c20513650a1952ebe3368c7dc70306f8 \
--hash=sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd \
--hash=sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7 \
--hash=sha256:bf16ba1b4d0b6b7c8e534936632270cf70eb00dbe09005bc345b2677b726855c \
--hash=sha256:cf1845d02ad822a369a49f2bb9345b1614744267682e7a03527dc3bf6eea1777 \
--hash=sha256:d69141514cc30b774ceea5e3ed3a6635c8d8a96edf664689b890f4089111fb35 \
--hash=sha256:d9c7f76c0673154f044e9d78c8655fb4213f6ca31a836df48b40fe5d187717b9 \
--hash=sha256:dbce0b29841537a2fa4a214c2bbf14de3587c9680caa9b4e217568472490b28f \
--hash=sha256:dc624f6bc473dacdf7ef7eb8678d0d08edf15cd94fad6ae5c7d6cc67a4e4902f \
--hash=sha256:e158cb00350dc278f3b91551101aa7d12415a66ebf2c91d8d5ac14e56ddd3ad0 \
--hash=sha256:e491916b378fba47242221bb9ead245211b70d504f495d105d17b14a24b4907c \
--hash=sha256:e795b7eb908249c4e43c7c99fac7c2c75dab0c43566e37db472a355f63693d71 \
--hash=sha256:e7e480451b9fa137494bccd3a7d69adbe8ac65a87d97be61e11f1b1050a5bac3 \
--hash=sha256:e91206ee562682b51b98ef4b26a6ef48fd84e15fd4c4bc5ec768eb641d206838 \
--hash=sha256:e9871b1ffbfa9656b60aeee92ed5136a5742696006fa322b29ea3d8da0ecc9cf \
--hash=sha256:e9aeb04d6aef139de265b29683e119b638208f88cf73cdd1658aa07221165321 \
--hash=sha256:ebaea975e03d3141d9d3a507df75c9b3ec90fa9d2ffd07567b3a978d9d790b26 \
--hash=sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec \
--hash=sha256:f13c32a3abd6079a66d9526e18dad9b6d280384d49d7c54040cd57b6424041d9 \
--hash=sha256:f7401aebd7f581d7f83a439d87d474999317ee099218e5ad25d125290990ba65 \
--hash=sha256:fa4ecea169a355be7a3ade2c783e2ed12f0e40d2c5621cda8b3297faf7fbb9f5 \
--hash=sha256:fbd139c8447d25dd750ab79ee274cc5e1fe80fc56340ab10b18a195e1b6eca3e \
--hash=sha256:fdafc9cce40277e0f7a0feabce0ee50dd2fa1800f3b38015e51296b5e814048d \
--hash=sha256:fe3cca2e4e8a592be0f269a1ca4835c25199d9f3ce815c8491048f785b0a0198 \
--hash=sha256:ffd0c5368496f41b0944be820fcb7a838aa6e623d250b01acf2643939c3f99d7
# via
# -r .github/scripts/requirements_dev.in
# pdf2image
# weasyprint
platformdirs==4.9.6 \
--hash=sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a \
--hash=sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917
platformdirs==4.10.0 \
--hash=sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7 \
--hash=sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a
# via
# python-discovery
# virtualenv
@@ -381,9 +393,9 @@ pyphen==0.17.2 \
--hash=sha256:3a07fb017cb2341e1d9ff31b8634efb1ae4dc4b130468c7c39dd3d32e7c3affd \
--hash=sha256:f60647a9c9b30ec6c59910097af82bc5dd2d36576b918e44148d8b07ef3b4aa3
# via weasyprint
python-discovery==1.2.2 \
--hash=sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb \
--hash=sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a
python-discovery==1.4.4 \
--hash=sha256:5cad33982d412c1f3ffb8f9ca4ea292c9680bca3942451d30b69c37fce53a4a3 \
--hash=sha256:abebe9120b43453b68c908acfb1e72a19d1a959ed2cb620ad38fc57d08056dbe
# via virtualenv
pyyaml==6.0.3 \
--hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \
@@ -470,17 +482,17 @@ tinyhtml5==2.1.0 \
--hash=sha256:60a50ec3d938a37e491efa01af895853060943dcebb5627de5b10d188b338a67 \
--hash=sha256:6e11cfff38515834268daf89d5f85bbde0b6dd02e8d9e212d1385c2289b89f0a
# via weasyprint
unoserver==3.6 \
--hash=sha256:25c360fa194396a89cb79b4edd2735f8e4f0fd8531e59db3952114585bd7df05 \
--hash=sha256:e446bcb3638c51880f002aaeecab1cf74dfa9df81035f027f7ff2e081b6d7015
unoserver==3.7 \
--hash=sha256:b05f9578506ac7374ae1b314c3a79528636c542ac78220a9ce99110584ca424b \
--hash=sha256:fc44e6808071c9d2957e705ecf1742cea8a582aa5d5cc23babf36bb332ec6e8e
# via -r .github/scripts/requirements_dev.in
virtualenv==21.2.4 \
--hash=sha256:29d21e941795206138d0f22f4e45ff7050e5da6c6472299fb7103318763861ac \
--hash=sha256:b294ef68192638004d72524ce7ef303e9d0cf5a44c95ce2e54a7500a6381cada
virtualenv==21.6.1 \
--hash=sha256:15f978b7cd329f24855ff4a0c4b4899cc7678589f49adbdcbbb4d3232e641128 \
--hash=sha256:afe991df855715a2b2f60edfcc0107ef95a79fdfd8cb4cdaa71603d1c12e463b
# via pre-commit
weasyprint==68.1 \
--hash=sha256:4dc3ba63c68bbbce3e9617cb2226251c372f5ee90a8a484503b1c099da9cf5be \
--hash=sha256:d3b752049b453a5c95edb27ce78d69e9319af5a34f257fa0f4c738c701b4184e
weasyprint==69.0 \
--hash=sha256:475951cfd917014de6d4d005caff48c6aa867e7e42b80cd5b16a0484a1609ee6 \
--hash=sha256:a7a32f39ca16bd82ef11de99c92ea4b5f14951c9033af035e451ce4f4ee0a88c
# via -r .github/scripts/requirements_dev.in
webencodings==0.5.1 \
--hash=sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78 \
@@ -489,27 +501,28 @@ webencodings==0.5.1 \
# cssselect2
# tinycss2
# tinyhtml5
zopfli==0.4.1 \
--hash=sha256:02086247dd12fda929f9bfe8b3962b6bcdbfc8c82e99255aebcf367867cf0760 \
--hash=sha256:07a5cdc5d1aaa6c288c5d9f5a5383042ba743641abf8e2fd898dcad622d8a38e \
--hash=sha256:27823dc1161a4031d1c25925fd45d9868ec0cbc7692341830a7dcfa25063662c \
--hash=sha256:2f992ac7d83cbddd889e1813ace576cbc91a05d5d7a0a21b366e2e5f492e7707 \
--hash=sha256:4238d4d746d1095e29c9125490985e0c12ffd3654f54a24af551e2391e936d54 \
--hash=sha256:5a4c22b6161f47f5bd34637dbaee6735abd287cd64e0d1ce28ef1871bf625f4b \
--hash=sha256:84a31ba9edc921b1d3a4449929394a993888f32d70de3a3617800c428a947b9b \
--hash=sha256:a899eca405662a23ae75054affa3517a060362eae1185d3d791c86a50153c4dd \
--hash=sha256:a93c2ecafff372de6c0aa2212eff18a75f6c71a100372fee7b4b129cc0b6f9a7 \
--hash=sha256:cb136a74d14a4ecfae29cb0fdecece58a6c115abc9a74c12bc6ac62e80f229d7 \
--hash=sha256:d7bcee1b189d64ec33d1e05cfa1b6a1268c29329c382f6ca1bd6245b04925c57 \
--hash=sha256:fdfb7ce9f5de37a5b2f75dd2642fd7717956ef2a72e0387302a36d382440db07
zopfli==0.4.3 \
--hash=sha256:0087c9a6f0c8a052be0f6d1a9bb71b6caffdd3e10201d6d6166e28d482cebe6d \
--hash=sha256:47604eee5c6704bdf0e94d8391fe3b74ddb2abd84128fbcfdc3ee0fc265feaef \
--hash=sha256:62248dbf8dbcbd588ee194b210e5be9fa80bce29641f55599d6d394bd2a9d8a3 \
--hash=sha256:628c3e941752880b3491db8d44163d0aedb221944e22a17187ff7fc549b050f6 \
--hash=sha256:769875152d0625c46707bcca57d4b2233fe653482067acd55fbf6ec525cb9bdc \
--hash=sha256:7e9703ca6e7ef66c8d05e0826b6f558b680c9db8206f84f05a3ee93430a12e42 \
--hash=sha256:7fa3c35193475290e3f007bbcdebdbae64ba2f012d75c632da0d727e1da50d5e \
--hash=sha256:88f4fbe429aad72bc206275d81fab11a097e0f951a5848d1f51083c37ea73073 \
--hash=sha256:921c2c9907f4364963848da5ad194b46d68865e07fdb975d04fd09bc42d47357 \
--hash=sha256:d3a50f91a13cea9bafe025de8fd87a005eb26de02a4f0c193127ddbf23ac8ebe \
--hash=sha256:d4f51dd1ab5312e837e2091284e0d9f1a138188f2e65812f9a5799dc02c45f94 \
--hash=sha256:eb0c9c1d40a8cb1d58762d7e57290ccb753e0828c4d01be8acb59aae5d0ca206 \
--hash=sha256:f2e0adcf7d36c6fd0dd36cc771ef7f0c5803a05666feafcd90d7170174a4148e
# via fonttools
# The following packages are considered to be unsafe in a requirements file:
pip==26.0.1 \
--hash=sha256:bdb1b08f4274833d62c1aa29e20907365a2ceb950410df15fc9521bad440122b \
--hash=sha256:c4037d8a277c89b320abe636d59f91e6d0922d08a05b60e85e53b296613346d8
pip==26.1.2 \
--hash=sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab \
--hash=sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605
# via -r .github/scripts/requirements_dev.in
setuptools==82.0.1 \
--hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \
--hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb
setuptools==83.0.0 \
--hash=sha256:025bccbbf0fa05b6192bc64ae1e7b16e001fd6d6d4d5de03c97b1c1ade523bef \
--hash=sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3
# via -r .github/scripts/requirements_dev.in
+4 -4
View File
@@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile --generate-hashes --output-file='.github\scripts\requirements_sync_readme.txt' --strip-extras '.github\scripts\requirements_sync_readme.in'
@@ -8,7 +8,7 @@ tomli-w==1.2.0 \
--hash=sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90 \
--hash=sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021
# via -r .github/scripts/requirements_sync_readme.in
tomlkit==0.14.0 \
--hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \
--hash=sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064
tomlkit==0.15.0 \
--hash=sha256:4dbc8f0fc024412b57ced8757ac7461305126a648ff8c2c807fcb8e133a78738 \
--hash=sha256:7d1a9ecba3086638211b13814ea79c90dd54dd11993564376f3aa92271f5c7a3
# via -r .github/scripts/requirements_sync_readme.in
+1 -3
View File
@@ -14,9 +14,7 @@ from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
from cryptography.exceptions import InvalidSignature
ART_ROOT = Path(sys.argv[1])
CONF = Path(
sys.argv[2] if len(sys.argv) > 2 else "frontend/editor/src-tauri/tauri.conf.json"
)
CONF = Path(sys.argv[2] if len(sys.argv) > 2 else "frontend/src-tauri/tauri.conf.json")
def load_pubkey():
+13 -40
View File
@@ -23,13 +23,9 @@ permissions:
pull-requests: write
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
check-pr:
if: (github.event_name == 'pull_request' && github.event.action != 'closed') || github.event_name == 'workflow_dispatch'
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
outputs:
should_deploy: ${{ steps.decide.outputs.should_deploy }}
is_fork: ${{ steps.resolve.outputs.is_fork }}
@@ -39,7 +35,7 @@ jobs:
pr_ref: ${{ steps.resolve.outputs.ref }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -101,8 +97,8 @@ jobs:
echo "allow_fork=${allow_fork:-false}" >> $GITHUB_OUTPUT
deploy-v2-pr:
needs: [pick, check-pr]
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
needs: check-pr
runs-on: ubuntu-latest
if: needs.check-pr.outputs.should_deploy == 'true' && (needs.check-pr.outputs.is_fork == 'false' || needs.check-pr.outputs.allow_fork == 'true')
# Concurrency control - only one deployment per PR at a time
concurrency:
@@ -112,17 +108,14 @@ jobs:
contents: read
issues: write
pull-requests: write
id-token: write
env:
USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' }}
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
# Single source of truth for whether this preview embeds the admin portal:
# drives the image build-arg and the deployment comment.
BUILD_PORTAL: "true"
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -190,13 +183,8 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0 # Fetch full history for commit hash detection
- name: Set up Depot CLI
if: env.USE_DEPOT == 'true'
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.0.0
- name: Set up Docker Buildx
if: env.USE_DEPOT != 'true'
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Get version number
id: versionNumber
@@ -205,7 +193,7 @@ jobs:
echo "versionNumber=$VERSION" >> $GITHUB_OUTPUT
- name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_API }}
@@ -240,22 +228,8 @@ jobs:
echo "Image needs to be built"
fi
- name: Build and push V2 image (Depot)
if: env.USE_DEPOT == 'true' && steps.check-image.outputs.exists == 'false'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.16.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: .
file: ./docker/embedded/Dockerfile
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-${{ steps.commit-hash.outputs.app_short }}
build-args: |
VERSION_TAG=v2-alpha
BUILD_PORTAL=${{ env.BUILD_PORTAL }}
platforms: linux/amd64
- name: Build and push V2 image (Docker fork fallback)
if: env.USE_DEPOT != 'true' && steps.check-image.outputs.exists == 'false'
- name: Build and push V2 image
if: steps.check-image.outputs.exists == 'false'
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
@@ -346,7 +320,7 @@ jobs:
# under the exact same access rules as the app preview.
- name: Detect Storybook changes
id: sb-changes
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
with:
list-files: json
filters: |
@@ -357,7 +331,7 @@ jobs:
- name: Set up Node.js for Storybook
if: steps.sb-changes.outputs.storybook == 'true'
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
@@ -474,8 +448,7 @@ jobs:
cleanup-v2-deployment:
if: github.event.action == 'closed'
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
@@ -483,7 +456,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -34,12 +34,8 @@ permissions:
pull-requests: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
check-comment:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
permissions:
issues: write
if: |
@@ -74,7 +70,7 @@ jobs:
enable_prototypes: ${{ steps.check-prototypes-flag.outputs.enable_prototypes }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -179,19 +175,15 @@ jobs:
}
deploy-pr:
needs: [pick, check-comment]
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
needs: check-comment
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
id-token: write
env:
USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' }}
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -219,10 +211,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
gradle-version: 9.6.0
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
@@ -240,36 +238,16 @@ jobs:
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
STIRLING_PDF_DESKTOP_UI: false
- name: Set up Depot CLI
if: env.USE_DEPOT == 'true'
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.0.0
- name: Set up Docker Buildx
if: env.USE_DEPOT != 'true'
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_API }}
- name: Build and push PR-specific image (Depot)
if: env.USE_DEPOT == 'true'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.16.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: .
file: ./docker/embedded/Dockerfile
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:pr-${{ needs.check-comment.outputs.pr_number }}
build-args: |
VERSION_TAG=alpha
PROTOTYPES_BUILD=${{ needs.check-comment.outputs.enable_prototypes }}
platforms: linux/amd64
- name: Build and push PR-specific image (Docker fork fallback)
if: env.USE_DEPOT != 'true'
- name: Build and push PR-specific image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
@@ -283,19 +261,8 @@ jobs:
PROTOTYPES_BUILD=${{ needs.check-comment.outputs.enable_prototypes }}
platforms: linux/amd64
- name: Build and push engine image (Depot)
if: env.USE_DEPOT == 'true' && needs.check-comment.outputs.enable_prototypes == 'true'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.16.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: ./engine
file: ./engine/Dockerfile
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:engine-pr-${{ needs.check-comment.outputs.pr_number }}
platforms: linux/amd64
- name: Build and push engine image (Docker fork fallback)
if: env.USE_DEPOT != 'true' && needs.check-comment.outputs.enable_prototypes == 'true'
- name: Build and push engine image
if: needs.check-comment.outputs.enable_prototypes == 'true'
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: ./engine
@@ -510,11 +477,10 @@ jobs:
handle-label-commands:
if: ${{ github.event.issue.pull_request != null }}
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+5 -32
View File
@@ -2,13 +2,8 @@ name: _runner-pick
# Tiny reusable workflow that classifies the trigger as either a "fork PR
# from an untrusted contributor" or a "trusted commit" so downstream jobs
# can pick a runner class without each one duplicating the 200-char gate
# expression in their own `runs-on:`.
#
# It also owns the single Depot kill-switch (use_depot). Depot is currently
# disabled repo-wide; downstream jobs gate their Depot runner/build usage on
# use_depot so nothing has to be deleted to turn Depot off. Flip DEPOT_ENABLED
# in the decide step to switch Depot back on.
# can trust-gate (skip secret-dependent jobs on forks) without each one
# duplicating the gate expression.
#
# Caller pattern:
#
@@ -18,15 +13,12 @@ name: _runner-pick
#
# real-work:
# needs: pick
# runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-8' || 'ubuntu-latest' }}
# if: needs.pick.outputs.is_fork != 'true'
# steps: [...]
#
# Outputs:
# is_fork: "true" when the trigger is a pull_request from a fork or an
# untrusted author_association, "false" otherwise. Use this for
# trust gating (skipping secret-dependent jobs on forks).
# use_depot: "true" when downstream jobs should use Depot runners/builders.
# Currently forced "false" (Depot disabled repo-wide).
# untrusted author_association, "false" otherwise.
on:
workflow_call:
@@ -34,9 +26,6 @@ on:
is_fork:
description: '"true" if the trigger is an untrusted fork PR.'
value: ${{ jobs.pick.outputs.is_fork }}
use_depot:
description: '"true" when downstream jobs should use Depot. Currently forced off.'
value: ${{ jobs.pick.outputs.use_depot }}
permissions:
contents: read
@@ -47,10 +36,9 @@ jobs:
timeout-minutes: 1
outputs:
is_fork: ${{ steps.decide.outputs.is_fork }}
use_depot: ${{ steps.decide.outputs.use_depot }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -63,12 +51,6 @@ jobs:
run: |
set -eu
# Depot kill-switch. Depot is disabled repo-wide: no job uses Depot
# runners or the Depot build actions while this is false. All the
# Depot wiring is left in place - set DEPOT_ENABLED=true to switch it
# back on (it then activates on trusted, non-fork triggers as before).
DEPOT_ENABLED=false
if [ -z "${PR_NUMBER:-}" ]; then
# Not a pull_request event at all (push, schedule, workflow_dispatch,
# workflow_call from a non-PR trigger) -> trusted by default.
@@ -82,13 +64,4 @@ jobs:
esac
fi
# Depot only ever ran on trusted triggers, so gate it on both the
# kill-switch and is_fork.
if [ "${DEPOT_ENABLED}" = "true" ] && [ "${is_fork}" = "false" ]; then
use_depot=true
else
use_depot=false
fi
echo "is_fork=${is_fork}" >> "$GITHUB_OUTPUT"
echo "use_depot=${use_depot}" >> "$GITHUB_OUTPUT"
+3 -4
View File
@@ -18,11 +18,9 @@ jobs:
permissions:
contents: read
pull-requests: write
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -30,9 +28,10 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
cache-suffix: ai-engine
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
+2 -2
View File
@@ -19,7 +19,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -87,7 +87,7 @@ jobs:
- name: AI PR Title Analysis
if: steps.actor.outputs.is_repo_dev == 'true'
id: ai-title-analysis
uses: actions/ai-inference@17ff458cb182449bbb2e43701fcd98f6af8f6570 # v2.1.0
uses: actions/ai-inference@a7805884c80886efc241e94a5351df715968a0ad # v2.1.1
with:
model: openai/gpt-4o
system-prompt-file: ".github/config/system-prompt.txt"
+2 -2
View File
@@ -26,7 +26,7 @@ jobs:
jar_sha256: ${{ steps.hashes.outputs.jar_sha256 }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -70,7 +70,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
pull-requests: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+9 -19
View File
@@ -19,14 +19,8 @@ permissions:
pull-requests: write
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
build:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-8' || 'ubuntu-latest' }}
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
@@ -34,7 +28,7 @@ jobs:
flavor: [core, proprietary, saas]
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
@@ -46,20 +40,16 @@ jobs:
java-version: ${{ matrix.jdk-version }}
distribution: "temurin"
- name: Cache Gradle dependency artifacts
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.gradle/caches/modules-2/files-2.1
~/.gradle/caches/modules-2/metadata-2.*
key: gradle-deps-${{ runner.os }}-jdk-${{ matrix.jdk-version }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties', '**/*.gradle', '**/*.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'gradle/libs.versions.toml') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
cache-disabled: true
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-${{ matrix.jdk-version }}-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-${{ matrix.jdk-version }}-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
@@ -247,7 +237,7 @@ jobs:
# so skip it for merge_group runs and workflow_dispatch.
if: github.event_name == 'pull_request'
id: jacoco
uses: madrapps/jacoco-report@50d3aff4548aa991e6753342d9ba291084e63848 # v1.7.2
uses: madrapps/jacoco-report@e51ce1f46f7f8b5331593f935e59cbaf44b84920 # v1.8.0
with:
paths: |
${{ github.workspace }}/**/build/reports/jacoco/test/jacocoTestReport.xml
+84 -20
View File
@@ -15,23 +15,11 @@ name: Enterprise E2E (Playwright)
on:
workflow_call:
inputs:
depot_cores:
description: "Depot runner vCPU count (used in runs-on). Override for benchmarking."
required: false
type: string
default: "8"
push:
branches: ["main"]
schedule:
- cron: "0 4 * * *"
workflow_dispatch:
inputs:
depot_cores:
description: "Depot runner vCPU count (used in runs-on). Override for benchmarking."
required: false
type: string
default: "8"
# No `concurrency:` block here on purpose. When this workflow is called via
# workflow_call from build.yml, ${{ github.workflow }}/event_name/pr_number
@@ -50,20 +38,19 @@ jobs:
playwright-e2e-enterprise:
needs: pick
# Skip on fork PRs / untrusted authors: they have no PREMIUM_KEY_ENTERPRISE
# (nor DEPOT_TOKEN), so the suite can't boot premium and would fail. See the
# header comment. GitHub reports the skipped reusable workflow as success.
# Skip on fork PRs / untrusted authors: they have no PREMIUM_KEY_ENTERPRISE,
# so the suite can't boot premium and would fail. See the header comment.
# GitHub reports the skipped reusable workflow as success.
if: needs.pick.outputs.is_fork != 'true'
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }}
runs-on: ubuntu-latest
timeout-minutes: 45
env:
PREMIUM_KEY: ${{ secrets.PREMIUM_KEY_ENTERPRISE }}
PREMIUM_ENABLED: "true"
SYSTEM_ENABLEANALYTICS: "false"
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
@@ -73,8 +60,18 @@ jobs:
with:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
@@ -297,7 +294,7 @@ jobs:
if: always()
working-directory: frontend
run: >
npx tsx editor/scripts/report-flaky-tests.mts
npx tsx scripts/report-flaky-tests.mts
"${{ github.workspace }}/frontend/playwright-report/results-oauth.json"
"${{ github.workspace }}/frontend/playwright-report/results-saml.json"
"${{ github.workspace }}/frontend/playwright-report/results-feature.json"
@@ -308,3 +305,70 @@ jobs:
name: playwright-report-enterprise-${{ github.run_id }}
path: frontend/playwright-report/
retention-days: 7
# Multi-node regression: builds + seeds the clustered stack (testing/compose/docker-compose-multinode.yml)
# and runs behave features/multinode. Licence-gated, so it runs after the Playwright job (not in parallel).
multinode-e2e:
needs: [pick, playwright-e2e-enterprise]
# Nightly cron + manual dispatch only (heavy build), fork-gated for the licence secret.
if: >-
always() && needs.pick.outputs.is_fork != 'true'
&& (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') }}
timeout-minutes: 60
env:
PREMIUM_KEY: ${{ secrets.PREMIUM_KEY_ENTERPRISE }}
PREMIUM_ENABLED: "true"
SYSTEM_ENABLEANALYTICS: "false"
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
MN_COMPOSE: docker-compose-multinode.yml
steps:
- name: Harden Runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
cache: "pip"
cache-dependency-path: ./testing/cucumber/requirements.txt
- name: Install behave test deps
run: |
pip install --require-hashes --only-binary=:all: -r ./testing/cucumber/requirements.txt
- name: Build the multi-node image
working-directory: testing/compose
run: docker compose -f "$MN_COMPOSE" build
- name: Bring up the cluster and wait for both nodes healthy
working-directory: testing/compose
run: |
docker compose -f "$MN_COMPOSE" up -d
for i in $(seq 1 90); do
h1=$(docker inspect -f '{{.State.Health.Status}}' multinode-stirling-1 2>/dev/null || echo starting)
h2=$(docker inspect -f '{{.State.Health.Status}}' multinode-stirling-2 2>/dev/null || echo starting)
if [ "$h1" = healthy ] && [ "$h2" = healthy ]; then echo "both nodes healthy"; exit 0; fi
sleep 5
done
echo "::error::nodes did not become healthy"
docker compose -f "$MN_COMPOSE" logs --tail=200 stirling-1 stirling-2
exit 1
- name: Seed the cluster (teams, users, S3 connection, policy)
working-directory: testing/compose
run: docker compose -f "$MN_COMPOSE" --profile seed run --rm seed
- name: Run multi-node regression (implemented guarantees)
working-directory: testing/cucumber
# -e overrides behave.ini's exclusion of features/multinode; ~@known_gap skips any tracked-gap scenarios.
run: python -m behave features/multinode -e "features/enterprise" --tags="~@known_gap ~@destructive" --no-capture -f plain
- name: Run multi-node failover (destructive)
working-directory: testing/cucumber
run: python -m behave features/multinode -e "features/enterprise" --tags="@destructive ~@known_gap" --no-capture -f plain
- name: Dump node logs on failure
if: failure()
working-directory: testing/compose
run: docker compose -f "$MN_COMPOSE" logs --tail=400 stirling-1 stirling-2
- name: Tear down
if: always()
working-directory: testing/compose
run: docker compose -f "$MN_COMPOSE" --profile seed down -v --remove-orphans
+64 -18
View File
@@ -48,20 +48,55 @@ jobs:
proprietary: ${{ steps.changes.outputs.proprietary }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check for file changes
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
id: changes
with:
filters: .github/config/.files.yaml
build:
gradle-cache-prime:
name: Prime shared Gradle cache
needs: [files-changed]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up JDK 25
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Resolve backend dependencies
run: ./gradlew :stirling-pdf:classes -PnoSpotless --no-daemon
env:
STIRLING_FLAVOR: saas
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
build:
needs: [files-changed, gradle-cache-prime]
permissions:
actions: read
contents: read
@@ -76,7 +111,7 @@ jobs:
# works after Hibernate's ddl-auto=update migrates the schema. Gated on
# the `project` filter so doc-only PRs skip this ~5-minute job.
if: needs.files-changed.outputs.project == 'true'
needs: [files-changed]
needs: [files-changed, gradle-cache-prime]
permissions:
contents: read
uses: ./.github/workflows/db-migration-test.yml
@@ -84,7 +119,7 @@ jobs:
check-generateOpenApiDocs:
if: needs.files-changed.outputs.openapi == 'true'
needs: [files-changed]
needs: [files-changed, gradle-cache-prime]
permissions:
contents: read
uses: ./.github/workflows/check-openapi.yml
@@ -99,6 +134,17 @@ jobs:
uses: ./.github/workflows/frontend-validation.yml
secrets: inherit
# Advisory: deliberately NOT in all-checks-passed. It reports on the stories a
# branch touches so a regression is visible in review, but a browser scan is
# too new here to block merges on. Promote it once its pass/fail proves stable.
frontend-a11y:
if: needs.files-changed.outputs.frontend == 'true'
needs: [files-changed]
permissions:
contents: read
uses: ./.github/workflows/frontend-a11y.yml
secrets: inherit
playwright-e2e:
if: needs.files-changed.outputs.frontend == 'true'
needs: [files-changed]
@@ -109,7 +155,7 @@ jobs:
playwright-e2e-live:
if: needs.files-changed.outputs.frontend == 'true'
needs: [files-changed]
needs: [files-changed, gradle-cache-prime]
permissions:
contents: read
uses: ./.github/workflows/e2e-live.yml
@@ -117,7 +163,7 @@ jobs:
playwright-e2e-enterprise:
if: needs.files-changed.outputs.proprietary == 'true'
needs: [files-changed]
needs: [files-changed, gradle-cache-prime]
permissions:
contents: read
uses: ./.github/workflows/build-enterprise.yml
@@ -125,7 +171,7 @@ jobs:
check-licence:
if: needs.files-changed.outputs.build == 'true'
needs: [files-changed, build]
needs: [files-changed, build, gradle-cache-prime]
permissions:
contents: read
uses: ./.github/workflows/check-licence.yml
@@ -133,7 +179,7 @@ jobs:
docker-compose-tests:
if: needs.files-changed.outputs.project == 'true'
needs: [files-changed]
needs: [files-changed, gradle-cache-prime]
permissions:
actions: write
contents: read
@@ -145,11 +191,10 @@ jobs:
test-build-docker-images:
if: github.event_name == 'pull_request' && needs.files-changed.outputs.project == 'true'
needs: [files-changed, build, check-generateOpenApiDocs, check-licence]
needs: [files-changed, build, check-generateOpenApiDocs, check-licence, gradle-cache-prime]
permissions:
contents: read
packages: read
id-token: write
uses: ./.github/workflows/test-build-docker.yml
secrets: inherit
with:
@@ -164,13 +209,14 @@ jobs:
pull-requests: write
uses: ./.github/workflows/tauri-build.yml
secrets: inherit
# PR smoke build: Linux only (fastest + cheapest to compile), unsigned,
# deb-only, no AppImage. The full signed multi-OS matrix runs on release;
# PR smoke build: macOS + Windows (the platforms our developers use).
# sign: true only reaches macOS - tauri-build's per-platform gate keeps
# Windows/Linux signing on main, and an unsigned .dmg cannot be opened.
# The full signed multi-OS matrix runs on release;
# nightly still warms the Rust cache with all-OS defaults.
with:
platform: linux
sign: false
minimal: true
platform: windows-macos
sign: true
ai-engine:
if: needs.files-changed.outputs.engine == 'true'
@@ -188,7 +234,7 @@ jobs:
# frontend filter, so a CSS-only PR does not pay for a backend build.
generated-models:
if: needs.files-changed.outputs.generated-models == 'true'
needs: [files-changed]
needs: [files-changed, gradle-cache-prime]
permissions:
contents: read
pull-requests: write
@@ -258,7 +304,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+26 -30
View File
@@ -1,12 +1,12 @@
name: Check generated models
# Verifies the committed generated API models are still in sync with the Java
# OpenAPI spec: the frontend tool API types
# (frontend/editor/src/core/types/toolApiTypes.ts) and the engine tool
# models (engine/src/stirling/models/tool_models.py). Regenerates both with the
# single top-level `task tool-models` and fails if either committed file is
# out of date. Called from build.yml when the backend Java, frontend, or engine
# changes; also runs on push to main as a post-merge safety net.
# Verifies the committed generated files are still in sync with the Java OpenAPI
# spec: the request models (toolApiTypes.ts, tool_models.py) and the tool I/O
# tables saying what each endpoint accepts and produces (toolIO.ts, tool_io.py).
# Regenerates them all with the single top-level `task tool-models` and fails if
# any committed file is out of date. Called from build.yml when the
# backend Java, frontend, or engine changes; also runs on push to main as a
# post-merge safety net.
on:
workflow_call:
push:
@@ -21,11 +21,9 @@ jobs:
permissions:
contents: read
pull-requests: write
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -33,9 +31,10 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
cache-suffix: generated-models
- name: Set up JDK 25
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
@@ -43,13 +42,19 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
gradle-version: 9.6.0
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
@@ -58,18 +63,10 @@ jobs:
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
# Rebuilds the OpenAPI spec from the current Java and regenerates both the
# frontend types and the engine tool models from it.
- name: Regenerate generated models
run: task tool-models
- name: Verify generated models are up to date
id: models-check
continue-on-error: true
run: |
git diff --exit-code \
frontend/editor/src/core/types/toolApiTypes.ts \
engine/src/stirling/models/tool_models.py
run: task tool-models:check
- name: Comment on generated models check failure
# Only post a comment on PRs. github-script's PR helpers need an
@@ -84,9 +81,9 @@ jobs:
marker,
'### Generated Models Check Failed',
'',
'The generated `frontend/editor/src/core/types/toolApiTypes.ts` and/or `engine/src/stirling/models/tool_models.py` are out of date with the Java OpenAPI spec and will need to be regenerated before they can be merged in.',
'One or more generated files are out of date with the Java OpenAPI spec and will need to be regenerated before they can be merged in.',
'',
'Run `task tool-models` to regenerate both, then commit the updated files.',
'Run `task tool-models` to regenerate them, then commit the updated files.',
].join('\n');
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
@@ -117,11 +114,10 @@ jobs:
echo " Generated Models Check Failed"
echo "============================================"
echo ""
echo "The generated frontend API types and/or engine tool"
echo "models are out of date with the Java OpenAPI spec and"
echo "will need to be regenerated before they can be merged in."
echo "One or more generated files are out of date with the Java"
echo "OpenAPI spec and will need to be regenerated before merging."
echo ""
echo "Run 'task tool-models' to regenerate both, then"
echo "Run 'task tool-models' to regenerate them, then"
echo "commit the updated files."
echo "============================================"
exit 1
+7 -13
View File
@@ -11,11 +11,9 @@ permissions:
jobs:
check-licence:
runs-on: ubuntu-latest
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -28,20 +26,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle dependency artifacts
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.gradle/caches/modules-2/files-2.1
~/.gradle/caches/modules-2/metadata-2.*
key: gradle-deps-${{ runner.os }}-jdk-25-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties', '**/*.gradle', '**/*.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'gradle/libs.versions.toml') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
cache-disabled: true
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
+8 -18
View File
@@ -10,17 +10,11 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
check-generate-openapi-docs:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -33,20 +27,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle dependency artifacts
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.gradle/caches/modules-2/files-2.1
~/.gradle/caches/modules-2/metadata-2.*
key: gradle-deps-${{ runner.os }}-jdk-25-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties', '**/*.gradle', '**/*.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'gradle/libs.versions.toml') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
cache-disabled: true
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
+7 -7
View File
@@ -6,7 +6,7 @@ on:
pull_request_target:
types: [opened, synchronize, reopened]
paths:
- "frontend/editor/public/locales/*/translation.toml"
- "frontend/public/locales/*/translation.toml"
- ".github/scripts/check_language_toml.py"
- ".github/workflows/check_toml.yml"
@@ -27,7 +27,7 @@ jobs:
pull-requests: write # Allow writing to pull requests
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -76,7 +76,7 @@ jobs:
exit 1
fi
# Get changed files and filter for TOML translation files
gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^frontend/editor/public/locales/[a-zA-Z-]+/translation\.toml$' > changed_files.txt || echo "No matching TOML files found in PR"
gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^frontend/public/locales/[a-zA-Z-]+/translation\.toml$' > changed_files.txt || echo "No matching TOML files found in PR"
# Check if any files were found
if [ ! -s changed_files.txt ]; then
echo "No TOML translation files changed in this PR"
@@ -166,12 +166,12 @@ jobs:
// Determine reference file
let referenceFilePath;
if (changedFiles.includes("frontend/editor/public/locales/en-US/translation.toml")) {
if (changedFiles.includes("frontend/public/locales/en-US/translation.toml")) {
console.log("Using PR branch reference file.");
const { data: fileContent } = await github.rest.repos.getContent({
owner: prRepoOwner,
repo: prRepoName,
path: "frontend/editor/public/locales/en-US/translation.toml",
path: "frontend/public/locales/en-US/translation.toml",
ref: branch,
});
@@ -183,7 +183,7 @@ jobs:
const { data: fileContent } = await github.rest.repos.getContent({
owner: repoOwner,
repo: repoName,
path: "frontend/editor/public/locales/en-US/translation.toml",
path: "frontend/public/locales/en-US/translation.toml",
ref: "main",
});
@@ -196,7 +196,7 @@ jobs:
core.exportVariable("REFERENCE_FILE", referenceFilePath);
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
+12 -20
View File
@@ -29,16 +29,12 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
aggregate:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
@@ -50,23 +46,19 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle dependency artifacts
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.gradle/caches/modules-2/files-2.1
~/.gradle/caches/modules-2/metadata-2.*
key: gradle-deps-${{ runner.os }}-jdk-25-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties', '**/*.gradle', '**/*.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'gradle/libs.versions.toml') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
cache-disabled: true
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
@@ -85,7 +77,7 @@ jobs:
# Each lands as a sibling dir under coverage-execs/, with the .exec
# files preserving their original relative paths.
- name: Download all .exec artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v6.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: jacoco-exec-*
path: coverage-execs/
@@ -210,7 +202,7 @@ jobs:
# absence on backend-only runs by skipping the download entirely
# when the producer job was not part of this workflow run.
if: inputs.frontend-validation-result == 'success'
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v6.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: frontend-coverage
path: matrix-inputs/vitest/
@@ -220,7 +212,7 @@ jobs:
# e2e-live uploads the artifact with a stable name. Skip the
# download entirely when the producer job did not run.
if: inputs.playwright-e2e-live-result == 'success'
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v6.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: playwright-frontend-coverage
path: matrix-inputs/playwright/
+10 -20
View File
@@ -12,18 +12,12 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
migration-test:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-8' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
timeout-minutes: 30
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -36,23 +30,19 @@ jobs:
java-version: 25
distribution: temurin
- name: Cache Gradle dependency artifacts
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.gradle/caches/modules-2/files-2.1
~/.gradle/caches/modules-2/metadata-2.*
key: gradle-deps-${{ runner.os }}-jdk-25-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties', '**/*.gradle', '**/*.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'gradle/libs.versions.toml') }}
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
cache-disabled: true
# No `-PnoSpotless` here yet because the upstream cache layer matches the
# backend build's; reuse keeps cold-cache cost identical.
# Keep the normal formatting path here so this smoke test exercises the
# same Gradle configuration as the backend build.
- name: Build Stirling-PDF JAR
env:
MAVEN_USER: ${{ secrets.MAVEN_USER }}
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+8 -51
View File
@@ -10,38 +10,23 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
deploy-v2-on-push:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
concurrency:
group: deploy-v2-push-V2
cancel-in-progress: true
permissions:
contents: read
id-token: write
env:
USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' }}
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Depot CLI
if: env.USE_DEPOT == 'true'
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.0.0
- name: Set up Docker Buildx
if: env.USE_DEPOT != 'true'
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Get commit hashes for frontend and backend
id: commit-hashes
@@ -100,27 +85,13 @@ jobs:
fi
- name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_API }}
- name: Build and push frontend image (Depot)
if: env.USE_DEPOT == 'true' && steps.check-frontend.outputs.exists == 'false'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.16.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: .
file: ./docker/frontend/Dockerfile
push: true
tags: |
${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-${{ steps.commit-hashes.outputs.frontend_short }}
${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-frontend-latest
build-args: VERSION_TAG=v2-alpha
platforms: linux/amd64
- name: Build and push frontend image (Docker fork fallback)
if: env.USE_DEPOT != 'true' && steps.check-frontend.outputs.exists == 'false'
- name: Build and push frontend image
if: steps.check-frontend.outputs.exists == 'false'
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
@@ -134,22 +105,8 @@ jobs:
build-args: VERSION_TAG=v2-alpha
platforms: linux/amd64
- name: Build and push backend image (Depot)
if: env.USE_DEPOT == 'true' && steps.check-backend.outputs.exists == 'false'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.16.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: .
file: ./docker/backend/Dockerfile
push: true
tags: |
${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-${{ steps.commit-hashes.outputs.backend_short }}
${{ secrets.DOCKER_HUB_USERNAME }}/test:v2-backend-latest
build-args: VERSION_TAG=v2-alpha
platforms: linux/amd64
- name: Build and push backend image (Docker fork fallback)
if: env.USE_DEPOT != 'true' && steps.check-backend.outputs.exists == 'false'
- name: Build and push backend image
if: steps.check-backend.outputs.exists == 'false'
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
+10 -25
View File
@@ -11,32 +11,21 @@ on:
required: false
type: string
default: "false"
depot_cores:
description: "Depot runner vCPU count (used in runs-on). Override for benchmarking. Tuned to 4 because bench showed 16 was within noise of 4."
required: false
type: string
default: "4"
permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
docker-compose-tests:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '4') || 'ubuntu-latest' }}
runs-on: ubuntu-latest
permissions:
actions: write
contents: read
checks: write
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -49,20 +38,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle dependency artifacts
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.gradle/caches/modules-2/files-2.1
~/.gradle/caches/modules-2/metadata-2.*
key: gradle-deps-${{ runner.os }}-jdk-25-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties', '**/*.gradle', '**/*.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'gradle/libs.versions.toml') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
cache-disabled: true
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
# When the PR changes the base image, test.sh builds it locally
# (stirling-pdf-base:local) into the daemon image store. A buildx
@@ -72,7 +57,7 @@ jobs:
# runtime token isn't exposed) since the docker driver can't use it.
- name: Set up Docker Buildx
if: inputs.docker-base-changed != 'true'
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
# Expose ACTIONS_RUNTIME_TOKEN / ACTIONS_RESULTS_URL for docker buildx type=gha cache backend.
- name: Expose GitHub runtime for Buildx cache
@@ -85,7 +70,7 @@ jobs:
sudo chmod +x /usr/local/bin/docker-compose
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: "pip" # caching pip dependencies
+46 -19
View File
@@ -5,27 +5,17 @@ name: Playwright E2E (live backend)
# server.
on:
workflow_call:
inputs:
depot_cores:
description: "Depot runner vCPU count (used in runs-on). Override for benchmarking."
required: false
type: string
default: "8"
permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
playwright-e2e-live:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
@@ -35,8 +25,36 @@ jobs:
with:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
# Gradle does not retry 429s, and a cold cache resolving the buildscript
# classpath is exactly where Maven Central rate-limits us. Retry it here,
# where a failure is cheap, instead of inside the backgrounded bootRun.
- name: Prime Gradle dependencies
env:
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
run: |
for attempt in 1 2 3; do
if ./gradlew --quiet -PnoSpotless :stirling-pdf:classes; then
exit 0
fi
echo "::warning::Gradle dependency resolution failed (attempt $attempt of 3)"
sleep $((attempt * 30))
done
echo "::error::Gradle could not resolve dependencies after 3 attempts"
exit 1
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
@@ -63,6 +81,11 @@ jobs:
# to aggregate. Chromium-only - other engines silently skip.
PW_COVERAGE: "1"
PLAYWRIGHT_JSON_OUTPUT_FILE: ${{ github.workspace }}/frontend/playwright-report/results.json
# Internal mirror, as in backend-build.yml. Empty on Dependabot and
# fork PRs, where the build falls back to Maven Central.
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
run: task e2e:live
- name: Flag flaky tests
# Runs regardless of the test outcome: a flaky test (passed on retry)
@@ -70,12 +93,16 @@ jobs:
# ::warning:: annotations + a job summary; never fails the job.
if: always()
working-directory: frontend
run: npx tsx editor/scripts/report-flaky-tests.mts "$PLAYWRIGHT_JSON_OUTPUT_FILE"
run: npx tsx scripts/report-flaky-tests.mts "$PLAYWRIGHT_JSON_OUTPUT_FILE"
env:
PLAYWRIGHT_JSON_OUTPUT_FILE: ${{ github.workspace }}/frontend/playwright-report/results.json
- name: Generate JaCoCo report from e2e:live .exec
if: always()
id: live-coverage
env:
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
# `if: always()` so even a failed test run still produces a
# report from whatever flows did exercise the backend before
# the failure. The task itself tolerates a missing .exec
@@ -94,7 +121,7 @@ jobs:
fi
- name: Set up Python for coverage summary
if: always() && steps.live-coverage.outputs.report == 'true'
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: Install defusedxml for coverage summary
@@ -134,7 +161,7 @@ jobs:
# a summary even on backend failure, as long as some Playwright
# tests ran far enough to dump V8 coverage.
if: always()
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
@@ -203,8 +230,8 @@ jobs:
run: |
echo "::group::Playwright output dirs"
# Playwright anchors its default outputDir + HTML report to the
# nearest package.json, which is frontend/ (frontend/editor has
# none), so artifacts land under frontend/, not frontend/editor/.
# nearest package.json, which is frontend/ (frontend has
# none), so artifacts land under frontend/, not frontend/.
ls -la frontend/playwright-report 2>/dev/null \
|| echo "no playwright-report at frontend/"
ls -la frontend/test-results 2>/dev/null \
@@ -219,7 +246,7 @@ jobs:
# test-results/ holds the per-test trace.zip (with browser console
# logs) + screenshots/video; playwright-report/ is the HTML report.
# Both live under frontend/ (Playwright anchors them to the nearest
# package.json, which is frontend/; frontend/editor has none).
# package.json, which is frontend/; frontend has none).
path: |
frontend/playwright-report/
frontend/test-results/
+4 -14
View File
@@ -5,32 +5,22 @@ name: Playwright E2E (stubbed)
# mocks API responses in the browser.
on:
workflow_call:
inputs:
depot_cores:
description: "Depot runner vCPU count (used in runs-on). Override for benchmarking. Tuned to 8 to match the other playwright workflows; bench showed flat scaling above 8."
required: false
type: string
default: "8"
permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
playwright-e2e:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
@@ -53,7 +43,7 @@ jobs:
# ::warning:: annotations + a job summary; never fails the job.
if: always()
working-directory: frontend
run: npx tsx editor/scripts/report-flaky-tests.mts "$PLAYWRIGHT_JSON_OUTPUT_FILE"
run: npx tsx scripts/report-flaky-tests.mts "$PLAYWRIGHT_JSON_OUTPUT_FILE"
env:
PLAYWRIGHT_JSON_OUTPUT_FILE: ${{ github.workspace }}/frontend/playwright-report/results.json
- name: Upload Playwright report
+60
View File
@@ -0,0 +1,60 @@
name: Frontend a11y regression gate
# Reusable workflow called from build.yml when frontend sources change.
#
# Scans the stories this branch touches in real Chromium and runs axe against
# each. Existing violations are grandfathered in .storybook/a11y-baseline.json;
# the check fails on a NEW violation — a story breaking a rule it wasn't already
# breaking — or on a story that fails to render at all.
#
# Only changed stories, because a full sweep is ~30 minutes: far too slow to sit
# in front of every merge. The whole suite is scanned nightly instead
# (nightly.yml), which catches anything a branch didn't touch.
#
# Advisory for now: this is not in build.yml's all-checks-passed list, so a
# failure reports without blocking. Promote it once a few weeks of runs show the
# pass/fail is stable.
on:
workflow_call:
permissions:
contents: read
jobs:
frontend-a11y:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Harden Runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# Need the base branch too, to diff against it.
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
cache-dependency-path: frontend/package-lock.json
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
- name: a11y gate (changed stories)
run: task frontend:storybook:a11y:changed -- origin/${{ github.base_ref || 'main' }}
- name: Upload scan reports
# The reports carry the offending selector and help text for each
# violation; without them a red run can only be understood by
# reproducing the whole scan locally.
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: a11y-scan-${{ github.run_id }}
path: frontend/.a11y-scan/
retention-days: 7
if-no-files-found: ignore
# The reports live in a dot-directory, which upload-artifact treats as
# hidden and silently skips by default.
include-hidden-files: true
@@ -19,20 +19,16 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
files-changed:
name: detect what files changed
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
timeout-minutes: 3
outputs:
licenses-frontend: ${{ steps.changes.outputs.licenses-frontend }}
licenses-backend: ${{ steps.changes.outputs.licenses-backend }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -40,7 +36,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check for file changes
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
id: changes
with:
filters: .github/config/.files.yaml
@@ -48,15 +44,15 @@ jobs:
generate-frontend-license-report:
if: needs.files-changed.outputs.licenses-frontend == 'true'
name: Generate Frontend License Report
needs: [pick, files-changed]
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
needs: files-changed
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
repository-projects: write # Required for enabling automerge
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -84,7 +80,7 @@ jobs:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
@@ -117,31 +113,31 @@ jobs:
NPM_CONFIG_IGNORE_SCRIPTS: "true"
working-directory: frontend
run: |
mkdir -p editor/src/assets
npx --yes license-report --only=prod --output=json > editor/src/assets/3rdPartyLicenses.json
mkdir -p src/assets
npx --yes license-report --only=prod --output=json > src/assets/3rdPartyLicenses.json
- name: Postprocess with project script (BASE version)
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true
env:
PR_IS_FORK: "true"
run: |
node base/frontend/editor/scripts/generate-licenses.js \
--input frontend/editor/src/assets/3rdPartyLicenses.json
node base/frontend/scripts/generate-licenses.js \
--input frontend/src/assets/3rdPartyLicenses.json
- name: Copy postprocessed artifacts back (fork PRs)
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true
run: |
mkdir -p frontend/editor/src/assets
if [ -f "base/frontend/editor/src/assets/3rdPartyLicenses.json" ]; then
cp base/frontend/editor/src/assets/3rdPartyLicenses.json frontend/editor/src/assets/3rdPartyLicenses.json
mkdir -p frontend/src/assets
if [ -f "base/frontend/src/assets/3rdPartyLicenses.json" ]; then
cp base/frontend/src/assets/3rdPartyLicenses.json frontend/src/assets/3rdPartyLicenses.json
fi
if [ -f "base/frontend/editor/src/assets/license-warnings.json" ]; then
cp base/frontend/editor/src/assets/license-warnings.json frontend/editor/src/assets/license-warnings.json
if [ -f "base/frontend/src/assets/license-warnings.json" ]; then
cp base/frontend/src/assets/license-warnings.json frontend/src/assets/license-warnings.json
fi
- name: Check for license warnings
run: |
if [ -f "frontend/editor/src/assets/license-warnings.json" ]; then
if [ -f "frontend/src/assets/license-warnings.json" ]; then
echo "LICENSE_WARNINGS_EXIST=true" >> $GITHUB_ENV
else
echo "LICENSE_WARNINGS_EXIST=false" >> $GITHUB_ENV
@@ -189,10 +185,10 @@ jobs:
echo ""
if [ "${LICENSE_WARNINGS_EXIST}" = "true" ]; then
echo "❌ **Failed** incompatible or unknown licenses found."
if [ -f "frontend/editor/src/assets/license-warnings.json" ]; then
if [ -f "frontend/src/assets/license-warnings.json" ]; then
echo ""
echo "### Warnings"
jq -r '.warnings[] | "- \(.message)"' frontend/editor/src/assets/license-warnings.json || true
jq -r '.warnings[] | "- \(.message)"' frontend/src/assets/license-warnings.json || true
fi
else
echo "✅ **Passed** no license warnings detected."
@@ -218,7 +214,7 @@ jobs:
const fs = require('fs');
let warningDetails = '';
try {
const warnings = JSON.parse(fs.readFileSync('frontend/editor/src/assets/license-warnings.json', 'utf8'));
const warnings = JSON.parse(fs.readFileSync('frontend/src/assets/license-warnings.json', 'utf8'));
warningDetails = warnings.warnings.map(w => `- ${w.message}`).join('\n');
} catch (e) {
warningDetails = 'Unable to read warning details';
@@ -258,7 +254,7 @@ jobs:
- name: Commit changes (Push only)
if: github.event_name == 'push'
run: |
git add frontend/editor/src/assets/3rdPartyLicenses.json
git add frontend/src/assets/3rdPartyLicenses.json
# Note: Do NOT commit license-warnings.json - it's only for PR review
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
@@ -276,7 +272,7 @@ jobs:
The following licenses may require review for corporate compatibility:
$(cat frontend/editor/src/assets/license-warnings.json | jq -r '.warnings[].message')
$(cat frontend/src/assets/license-warnings.json | jq -r '.warnings[].message')
Please review these licenses to ensure they are acceptable for your use case."
fi
@@ -299,7 +295,10 @@ jobs:
base: main
title: "Update Frontend 3rd Party Licenses"
body: ${{ env.PR_BODY }}
labels: Licenses,github-actions,frontend
labels: |
Licenses
github-actions
Front End
draft: false
delete-branch: true
sign-commits: true
@@ -318,18 +317,16 @@ jobs:
generate-backend-license-report:
if: needs.files-changed.outputs.licenses-backend == 'true'
needs: [pick, files-changed]
needs: files-changed
name: Generate Backend License Report
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
repository-projects: write # Required for enabling automerge
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -353,10 +350,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
gradle-version: 9.6.0
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
@@ -520,7 +523,10 @@ jobs:
base: main
title: "Update Backend 3rd Party Licenses"
body: ${{ env.PR_BODY }}
labels: Licenses,github-actions,backend
labels: |
Licenses
github-actions
Back End
delete-branch: true
sign-commits: true
+7 -11
View File
@@ -11,21 +11,17 @@ permissions:
pull-requests: write
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
frontend-validation:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
@@ -121,7 +117,7 @@ jobs:
run: task frontend:test:coverage
- name: Set up Python for coverage summary
if: always()
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
- name: Install defusedxml for coverage summary
@@ -134,19 +130,19 @@ jobs:
run: |
python scripts/coverage-summary.py \
--title "Frontend Vitest coverage" \
--vitest frontend/editor/coverage/coverage-summary.json \
--vitest frontend/coverage/coverage-summary.json \
--github-step-summary
- name: Upload vitest coverage report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: frontend-coverage
path: frontend/editor/coverage/
path: frontend/coverage/
retention-days: 7
if-no-files-found: warn
- name: Upload frontend build artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: frontend-build
path: frontend/editor/dist/
path: frontend/dist/
retention-days: 3
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
issues: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+147 -54
View File
@@ -12,13 +12,14 @@ on:
- "true"
- "false"
platform:
description: "Platform to build (windows, macos, linux, or all)"
description: "Platform to build (windows, windows-arm64, macos, linux, or all)"
required: true
default: "all"
type: choice
options:
- all
- windows
- windows-arm64
- macos
- linux
sign:
@@ -36,19 +37,15 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
determine-matrix:
if: ${{ vars.CI_PROFILE != 'lite' }}
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
version: ${{ steps.versionNumber.outputs.versionNumber }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -60,20 +57,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle dependencies
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
@@ -91,31 +84,40 @@ jobs:
- name: Determine build matrix
id: set-matrix
run: |
# windows-arm64: NSIS only (WiX MSI has no arm64 support in Tauri) and no
# JPDFium natives yet - flip to windows-arm64 once JPDFium ships them.
WINDOWS='{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64","jpdfium_platforms":"windows-x64"}'
WINDOWS_ARM64='{"platform":"windows-11-arm","args":"--target aarch64-pc-windows-msvc --bundles nsis","name":"windows-arm64","jpdfium_platforms":"none"}'
MACOS='{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal","jpdfium_platforms":"darwin-arm64,darwin-x64"}'
LINUX='{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64","jpdfium_platforms":"linux-x64"}'
ALL="$WINDOWS,$WINDOWS_ARM64,$MACOS,$LINUX"
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
case "${{ github.event.inputs.platform }}" in
"windows")
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64","jpdfium_platforms":"windows-x64"}]}' >> $GITHUB_OUTPUT
echo "matrix={\"include\":[$WINDOWS,$WINDOWS_ARM64]}" >> $GITHUB_OUTPUT
;;
"windows-arm64")
echo "matrix={\"include\":[$WINDOWS_ARM64]}" >> $GITHUB_OUTPUT
;;
"macos")
echo 'matrix={"include":[{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal","jpdfium_platforms":"darwin-arm64,darwin-x64"}]}' >> $GITHUB_OUTPUT
echo "matrix={\"include\":[$MACOS]}" >> $GITHUB_OUTPUT
;;
"linux")
echo 'matrix={"include":[{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64","jpdfium_platforms":"linux-x64"}]}' >> $GITHUB_OUTPUT
echo "matrix={\"include\":[$LINUX]}" >> $GITHUB_OUTPUT
;;
*)
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64","jpdfium_platforms":"windows-x64"},{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal","jpdfium_platforms":"darwin-arm64,darwin-x64"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64","jpdfium_platforms":"linux-x64"}]}' >> $GITHUB_OUTPUT
echo "matrix={\"include\":[$ALL]}" >> $GITHUB_OUTPUT
;;
esac
else
# For push/release events, build all platforms
echo 'matrix={"include":[{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64","jpdfium_platforms":"windows-x64"},{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal","jpdfium_platforms":"darwin-arm64,darwin-x64"},{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64","jpdfium_platforms":"linux-x64"}]}' >> $GITHUB_OUTPUT
echo "matrix={\"include\":[$ALL]}" >> $GITHUB_OUTPUT
fi
build-jars:
needs: [pick, determine-matrix]
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
needs: determine-matrix
runs-on: ubuntu-latest
strategy:
matrix:
variant:
@@ -133,7 +135,7 @@ jobs:
file_suffix: "-server"
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -145,14 +147,20 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
gradle-version: 9.6.0
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Setup Node.js
if: matrix.variant.build_frontend == true
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: "npm"
@@ -195,10 +203,9 @@ jobs:
SM_API_KEY: ${{ secrets.SM_API_KEY }}
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
RELEASE_GPG_PRIVATE_KEY: ${{ secrets.RELEASE_GPG_PRIVATE_KEY }}
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
allowed-endpoints: >
@@ -215,7 +222,7 @@ jobs:
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libjavascriptcoregtk-4.0-dev libsoup2.4-dev libjavascriptcoregtk-4.1-dev libsoup-3.0-dev
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: "npm"
@@ -243,16 +250,23 @@ jobs:
if: matrix.platform == 'macos-15'
run: echo "X64_JAVA_HOME=$JAVA_HOME" >> "$GITHUB_ENV"
# Temurin has no windows-aarch64 JDK 25 yet; Microsoft OpenJDK does.
- name: Set up JDK 25
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
java-version: "25"
distribution: "temurin"
distribution: ${{ matrix.platform == 'windows-11-arm' && 'microsoft' || 'temurin' }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
gradle-version: 9.6.0
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
@@ -278,7 +292,7 @@ jobs:
# DigiCert KeyLocker Setup (Cloud HSM)
- name: Setup DigiCert KeyLocker
id: digicert-setup
if: ${{ matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
if: ${{ startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
uses: digicert/ssm-code-signing@1d820463733701cf1484c7eb5d7d24a15ca2c454 # v1.2.1
env:
SM_API_KEY: ${{ secrets.SM_API_KEY }}
@@ -288,7 +302,7 @@ jobs:
SM_HOST: ${{ secrets.SM_HOST }}
- name: Setup DigiCert KeyLocker Certificate
if: ${{ matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
if: ${{ startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
shell: pwsh
run: |
Write-Host "Setting up DigiCert KeyLocker environment..."
@@ -323,7 +337,7 @@ jobs:
# Traditional PFX Certificate Import (fallback if KeyLocker not configured)
- name: Import Windows Code Signing Certificate
if: ${{ matrix.platform == 'windows-latest' && env.SM_API_KEY == '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
if: ${{ startsWith(matrix.platform, 'windows') && env.SM_API_KEY == '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
@@ -391,7 +405,7 @@ jobs:
# Without this, signCommand failures are opaque (Tauri captures but drops
# smctl's stderr) - running these loudly surfaces auth/env/keypair issues.
- name: Preflight smctl
if: ${{ matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
if: ${{ startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
shell: pwsh
env:
KEYPAIR_ALIAS: ${{ secrets.SM_KEYPAIR_ALIAS }}
@@ -422,12 +436,12 @@ jobs:
# smctl reads SM_HOST, SM_API_KEY, SM_CLIENT_CERT_FILE, SM_CLIENT_CERT_PASSWORD
# from env (set by prior DigiCert setup step). No --config-file needed.
- name: Configure Windows code signing
if: ${{ matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
if: ${{ startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
shell: bash
env:
KEYPAIR_ALIAS: ${{ secrets.SM_KEYPAIR_ALIAS }}
run: |
cat > ./frontend/editor/src-tauri/tauri.windows.conf.json <<EOF
cat > ./frontend/src-tauri/tauri.windows.conf.json <<EOF
{
"bundle": {
"windows": {
@@ -440,7 +454,7 @@ jobs:
}
EOF
echo "Generated tauri.windows.conf.json (alias masked):"
sed "s/${KEYPAIR_ALIAS}/***/g" ./frontend/editor/src-tauri/tauri.windows.conf.json
sed "s/${KEYPAIR_ALIAS}/***/g" ./frontend/src-tauri/tauri.windows.conf.json
- name: Import release GPG signing key (Linux)
if: matrix.platform == 'ubuntu-22.04' && env.RELEASE_GPG_PRIVATE_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master')
@@ -488,11 +502,59 @@ jobs:
SM_CODE_SIGNING_CERT_SHA1_HASH: ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }}
CI: true
with:
projectPath: ./frontend/editor
projectPath: ./frontend
tauriScript: npx tauri
args: ${{ matrix.args }}
updaterJsonKeepUniversal: true
# Bundled libwayland conflicts with the host's on some distros (Fedora
# Wayland: EGL_BAD_PARAMETER, blank window - #6878). Repack without it,
# then regenerate the updater .sig (repack invalidates the original) and
# GPG-sign again when release signing is on.
- name: Strip bundled Wayland libs from AppImage
if: matrix.platform == 'ubuntu-22.04'
continue-on-error: true
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
GPG_SIGN: ${{ (env.RELEASE_GPG_PRIVATE_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master')) && '1' || '0' }}
SIGN_KEY: ${{ vars.RELEASE_GPG_FINGERPRINT }}
APPIMAGETOOL_SIGN_PASSPHRASE: ${{ secrets.RELEASE_GPG_PASSPHRASE }}
run: |
set -euo pipefail
AI=$(find "$PWD/frontend/src-tauri/target" -name "*.AppImage" | head -1)
if [ -z "$AI" ]; then echo "No AppImage found - skipping"; exit 0; fi
chmod +x "$AI"
WORK=$(mktemp -d)
(cd "$WORK" && "$AI" --appimage-extract >/dev/null)
if ! ls "$WORK/squashfs-root/usr/lib/"libwayland-* >/dev/null 2>&1; then
echo "No bundled libwayland - nothing to strip"
rm -rf "$WORK"
exit 0
fi
rm -f "$WORK/squashfs-root/usr/lib/"libwayland-*
curl -fsSL -o "$WORK/appimagetool" \
https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
# Pinned checksum: never execute an unverified downloaded binary. On
# mismatch (upstream rebuilt continuous) the step aborts and the
# original AppImage ships unchanged - update the pin deliberately.
echo "a6d71e2b6cd66f8e8d16c37ad164658985e0cf5fcaa950c90a482890cb9d13e0 $WORK/appimagetool" | sha256sum -c -
chmod +x "$WORK/appimagetool"
SIGN_ARGS=()
if [ "$GPG_SIGN" = "1" ] && [ -n "${SIGN_KEY:-}" ]; then
SIGN_ARGS=(--sign --sign-key "$SIGN_KEY")
fi
"$WORK/appimagetool" --appimage-extract-and-run "${SIGN_ARGS[@]}" "$WORK/squashfs-root" "$AI.new"
# Updater payload signature must match the repacked bytes. The CLI
# reads the key/password from env - never pass secrets as argv.
if [ -n "${TAURI_SIGNING_PRIVATE_KEY:-}" ]; then
(cd frontend && npx tauri signer sign "$AI.new")
mv "$AI.new.sig" "$AI.sig"
fi
mv "$AI.new" "$AI"
rm -rf "$WORK"
echo "Stripped bundled libwayland from $(basename "$AI")"
- name: Clear release GPG key from runner keyring (Linux)
if: always() && matrix.platform == 'ubuntu-22.04' && env.RELEASE_GPG_PRIVATE_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master')
env:
@@ -509,14 +571,35 @@ jobs:
# artifact. Tauri signs a COPY when bundling into the MSI and leaves the raw
# cargo output unsigned, so checking it produces false negatives.
- name: Verify Windows Code Signature
if: ${{ matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
if: ${{ startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && (github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.sign != 'false') || github.ref == 'refs/heads/V2-master') }}
timeout-minutes: 15
shell: pwsh
run: |
# arm64 ships an NSIS installer, not an MSI. Tauri's signCommand signs the
# inner exe before packing and the setup exe after, so verifying the setup
# exe is the arm64 equivalent of the MSI + inner-exe check below.
if ("${{ matrix.platform }}" -eq "windows-11-arm") {
$setupExes = Get-ChildItem -Path "./frontend/src-tauri/target" -Filter "*-setup.exe" -Recurse -File
if ($setupExes.Count -eq 0) {
Write-Host "[ERROR] No NSIS installer found under target/"
exit 1
}
foreach ($exe in $setupExes) {
$sig = Get-AuthenticodeSignature -FilePath $exe.FullName
Write-Host "NSIS installer: $($exe.Name) Status=$($sig.Status), Signer=$($sig.SignerCertificate.Subject)"
if ($sig.Status -ne "Valid") {
Write-Host "[ERROR] NSIS installer is not signed"
exit 1
}
}
Write-Host "[SUCCESS] NSIS installer is properly signed"
exit 0
}
$allSigned = $true
# Check MSI installer (outer wrapper - what users download)
$msiFiles = Get-ChildItem -Path "./frontend/editor/src-tauri/target" -Filter "*.msi" -Recurse -File
$msiFiles = Get-ChildItem -Path "./frontend/src-tauri/target" -Filter "*.msi" -Recurse -File
if ($msiFiles.Count -eq 0) {
Write-Host "[ERROR] No MSI found under target/"
exit 1
@@ -576,7 +659,7 @@ jobs:
# but drops stderr when the command exits non-zero, making failures opaque.
# The real errors live in smctl's log files - surface them here for debugging.
- name: Dump smctl logs on failure
if: ${{ failure() && matrix.platform == 'windows-latest' && env.SM_API_KEY != '' }}
if: ${{ failure() && startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' }}
shell: pwsh
run: |
$logDir = "$env:USERPROFILE\.signingmanager\logs"
@@ -599,7 +682,7 @@ jobs:
# Absolute dist path so the cd below can't break the copy targets.
DIST="$GITHUB_WORKSPACE/dist"
mkdir -p "$DIST"
cd ./frontend/editor/src-tauri/target
cd ./frontend/src-tauri/target
echo "=== tauri bundle artifacts ==="
find . -path "*/bundle/*" \( -name "*.msi" -o -name "*.deb" \
@@ -612,6 +695,11 @@ jobs:
if [ "${{ matrix.platform }}" = "windows-latest" ]; then
find . -name "*.msi" -exec cp {} "$DIST/Stirling-PDF-${{ matrix.name }}.msi" \;
find . -name "*.msi.sig" -exec cp {} "$DIST/Stirling-PDF-${{ matrix.name }}.msi.sig" \;
elif [ "${{ matrix.platform }}" = "windows-11-arm" ]; then
# arm64 ships the NSIS installer (WiX MSI has no arm64 support in Tauri).
# The setup exe is also its own updater payload (-> sibling .sig).
find . -name "*-setup.exe" -exec cp {} "$DIST/Stirling-PDF-${{ matrix.name }}-setup.exe" \;
find . -name "*-setup.exe.sig" -exec cp {} "$DIST/Stirling-PDF-${{ matrix.name }}-setup.exe.sig" \;
elif [ "${{ matrix.platform }}" = "macos-15" ]; then
# DMG = manual install; .app.tar.gz (+ .sig) = updater payload.
# Raw .app is intentionally not shipped (hundreds of MB of uncompressed input).
@@ -638,13 +726,13 @@ jobs:
retention-days: 1
collect-and-release:
needs: [pick, determine-matrix, build, build-jars]
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
needs: [determine-matrix, build, build-jars]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -655,7 +743,7 @@ jobs:
with:
sparse-checkout: |
.github/scripts/verify-updater-signatures.py
frontend/editor/src-tauri/tauri.conf.json
frontend/src-tauri/tauri.conf.json
sparse-checkout-cone-mode: false
- name: Download all Tauri artifacts
@@ -726,6 +814,10 @@ jobs:
'bundles': ['Stirling-PDF-windows-x86_64.msi'],
'targets': ['windows-x86_64-msi', 'windows-x86_64'],
},
{
'bundles': ['Stirling-PDF-windows-arm64-setup.exe'],
'targets': ['windows-aarch64-nsis', 'windows-aarch64'],
},
{
'bundles': ['Stirling-PDF-macos-universal.app.tar.gz'],
'targets': ['darwin-x86_64', 'darwin-aarch64'],
@@ -800,7 +892,7 @@ jobs:
run: |
python3 -m pip install --quiet 'cryptography==44.0.0'
python3 .github/scripts/verify-updater-signatures.py \
./artifacts/tauri frontend/editor/src-tauri/tauri.conf.json
./artifacts/tauri frontend/src-tauri/tauri.conf.json
# workflow_dispatch path requires platform=='all' so a single-platform
# dispatch can't overwrite an existing release's full latest.json with a
@@ -810,7 +902,7 @@ jobs:
# instead of silently shipping a broken auto-update.
- name: Upload binaries to Release
if: (github.event_name == 'workflow_dispatch' && github.event.inputs.test_mode != 'true' && github.event.inputs.platform == 'all') || github.event_name == 'release' || github.ref == 'refs/heads/V2-master'
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: v${{ needs.determine-matrix.outputs.version }}
# Don't regenerate/append notes on re-runs, and don't force this into the
@@ -824,6 +916,7 @@ jobs:
files: |
./artifacts/**/*.jar
./artifacts/**/*.msi
./artifacts/**/*-setup.exe
./artifacts/**/*.dmg
./artifacts/**/*.app.tar.gz
./artifacts/**/*.deb
+46 -7
View File
@@ -13,16 +13,12 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
playwright-all-browsers:
name: Playwright (chromium + firefox + webkit)
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -30,7 +26,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
@@ -57,6 +53,49 @@ jobs:
path: frontend/playwright-report/
retention-days: 14
# Whole-suite accessibility sweep. Pull requests only scan the stories they
# touch (frontend-a11y.yml) because a full pass takes ~30 minutes; this covers
# everything else, so a violation introduced by a change somewhere other than
# the story itself — a shared component, a theme token — still surfaces within
# a day.
a11y-all-stories:
name: a11y (every story)
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
cache-dependency-path: frontend/package-lock.json
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
- name: a11y gate (every story)
run: task frontend:storybook:a11y
- name: Upload scan reports
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: a11y-scan-nightly-${{ github.run_id }}
path: frontend/.a11y-scan/
retention-days: 14
if-no-files-found: ignore
# The reports live in a dot-directory, which upload-artifact treats as
# hidden and silently skips by default.
include-hidden-files: true
# Builds all desktop platforms on a schedule so the Rust dependency cache is
# written on main, where PR and merge-queue tauri builds can restore it.
warm-tauri-cache:
+2 -2
View File
@@ -28,7 +28,7 @@ jobs:
jar_sha256: ${{ steps.hashes.outputs.jar_sha256 }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -79,7 +79,7 @@ jobs:
contents: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+159
View File
@@ -0,0 +1,159 @@
name: PR conflict labeler
on:
pull_request_target:
types:
- opened
- reopened
- synchronize
- edited
- ready_for_review
schedule:
- cron: "17 */6 * * *"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: pr-conflict-labeler-${{ github.event.pull_request.number || 'all-open-prs' }}
cancel-in-progress: false
env:
CONFLICT_LABEL: "has conflicts"
jobs:
label-conflicts:
name: Label conflicted PRs
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: read
steps:
- name: Harden Runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Check out the repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up stirling-bot token
id: setup-bot
uses: ./.github/actions/setup-bot
with:
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Apply conflict label
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ steps.setup-bot.outputs.token }}
script: |
const conflictLabel = process.env.CONFLICT_LABEL;
const owner = context.repo.owner;
const repo = context.repo.repo;
const eventPullRequest = context.payload.pull_request;
async function sleep(ms) {
await new Promise((resolve) => setTimeout(resolve, ms));
}
async function getPullRequestWithMergeableState(pullNumber) {
for (let attempt = 1; attempt <= 6; attempt += 1) {
const { data: pull } = await github.rest.pulls.get({
owner,
repo,
pull_number: pullNumber,
});
if (pull.mergeable !== null) {
return pull;
}
core.info(`PR #${pullNumber}: mergeable is not ready yet (attempt ${attempt}/6).`);
await sleep(5000);
}
const { data: pull } = await github.rest.pulls.get({
owner,
repo,
pull_number: pullNumber,
});
return pull;
}
async function ensureConflictLabel() {
try {
await github.rest.issues.getLabel({
owner,
repo,
name: conflictLabel,
});
} catch (error) {
if (error.status !== 404) {
throw error;
}
await github.rest.issues.createLabel({
owner,
repo,
name: conflictLabel,
color: 'D93F0B',
description: 'Pull request has merge conflicts with the base branch',
});
core.info(`Created '${conflictLabel}' label.`);
}
}
async function labelPullRequest(pull) {
const existingLabels = pull.labels.map((label) => label.name);
const hasConflictLabel = existingLabels.includes(conflictLabel);
const hasConflicts = pull.mergeable === false && pull.mergeable_state === 'dirty';
if (hasConflicts && !hasConflictLabel) {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: pull.number,
labels: [conflictLabel],
});
core.info(`Added '${conflictLabel}' to PR #${pull.number}.`);
return;
}
if (!hasConflicts && hasConflictLabel) {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: pull.number,
name: conflictLabel,
});
core.info(`Removed '${conflictLabel}' from PR #${pull.number}.`);
return;
}
core.info(`PR #${pull.number}: no label change needed (mergeable=${pull.mergeable}, mergeable_state=${pull.mergeable_state}).`);
}
await ensureConflictLabel();
let pullNumbers;
if (eventPullRequest) {
pullNumbers = [eventPullRequest.number];
} else {
const pulls = await github.paginate(github.rest.pulls.list, {
owner,
repo,
state: 'open',
per_page: 100,
});
pullNumbers = pulls.map((pull) => pull.number);
core.info(`Checking ${pullNumbers.length} open PR(s).`);
}
for (const pullNumber of pullNumbers) {
const pull = await getPullRequestWithMergeableState(pullNumber);
await labelPullRequest(pull);
}
+3 -2
View File
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -25,9 +25,10 @@ jobs:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
cache-suffix: pre-commit
- name: Install Task
uses: go-task/setup-task@3be4020d41929789a01026e0e427a4321ce0ad44 # v2.0.0
+4 -4
View File
@@ -43,20 +43,20 @@ jobs:
echo "version=${VERSION}" >> $GITHUB_OUTPUT
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_API }}
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -64,7 +64,7 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
+8 -13
View File
@@ -53,7 +53,7 @@ jobs:
RUN_UNOSERVER: ${{ github.event_name != 'workflow_dispatch' || inputs.build_unoserver }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -65,24 +65,20 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle dependencies
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
@@ -107,13 +103,13 @@ jobs:
cosign-release: "v2.4.1"
- name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_API }}
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -139,7 +135,6 @@ jobs:
tags: |
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }},enable=${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/V2-master' }}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/V2-master' }}
type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/testMain' }}
- name: Build and push Unified Dockerfile (latest variant)
id: build-push-latest
+3 -3
View File
@@ -18,7 +18,7 @@ jobs:
packages: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -26,13 +26,13 @@ jobs:
uses: imjasonh/setup-crane@31b88afe9de28ae0ffa220711af4b60be9435f6e # v0.4
- name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_API }}
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry: ghcr.io
username: ${{ github.actor }}
+2 -2
View File
@@ -35,7 +35,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -75,6 +75,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v3.29.5
uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v3.29.5
with:
sarif_file: results.sarif
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
pull-requests: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+11 -11
View File
@@ -22,18 +22,12 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
push:
if: ${{ vars.CI_PROFILE != 'lite' }}
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
env:
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -45,10 +39,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
gradle-version: 9.6.0
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Generate Swagger documentation
run: ./gradlew :stirling-pdf:generateOpenApiDocs
+95
View File
@@ -0,0 +1,95 @@
name: Sync Portal Docs
# Regenerates the portal Developer Docs manifest from the Stirling docs repo and
# opens a PR when it changes. Runs weekly, on manual dispatch, or when the docs
# repo fires a `docs-updated` repository_dispatch.
on:
schedule:
- cron: "0 6 * * 1"
workflow_dispatch:
inputs:
ref:
description: "Docs repo ref (branch or tag) to sync from"
required: false
default: "main"
repository_dispatch:
types: [docs-updated]
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
permissions:
contents: read
jobs:
sync:
name: Sync docs manifest
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
pull-requests: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Setup GitHub App Bot
id: setup-bot
uses: ./.github/actions/setup-bot
with:
app-id: ${{ secrets.GH_APP_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "22"
cache: "npm"
cache-dependency-path: frontend/package-lock.json
- name: Install frontend dependencies
working-directory: frontend
env:
NPM_CONFIG_IGNORE_SCRIPTS: "true"
run: npm ci --ignore-scripts --audit=false --fund=false
- name: Regenerate docs manifest
working-directory: frontend
env:
DOCS_REF: ${{ github.event.inputs.ref || github.event.client_payload.ref || 'main' }}
GITHUB_TOKEN: ${{ steps.setup-bot.outputs.token }}
run: npm run docs:sync
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ steps.setup-bot.outputs.token }}
commit-message: "Sync portal docs from docs repo"
committer: ${{ steps.setup-bot.outputs.committer }}
author: ${{ steps.setup-bot.outputs.committer }}
signoff: true
branch: sync-portal-docs
base: main
title: "Sync portal docs from docs repo"
body: |
Auto-generated by ${{ steps.setup-bot.outputs.app-slug }}[bot].
Regenerates `frontend/src/processor/proprietary/generated/docsManifest.json`
from the Stirling docs repo via `npm run docs:sync`.
labels: |
Documentation
github-actions
Front End
add-paths: frontend/src/processor/proprietary/generated/docsManifest.json
delete-branch: true
sign-commits: true
+10 -8
View File
@@ -10,8 +10,9 @@ on:
- "app/common/build.gradle"
- "app/core/build.gradle"
- "app/proprietary/build.gradle"
- "gradle/spotless.gradle"
- "README.md"
- "frontend/editor/public/locales/*/translation.toml"
- "frontend/public/locales/*/translation.toml"
- "app/core/src/main/resources/static/3rdPartyLicenses.json"
- "scripts/ignore_translation.toml"
@@ -35,7 +36,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -51,7 +52,7 @@ jobs:
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.12"
cache: "pip" # caching pip dependencies
@@ -61,16 +62,17 @@ jobs:
pip install --require-hashes --only-binary=:all: -r ./.github/scripts/requirements_sync_readme.txt
- name: Install uv
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
cache-suffix: sync-files
- name: Install Task
uses: go-task/setup-task@3be4020d41929789a01026e0e427a4321ce0ad44 # v2.0.0
- name: Sync translation TOML files
run: |
python .github/scripts/check_language_toml.py --reference-file "frontend/editor/public/locales/en-US/translation.toml" --branch main
python .github/scripts/check_language_toml.py --reference-file "frontend/public/locales/en-US/translation.toml" --branch main
- name: Sort translation TOML files
run: |
@@ -78,7 +80,7 @@ jobs:
- name: Commit translation files
run: |
git add frontend/editor/public/locales/*/translation.toml
git add frontend/public/locales/*/translation.toml
git diff --staged --quiet || git commit -m ":memo: Sync translation files (TOML)" || echo "No changes detected"
- name: Sync README.md
@@ -108,7 +110,7 @@ jobs:
This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made:
#### **1. Synchronization of Translation Files**
- Updated translation files (`frontend/editor/public/locales/*/translation.toml`) to reflect changes in the reference file `en-US/translation.toml`.
- Updated translation files (`frontend/public/locales/*/translation.toml`) to reflect changes in the reference file `en-US/translation.toml`.
- Ensured consistency and synchronization across all supported language files.
- Highlighted any missing or incomplete translations.
- **Format**: TOML
@@ -133,5 +135,5 @@ jobs:
sign-commits: true
add-paths: |
README.md
frontend/editor/public/locales/*/translation.toml
frontend/public/locales/*/translation.toml
scripts/ignore_translation.toml
+121 -40
View File
@@ -12,7 +12,7 @@ on:
workflow_call:
inputs:
platform:
description: "Platform to build (windows, macos, linux, or all)."
description: "Platform to build (windows, windows-arm64, macos, linux, windows-macos, or all)."
required: false
type: string
default: "all"
@@ -29,15 +29,17 @@ on:
workflow_dispatch:
inputs:
platform:
description: "Platform to build (windows, macos, linux, or all)"
description: "Platform to build (windows, windows-arm64, macos, linux, windows-macos, or all)"
required: true
default: "all"
type: choice
options:
- all
- windows
- windows-arm64
- macos
- linux
- windows-macos
sign:
description: "Sign and notarize the bundles."
required: false
@@ -61,7 +63,7 @@ jobs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -72,14 +74,19 @@ jobs:
PLATFORM: ${{ inputs.platform }}
run: |
WINDOWS='{"platform":"windows-latest","args":"--target x86_64-pc-windows-msvc","name":"windows-x86_64","jpdfium_platforms":"windows-x64"}'
# ARM64: NSIS only (WiX MSI has no arm64 support in Tauri) and no JPDFium
# natives yet - flip jpdfium_platforms to windows-arm64 once JPDFium ships it.
WINDOWS_ARM64='{"platform":"windows-11-arm","args":"--target aarch64-pc-windows-msvc --bundles nsis","name":"windows-arm64","jpdfium_platforms":"none"}'
MACOS='{"platform":"macos-15","args":"--target universal-apple-darwin","name":"macos-universal","jpdfium_platforms":"darwin-arm64,darwin-x64"}'
LINUX='{"platform":"ubuntu-22.04","args":"","name":"linux-x86_64","jpdfium_platforms":"linux-x64"}'
case "$PLATFORM" in
windows) ENTRIES=("$WINDOWS") ;;
macos) ENTRIES=("$MACOS") ;;
linux) ENTRIES=("$LINUX") ;;
*) ENTRIES=("$WINDOWS" "$MACOS" "$LINUX") ;;
windows) ENTRIES=("$WINDOWS" "$WINDOWS_ARM64") ;;
windows-arm64) ENTRIES=("$WINDOWS_ARM64") ;;
macos) ENTRIES=("$MACOS") ;;
linux) ENTRIES=("$LINUX") ;;
windows-macos) ENTRIES=("$WINDOWS" "$MACOS") ;;
*) ENTRIES=("$WINDOWS" "$WINDOWS_ARM64" "$MACOS" "$LINUX") ;;
esac
# Drop macOS entries when Apple certificate secret is unavailable
@@ -106,10 +113,14 @@ jobs:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
RELEASE_GPG_PRIVATE_KEY: ${{ secrets.RELEASE_GPG_PRIVATE_KEY }}
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
# Per-platform sign gate. macOS signs on any run with the cert available,
# PRs included: Gatekeeper blocks an unsigned .dmg, so an unsigned macOS
# PR build is not testable. Windows and Linux stay main-only, matching the
# gates on their own signing steps below.
SIGN_BUNDLE: ${{ inputs.sign && (matrix.platform == 'macos-15' && secrets.APPLE_CERTIFICATE != '' || github.ref == 'refs/heads/main') }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -123,7 +134,7 @@ jobs:
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libjavascriptcoregtk-4.0-dev libsoup2.4-dev libjavascriptcoregtk-4.1-dev libsoup-3.0-dev
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: "npm"
@@ -141,7 +152,7 @@ jobs:
- name: Cache Rust build
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
workspaces: frontend/editor/src-tauri
workspaces: frontend/src-tauri
# Stable key shared across workflows so the nightly warmer.
# rust-cache still appends OS + rustc + Cargo.lock.
shared-key: tauri-${{ matrix.name }}
@@ -161,16 +172,23 @@ jobs:
if: matrix.platform == 'macos-15'
run: echo "X64_JAVA_HOME=$JAVA_HOME" >> "$GITHUB_ENV"
# Temurin has no windows-aarch64 JDK 25 yet; Microsoft OpenJDK does.
- name: Set up JDK 25
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
java-version: "25"
distribution: "temurin"
distribution: ${{ matrix.platform == 'windows-11-arm' && 'microsoft' || 'temurin' }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
gradle-version: 9.6.0
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Setup Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
@@ -197,7 +215,7 @@ jobs:
# DigiCert KeyLocker Setup (Cloud HSM)
- name: Setup DigiCert KeyLocker
id: digicert-setup
if: ${{ inputs.sign && matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && github.ref == 'refs/heads/main' }}
if: ${{ inputs.sign && startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && github.ref == 'refs/heads/main' }}
uses: digicert/ssm-code-signing@1d820463733701cf1484c7eb5d7d24a15ca2c454 # v1.2.1
env:
SM_API_KEY: ${{ secrets.SM_API_KEY }}
@@ -207,7 +225,7 @@ jobs:
SM_HOST: ${{ secrets.SM_HOST }}
- name: Setup DigiCert KeyLocker Certificate
if: ${{ inputs.sign && matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && github.ref == 'refs/heads/main' }}
if: ${{ inputs.sign && startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && github.ref == 'refs/heads/main' }}
shell: pwsh
run: |
Write-Host "Setting up DigiCert KeyLocker environment..."
@@ -242,7 +260,7 @@ jobs:
# Traditional PFX Certificate Import (fallback if KeyLocker not configured)
- name: Import Windows Code Signing Certificate
if: ${{ inputs.sign && matrix.platform == 'windows-latest' && env.SM_API_KEY == '' && github.ref == 'refs/heads/main' }}
if: ${{ inputs.sign && startsWith(matrix.platform, 'windows') && env.SM_API_KEY == '' && github.ref == 'refs/heads/main' }}
env:
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
@@ -273,7 +291,7 @@ jobs:
}
- name: Import Apple Developer Certificate
if: inputs.sign && matrix.platform == 'macos-15' && env.APPLE_CERTIFICATE != ''
if: env.SIGN_BUNDLE == 'true' && matrix.platform == 'macos-15'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
@@ -294,7 +312,7 @@ jobs:
rm certificate.p12
- name: Verify Certificate
if: inputs.sign && matrix.platform == 'macos-15' && env.APPLE_CERTIFICATE != ''
if: env.SIGN_BUNDLE == 'true' && matrix.platform == 'macos-15'
run: |
echo "Verifying Apple Developer Certificate..."
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
@@ -317,7 +335,7 @@ jobs:
ls -la /usr/bin/hd* || echo "No hd* tools found"
- name: Preflight smctl
if: ${{ inputs.sign && matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && github.ref == 'refs/heads/main' }}
if: ${{ inputs.sign && startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && github.ref == 'refs/heads/main' }}
shell: pwsh
env:
KEYPAIR_ALIAS: ${{ secrets.SM_KEYPAIR_ALIAS }}
@@ -330,12 +348,12 @@ jobs:
if ($LASTEXITCODE -ne 0) { Write-Host "[WARN] smctl windows certsync returned non-zero - continuing" }
- name: Configure Windows code signing
if: ${{ inputs.sign && matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && github.ref == 'refs/heads/main' }}
if: ${{ inputs.sign && startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && github.ref == 'refs/heads/main' }}
shell: bash
env:
KEYPAIR_ALIAS: ${{ secrets.SM_KEYPAIR_ALIAS }}
run: |
cat > ./frontend/editor/src-tauri/tauri.windows.conf.json <<EOF
cat > ./frontend/src-tauri/tauri.windows.conf.json <<EOF
{
"bundle": {
"windows": {
@@ -367,7 +385,7 @@ jobs:
fi
- name: Build Tauri app (signed)
if: inputs.sign
if: env.SIGN_BUNDLE == 'true'
uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # v0.6.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -394,7 +412,7 @@ jobs:
SM_CODE_SIGNING_CERT_SHA1_HASH: ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }}
CI: true
with:
projectPath: ./frontend/editor
projectPath: ./frontend
tauriScript: npx tauri
# Linux: build deb+rpm only here (deb-only on minimal smoke builds).
# AppImage runs in its own continue-on-error step below so its
@@ -402,7 +420,7 @@ jobs:
args: ${{ matrix.platform == 'ubuntu-22.04' && (inputs.minimal && '--bundles deb' || '--bundles deb,rpm') || matrix.args }}
- name: Build Tauri app (unsigned)
if: ${{ !inputs.sign }}
if: env.SIGN_BUNDLE != 'true'
uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # v0.6.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -414,12 +432,14 @@ jobs:
VITE_SAAS_BACKEND_API_URL: ${{ secrets.VITE_SAAS_BACKEND_API_URL || 'https://api.stirlingpdf.com' }}
CI: true
with:
projectPath: ./frontend/editor
projectPath: ./frontend
tauriScript: npx tauri
# Linux: build deb+rpm only here (deb-only on minimal smoke builds).
# AppImage runs in its own continue-on-error step below so its
# persistent linuxdeploy failure (#6127 onwards) does not tank uploads.
args: ${{ matrix.platform == 'ubuntu-22.04' && (inputs.minimal && '--bundles deb' || '--bundles deb,rpm') || matrix.args }}
args: >-
${{ matrix.platform == 'ubuntu-22.04' && (inputs.minimal && '--bundles deb' || '--bundles deb,rpm') || matrix.args }}
--config '{"bundle":{"createUpdaterArtifacts":false}}'
# AppImage is decoupled so its linuxdeploy run gets a fresh process
# (rpm scratch state torn down) and its failure can't tank deb/rpm.
@@ -440,10 +460,41 @@ jobs:
VITE_SAAS_BACKEND_API_URL: ${{ secrets.VITE_SAAS_BACKEND_API_URL || 'https://api.stirlingpdf.com' }}
CI: true
with:
projectPath: ./frontend/editor
projectPath: ./frontend
tauriScript: npx tauri
args: --bundles appimage
# Bundled libwayland conflicts with the host's on some distros (Fedora
# Wayland: EGL_BAD_PARAMETER, blank window - #6878). The AppImage
# ecosystem excludelist agrees these libs must come from the system.
- name: Strip bundled Wayland libs from AppImage
if: matrix.platform == 'ubuntu-22.04' && !inputs.minimal
continue-on-error: true
run: |
set -euo pipefail
AI=$(find "$PWD/frontend/src-tauri/target" -name "*.AppImage" | head -1)
if [ -z "$AI" ]; then echo "No AppImage found - skipping"; exit 0; fi
chmod +x "$AI"
WORK=$(mktemp -d)
(cd "$WORK" && "$AI" --appimage-extract >/dev/null)
if ! ls "$WORK/squashfs-root/usr/lib/"libwayland-* >/dev/null 2>&1; then
echo "No bundled libwayland - nothing to strip"
rm -rf "$WORK"
exit 0
fi
rm -f "$WORK/squashfs-root/usr/lib/"libwayland-*
curl -fsSL -o "$WORK/appimagetool" \
https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
# Pinned checksum: never execute an unverified downloaded binary. On
# mismatch (upstream rebuilt continuous) the step aborts and the
# original AppImage ships unchanged - update the pin deliberately.
echo "a6d71e2b6cd66f8e8d16c37ad164658985e0cf5fcaa950c90a482890cb9d13e0 $WORK/appimagetool" | sha256sum -c -
chmod +x "$WORK/appimagetool"
"$WORK/appimagetool" --appimage-extract-and-run "$WORK/squashfs-root" "$AI.new"
mv "$AI.new" "$AI"
rm -rf "$WORK"
echo "Stripped bundled libwayland from $(basename "$AI")"
- name: Clear release GPG key from runner keyring (Linux)
if: always() && inputs.sign && matrix.platform == 'ubuntu-22.04' && env.RELEASE_GPG_PRIVATE_KEY != '' && github.ref == 'refs/heads/main'
env:
@@ -455,10 +506,10 @@ jobs:
fi
- name: Verify notarization (macOS only)
if: inputs.sign && matrix.platform == 'macos-15'
if: env.SIGN_BUNDLE == 'true' && matrix.platform == 'macos-15'
run: |
echo "🔍 Verifying notarization status..."
cd ./frontend/editor/src-tauri/target
cd ./frontend/src-tauri/target
DMG_FILE=$(find . -name "*.dmg" | head -1)
if [ -n "$DMG_FILE" ]; then
echo "Found DMG: $DMG_FILE"
@@ -475,13 +526,16 @@ jobs:
# Absolute dist path so the cd below can't break the copy targets.
DIST="$GITHUB_WORKSPACE/dist"
mkdir -p "$DIST"
cd ./frontend/editor/src-tauri/target
cd ./frontend/src-tauri/target
# Find and rename artifacts based on platform
if [ "${{ matrix.platform }}" = "windows-latest" ]; then
# Only ship the MSI installer. The loose exe and WiX toolset exes
# are not the user-facing installer - the MSI contains the signed inner exe.
find . -name "*.msi" -exec cp {} "$DIST/Stirling-PDF-${{ matrix.name }}.msi" \;
elif [ "${{ matrix.platform }}" = "windows-11-arm" ]; then
# arm64 ships the NSIS installer (WiX MSI has no arm64 support in Tauri).
find . -name "*-setup.exe" -exec cp {} "$DIST/Stirling-PDF-${{ matrix.name }}-setup.exe" \;
elif [ "${{ matrix.platform }}" = "macos-15" ]; then
find . -name "*.dmg" -exec cp {} "$DIST/Stirling-PDF-${{ matrix.name }}.dmg" \;
else
@@ -493,9 +547,28 @@ jobs:
# Verify the MSI AND the inner exe extracted from it are signed.
# The inner exe is what gets installed on users' machines and what AV scans.
- name: Verify Windows Code Signature
if: inputs.sign && matrix.platform == 'windows-latest' && env.SM_API_KEY != '' && github.ref == 'refs/heads/main'
if: inputs.sign && startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' && github.ref == 'refs/heads/main'
shell: pwsh
run: |
# arm64 ships an NSIS installer, not an MSI. Tauri's signCommand signs the
# inner exe before packing and the setup exe after, so verifying the setup
# exe is the arm64 equivalent of the MSI + inner-exe check below.
if ("${{ matrix.platform }}" -eq "windows-11-arm") {
$exePath = "./dist/Stirling-PDF-${{ matrix.name }}-setup.exe"
if (-not (Test-Path $exePath)) {
Write-Host "[ERROR] NSIS installer not found at $exePath"
exit 1
}
$sig = Get-AuthenticodeSignature -FilePath $exePath
Write-Host "NSIS installer: Status=$($sig.Status), Signer=$($sig.SignerCertificate.Subject)"
if ($sig.Status -ne "Valid") {
Write-Host "[ERROR] NSIS installer is not signed"
exit 1
}
Write-Host "[SUCCESS] NSIS installer is properly signed"
exit 0
}
$allSigned = $true
$msiPath = "./dist/Stirling-PDF-${{ matrix.name }}.msi"
@@ -541,7 +614,7 @@ jobs:
Write-Host "[SUCCESS] MSI and inner exe are properly signed"
- name: Dump smctl logs on failure
if: ${{ failure() && matrix.platform == 'windows-latest' && env.SM_API_KEY != '' }}
if: ${{ failure() && startsWith(matrix.platform, 'windows') && env.SM_API_KEY != '' }}
shell: pwsh
run: |
$logDir = "$env:USERPROFILE\.signingmanager\logs"
@@ -565,10 +638,10 @@ jobs:
- name: Verify build artifacts
shell: bash
run: |
cd ./frontend/editor/src-tauri/target
cd ./frontend/src-tauri/target
# Check for expected artifacts based on platform
if [ "${{ matrix.platform }}" = "windows-latest" ]; then
if [ "${{ matrix.platform }}" = "windows-latest" ] || [ "${{ matrix.platform }}" = "windows-11-arm" ]; then
echo "Checking for Windows artifacts..."
find . -name "*.exe" -o -name "*.msi" | head -5
if [ $(find . -name "*.exe" | wc -l) -eq 0 ]; then
@@ -596,7 +669,7 @@ jobs:
- name: Test artifact sizes
shell: bash
run: |
cd ./frontend/editor/src-tauri/target
cd ./frontend/src-tauri/target
echo "Artifact sizes for ${{ matrix.name }}:"
find . -name "*.exe" -o -name "*.dmg" -o -name "*.deb" -o -name "*.rpm" -o -name "*.AppImage" -o -name "*.msi" | while read file; do
if [ -f "$file" ]; then
@@ -612,12 +685,19 @@ jobs:
pr-comment:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'pull_request' && needs.build.result == 'success'
# Fork and Dependabot pull_request runs receive a read-only GITHUB_TOKEN,
# so the API cannot create or update PR comments there. The artifacts are
# still uploaded and remain available from the Actions run page.
if: >-
github.event_name == 'pull_request' &&
needs.build.result == 'success' &&
!github.event.pull_request.head.repo.fork &&
github.actor != 'dependabot[bot]'
permissions:
pull-requests: write
steps:
- name: Harden the runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -640,6 +720,7 @@ jobs:
// Map of expected artifact names to display info
const artifactMap = {
'Stirling-PDF-windows-x86_64': { icon: '🪟', platform: 'Windows x64', files: '.exe, .msi' },
'Stirling-PDF-windows-arm64': { icon: '🪟', platform: 'Windows ARM64', files: '-setup.exe (NSIS)' },
'Stirling-PDF-macos-universal': { icon: '🍎', platform: 'macOS Universal', files: '.dmg' },
'Stirling-PDF-linux-x86_64': { icon: '🐧', platform: 'Linux x64', files: '.deb, .rpm, .AppImage' }
};
@@ -708,7 +789,7 @@ jobs:
if: always()
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+17 -84
View File
@@ -17,19 +17,11 @@ on:
required: false
type: string
default: "false"
depot_cores:
description: "Depot runner vCPU count (used in runs-on). Override for benchmarking."
required: false
type: string
default: "8"
permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
# TODO: extract a pre-matrix `prepare` job that runs once and produces
# shared artifacts for the three matrix entries below to consume:
# 1. `task backend:build` — currently runs 3× in parallel with
@@ -45,14 +37,7 @@ jobs:
# spring-security=true matrix entry if `task backend:build` and
# `task backend:build:ci` produce equivalent JARs (verify before wiring).
test-build-docker-images:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }}
permissions:
contents: read
id-token: write
env:
USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' && inputs.docker-base-changed != 'true' }}
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
@@ -68,7 +53,7 @@ jobs:
cache-scope: stirling-pdf-fat
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -76,7 +61,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -99,20 +84,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Cache Gradle dependency artifacts
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
~/.gradle/caches/modules-2/files-2.1
~/.gradle/caches/modules-2/metadata-2.*
key: gradle-deps-${{ runner.os }}-jdk-25-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties', '**/*.gradle', '**/*.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'gradle/libs.versions.toml') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
with:
gradle-version: 9.6.0
cache-disabled: true
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Install Task
uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
@@ -125,18 +106,12 @@ jobs:
DISABLE_ADDITIONAL_FEATURES: true
STIRLING_PDF_DESKTOP_UI: false
- name: Set up Depot CLI
if: env.USE_DEPOT == 'true'
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.0.0
- name: Set up QEMU
if: env.USE_DEPOT != 'true'
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
if: env.USE_DEPOT != 'true'
id: buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Build base image locally (PR base change only)
if: github.event_name == 'pull_request' && inputs.docker-base-changed == 'true'
@@ -182,24 +157,10 @@ jobs:
--tag stirling-pdf-embedded:pr-test \
.
- name: Build ${{ matrix.docker-rev }} (Depot)
if: env.USE_DEPOT == 'true'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.16.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: .
file: ./${{ matrix.docker-rev }}
push: false
platforms: ${{ steps.build-params.outputs.platforms }}
build-args: |
BASE_IMAGE=${{ steps.build-params.outputs.base_image }}
provenance: true
sbom: true
# Fork PRs that did NOT change the base use the buildx container builder
# PRs that did NOT change the base use the buildx container builder
# (multi-platform + gha cache) against the published base image.
- name: Build ${{ matrix.docker-rev }} (Docker fork fallback)
if: env.USE_DEPOT != 'true' && inputs.docker-base-changed != 'true'
- name: Build ${{ matrix.docker-rev }}
if: inputs.docker-base-changed != 'true'
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
builder: ${{ steps.buildx.outputs.name }}
@@ -227,52 +188,24 @@ jobs:
if-no-files-found: warn
test-build-unoserver-image:
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }}
permissions:
contents: read
id-token: write
env:
USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' && inputs.docker-base-changed != 'true' }}
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout Repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Depot CLI
if: env.USE_DEPOT == 'true'
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.0.0
- name: Set up QEMU
if: env.USE_DEPOT != 'true'
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
if: env.USE_DEPOT != 'true'
id: buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Build docker/unoserver/Dockerfile (Depot)
if: env.USE_DEPOT == 'true'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.16.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: .
file: ./docker/unoserver/Dockerfile
push: false
load: true
platforms: linux/amd64
tags: stirling-unoserver:pr-test
provenance: false
sbom: false
- name: Build docker/unoserver/Dockerfile (Docker fork fallback)
if: env.USE_DEPOT != 'true'
- name: Build docker/unoserver/Dockerfile
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
builder: ${{ steps.buildx.outputs.name }}
+24 -47
View File
@@ -20,22 +20,12 @@ permissions:
contents: read
jobs:
pick:
uses: ./.github/workflows/_runner-pick.yml
deploy:
if: ${{ vars.CI_PROFILE != 'lite' }}
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
permissions:
contents: read
id-token: write
env:
USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' }}
DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
@@ -48,10 +38,16 @@ jobs:
java-version: "25"
distribution: "temurin"
- name: Setup Gradle
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
- name: Cache Gradle User Home
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
gradle-version: 9.6.0
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties', 'gradle/libs.versions.toml', 'settings.gradle', 'build.gradle', 'app/**/build.gradle', 'gradle/**/*.gradle') }}
restore-keys: |
gradle-${{ runner.os }}-${{ runner.arch }}-jdk-25-
gradle-${{ runner.os }}-${{ runner.arch }}-
- name: Build with Gradle
run: ./gradlew build
@@ -61,13 +57,8 @@ jobs:
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
DISABLE_ADDITIONAL_FEATURES: true
- name: Set up Depot CLI
if: env.USE_DEPOT == 'true'
uses: depot/setup-action@15c09a5f77a0840ad4bce955686522a257853461 # v1.0.0
- name: Set up Docker Buildx
if: env.USE_DEPOT != 'true'
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Get version number
id: versionNumber
@@ -76,25 +67,12 @@ jobs:
echo "versionNumber=$VERSION" >> $GITHUB_OUTPUT
- name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_API }}
- name: Build and push test image (Depot)
if: env.USE_DEPOT == 'true'
uses: depot/build-push-action@98e78adca7817480b8185f474a400b451d74e287 # v1.16.0
with:
project: ${{ vars.DEPOT_PROJECT_ID }}
context: .
file: ./docker/embedded/Dockerfile
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:test-${{ github.sha }}
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
platforms: linux/amd64
- name: Build and push test image (Docker fork fallback)
if: env.USE_DEPOT != 'true'
- name: Build and push test image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
@@ -153,39 +131,38 @@ jobs:
files-changed:
if: always()
name: detect what files changed
needs: pick
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
runs-on: ubuntu-latest
timeout-minutes: 3
outputs:
frontend: ${{ steps.changes.outputs.frontend }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check for file changes
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
id: changes
with:
filters: ".github/config/.files.yaml"
test:
if: needs.files-changed.outputs.frontend == 'true'
needs: [pick, deploy, files-changed]
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
needs: [deploy, files-changed]
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
cache: "npm"
cache-dependency-path: frontend/package-lock.json
@@ -208,13 +185,13 @@ jobs:
FORCE_COLOR: "3"
cleanup:
needs: [pick, deploy, test]
runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }}
needs: [deploy, test]
runs-on: ubuntu-latest
if: always()
steps:
- name: Harden Runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
+7 -4
View File
@@ -22,6 +22,9 @@ pipeline/
customFiles/
configs/
watchedFolders/
# The rule above targets the app's runtime watched-folders working dir, but it
# also matches this frontend source component dir; keep the source tracked.
!frontend/src/editor/proprietary/components/watchedFolders/
clientWebUI/
# Scratch dir used by local fixture-regeneration runs (see
# app/proprietary/src/test/resources/db-migration-fixtures/README.md).
@@ -171,7 +174,7 @@ app/proprietary/build
common/build
proprietary/build
stirling-pdf/build
frontend/editor/src-tauri/provisioner/target
frontend/src-tauri/provisioner/target
# Byte-compiled / optimized / DLL files
__pycache__/
@@ -222,7 +225,7 @@ out/
*.asc
# Allow test fixture certificates (synthetic, no real credentials)
!frontend/editor/src/core/tests/test-fixtures/certs/**
!frontend/src/editor/core/tests/test-fixtures/certs/**
# SSH Keys
*.pub
@@ -264,7 +267,7 @@ node_modules/
*compact*.json
test_batch.json
*.backup.*.json
frontend/editor/public/locales/*/translation.backup*.json
frontend/public/locales/*/translation.backup*.json
# Development/build artifacts
.gradle-cache/
@@ -289,4 +292,4 @@ docs/type3/signatures/
*.playwright-mcp.png
# Local screenshot artifacts from *-screenshots.spec.ts
frontend/editor/screenshots/
frontend/screenshots/
+2 -2
View File
@@ -15,10 +15,10 @@ testing/compose/validate-mcp-test.sh:curl-auth-header:92
testing/compose/validate-mcp-test.sh:curl-auth-header:116
# Storybook example showing curl with a fake Bearer token placeholder (sk_live_a3f8...).
frontend/editor/src/proprietary/ui/CodeBlock.stories.tsx:curl-auth-header:5
frontend/src/editor/proprietary/ui/CodeBlock.stories.tsx:curl-auth-header:5
# Truncated placeholder API key in portal docs example (sk_live_8f2c...e10) - not a real secret.
frontend/editor/src/portal/components/docs/GettingStartedSection.tsx:generic-api-key:30
frontend/src/processor/proprietary/components/docs/GettingStartedSection.tsx:generic-api-key:30
# False positive: generic-api-key matches the Java type name "X509Certificate"
# in a method signature (CreateSignatureBase.resolveSignatureAlgorithm) - not a secret.
+1 -1
View File
@@ -1,5 +1,5 @@
{
"ignoredFiles": [
"frontend/editor/src-tauri/icons/icon.png"
"frontend/src-tauri/icons/icon.png"
]
}
+10
View File
@@ -114,6 +114,15 @@ tasks:
- cmd: ./gradlew test
platforms: [linux, darwin]
test:force:
desc: "Run backend tests, ignoring cached results"
aliases: [test:no-cache]
cmds:
- cmd: cmd /c ".\gradlew.bat cleanTest test --no-build-cache"
platforms: [windows]
- cmd: ./gradlew cleanTest test --no-build-cache
platforms: [linux, darwin]
format:
desc: "Auto-fix code formatting"
cmds:
@@ -137,6 +146,7 @@ tasks:
swagger:
desc: "Generate OpenAPI docs"
run: once
cmds:
- cmd: cmd /c ".\gradlew.bat :stirling-pdf:copySwaggerDoc"
platforms: [windows]
+7 -16
View File
@@ -22,6 +22,7 @@ vars:
linux-amd64) echo "linux-x64";;
linux-arm64) echo "linux-arm64";;
windows-amd64) echo "windows-x64";;
windows-arm64) echo "none";; # no JPDFium windows-arm64 natives published yet
*) echo "all";;
esac
fi
@@ -38,7 +39,6 @@ tasks:
provisioner:
desc: "Build installer provisioner"
platforms: [windows]
dir: editor
cmds:
- node scripts/build-provisioner.mjs
@@ -46,55 +46,48 @@ tasks:
desc: "Start Tauri desktop dev mode"
deps: [prepare]
ignore_error: true
dir: editor
cmds:
- npx tauri dev --no-watch
build:
desc: "Build Tauri desktop app (production)"
deps: [prepare]
dir: editor
cmds:
- npx tauri build
build:dev:
desc: "Build Tauri desktop app (dev, no bundling)"
deps: [prepare]
dir: editor
cmds:
- npx tauri build --no-bundle
build:dev:mac:
desc: "Build Tauri desktop .app bundle (macOS)"
deps: [prepare]
dir: editor
cmds:
- npx tauri build --bundles app --config '{"bundle":{"createUpdaterArtifacts":false}}'
build:dev:windows:
desc: "Build Tauri desktop NSIS installer (Windows)"
deps: [prepare]
dir: editor
cmds:
- npx tauri build --bundles nsis --config '{"bundle":{"createUpdaterArtifacts":false}}'
build:dev:linux:
desc: "Build Tauri desktop AppImage (Linux)"
deps: [prepare]
dir: editor
cmds:
- npx tauri build --bundles appimage --config '{"bundle":{"createUpdaterArtifacts":false}}'
test:
desc: "Run Tauri/Cargo tests"
deps: [prepare]
dir: editor/src-tauri
dir: src-tauri
cmds:
- cargo test
clean:
desc: "Clean Tauri/Cargo build artifacts"
dir: editor
cmds:
- task: jlink:clean
- cd src-tauri && cargo clean
@@ -116,7 +109,6 @@ tasks:
jlink:verify:
desc: "Fail the build if the bundled JRE is older than the app JAR requires"
dir: editor
env:
REQUIRED_JAVA: "{{.REQUIRED_JAVA}}"
cmds:
@@ -134,15 +126,15 @@ tasks:
platforms: [windows]
- cmd: ./gradlew bootJar --no-daemon -PjpdfiumPlatforms={{.JPDFIUM_PLATFORMS}}
platforms: [linux, darwin]
- mkdir -p frontend/editor/src-tauri/libs
- cp app/core/build/libs/stirling-pdf-*.jar frontend/editor/src-tauri/libs/
- mkdir -p frontend/src-tauri/libs
- cp app/core/build/libs/stirling-pdf-*.jar frontend/src-tauri/libs/
status:
- test -f frontend/editor/src-tauri/libs/stirling-pdf-*.jar
- test -f frontend/src-tauri/libs/stirling-pdf-*.jar
jlink:runtime:
desc: "Create custom JRE with jlink"
deps: [jlink:jar]
dir: editor/src-tauri
dir: src-tauri
cmds:
- rm -rf runtime/jre
- mkdir -p runtime
@@ -201,7 +193,7 @@ tasks:
jlink:clean:
desc: "Remove JLink runtime and bundled JARs"
dir: editor/src-tauri
dir: src-tauri
cmds:
- rm -rf libs runtime
@@ -214,7 +206,6 @@ tasks:
desc: "Create universal (arm64+x86_64) JRE for the macOS Tauri build"
deps: [jlink:jar]
platforms: [darwin]
dir: editor
env:
JLINK_MODULES: "{{.JLINK_MODULES}}"
OUTPUT_DIR: src-tauri/runtime/jre
+5 -5
View File
@@ -3,14 +3,14 @@ version: '3'
tasks:
install:
desc: "Install Playwright browsers"
dir: frontend/editor
dir: frontend
deps: [ ':frontend:install' ]
cmds:
- npx playwright install {{.CLI_ARGS}} --with-deps
stubbed:
desc: "Run stubbed E2E tests"
dir: frontend/editor
dir: frontend
deps: [ ':frontend:prepare' ]
cmds:
- npx playwright test --project=stubbed {{.CLI_ARGS}}
@@ -82,7 +82,7 @@ tasks:
live:runner:
internal: true
deps: [ ':frontend:prepare' ]
dir: frontend/editor
dir: frontend
vars:
BASE_DIR: '{{.ROOT_DIR}}/.test-state/playwright'
cmds:
@@ -151,14 +151,14 @@ tasks:
up first with:
task e2e:oauth:up
task e2e:saml:up
dir: frontend/editor
dir: frontend
deps: [ ':frontend:prepare' ]
cmds:
- npx playwright test --project=enterprise {{.CLI_ARGS}}
cross-browser:
desc: "Run stubbed E2E tests on Chromium, Firefox, and WebKit"
dir: frontend/editor
dir: frontend
deps: [ ':frontend:prepare' ]
cmds:
- npx playwright test --project=stubbed --project=stubbed-firefox --project=stubbed-webkit {{.CLI_ARGS}}
+8 -1
View File
@@ -102,12 +102,19 @@ tasks:
desc: "Generate tool_models.py from Java OpenAPI spec (SwaggerDoc.json)"
deps: [install, ":backend:swagger"]
cmds:
- uv run python scripts/generate_tool_models.py --spec ../SwaggerDoc.json --output src/stirling/models/tool_models.py
- uv run python scripts/generate_tool_models.py --spec ../SwaggerDoc.json --output src/stirling/models/tool_models.py --io-output src/stirling/models/tool_io.py
sources:
- ../SwaggerDoc.json
- scripts/generate_tool_models.py
generates:
- src/stirling/models/tool_models.py
- src/stirling/models/tool_io.py
tool-models:check:
desc: "Fail if the committed tool models are out of date"
deps: [install, ":backend:swagger"]
cmds:
- uv run python scripts/generate_tool_models.py --spec ../SwaggerDoc.json --output src/stirling/models/tool_models.py --io-output src/stirling/models/tool_io.py --check
clean:
desc: "Clean build artifacts"
+131 -49
View File
@@ -3,7 +3,7 @@ version: '3'
# Tasks operate from the workspace root (frontend/). Editor commands pass
# `editor` as the vite project root (positional after `build` / before the
# mode flag) or use `--project editor/...` for tsc — so the editor lives
# under frontend/editor/ without each task needing a cd.
# under frontend/ without each task needing a cd.
tasks:
install:
@@ -26,34 +26,34 @@ tasks:
vars:
MODE: '{{.MODE | default ""}}'
cmds:
- npx tsx editor/scripts/setup-env.mts{{if .MODE}} --{{.MODE}}{{end}}
- npx tsx scripts/setup-env.mts{{if .MODE}} --{{.MODE}}{{end}}
sources:
- editor/scripts/setup-env.mts
- scripts/setup-env.mts
generates:
- editor/.env.local
- editor/.env{{if .MODE}}.{{.MODE}}{{end}}.local
- .env.local
- .env{{if .MODE}}.{{.MODE}}{{end}}.local
prepare:icons:
internal: true
run: once
deps: [install]
cmds:
- node editor/scripts/generate-icons.js
- node scripts/generate-icons.js
prepare:og:
internal: true
run: when_changed
desc: "Regenerate OG/social-preview metadata from the tool registry"
cmds:
- node editor/scripts/generate-og-metadata.mjs
- node scripts/generate-og-metadata.mjs
sources:
- editor/src/core/types/toolId.ts
- editor/src/core/utils/urlMapping.ts
- editor/src/core/data/useTranslatedToolRegistry.tsx
- editor/public/og_images/*.png
- src/editor/core/types/toolId.ts
- src/editor/core/utils/urlMapping.ts
- src/editor/core/data/useTranslatedToolRegistry.tsx
- public/og_images/*.png
generates:
- editor/src/core/data/ogImageMap.json
- editor/public/og-metadata.json
- src/editor/core/data/ogImageMap.json
- public/og-metadata.json
prepare:
desc: "Set up dev environment"
@@ -85,9 +85,10 @@ tasks:
# full path, hostname, or user. Consumed at dev-serve time by vite.config
# and dropped from production builds.
STIRLING_DEV_LABEL:
sh: basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
sh: >-
{{if eq OS "windows"}}powershell -NoProfile -Command '$root = git rev-parse --show-toplevel 2>$null; if (-not $root) { $root = (Get-Location).Path }; Split-Path -Leaf $root'{{else}}basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)"{{end}}
cmds:
- npx vite editor --mode {{.MODE}} --port {{.PORT}}{{if .OPEN}} --open{{end}}
- npx vite --mode {{.MODE}} --port {{.PORT}}{{if .OPEN}} --open{{end}}
dev:
desc: "Start frontend dev server"
@@ -142,13 +143,13 @@ tasks:
desc: "Production build (default mode)"
deps: [prepare]
cmds:
- npx vite build editor
- npx vite build
build:core:
desc: "Build for core mode"
deps: [prepare]
cmds:
- npx vite build editor --mode core
- npx vite build --mode core
build:proprietary:
desc: "Build for proprietary mode"
@@ -156,7 +157,7 @@ tasks:
vars:
PREVIEW: '{{.PREVIEW | default ""}}'
cmds:
- '{{if .PREVIEW}}VITE_BUILD_FOR_PREVIEW=1 {{end}}npx vite build editor --mode proprietary'
- '{{if .PREVIEW}}VITE_BUILD_FOR_PREVIEW=1 {{end}}npx vite build --mode proprietary'
build:saas:
desc: "Build for SaaS mode"
@@ -164,7 +165,7 @@ tasks:
- task: prepare
vars: { MODE: saas }
cmds:
- npx vite build editor --mode saas
- npx vite build --mode saas
build:desktop:
desc: "Build for desktop mode"
@@ -172,27 +173,85 @@ tasks:
- task: prepare
vars: { MODE: desktop }
cmds:
- npx vite build editor --mode desktop
- npx vite build --mode desktop
build:prototypes:
desc: "Build for prototypes mode"
deps: [prepare]
cmds:
- npx vite build editor --mode prototypes
- npx vite build --mode prototypes
storybook:
desc: "Start Storybook dev server"
deps: [install]
deps: [prepare]
cmds:
- npx storybook dev -p 6006 {{.CLI_ARGS}}
storybook:build:
desc: "Build static Storybook"
deps: [install]
deps: [prepare]
cmds:
- npx storybook build {{.CLI_ARGS}}
storybook:browser:
internal: true
desc: "Install the Chromium build the story scan runs in"
run: once
deps: [install]
cmds:
- npx playwright install chromium
storybook:test:
desc: "Scan every story in real Chromium: it must render and pass axe"
deps: [prepare, storybook:browser]
cmds:
# Runs each story as a browser test. Pass a filter through, e.g.
# task frontend:storybook:test -- Button
- npx vitest run --config .storybook/vitest.config.ts {{.CLI_ARGS}}
storybook:a11y:
desc: "a11y regression gate over every story: fail only on NEW axe violations"
deps: [prepare, storybook:browser]
cmds:
- node .storybook/a11y-scan.mjs
- node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt
storybook:a11y:changed:
desc: "a11y gate over the stories this branch affects (default base origin/main)"
summary: |
Scans the stories a branch affects, which is what pull requests run — a
full scan takes ~30 minutes, far too long to sit in front of every merge.
A story is affected if its file changed, or if a same-named sibling
source file changed (editing Button.tsx or Button.css re-scans
Button.stories.tsx — the story renders the live component, so a component
edit changes what the story shows without touching the story file).
Changes that ripple further than a component's own stories are covered by
the nightly full sweep.
Pass a base ref through CLI_ARGS, e.g.
task frontend:storybook:a11y:changed -- origin/release
deps: [prepare, storybook:browser]
vars:
BASE: '{{.CLI_ARGS | default "origin/main"}}'
CHANGED:
sh: node .storybook/a11y-changed.mjs {{.CLI_ARGS | default "origin/main"}}
cmds:
- cmd: |
if [ -z '{{.CHANGED}}' ]; then
echo "a11y: no story files affected vs {{.BASE}} — nothing to check"
exit 0
fi
node .storybook/a11y-scan.mjs {{.CHANGED}}
node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt
storybook:a11y:record:
desc: "Re-record the a11y baseline (run after intentionally fixing/adding violations)"
deps: [prepare, storybook:browser]
cmds:
- node .storybook/a11y-scan.mjs
- node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt --record
# ============================================================
# Code quality
# ============================================================
@@ -204,18 +263,32 @@ tasks:
- task: lint:eslint
- task: lint:dpdm
- task: lint:colors
- task: lint:css
lint:colors:
desc: "Enforce theme tokens — colours in core/theme route through the palette"
lint:css:
desc: "Lint stylesheets for duplicate selectors"
deps: [install]
cmds:
- node editor/scripts/lint/theme-lint.mjs
# Covers the whole editor tree, including the portal/processor layer and
# public/css. Vendored CSS and build output are excluded via ignoreFiles
# in stylelint.config.mjs.
- npx stylelint "src/**/*.css"
lint:colors:
desc: "Enforce theme tokens — no hardcoded colours or raw primitives in components"
aliases: [lint:colours]
deps: [install]
cmds:
- node scripts/lint/theme-lint.mjs
- node scripts/lint/theme-lint.mjs css-colors
- node scripts/lint/theme-lint.mjs code-colors
- node scripts/lint/theme-lint.mjs no-primitives
contrast:
desc: "Report low-contrast theme token pairs (warning only, never blocks)"
deps: [install]
cmds:
- node editor/scripts/lint/theme-lint.mjs contrast
- node scripts/lint/theme-lint.mjs contrast
lint:eslint:
desc: "Run ESLint linting"
@@ -229,7 +302,7 @@ tasks:
cmds:
# Globs so dpdm walks the whole tree. dpdm expands the braces itself, so this is
# shell-agnostic. Covers the whole editor tree, including the portal layer.
- npx dpdm "editor/src/**/*.{ts,tsx}" --circular --no-warning --no-tree --exit-code circular:1
- npx dpdm "src/**/*.{ts,tsx}" --circular --no-warning --no-tree --exit-code circular:1
lint:fix:
desc: "Auto-fix lint issues"
@@ -270,14 +343,14 @@ tasks:
deps: [prepare]
cmds:
- task: typecheck:_run
vars: { PROJECT: editor/src/core/tsconfig.json }
vars: { PROJECT: src/editor/core/tsconfig.json }
typecheck:proprietary:
desc: "Typecheck proprietary build variant"
deps: [prepare]
cmds:
- task: typecheck:_run
vars: { PROJECT: editor/src/proprietary/tsconfig.json }
vars: { PROJECT: src/editor/proprietary/tsconfig.json }
typecheck:saas:
desc: "Typecheck SaaS build variant"
@@ -286,7 +359,7 @@ tasks:
vars: { MODE: saas }
cmds:
- task: typecheck:_run
vars: { PROJECT: editor/src/saas/tsconfig.json }
vars: { PROJECT: src/editor/saas/tsconfig.json }
typecheck:desktop:
desc: "Typecheck desktop build variant"
@@ -295,35 +368,42 @@ tasks:
vars: { MODE: desktop }
cmds:
- task: typecheck:_run
vars: { PROJECT: editor/src/desktop/tsconfig.json }
vars: { PROJECT: src/editor/desktop/tsconfig.json }
typecheck:cloud:
desc: "Typecheck cloud shared layer (standalone)"
deps: [prepare]
cmds:
- task: typecheck:_run
vars: { PROJECT: editor/src/cloud/tsconfig.json }
vars: { PROJECT: src/editor/cloud/tsconfig.json }
typecheck:scripts:
desc: "Typecheck scripts"
deps: [prepare]
cmds:
- task: typecheck:_run
vars: { PROJECT: editor/scripts/tsconfig.json }
vars: { PROJECT: scripts/tsconfig.json }
typecheck:prototypes:
desc: "Typecheck prototypes build variant"
deps: [prepare]
cmds:
- task: typecheck:_run
vars: { PROJECT: editor/src/prototypes/tsconfig.json }
vars: { PROJECT: src/editor/prototypes/tsconfig.json }
typecheck:portal:
desc: "Typecheck developer portal build variant"
deps: [install]
cmds:
- task: typecheck:_run
vars: { PROJECT: editor/src/portal/tsconfig.json }
vars: { PROJECT: src/processor/proprietary/tsconfig.json }
typecheck:storybook:
desc: "Typecheck Storybook config and stories"
deps: [prepare]
cmds:
- task: typecheck:_run
vars: { PROJECT: .storybook/tsconfig.json }
typecheck:all:
desc: "Typecheck all build variants"
@@ -336,6 +416,7 @@ tasks:
- task: typecheck:scripts
- task: typecheck:prototypes
- task: typecheck:portal
- task: typecheck:storybook
# ============================================================
# Quality Gate
@@ -352,7 +433,7 @@ tasks:
og:check:
desc: "Fail if committed OG/social-preview metadata is out of date"
cmds:
- node editor/scripts/generate-og-metadata.mjs --check
- node scripts/generate-og-metadata.mjs --check
check:all:
desc: "Full CI quality gate"
@@ -380,13 +461,13 @@ tasks:
desc: "Run editor tests"
deps: [prepare]
cmds:
- npx vitest run --root editor
- npx vitest run --root .
test:watch:
desc: "Run tests in watch mode"
deps: [prepare]
cmds:
- npx vitest --watch --root editor
- npx vitest --watch --root .
test:coverage:
desc: "Run tests with coverage (one-shot; CI-friendly)."
@@ -397,12 +478,12 @@ tasks:
# coverage-summary.py helper consumes; html/text are kept for humans.
#
# reportsDirectory is pinned to ./coverage relative to vitest's root
# (--root editor), so output lands at frontend/editor/coverage/. The
# (--root .), so output lands at frontend/coverage/. The
# CI upload step reads from that path. An earlier attempt with
# `./editor/coverage` double-nested into frontend/editor/editor/coverage;
# `./editor/coverage` double-nested into frontend/coverage;
# pinning future-proofs against vitest changing the default.
- >
npx vitest run --root editor --coverage
npx vitest run --root . --coverage
--coverage.provider=v8
--coverage.reporter=text-summary
--coverage.reporter=json-summary
@@ -417,24 +498,25 @@ tasks:
desc: "Generate tool API types from the Java OpenAPI spec"
deps: [install, ":backend:swagger"]
cmds:
- npx tsx editor/scripts/generate-tool-api-types.mts --spec ../SwaggerDoc.json --output editor/src/core/types/toolApiTypes.ts
- npx tsx scripts/generate-tool-api-types.mts --spec ../SwaggerDoc.json --output src/editor/core/types/toolApiTypes.ts --io-output src/editor/core/types/toolIO.ts
sources:
- editor/scripts/generate-tool-api-types.mts
- scripts/generate-tool-api-types.mts
- ../SwaggerDoc.json
generates:
- editor/src/core/types/toolApiTypes.ts
- src/editor/core/types/toolApiTypes.ts
- src/editor/core/types/toolIO.ts
tool-models:check:
desc: "Fail if committed tool API types are out of date"
deps: [install, ":backend:swagger"]
cmds:
- npx tsx editor/scripts/generate-tool-api-types.mts --spec ../SwaggerDoc.json --output editor/src/core/types/toolApiTypes.ts --check
- npx tsx scripts/generate-tool-api-types.mts --spec ../SwaggerDoc.json --output src/editor/core/types/toolApiTypes.ts --io-output src/editor/core/types/toolIO.ts --check
licenses:generate:
desc: "Generate frontend license report"
deps: [install]
cmds:
- node editor/scripts/generate-licenses.js
- node scripts/generate-licenses.js
# ============================================================
# Clean
@@ -443,7 +525,7 @@ tasks:
clean:
desc: "Clean build artifacts and caches"
cmds:
- cmd: powershell rm -Recurse -Force -ErrorAction SilentlyContinue node_modules/.vite, editor/dist, dist
- cmd: powershell rm -Recurse -Force -ErrorAction SilentlyContinue node_modules/.vite, dist, dist
platforms: [windows]
- cmd: rm -rf node_modules/.vite editor/dist dist
- cmd: rm -rf node_modules/.vite dist dist
platforms: [linux, darwin]
+4 -4
View File
@@ -21,7 +21,7 @@ vars:
':(exclude).devcontainer/*'
':(exclude)app/core/src/main/resources/*'
':(exclude)app/proprietary/src/main/resources/*'
':(exclude)frontend/editor/public/vendor/*'
':(exclude)frontend/public/vendor/*'
':(exclude)*Dockerfile*'
':(exclude)*pdfjs*'
':(exclude)*thirdParty*'
@@ -39,7 +39,7 @@ vars:
':(exclude)*.min.*'
':(exclude)*diff.js'
':(exclude).github/workflows/*'
LOCALE_TOML: 'frontend/editor/public/locales/*/translation.toml'
LOCALE_TOML: 'frontend/public/locales/*/translation.toml'
# gitleaks is pinned + checksum-verified by scripts/pre-commit/install_gitleaks.py,
# which owns the version and caches the binary here.
@@ -73,7 +73,7 @@ tasks:
- task: gitleaks
install:
desc: "Install the pinned pre-commit Python tools (ruff, codespell, toml-sort)"
desc: "Install the pinned pre-commit Python tools"
run: once
cmds:
- uv sync --project scripts/pre-commit --locked
@@ -112,7 +112,7 @@ tasks:
toml-sort:
deps: [install]
cmds:
- uv run --project scripts/pre-commit --no-sync toml-sort --all --ignore-case {{if .FIX}}--in-place{{else}}--check{{end}} {{.LOCALE_TOML}}
- uv run --project scripts/pre-commit --no-sync python scripts/pre-commit/sort_locale_toml.py {{if .FIX}}--fix {{end}}{{.LOCALE_TOML}}
whitespace:
cmds:
+6 -6
View File
@@ -10,14 +10,14 @@ When adding tools, follow this systematic approach using the established pattern
Create these files in the correct directories:
```
frontend/editor/src/hooks/tools/[toolName]/
frontend/src/hooks/tools/[toolName]/
├── use[ToolName]Parameters.ts # Parameter definitions and validation
└── use[ToolName]Operation.ts # Tool operation logic using useToolOperation
frontend/editor/src/components/tools/[toolName]/
frontend/src/components/tools/[toolName]/
└── [ToolName]Settings.tsx # Settings UI component (if needed)
frontend/editor/src/tools/
frontend/src/tools/
└── [ToolName].tsx # Main tool component
```
@@ -128,7 +128,7 @@ export default [ToolName] as ToolComponent;
## 3. Register Tool in System
Update these files to register your new tool:
**Tool Registry** (`frontend/editor/src/data/useTranslatedToolRegistry.tsx`):
**Tool Registry** (`frontend/src/data/useTranslatedToolRegistry.tsx`):
1. Add imports at the top:
```typescript
import [ToolName] from "../tools/[ToolName]";
@@ -155,7 +155,7 @@ import [ToolName]Settings from "../components/tools/[toolName]/[ToolName]Setting
## 4. Add Tooltips (Optional but Recommended)
Create user-friendly tooltips to help non-technical users understand your tool. **Use simple, clear language - avoid technical jargon:**
**Tooltip Hook** (`frontend/editor/src/components/tooltips/use[ToolName]Tips.ts`):
**Tooltip Hook** (`frontend/src/components/tooltips/use[ToolName]Tips.ts`):
```typescript
import { useTranslation } from 'react-i18next';
import { TooltipContent } from '../../types/tips';
@@ -202,7 +202,7 @@ const [ToolName] = (props: BaseToolProps) => {
## 5. Add Translations
Update translation files. **Important: Only update `en-US` files** - other languages are handled separately.
**File to update:** `frontend/editor/public/locales/en-US/translation.toml`
**File to update:** `frontend/public/locales/en-US/translation.toml`
**Required Translation Keys**:
```toml
+17 -17
View File
@@ -139,10 +139,10 @@ The project structure is defined in `engine/pyproject.toml`. Any new dependencie
#### Environment Variables
- All `VITE_*` variables must be declared in the appropriate committed env file:
- `frontend/editor/.env` — core and shared vars (base, loaded in every mode)
- `frontend/editor/.env.proprietary` — proprietary-only vars, e.g. the admin portal's SaaS/account-link keys (layered on top of `.env` in proprietary mode)
- `frontend/editor/.env.saas` — SaaS-only vars (layered on top of `.env` in SaaS mode)
- `frontend/editor/.env.desktop` — desktop (Tauri)-only vars (layered on top of `.env` in desktop mode)
- `frontend/.env` — core and shared vars (base, loaded in every mode)
- `frontend/.env.proprietary` — proprietary-only vars, e.g. the admin portal's SaaS/account-link keys (layered on top of `.env` in proprietary mode)
- `frontend/.env.saas` — SaaS-only vars (layered on top of `.env` in SaaS mode)
- `frontend/.env.desktop` — desktop (Tauri)-only vars (layered on top of `.env` in desktop mode)
- These files are committed to Git and must not contain private keys
- Local overrides (API keys, machine-specific settings) go in uncommitted sibling `.env.local` / `.env.saas.local` / `.env.desktop.local` files — Vite automatically layers them on top
- Never use `|| 'hardcoded-fallback'` inline — put defaults in the committed env files
@@ -153,9 +153,9 @@ The project structure is defined in `engine/pyproject.toml`. Any new dependencie
#### Import Paths - CRITICAL
**ALWAYS use `@app/*` for imports.** Do not use `@core/*` or `@proprietary/*` unless explicitly wrapping/extending a lower layer implementation.
For a broader explanation of the frontend layering and override architecture, read @frontend/editor/DeveloperGuide.md
For a broader explanation of the frontend layering and override architecture, read @frontend/DeveloperGuide.md
Before touching colours or theming (tokens, dark mode, accent colours), read @frontend/editor/src/core/theme/README.md — it explains the palette/`--c-*` token system and the rule that literal colours live only in `primitives.css`.
Before touching colours or theming (tokens, dark mode, accent colours), read @frontend/src/editor/core/theme/README.md — it explains the palette/`--c-*` token system and the rule that literal colours live only in `primitives.css`.
```typescript
// ✅ CORRECT - Use @app/* for all imports
@@ -270,7 +270,7 @@ Frontend designed for **stateful document processing**:
- No file reloading between tools - performance critical for large PDFs (up to 100GB+)
#### FileContext - Central State Management
**Location**: `frontend/editor/src/core/contexts/FileContext.tsx`
**Location**: `frontend/src/editor/core/contexts/FileContext.tsx`
- **Active files**: Currently loaded PDFs and their variants
- **Tool navigation**: Current mode (viewer/pageEditor/fileEditor/toolName)
- **Memory management**: PDF document cleanup, blob URL lifecycle, Web Worker management
@@ -295,7 +295,7 @@ Without cleanup: browser crashes with memory leaks.
**Architecture**: Modular hook-based system with clear separation of concerns:
- **useToolOperation** (`frontend/editor/src/core/hooks/tools/shared/useToolOperation.ts`): Main orchestrator hook
- **useToolOperation** (`frontend/src/editor/core/hooks/tools/shared/useToolOperation.ts`): Main orchestrator hook
- Coordinates all tool operations with consistent interface
- Integrates with FileContext for operation tracking
- Handles validation, error handling, and UI state management
@@ -383,7 +383,7 @@ return useToolOperation({
### Frontend Directory Structure
The frontend is organized with a clear separation of concerns:
- **`frontend/editor/src/core/`**: Main application code (shared, production-ready components)
- **`frontend/src/editor/core/`**: Main application code (shared, production-ready components)
- **`core/components/`**: React components organized by feature
- `core/components/tools/`: Individual PDF tool implementations
- `core/components/viewer/`: PDF viewer components
@@ -401,17 +401,17 @@ The frontend is organized with a clear separation of concerns:
- **`core/data/`**: Static data (tool taxonomy, etc.)
- **`core/services/`**: Business logic services (PDF processing, storage, etc.)
- **`frontend/editor/src/desktop/`**: Desktop-specific (Tauri) code
- **`frontend/editor/src/proprietary/`**: Proprietary/licensed features
- **`frontend/editor/src-tauri/`**: Tauri (Rust) native desktop application code
- **`frontend/editor/public/`**: Static assets served directly
- **`frontend/src/editor/desktop/`**: Desktop-specific (Tauri) code
- **`frontend/src/editor/proprietary/`**: Proprietary/licensed features
- **`frontend/src-tauri/`**: Tauri (Rust) native desktop application code
- **`frontend/public/`**: Static assets served directly
- `public/locales/`: Translation JSON files
### Component Architecture
- **Static Assets**: CSS, JS, and resources in `src/main/resources/static/` (legacy) + `frontend/editor/public/` (modern)
- **Static Assets**: CSS, JS, and resources in `src/main/resources/static/` (legacy) + `frontend/public/` (modern)
- **Internationalization**:
- Backend: `messages_*.properties` files
- Frontend: JSON files in `frontend/editor/public/locales/` (converted from .properties)
- Frontend: JSON files in `frontend/public/locales/` (converted from .properties)
- Conversion Script: `scripts/convert_properties_to_json.py`
### Configuration Modes
@@ -436,7 +436,7 @@ The frontend is organized with a clear separation of concerns:
4. **Code Style**: Spotless enforces Google Java Format automatically (`task backend:format`)
5. **Translations**:
- Backend: Use helper scripts in `/scripts` for multi-language updates
- Frontend: Update JSON files in `frontend/editor/public/locales/` or use conversion script
- Frontend: Update JSON files in `frontend/public/locales/` or use conversion script
6. **Documentation**: API docs auto-generated and available at `/swagger-ui/index.html`
## Frontend Architecture Status
@@ -454,7 +454,7 @@ The frontend is organized with a clear separation of concerns:
## Translation Rules
- **CRITICAL**: Always update translations in `en-US` only - all other languages (including `en-GB`) are handled separately
- Translation files are located in `frontend/editor/public/locales/`
- Translation files are located in `frontend/public/locales/`
- After changing any translation file, run `task pre-commit:fix`
## Important Notes
+1 -1
View File
@@ -21,7 +21,7 @@ This project uses [Task](https://taskfile.dev/) as a unified command runner. Aft
1. Install the `task` CLI: https://taskfile.dev/installation/
2. Run `task install` to install all dependencies
3. Run `task dev` to start backend + frontend
3. Run `task dev` to start backend + frontend or `task desktop:dev` to start the desktop application
4. Run `task check` before submitting a PR
Run `task --list` to see all available commands.
+35 -2
View File
@@ -458,7 +458,7 @@ For Stirling 2.0, new features are built as React components:
1. **Create the React Component:**
```typescript
// frontend/editor/src/tools/NewTool.tsx
// frontend/src/tools/NewTool.tsx
import { useState } from 'react';
import { Button, FileInput, Container } from '@mantine/core';
@@ -504,7 +504,8 @@ For Stirling 2.0, new features are built as React components:
1. **Create a New Controller:**
- Create a new Java class in the `stirling-pdf/src/main/java/stirling/software/SPDF/controller/api` directory.
- Annotate the class with `@RestController` and `@RequestMapping` to define the API endpoint.
- Ensure to add API documentation annotations like `@Tag(name = "General", description = "General APIs")` and `@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")`.
- Ensure to add API documentation annotations like `@Tag(name = "General", description = "General APIs")` and `@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates.")`.
- If the endpoint transforms a document, declare what it accepts and produces with `@ToolIO`, for example `@ToolIO(produces = ToolFormat.PDF)`. This is what lets a pipeline containing the step be checked before it runs, so a chain that cannot work is caught in the builder rather than part-way through a job. Endpoints under the tool namespaces are required to carry it - `ToolIODeclarationCoverageTest` fails the build otherwise. See [Declaring tool inputs and outputs](#declaring-tool-inputs-and-outputs).
```java
package stirling.software.SPDF.controller.api;
@@ -578,6 +579,38 @@ For Stirling 2.0, new features are built as React components:
}
```
### Declaring tool inputs and outputs
An endpoint that transforms a document declares what it accepts and produces with `@ToolIO`. This is the single source of truth: it is published into the OpenAPI spec as an `x-stirling-io` extension, and generated from there into the frontend (`toolIO.ts`) and the AI engine (`tool_io.py`). A pipeline can therefore be checked while it is being edited, instead of failing part-way through a job.
```java
@ToolIO(produces = ToolFormat.PDF)
```
`accepts` defaults to `{ ToolFormat.PDF }` and `arity` to `ToolArity.SISO`, so most tools only declare what they produce.
- **`ToolFormat`** is the kind of file: `PDF`, `PDF_ENCRYPTED`, `IMAGE`, `ZIP`, `WORD`, `PPT`, `EXCEL`, `CSV`, `HTML`, `XML`, `JSON`, `TEXT`, `MARKDOWN`, `JAVASCRIPT`, `EBOOK`, `EMAIL`, `POSTSCRIPT`, `VIDEO`, `CBZ`, `CBR`, plus `ANY` (accepts or produces anything) and `NONE` (returns a report, not a file). Encryption is a format rather than a flag, so the default `accepts = PDF` means an endpoint rejects an encrypted PDF unless it opts in.
- **`ToolArity`** is how many files go in and out: `SISO`, `SIMO`, `MISO`, `MIMO`. This axis carries ZIP-as-transport. A splitter is `produces = PDF, arity = SIMO`, and the caller unpacks the archive; an endpoint whose deliverable really is an archive declares `produces = ZIP` with a single-output arity and stays packed.
When the output depends on a parameter, declare the exception as a case rather than picking one answer. Add Password produces an encrypted PDF unless both passwords are blank, in which case it has only set permissions:
```java
@ToolIO(
produces = ToolFormat.PDF_ENCRYPTED,
cases =
@ToolIOCase(
when = {
@ToolIOWhen(param = "password", matches = ""),
@ToolIOWhen(param = "ownerPassword", matches = "")
},
produces = ToolFormat.PDF,
arity = ToolArity.SISO))
```
Every condition in a `when` must hold for the case to apply, and `matches` is compared as a string, case-insensitively, with an empty string matching an absent or blank value. If a case reads a parameter that is not set yet, the output is reported as uncertain and the chain warns rather than erroring.
Endpoints under the tool namespaces must carry a declaration; `ToolIODeclarationCoverageTest` fails the build for any that does not, with a short allowlist for endpoints that manage a session, a device or a stored resource rather than transforming a document. The matching rules are implemented three times (Java `ToolChainValidator`, `toolIOCompat.ts`, `tool_io_compat.py`) and pinned to the same answers by the shared fixtures in `testing/tool-io-cases.json`, so a behaviour change belongs in that file first.
## Adding New Translations to Existing Language Files in Stirling-PDF
When adding a new feature or modifying existing ones in Stirling-PDF, you'll need to add new translation entries to the existing language files. Here's a step-by-step guide:
+12 -12
View File
@@ -10,18 +10,18 @@ if that directory exists, is licensed under the license defined in "app/propriet
if that directory exists, is licensed under the license defined in "app/saas/LICENSE".
* All content that resides under the "engine/" directory of this repository,
if that directory exists, is licensed under the license defined in "engine/LICENSE".
* All content that resides under the "frontend/editor/src/proprietary/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/editor/src/proprietary/LICENSE".
* All content that resides under the "frontend/editor/src/desktop/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/editor/src/desktop/LICENSE".
* All content that resides under the "frontend/editor/src/saas/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/editor/src/saas/LICENSE".
* All content that resides under the "frontend/editor/src/cloud/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/editor/src/cloud/LICENSE".
* All content that resides under the "frontend/editor/src/prototypes/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/editor/src/prototypes/LICENSE".
* All content that resides under the "frontend/editor/src/portal/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/editor/src/portal/LICENSE".
* All content that resides under the "frontend/src/editor/proprietary/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/src/editor/proprietary/LICENSE".
* All content that resides under the "frontend/src/editor/desktop/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/src/editor/desktop/LICENSE".
* All content that resides under the "frontend/src/editor/saas/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/src/editor/saas/LICENSE".
* All content that resides under the "frontend/src/editor/cloud/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/src/editor/cloud/LICENSE".
* All content that resides under the "frontend/src/editor/prototypes/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/src/editor/prototypes/LICENSE".
* All content that resides under the "frontend/src/processor/" directory of this repository,
if that directory exists, is licensed under the license defined in "frontend/src/processor/LICENSE".
* Content outside of the above mentioned directories or restrictions above is
available under the MIT License as defined below.
+6
View File
@@ -194,6 +194,12 @@ tasks:
- task: frontend:tool-models
- task: engine:tool-models
tool-models:check:
desc: "Fail if any committed API model is out of date"
cmds:
- task: frontend:tool-models:check
- task: engine:tool-models:check
# ============================================================
# Quality Gate
# ============================================================
+1 -1
View File
@@ -86,7 +86,7 @@ If you're using Tauri's built-in updater feature:
## Configuration Files
### 1. Tauri Configuration (frontend/editor/src-tauri/tauri.conf.json)
### 1. Tauri Configuration (frontend/src-tauri/tauri.conf.json)
The Windows signing configuration is already set up:
+20 -8
View File
@@ -32,6 +32,14 @@
"moduleName": ".*",
"moduleLicense": "BSD-4 License"
},
{
"moduleName": ".*",
"moduleLicense": "Revised BSD"
},
{
"moduleName": ".*",
"moduleLicense": "ISC"
},
{
"moduleName": ".*",
"moduleLicense": "MIT"
@@ -48,6 +56,10 @@
"moduleName": ".*",
"moduleLicense": "MIT-0"
},
{
"moduleName": ".*",
"moduleLicense": "MIT license"
},
{
"moduleName": "com.github.jai-imageio:jai-imageio-core",
"moduleLicense": "LICENSE.txt"
@@ -144,6 +156,14 @@
"moduleName": ".*",
"moduleLicense": "GNU GENERAL PUBLIC LICENSE, Version 2 + Classpath Exception"
},
{
"moduleName": ".*",
"moduleLicense": "GNU Lesser Public License"
},
{
"moduleName": ".*",
"moduleLicense": "The GNU Lesser General Public License"
},
{
"moduleName": "com.martiansoftware:jsap",
"moduleLicense": "LGPL"
@@ -212,14 +232,6 @@
"moduleName": "com.google.re2j:re2j",
"moduleLicense": "Go License"
},
{
"moduleName": "com.hubspot:algebra",
"moduleLicense": null
},
{
"moduleName": "com.hubspot.immutables:immutables-exceptions",
"moduleLicense": null
},
{
"moduleName": ".*",
"moduleLicense": "UnRar License"
+13 -33
View File
@@ -2,32 +2,6 @@
bootRun {
enabled = false
}
spotless {
java {
target 'src/**/java/**/*.java'
targetExclude 'src/main/java/org/apache/**'
googleJavaFormat(googleJavaFormatVersion).aosp().reorderImports(false)
// google-java-format 1.28.0 bundles Guava 32.x which crashes Spotless lint on JDK 24/25
suppressLintsFor { setStep('google-java-format') }
importOrder("java", "javax", "org", "com", "net", "io", "jakarta", "lombok", "me", "stirling")
trimTrailingWhitespace()
leadingTabsToSpaces()
endWithNewline()
}
yaml {
target '**/*.yml', '**/*.yaml'
trimTrailingWhitespace()
leadingTabsToSpaces()
endWithNewline()
}
format 'gradle', {
target '**/gradle/*.gradle', '**/*.gradle'
trimTrailingWhitespace()
leadingTabsToSpaces()
endWithNewline()
}
}
dependencies {
api "com.google.guava:guava:${guavaVersion}"
api 'org.springframework.boot:spring-boot-starter-webmvc'
@@ -42,7 +16,7 @@ dependencies {
api "org.apache.pdfbox:pdfbox-io:$pdfboxVersion"
api "org.apache.pdfbox:xmpbox:$pdfboxVersion"
api "org.apache.pdfbox:preflight:$pdfboxVersion"
api 'com.github.junrar:junrar:7.5.10' // RAR archive support for CBR files
api 'com.github.junrar:junrar:8.0.0' // RAR archive support for CBR files
api 'jakarta.servlet:jakarta.servlet-api:6.1.0'
api 'org.snakeyaml:snakeyaml-engine:3.0.1'
api "org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.3"
@@ -62,18 +36,24 @@ dependencies {
api "com.stirling:jpdfium:${jpdfiumVersion}"
// -PjpdfiumPlatforms=all|<csv of linux-x64,linux-arm64,darwin-x64,darwin-arm64,windows-x64>
// -PjpdfiumPlatforms=all|none|<csv of linux-x64,linux-arm64,darwin-x64,darwin-arm64,windows-x64>
// 'none' skips natives entirely (windows-arm64 builds, until JPDFium ships that platform).
def jpdfiumPlatformsProp = (project.findProperty('jpdfiumPlatforms') ?: 'all').toString().trim()
def jpdfiumAllPlatforms = ['linux-x64', 'linux-arm64', 'darwin-x64', 'darwin-arm64', 'windows-x64']
def jpdfiumPlatforms = jpdfiumPlatformsProp == 'all'
? jpdfiumAllPlatforms
: jpdfiumPlatformsProp.split(',').collect { it.trim() }.findAll { it }
def jpdfiumPlatforms
if (jpdfiumPlatformsProp == 'all') {
jpdfiumPlatforms = jpdfiumAllPlatforms
} else if (jpdfiumPlatformsProp == 'none') {
jpdfiumPlatforms = []
} else {
jpdfiumPlatforms = jpdfiumPlatformsProp.split(',').collect { it.trim() }.findAll { it }
}
def jpdfiumInvalid = jpdfiumPlatforms.findAll { !jpdfiumAllPlatforms.contains(it) }
if (jpdfiumInvalid) {
throw new GradleException("Unknown jpdfiumPlatforms value(s): ${jpdfiumInvalid.join(', ')}. " +
"Valid: ${jpdfiumAllPlatforms.join(', ')} or 'all'.")
"Valid: ${jpdfiumAllPlatforms.join(', ')}, 'all' or 'none'.")
}
logger.lifecycle("JPDFium native platforms: ${jpdfiumPlatforms.join(', ')}")
logger.lifecycle("JPDFium native platforms: ${jpdfiumPlatforms ? jpdfiumPlatforms.join(', ') : 'none'}")
jpdfiumPlatforms.each { platform ->
runtimeOnly "com.stirling:jpdfium-natives-${platform}:${jpdfiumVersion}"
}
@@ -338,6 +338,7 @@ public class EndpointConfiguration {
addEndpointToGroup("PageOps", "split-pages");
addEndpointToGroup("PageOps", "rearrange-pages");
addEndpointToGroup("PageOps", "rotate-pdf");
addEndpointToGroup("PageOps", "auto-rotate-pdf");
addEndpointToGroup("PageOps", "multi-page-layout");
addEndpointToGroup("PageOps", "booklet-imposition");
addEndpointToGroup("PageOps", "scale-pages");
@@ -0,0 +1,105 @@
package stirling.software.common.config.swagger;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springdoc.core.customizers.GlobalOperationCustomizer;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import stirling.software.common.model.tool.ToolArity;
import stirling.software.common.model.tool.ToolFormat;
import stirling.software.common.model.tool.ToolIO;
import stirling.software.common.model.tool.ToolIOCase;
import stirling.software.common.model.tool.ToolIOWhen;
/**
* Publishes each {@link ToolIO} into the spec as {@code x-stirling-io}, which is how the frontend
* and the AI engine get it.
*
* <p>Also appends the {@code Input:/Output:/Type:} line the docs used to carry by hand, so the
* published text is unchanged without anyone maintaining it.
*/
@Component
public class ToolIOOperationCustomizer
implements GlobalOperationCustomizer, GlobalOpenApiCustomizer {
public static final String EXTENSION_NAME = "x-stirling-io";
public static final String VOCABULARY_EXTENSION_NAME = "x-stirling-io-vocabulary";
// Published separately from the declarations: generators need the full vocabulary for their
// enums, and deriving it from what is present would shrink it when an endpoint is disabled.
@Override
public void customise(OpenAPI openApi) {
Map<String, Object> vocabulary = new LinkedHashMap<>();
vocabulary.put("formats", names(ToolFormat.values()));
vocabulary.put("arities", names(ToolArity.values()));
openApi.addExtension(VOCABULARY_EXTENSION_NAME, vocabulary);
}
@Override
public Operation customize(Operation operation, HandlerMethod handlerMethod) {
ToolIO declaration = handlerMethod.getMethodAnnotation(ToolIO.class);
if (declaration == null) {
return operation;
}
operation.addExtension(EXTENSION_NAME, toExtension(declaration));
operation.setDescription(appendSummaryLine(operation.getDescription(), declaration));
return operation;
}
private static Map<String, Object> toExtension(ToolIO declaration) {
Map<String, Object> extension = new LinkedHashMap<>();
extension.put("accepts", names(declaration.accepts()));
extension.put("produces", declaration.produces().name());
extension.put("arity", declaration.arity().name());
if (declaration.cases().length > 0) {
extension.put("cases", cases(declaration));
}
return extension;
}
private static List<Map<String, Object>> cases(ToolIO declaration) {
return Arrays.stream(declaration.cases()).map(ToolIOOperationCustomizer::toCase).toList();
}
private static Map<String, Object> toCase(ToolIOCase rule) {
Map<String, Object> entry = new LinkedHashMap<>();
entry.put(
"when",
Arrays.stream(rule.when()).map(ToolIOOperationCustomizer::toCondition).toList());
entry.put("produces", rule.produces().name());
entry.put("arity", rule.arity().name());
return entry;
}
private static Map<String, Object> toCondition(ToolIOWhen condition) {
Map<String, Object> entry = new LinkedHashMap<>();
entry.put("param", condition.param());
entry.put("matches", List.of(condition.matches()));
return entry;
}
private static List<String> names(Enum<?>[] values) {
return Arrays.stream(values).map(Enum::name).toList();
}
private static String appendSummaryLine(String description, ToolIO declaration) {
String summary =
"Input:"
+ String.join("/", names(declaration.accepts()))
+ " Output:"
+ declaration.produces().name()
+ " Type:"
+ declaration.arity().name();
return description == null || description.isBlank()
? summary
: description.trim() + " " + summary;
}
}
@@ -208,9 +208,10 @@ public class ApplicationProperties {
public static class Policies {
/**
* Absolute directories that policy folder input sources and output sinks may read from or
* write to. Empty (the default) disables folder access entirely, so a policy can never be
* pointed at an arbitrary server path. Stirling's own config directory is always
* off-limits, and folder access is always disabled in SaaS mode regardless of this list.
* write to. Empty (the default) disables folder access except to implicitly defined
* folders, such as server storage folders (if enabled) and the pipeline watched folders.
* Stirling's own config directory is always off-limits, and folder access is always
* disabled in SaaS mode regardless of this list.
*/
private List<String> allowedFolderRoots = new java.util.ArrayList<>();
@@ -249,6 +250,44 @@ public class ApplicationProperties {
* in-network object store.
*/
private boolean allowPrivateS3Endpoints = false;
/**
* Whether a network source's host (SFTP, FTP, or SMB) may resolve to a loopback,
* link-local, or private address. Off by default so a connection cannot be pointed at
* internal services; enable for an on-network file server (e.g. an internal SFTP drop or a
* Samba share).
*/
private boolean allowPrivateNetworkSources = false;
/**
* Hostnames (exact, case-insensitive) that a network source may use even when they resolve
* to a private or local address and {@code allowPrivateNetworkSources} is off. Lets shared
* infra allow one named on-prem file server without opening every internal host.
*/
private List<String> allowedPrivateNetworkHosts = new java.util.ArrayList<>();
/**
* Whether an API/Purview/ConsignO integration's base URL may resolve to a loopback,
* link-local, or private address. Off by default: unlike S3 connections, any user may
* create one of these, so without this gate a user could point a connection at the cloud
* metadata address and have the server fetch it for them. Enable only when integrations
* genuinely live inside the network (e.g. an on-prem ConsignO or an internal API gateway).
*/
private boolean allowPrivateApiEndpoints = false;
/**
* Whether administrators may define their own API integrations - a free-form base URL,
* path, body and headers - as opposed to only using the built-in vendor presets (Purview,
* ConsignO, S3). On by default, and admin-only regardless: a custom integration can point
* the server at any host, so it is authoring power, not self-serve.
*
* <p>Turning this off stops new custom integrations being created or edited. Ones that
* already exist keep running, because a policy that silently stopped calling out would be a
* worse surprise than one that keeps working; disable the connection itself to stop it.
*/
private boolean allowCustomApiIntegrations = true;
private long webhookMaxBytes = 104857600L;
}
@Data
@@ -303,6 +342,102 @@ public class ApplicationProperties {
* explicitly requests it via {@code AiEngineClient.postWithTimeout}.
*/
private int longRunningTimeoutSeconds = 600;
/** Timeout (seconds) for the SSE stream held open by long-running orchestrator runs. */
private int streamTimeoutSeconds = 1800;
/**
* Whether the processor pushes settings-derived AI config to the engine on startup/save.
* Pin false for env-driven deployments (SaaS) to keep the engine env-controlled.
*/
private boolean pushConfigToEngine = true;
/** Model + provider selection, forwarded to the engine per-request. */
private Models models = new Models();
/** Retrieval-augmented-generation (RAG) knobs, forwarded to the engine per-request. */
private Rag rag = new Rag();
/** Request size / cost guardrails. */
private Limits limits = new Limits();
/** Per-capability on/off switches so an admin can disable individual AI tools. */
private Features features = new Features();
@Data
public static class Models {
/** Provider driving the model strings: 'anthropic', 'openai', 'ollama', or 'custom'. */
private String provider = "anthropic";
/** High-quality tier model name (without provider prefix), e.g. 'claude-haiku-4-5'. */
private String smartModel = "claude-haiku-4-5";
/** Cheap/fast tier model name (without provider prefix). */
private String fastModel = "claude-haiku-4-5";
private int smartMaxTokens = 8192;
private int fastMaxTokens = 2048;
/**
* API key for the selected provider (secret; masked). Empty means the engine uses its
* own env credential (e.g. ANTHROPIC_API_KEY).
*/
private String apiKey = "";
/**
* OpenAI-compatible base URL for 'ollama' / 'custom' providers (e.g.
* http://ollama:11434/v1). Ignored for anthropic/openai. SSRF-sensitive - admin only.
*/
private String baseUrl = "";
}
@Data
public static class Rag {
/**
* Embedding provider: 'voyageai', 'openai', 'ollama', or 'custom' (OpenAI-compatible).
*/
private String embeddingProvider = "voyageai";
/** Embedding model name (without provider prefix), e.g. 'voyage-4'. */
private String embeddingModel = "voyage-4";
/**
* Secret API key for the embedding provider; masked + env-overridable like
* models.apiKey.
*/
private String embeddingApiKey = "";
/**
* OpenAI-compatible base URL for 'ollama' / 'custom' embedding providers (e.g.
* http://ollama:11434/v1). Ignored for voyageai/openai. SSRF-sensitive - admin only.
*/
private String embeddingBaseUrl = "";
/** How many chunks retrieval returns per search. */
private int topK = 20;
/** Per-run cap on knowledge-search tool calls before the agent must answer. */
private int maxSearches = 5;
}
@Data
public static class Limits {
private int maxPages = 200;
private int maxCharacters = 200000;
/** Process-wide cap on concurrent model API calls (engine restart to apply). */
private int modelMaxConcurrency = 32;
}
@Data
public static class Features {
private boolean chat = true;
private boolean documentQuestions = true;
private boolean createPdf = true;
private boolean mathAuditor = true;
private boolean pdfComment = true;
private boolean classify = true;
}
}
/**
@@ -956,6 +1091,20 @@ public class ApplicationProperties {
private Quotas quotas = new Quotas();
private Sharing sharing = new Sharing();
private Signing signing = new Signing();
private Encryption encryption = new Encryption();
/**
* Encryption at rest for stored files (Pro/Enterprise). Enabling encrypts new writes;
* disabling later only stops encrypting new writes — existing encrypted files keep
* decrypting as long as the key material is present. The master key is resolved like the
* credential key: {@code stirling.security.fileEncryptionKey} property, {@code
* STIRLING_FILE_ENCRYPTION_KEY} env var, or an auto-generated {@code file-encryption.key}
* in the config directory.
*/
@Data
public static class Encryption {
private boolean enabled = false;
}
@Data
public static class Local {
@@ -4,6 +4,8 @@ import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -47,6 +49,9 @@ public class JobResult {
*/
private final List<String> notes = new CopyOnWriteArrayList<>();
/** Key/value metadata that survives the write-through into the shared job store. */
private final Map<String, String> metadata = new ConcurrentHashMap<>();
/**
* Create a new JobResult with the given job ID
*
@@ -161,4 +166,16 @@ public class JobResult {
public List<String> getNotes() {
return Collections.unmodifiableList(notes);
}
/** Attach a metadata value, e.g. a policy id so cluster peers can identify a policy run. */
public void putMetadata(String key, String value) {
if (key != null && value != null) {
this.metadata.put(key, value);
}
}
/** An unmodifiable view of this job's metadata. */
public Map<String, String> getMetadata() {
return Collections.unmodifiableMap(metadata);
}
}
@@ -0,0 +1,24 @@
package stirling.software.common.model.tool;
/**
* How many files an endpoint consumes and produces (Single/Multiple In, Single/Multiple Out).
*
* <p>This axis carries ZIP-as-transport: a multi-output endpoint returns its results zipped and the
* caller unpacks them, so {@code split-pages} is {@code produces = PDF, arity = SIMO} rather than
* naming a ZIP-of-PDF format. An endpoint whose deliverable really is an archive declares {@link
* ToolFormat#ZIP} with a single-output arity and stays packed.
*/
public enum ToolArity {
SISO,
SIMO,
MISO,
MIMO;
public boolean isMultiInput() {
return this == MISO || this == MIMO;
}
public boolean isMultiOutput() {
return this == SIMO || this == MIMO;
}
}
@@ -0,0 +1,47 @@
package stirling.software.common.model.tool;
/**
* One problem found while checking a chain, against the step that cannot run. {@code code} is
* stable so the frontend can pick its own wording; {@code message} is an English fallback.
*/
public record ToolDiagnostic(int stepIndex, Severity severity, String code, String message) {
public enum Severity {
/** The chain cannot run as configured. Only this should block a save. */
ERROR,
/** May not run, depending on configuration or file content. */
WARN,
/** Worth knowing but not a problem, such as a step running once per file. */
INFO
}
/** The step declares no {@link ToolIO}, so nothing past it can be checked. */
public static final String UNDECLARED = "undeclared-operation";
/** The previous step's output is not a format this step accepts. */
public static final String FORMAT_MISMATCH = "format-mismatch";
/** The previous step's output depends on a parameter that is not set yet. */
public static final String OUTPUT_UNCERTAIN = "output-uncertain";
/** The pipeline's input files are not a format the first step accepts. */
public static final String SOURCE_MISMATCH = "source-mismatch";
/** The previous step emits several files and this one runs once per file. */
public static final String FAN_OUT = "fan-out";
/** The previous step emits several files and this one consumes them in a single call. */
public static final String FAN_IN = "fan-in";
public static ToolDiagnostic error(int stepIndex, String code, String message) {
return new ToolDiagnostic(stepIndex, Severity.ERROR, code, message);
}
public static ToolDiagnostic warn(int stepIndex, String code, String message) {
return new ToolDiagnostic(stepIndex, Severity.WARN, code, message);
}
public static ToolDiagnostic info(int stepIndex, String code, String message) {
return new ToolDiagnostic(stepIndex, Severity.INFO, code, message);
}
}
@@ -0,0 +1,62 @@
package stirling.software.common.model.tool;
import java.util.List;
import lombok.Getter;
/**
* The kind of file a tool endpoint consumes or produces.
*
* <p>Encryption is its own format rather than a separate attribute, so the endpoints accepting only
* {@link #PDF} reject an encrypted one without declaring anything.
*
* <p>Extensions are a lossy projection used for run-time file checks: {@link #PDF} and {@link
* #PDF_ENCRYPTED} share {@code pdf}, because a filename cannot tell you whether a PDF is encrypted.
*/
@Getter
public enum ToolFormat {
PDF("pdf"),
PDF_ENCRYPTED("pdf"),
// Vector formats are folded in: the extension set has always included svg/eps, and splitting
// them out would make chains that run fine today report as broken.
IMAGE("png", "jpg", "jpeg", "gif", "webp", "bmp", "tif", "tiff", "svg", "psd", "ai", "eps"),
/**
* An archive that is itself the deliverable. Multiple results use {@link ToolArity} instead.
*/
ZIP("zip", "rar", "7z", "tar", "gz", "bz2", "xz", "lz", "lzma", "z"),
WORD("doc", "docx", "odt", "rtf"),
PPT("ppt", "pptx", "odp"),
EXCEL("xls", "xlsx", "ods"),
CSV("csv"),
HTML("html", "htm", "xhtml"),
XML("xml", "xsd", "xsl"),
JSON("json"),
TEXT("txt", "text", "md", "markdown"),
MARKDOWN("md", "markdown"),
JAVASCRIPT("js", "jsx"),
EBOOK("epub", "mobi", "azw3", "fb2", "txt", "docx"),
EMAIL("eml", "msg"),
POSTSCRIPT("ps", "eps"),
PCL("pcl", "pxl"),
XPS("xps", "oxps"),
VIDEO("mp4", "webm", "avi", "mov", "mkv"),
CBZ("cbz"),
CBR("cbr"),
/** Never reported as incompatible. */
ANY(),
/** A report or a status rather than a document. */
NONE();
private final List<String> extensions;
ToolFormat(String... extensions) {
this.extensions = List.of(extensions);
}
}
@@ -0,0 +1,30 @@
package stirling.software.common.model.tool;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* What a tool endpoint consumes and produces, so a chain of steps can be checked before it runs.
*
* <p>The single source of truth: read off the handler method by {@code ToolIORegistry}, published
* into the OpenAPI spec as {@code x-stirling-io}, and generated from there into the frontend and
* the AI engine.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ToolIO {
/** Defaulting to a plain PDF is what makes an ordinary endpoint reject an encrypted one. */
ToolFormat[] accepts() default {ToolFormat.PDF};
ToolFormat produces();
ToolArity arity() default ToolArity.SISO;
/** Overrides for an output that depends on a parameter; first match wins. */
ToolIOCase[] cases() default {};
}
@@ -0,0 +1,22 @@
package stirling.software.common.model.tool;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* An output that applies when every condition in {@link #when()} holds.
*
* <p>Conditions are ANDed because the interesting branches turn on more than one parameter: Add
* Password only leaves the document unencrypted when both passwords are absent.
*/
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ToolIOCase {
ToolIOWhen[] when();
ToolFormat produces();
ToolArity arity();
}
@@ -0,0 +1,19 @@
package stirling.software.common.model.tool;
import java.util.Map;
import java.util.Optional;
/**
* Supplies the {@link ToolIO} declaration for an endpoint path. An interface so a chain can be
* checked against a fixed set of declarations without standing up an application context.
*/
@FunctionalInterface
public interface ToolIOSource {
Optional<ToolIOSpec> find(String operationPath);
static ToolIOSource of(Map<String, ToolIOSpec> specs) {
Map<String, ToolIOSpec> copy = Map.copyOf(specs);
return path -> Optional.ofNullable(copy.get(path));
}
}
@@ -0,0 +1,108 @@
package stirling.software.common.model.tool;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
/** The runtime form of a {@link ToolIO} declaration, read off a handler method once at startup. */
public record ToolIOSpec(
Set<ToolFormat> accepts, ToolFormat produces, ToolArity arity, List<Case> cases) {
public record When(String param, List<String> matches) {
boolean holdsFor(Object value) {
String normalised = normalise(value);
return matches.stream().anyMatch(match -> normalise(match).equals(normalised));
}
}
/**
* Both sides of a condition are normalised at comparison, not at construction: the declaration
* reaches the frontend and the engine as published data, and normalising only one side there
* would silently disagree with this one.
*/
public static String normalise(Object value) {
return value == null ? "" : String.valueOf(value).trim().toLowerCase(Locale.ROOT);
}
public record Case(List<When> when, ToolFormat produces, ToolArity arity) {
public Case {
when = List.copyOf(when);
}
}
/** {@code certain} is false when a {@link Case} keys on a parameter whose value is unknown. */
public record Output(ToolFormat format, ToolArity arity, boolean certain) {}
public ToolIOSpec {
accepts = Set.copyOf(accepts);
cases = List.copyOf(cases);
}
public static ToolIOSpec from(ToolIO annotation) {
return new ToolIOSpec(
new LinkedHashSet<>(Arrays.asList(annotation.accepts())),
annotation.produces(),
annotation.arity(),
Arrays.stream(annotation.cases()).map(ToolIOSpec::toCase).toList());
}
private static Case toCase(ToolIOCase rule) {
List<When> when = Arrays.stream(rule.when()).map(ToolIOSpec::toWhen).toList();
return new Case(when, rule.produces(), rule.arity());
}
private static When toWhen(ToolIOWhen condition) {
return new When(condition.param(), List.of(condition.matches()));
}
/**
* First matching {@link Case} wins. If none match but one reads a parameter we cannot see, the
* declared output comes back uncertain: a value we never saw might have picked another branch.
*
* @param parameters the step's configured parameters, or null when not known
*/
public Output resolveOutput(Map<String, Object> parameters) {
boolean sawUnknownParam = false;
for (Case rule : cases) {
boolean allHold = true;
for (When condition : rule.when()) {
if (parameters == null || !parameters.containsKey(condition.param())) {
sawUnknownParam = true;
allHold = false;
continue;
}
allHold &= condition.holdsFor(parameters.get(condition.param()));
}
if (allHold) {
return new Output(rule.produces(), rule.arity(), true);
}
}
return new Output(produces, arity, !sawUnknownParam);
}
public Output resolveOutput() {
return resolveOutput(null);
}
public boolean acceptsFormat(ToolFormat format) {
return format == ToolFormat.ANY
|| accepts.contains(ToolFormat.ANY)
|| accepts.contains(format);
}
/** For run-time file checks. Empty means anything is accepted. */
public List<String> acceptedExtensions() {
if (accepts.contains(ToolFormat.ANY)) {
return List.of();
}
return accepts.stream()
.flatMap(format -> format.getExtensions().stream())
.distinct()
.toList();
}
}
@@ -0,0 +1,18 @@
package stirling.software.common.model.tool;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** One condition on a request parameter, guarding a {@link ToolIOCase}. */
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ToolIOWhen {
String param();
/**
* Compared as strings, case-insensitively. An empty string matches an absent or blank value.
*/
String[] matches();
}
@@ -983,7 +983,7 @@ public class PdfMarkdownConverter {
ordered.sort(Comparator.comparingDouble((Line l) -> l.y).reversed());
StringBuilder sb = new StringBuilder();
for (Line l : ordered) {
if (sb.length() > 0) {
if (!sb.isEmpty()) {
sb.append(' ');
}
sb.append(l.text);
@@ -46,9 +46,14 @@ public class InternalApiClient {
// The second alternation carves out `/api/v1/ai/tools/*` specifically — AI tools are
// dispatchable, but the broader `/api/v1/ai/` surface (orchestrate, health, etc.) is
// intentionally NOT permitted to avoid plan steps re-entering the orchestrator.
//
// `/api/v1/integration/*` holds third-party steps (external API call, Purview labelling,
// ConsignO). They reach outside the JVM, so the namespace is deliberately kept to tools that
// dereference an admin-owned connection rather than a caller-supplied host — see
// ApiConnectionResolver.
private static final Pattern ALLOWED_ENDPOINT_PATH =
Pattern.compile(
"^/api/v1/(general|misc|security|convert|filter)(/[A-Za-z0-9_-]+)+$"
"^/api/v1/(general|misc|security|convert|filter|integration)(/[A-Za-z0-9_-]+)+$"
+ "|^/api/v1/ai/tools(/[A-Za-z0-9_-]+)+$");
/**
@@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import jakarta.annotation.PreDestroy;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
@@ -63,6 +64,21 @@ public class JobExecutorService {
"Job executor configured with effective timeout of {} ms", this.effectiveTimeoutMs);
}
/** Stop the service-owned executor when the application context is closed or restarted. */
@PreDestroy
public void shutdown() {
log.debug("Shutting down job executor");
executor.shutdown();
try {
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
executor.shutdownNow();
}
}
public ResponseEntity<?> runJobGeneric(boolean async, Supplier<Object> work) {
return runJobGeneric(async, work, -1);
}
@@ -225,19 +225,21 @@ public class MobileScannerService {
Path sessionDir = getSafeSessionDirectory(sessionId);
if (Files.exists(sessionDir)) {
// Delete all files in session directory
Files.walk(sessionDir)
.sorted(
(a, b) ->
-a.compareTo(b)) // Reverse order to delete files before
// directory
.forEach(
path -> {
try {
Files.deleteIfExists(path);
} catch (IOException e) {
log.warn("Failed to delete file: {}", path, e);
}
});
try (var paths = Files.walk(sessionDir)) {
paths.sorted(
(a, b) ->
-a.compareTo(
b)) // Reverse order to delete files before
// directory
.forEach(
path -> {
try {
Files.deleteIfExists(path);
} catch (IOException e) {
log.warn("Failed to delete file: {}", path, e);
}
});
}
}
log.info("Deleted session: {}", sessionId);
} catch (IllegalArgumentException e) {
@@ -48,6 +48,10 @@ public class TaskManager {
@Value("${stirling.jobResultExpiryMinutes:30}")
private int jobResultExpiryMinutes = 30;
/** Maximum age of a task that never reached a terminal state. */
@Value("${stirling.job.pendingExpiryMinutes:1440}")
private int pendingJobExpiryMinutes = 1440;
private final FileStorage fileStorage;
private final JobStore jobStore;
private final ClusterBackplane clusterBackplane;
@@ -230,6 +234,18 @@ public class TaskManager {
return false;
}
/** Attach metadata to a job and write it through to the shared store for cluster peers. */
public boolean putMetadata(String jobId, String key, String value) {
JobResult jobResult = jobResults.get(jobId);
if (jobResult != null) {
jobResult.putMetadata(key, value);
writeThrough(jobId, jobResult);
return true;
}
log.warn("Attempted to set metadata on non-existent job ID: {}", jobId);
return false;
}
/**
* Get statistics about all jobs in the system
*
@@ -320,19 +336,32 @@ public class TaskManager {
}
LocalDateTime expiryThreshold =
LocalDateTime.now().minus(jobResultExpiryMinutes, ChronoUnit.MINUTES);
LocalDateTime pendingExpiryThreshold =
LocalDateTime.now().minus(pendingJobExpiryMinutes, ChronoUnit.MINUTES);
int removedCount = 0;
try {
for (Map.Entry<String, JobResult> entry : jobResults.entrySet()) {
JobResult result = entry.getValue();
// Remove completed jobs that are older than the expiry threshold
if (result.isComplete()
&& result.getCompletedAt() != null
&& result.getCompletedAt().isBefore(expiryThreshold)) {
boolean expiredCompletedJob =
result.isComplete()
&& result.getCompletedAt() != null
&& result.getCompletedAt().isBefore(expiryThreshold);
boolean abandonedPendingJob =
!result.isComplete()
&& result.getCreatedAt() != null
&& result.getCreatedAt().isBefore(pendingExpiryThreshold);
// Remove old terminal results and abandoned pending jobs. Without the second
// branch, a client that starts a task and never completes it keeps its result in
// memory forever.
if (expiredCompletedJob || abandonedPendingJob) {
// Clean up file results
cleanupJobFiles(result, entry.getKey());
if (expiredCompletedJob) {
cleanupJobFiles(result, entry.getKey());
}
// Remove the job result
jobResults.remove(entry.getKey());
@@ -378,7 +407,7 @@ public class TaskManager {
fileIds.add(rf.getFileId());
}
}
Map<String, String> meta = new HashMap<>();
Map<String, String> meta = new HashMap<>(result.getMetadata());
if (result.getNotes() != null && !result.getNotes().isEmpty()) {
meta.put("notesCount", Integer.toString(result.getNotes().size()));
}
@@ -0,0 +1,168 @@
package stirling.software.common.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import stirling.software.common.model.tool.ToolDiagnostic;
import stirling.software.common.model.tool.ToolFormat;
import stirling.software.common.model.tool.ToolIOSource;
import stirling.software.common.model.tool.ToolIOSpec;
/**
* Whether a chain of steps can run: what each produces against what the next accepts.
*
* <p>The frontend and the AI engine implement the same rules against their generated copies, so a
* chain can be checked without a round trip. {@code testing/tool-io-cases.json} pins all three to
* the same answers.
*/
@Service
@RequiredArgsConstructor
public class ToolChainValidator {
/** {@code parameters} may be null; only used to resolve an output that depends on one. */
public record Step(String operation, Map<String, Object> parameters) {}
private final ToolIOSource toolIO;
public List<ToolDiagnostic> validate(List<Step> steps) {
return validate(steps, null);
}
/**
* @param sourceFormat the format entering step one, or null when unknown
*/
public List<ToolDiagnostic> validate(List<Step> steps, ToolFormat sourceFormat) {
List<ToolDiagnostic> diagnostics = new ArrayList<>();
ToolIOSpec.Output carried = null;
for (int i = 0; i < steps.size(); i++) {
Step step = steps.get(i);
Optional<ToolIOSpec> found = toolIO.find(step.operation());
if (found.isEmpty()) {
diagnostics.add(
ToolDiagnostic.warn(
i,
ToolDiagnostic.UNDECLARED,
"Step "
+ step.operation()
+ " does not declare what it accepts or produces, so the"
+ " rest of the chain cannot be checked."));
// Nothing is known past an undeclared step.
carried = null;
continue;
}
ToolIOSpec spec = found.get();
// Only the first step is handed the pipeline's input. Every later step is handed the
// previous step's output, which is simply unknown once an undeclared step intervened -
// checking it against the input again would judge it on a format it never receives.
if (i == 0) {
checkSource(diagnostics, i, step, spec, sourceFormat);
} else if (carried != null) {
checkTransition(diagnostics, i, step, spec, carried);
}
carried = spec.resolveOutput(step.parameters());
}
return diagnostics;
}
public static boolean hasErrors(List<ToolDiagnostic> diagnostics) {
return diagnostics.stream().anyMatch(d -> d.severity() == ToolDiagnostic.Severity.ERROR);
}
private static void checkSource(
List<ToolDiagnostic> diagnostics,
int index,
Step step,
ToolIOSpec spec,
ToolFormat sourceFormat) {
if (sourceFormat == null || spec.acceptsFormat(sourceFormat)) {
return;
}
diagnostics.add(
ToolDiagnostic.error(
index,
ToolDiagnostic.SOURCE_MISMATCH,
"Step "
+ step.operation()
+ " accepts "
+ describe(spec)
+ " but the pipeline's input is "
+ sourceFormat
+ "."));
}
private static void checkTransition(
List<ToolDiagnostic> diagnostics,
int index,
Step step,
ToolIOSpec spec,
ToolIOSpec.Output previous) {
if (previous.format() == ToolFormat.NONE) {
diagnostics.add(
ToolDiagnostic.error(
index,
ToolDiagnostic.FORMAT_MISMATCH,
"The previous step returns a report rather than a file, so "
+ step.operation()
+ " has nothing to run on."));
return;
}
if (!spec.acceptsFormat(previous.format())) {
String message =
"Step "
+ step.operation()
+ " accepts "
+ describe(spec)
+ " but the previous step produces "
+ previous.format()
+ ".";
diagnostics.add(
previous.certain()
? ToolDiagnostic.error(index, ToolDiagnostic.FORMAT_MISMATCH, message)
// Unresolved output: may yet be fine once the step is configured.
: ToolDiagnostic.warn(index, ToolDiagnostic.OUTPUT_UNCERTAIN, message));
return;
}
if (!previous.certain()) {
diagnostics.add(
ToolDiagnostic.warn(
index,
ToolDiagnostic.OUTPUT_UNCERTAIN,
"The previous step's output depends on how it is configured, so this"
+ " step may not be able to run."));
return;
}
if (previous.arity().isMultiOutput()) {
diagnostics.add(
spec.arity().isMultiInput()
? ToolDiagnostic.info(
index,
ToolDiagnostic.FAN_IN,
"This step combines every file the previous step produced.")
: ToolDiagnostic.info(
index,
ToolDiagnostic.FAN_OUT,
"This step runs once for each file the previous step"
+ " produced."));
}
}
private static String describe(ToolIOSpec spec) {
return spec.accepts().stream()
.map(Enum::name)
.sorted()
.reduce((a, b) -> a + " or " + b)
.orElse("nothing");
}
}
@@ -0,0 +1,127 @@
package stirling.software.common.service;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import lombok.extern.slf4j.Slf4j;
import stirling.software.common.model.tool.ToolIO;
import stirling.software.common.model.tool.ToolIOSource;
import stirling.software.common.model.tool.ToolIOSpec;
/**
* Reads every {@link ToolIO} declaration off its handler method at startup and serves it by
* endpoint path. Replaces parsing the same information out of the description prose, which meant
* fetching our own {@code /v1/api-docs} over HTTP first.
*/
@Slf4j
@Service
public class ToolIORegistry implements ToolMetadataService, ToolIOSource {
private final ApplicationContext applicationContext;
// Written on the startup thread, read on request threads. Spring's lifecycle establishes
// happens-before, so no volatile (same as AiEngineEndpointResolver).
private Map<String, ToolIOSpec> specsByPath = Map.of();
// Keep this the only constructor: with two, Spring falls back to a no-arg one that isn't here.
public ToolIORegistry(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
/** A registry over known declarations rather than ones discovered from the context. */
static ToolIORegistry forSpecs(Map<String, ToolIOSpec> specs) {
ToolIORegistry registry = new ToolIORegistry(null);
registry.specsByPath = Map.copyOf(specs);
return registry;
}
@EventListener(ContextRefreshedEvent.class)
public void discoverToolIO() {
Map<String, ToolIOSpec> discovered = new TreeMap<>();
for (RequestMappingHandlerMapping mapping :
applicationContext.getBeansOfType(RequestMappingHandlerMapping.class).values()) {
mapping.getHandlerMethods()
.forEach((info, handler) -> register(discovered, info, handler));
}
specsByPath = Map.copyOf(discovered);
log.debug("Discovered {} endpoints declaring @ToolIO", specsByPath.size());
}
private static void register(
Map<String, ToolIOSpec> target, RequestMappingInfo info, HandlerMethod handler) {
ToolIO annotation = handler.getMethodAnnotation(ToolIO.class);
if (annotation == null) {
return;
}
ToolIOSpec spec = ToolIOSpec.from(annotation);
for (String pattern : extractPatterns(info)) {
target.put(pattern, spec);
}
}
@Override
public Optional<ToolIOSpec> find(String operationPath) {
return Optional.ofNullable(specsByPath.get(operationPath));
}
@Override
public boolean isMultiInput(String operationPath) {
return find(operationPath).map(spec -> spec.arity().isMultiInput()).orElse(false);
}
@Override
public List<String> getExtensionTypes(boolean output, String operationPath) {
Optional<ToolIOSpec> spec = find(operationPath);
if (spec.isEmpty()) {
return null;
}
List<String> extensions =
output
? spec.get().resolveOutput().format().getExtensions()
: spec.get().acceptedExtensions();
// Callers express "no restriction" as null.
return extensions.isEmpty() ? null : extensions;
}
@Override
public boolean shouldUnpackZipResponse(String operationPath) {
// Multi-output zips purely as transport. A single-output ZIP is the deliverable
// (extract-attachments) and stays packed.
return find(operationPath)
.map(spec -> spec.resolveOutput().arity().isMultiOutput())
.orElse(false);
}
private static Set<String> extractPatterns(RequestMappingInfo info) {
try {
Method getDirectPaths = info.getClass().getMethod("getDirectPaths");
Object result = getDirectPaths.invoke(info);
if (result instanceof Set<?> set) {
Set<String> patterns = new HashSet<>();
for (Object value : set) {
if (value instanceof String s) {
patterns.add(s);
}
}
return patterns;
}
} catch (Exception e) {
log.trace("getDirectPaths unavailable on RequestMappingInfo", e);
}
return Set.of();
}
}
@@ -17,12 +17,12 @@ public interface ToolMetadataService {
List<String> getExtensionTypes(boolean output, String operationPath);
/**
* Returns true when the endpoint's ZIP response is a transport for multiple typed results and
* should be unpacked: multi-output endpoints (Type:SIMO / Type:MIMO) and wrapper declarations
* such as {@code Output:ZIP-PDF} or {@code Output:IMAGE/ZIP}.
* Returns true when the endpoint's ZIP response is a transport for several results and should
* be unpacked, which is exactly the multi-output endpoints (a {@code SIMO} or {@code MIMO}
* arity).
*
* <p>Returns false for a bare {@code Output:ZIP} (e.g. {@code get-attachments}), where the
* archive itself is the deliverable and should be kept packed.
* <p>Returns false for an endpoint whose declared output is an archive in its own right (for
* example {@code extract-attachments}), where unpacking would discard the deliverable.
*/
boolean shouldUnpackZipResponse(String operationPath);
}
@@ -941,7 +941,7 @@ public class GeneralUtils {
}
// If no MAC address found, use hostname as fallback
if (sb.length() == 0) {
if (sb.isEmpty()) {
String hostname = InetAddress.getLocalHost().getHostName();
sb.append(hostname != null ? hostname : "unknown-host");
log.warn("No MAC address found, using hostname for fingerprint generation");
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.regex.Pattern;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
@@ -28,6 +29,8 @@ import lombok.extern.slf4j.Slf4j;
@Component
public class PdfTextLocator {
private static final Pattern NON_ALPHANUMERIC_PATTERN = Pattern.compile("[^A-Za-z0-9]");
/** One found line of text with its user-space bounding box. */
public record MatchedBox(float x, float y, float width, float height) {}
@@ -82,7 +85,7 @@ public class PdfTextLocator {
/** Strip everything non-alphanumeric and lowercase for tolerant matching. */
private static String normalize(String s) {
return s.replaceAll("[^A-Za-z0-9]", "").toLowerCase(Locale.ROOT);
return NON_ALPHANUMERIC_PATTERN.matcher(s).replaceAll("").toLowerCase(Locale.ROOT);
}
private static final class CapturedLine {
@@ -1,17 +1,22 @@
package stirling.software.common.util;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.UncheckedExecutionException;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public final class RegexPatternUtils {
private static final RegexPatternUtils INSTANCE = new RegexPatternUtils();
private final ConcurrentHashMap<PatternKey, Pattern> patternCache = new ConcurrentHashMap<>();
private static final long MAX_CACHED_PATTERNS = 512;
private final Cache<PatternKey, Pattern> patternCache =
CacheBuilder.newBuilder().maximumSize(MAX_CACHED_PATTERNS).build();
private static final String WHITESPACE_REGEX = "\\s++";
private static final String EXTENSION_REGEX = "\\.(?:[^.]*+)?$";
@@ -51,7 +56,7 @@ public final class RegexPatternUtils {
throw new IllegalArgumentException("Regex pattern cannot be null");
}
return patternCache.computeIfAbsent(new PatternKey(regex, 0), this::compilePattern);
return getOrCompile(new PatternKey(regex, 0));
}
/**
@@ -77,7 +82,7 @@ public final class RegexPatternUtils {
throw new IllegalArgumentException("Regex pattern cannot be null");
}
return patternCache.computeIfAbsent(new PatternKey(regex, flags), this::compilePattern);
return getOrCompile(new PatternKey(regex, flags));
}
/**
@@ -98,7 +103,7 @@ public final class RegexPatternUtils {
* @return true if pattern is cached, false otherwise
*/
public boolean isCached(String regex, int flags) {
return regex != null && patternCache.containsKey(new PatternKey(regex, flags));
return regex != null && patternCache.getIfPresent(new PatternKey(regex, flags)) != null;
}
/**
@@ -107,7 +112,7 @@ public final class RegexPatternUtils {
* @return number of patterns currently cached
*/
public int getCacheSize() {
return patternCache.size();
return (int) patternCache.size();
}
/**
@@ -115,7 +120,7 @@ public final class RegexPatternUtils {
* useful for testing or memory cleanup in long-running applications.
*/
public void clearCache() {
patternCache.clear();
patternCache.invalidateAll();
log.debug("Regex pattern cache cleared");
}
@@ -141,13 +146,32 @@ public final class RegexPatternUtils {
return false;
}
PatternKey key = new PatternKey(regex, flags);
boolean removed = patternCache.remove(key) != null;
boolean removed = patternCache.getIfPresent(key) != null;
patternCache.invalidate(key);
if (removed) {
log.debug("Removed regex pattern from cache: {} (flags: {})", regex, flags);
}
return removed;
}
private Pattern getOrCompile(PatternKey key) {
try {
return patternCache.get(key, () -> compilePattern(key));
} catch (UncheckedExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof PatternSyntaxException patternSyntaxException) {
throw patternSyntaxException;
}
throw e;
} catch (java.util.concurrent.ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof PatternSyntaxException patternSyntaxException) {
throw patternSyntaxException;
}
throw new IllegalStateException("Failed to compile regex pattern", cause);
}
}
/**
* Internal method to compile a pattern and handle errors consistently.
*
@@ -537,10 +561,6 @@ public final class RegexPatternUtils {
getPattern("[/\\\\?%*:|\"<>]"); // Unsafe filename characters
getPattern("[^a-zA-Z0-9 ]"); // Input sanitization
getPattern("[^a-zA-Z0-9]"); // Filename sanitization
// API doc patterns
getPattern("Output:\\s*(\\w+)");
getPattern("Input:\\s*(\\w+)");
getPattern("Type:\\s*(\\w+)");
log.debug("Pre-compiled {} common regex patterns", patternCache.size());
}
@@ -550,23 +570,6 @@ public final class RegexPatternUtils {
"^(?=.{1,320}$)(?=.{1,64}@)[A-Za-z0-9](?:[A-Za-z0-9_.+-]*[A-Za-z0-9])?@[^-][A-Za-z0-9-]+(?:\\.[A-Za-z0-9-]+)*(?:\\.[A-Za-z]{2,})$");
}
/* Pattern for matching Output:<TYPE> in API descriptions */
public Pattern getApiDocOutputTypePattern() {
return getPattern("Output:\\s*(\\w+)");
}
/* Pattern for matching Input:<TYPE> in API descriptions */
public Pattern getApiDocInputTypePattern() {
return getPattern("Input:\\s*(\\w+)");
}
/**
* Pattern for matching Type:<CODE> in API descriptions
*/
public Pattern getApiDocTypePattern() {
return getPattern("Type:\\s*(\\w+)");
}
/* Pattern for validating file extensions (2-4 alphanumeric, case-insensitive) */
public Pattern getFileExtensionValidationPattern() {
return getPattern("^[a-zA-Z0-9]{2,4}$", Pattern.CASE_INSENSITIVE);
@@ -1,7 +1,11 @@
package stirling.software.common.util;
import java.util.regex.Pattern;
public class RequestUriUtils {
private static final Pattern SHARE_LINK_PATTERN = Pattern.compile("^/share/[^/]+/?$");
public static boolean isStaticResource(String requestURI) {
return isStaticResource("", requestURI);
}
@@ -198,11 +202,12 @@ public class RequestUriUtils {
|| trimmedUri.startsWith("/readiness")
|| trimmedUri.startsWith(
"/api/v1/mobile-scanner/") // Mobile scanner endpoints (no auth)
|| trimmedUri.startsWith("/api/v1/webhooks/")
|| trimmedUri.startsWith("/v1/api-docs")
// Workflow participant endpoints - access controlled by share tokens, not login
|| trimmedUri.startsWith("/api/v1/workflow/participant/")
// Share-link SPA bootstrap; data APIs remain protected
|| trimmedUri.matches("^/share/[^/]+/?$");
|| SHARE_LINK_PATTERN.matcher(trimmedUri).matches();
}
private static String stripContextPath(String contextPath, String requestURI) {
@@ -154,7 +154,7 @@ class PdfMarkdownConverterTest {
|| isTableSeparatorRow(line)) {
continue;
}
if (sb.length() > 0) {
if (!sb.isEmpty()) {
sb.append('\n');
}
sb.append(line);

Some files were not shown because too many files have changed in this diff Show More