Commit Graph
5909 Commits
Author SHA1 Message Date
Balázs Szücs 190994262d fix(viewer): pass active document context to selection bridge and harden text selection tests 2026-08-27 22:56:53 +02:00
Ludy be13028209 chore(logging): enable gzipped log rotation and adjust test logging (#7648) 2026-08-27 18:41:40 +01:00
Andrei BlajandAndrei Blaj d4b1862654 feat(ocr): add rotatePages option for automatic page orientation correction (#6697)
Co-authored-by: Andrei Blaj <andrei@atta.systems>
Signed-off-by: Andrei Blaj <andrei@atta.systems>
2026-08-27 18:40:26 +01:00
jayakrishnaandJames Brunton 51835a7b5e fix: clean up Add Stamp image preview blob URLs (#6779)
Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-08-27 18:34:43 +01:00
briosandCopilot Autofix powered by AI 97c0ccf582 refactor(deps): optimize dependency footprints, and add lazy initialization with platform-specific JPDFium bundling (#7620)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-27 18:31:54 +01:00
Ludy 4e46ba3b5a chore: prevent duplicate Dependabot Gradle PRs (#7657)
## Description of Changes

- Removed overlapping Gradle subdirectory entries from
.github/dependabot.yml.
- Dependabot now monitors the root Gradle project through /.
- Prevents duplicate pull requests for dependencies declared in Gradle
subprojects.

Closes: Not applicable

---

## Checklist

### General

- [ ] I have read the Contribution Guidelines
- [ ] I have read the Stirling-PDF Developer Guide (if applicable)
- [x] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant documentation (if applicable)
- [ ] I have read the translation tag documentation (for new translation
tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos are attached

### Testing (if applicable)

- [ ] I have tested my changes locally
2026-08-27 17:16:24 +00:00
Ludy cbe3ef8f69 fix: validate frontend dependency installation (#7625)
# Description of Changes

The current check only verifies the existence of the `node_modules`
directory. After an incomplete or corrupted installation, this can lead
to the task being incorrectly marked as complete.

`npm ls --depth=0` instead checks whether the direct frontend
dependencies are actually installed and consistent. This reliably
detects and automatically repairs corrupted installations.

---

## 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-27 16:59:58 +00:00
EthanHealy01 5b5e922069 Make the upgrade banner neutral instead of gradient purple (#7696)
## What

The `promo` banner tone was a full-bleed `indigo-500 → purple-500`
gradient with white text and a black drop-shadow on the CTA. It was the
only saturated fill in the app, and against the warm neutral palette it
read as a foreign object above the workbench.

The bar is now app chrome:

| | Before | After |
|---|---|---|
| Background | 135° indigo→purple gradient | `--c-bg-raised` |
| Border | `transparent` | `--c-border-subtle` hairline |
| Icon | white glyph, no container | neutral glyph in a
`--c-surface-sunken` chip |
| Text | forced white | `--c-text` / `--c-text-muted` |
| CTA | `premium` accent (violet gradient) | `default` accent (same
primary button as the rest of the app) |


Before

<img width="1504" height="739" alt="Screenshot 2026-08-27 at 4 49 00 PM"
src="https://github.com/user-attachments/assets/a912d9e9-9590-4e1d-8202-1abb22a00f23"
/>


After

<img width="1061" height="665" alt="Screenshot 2026-08-27 at 4 48 30 PM"
src="https://github.com/user-attachments/assets/3be14aec-ccfe-4448-93b3-339a57be4937"
/>


Only caller is the friendly variant of `UpgradeBanner` (self-hosted,
under the free-tier user limit).

## Notes

- **No new theme tokens.** Every value is an existing `--c-*` semantic
token, so light and dark both follow automatically with no per-theme
overrides.
- The `premium` accent itself is untouched, so the upgrade CTAs in
`OfflineActivationCard` and `PairingPanel` are unaffected.
- `--c-hue-indigo` / `--c-hue-purple` are still used by
`SaaSOnboardingSlides`, `PaygFree` and `UpgradeModal`, so no tokens are
orphaned.
- Deleted comments describe rules that no longer exist (the gradient,
the white-on-gradient text overrides, the CTA shadow). No new comments
added.

## Verification

- `task frontend:check:all` passes (typecheck, oxlint, all four theme
linters, stylelint, format, tests, build, storybook build).
- `task frontend:storybook:a11y:changed` passes light and dark: 7
AppBanner stories, 0 violations. Both a11y baselines are empty, so this
is zero known violations rather than a baselined pass.
- Checked in Storybook under **Shared / AppBanner → All Top Bars**,
which renders every top bar the app can show side by side, in both
themes.
2026-08-27 15:57:15 +00:00
EthanHealy01 a215c30068 Add the missing en-US translations for classification labels (#7692)
Our classification labels were rendering their hardcoded English names
because the en-US locale file had no `classification` section at all, so
this adds the missing keys (labels and category names).

Also wires the category names through i18n, since those had no `t()`
call, and adds a test so a new label can't ship without its key.
2026-08-27 14:10:56 +00:00
Anthony Stirling 897c72e9d9 Fix tool panel scrolling so the action button stays reachable (#7688)
# Description of Changes

After ui rework all scrolling in all tool panels stopped working
This fixes this to allow tool panels to be scrollabe again




## What was wrong

PDF/UA is the only convert target whose settings panel overflows the
tool rail. Measured at 1920×1080: overflow was 0px for pdfa, pdfx, png,
docx, epub, and 158px for pdfua. Its action button sat at bottom: 1220
in a 1080px viewport — 140px below the fold — and the info alert was
clipped mid-sentence. The panel could be scrolled, but nothing said so
(Mantine's scrollbar auto-hides).

Normally the app would scroll the button into view for you. It didn't,
because both mechanisms built to do that were dead

## Cause:
Two separate mechanisms, both broken since the same commit (0a50e765b7,
frontend editor restructure, 2026-05-22):

1. ReviewToolStep - shared by all 47 tools. It looked for its scroll
container with:

stepRef.current.closest('[style*="overflow: auto"]')

Mantine's ScrollArea viewport sets inline overflow: scroll, not auto. I
measured it live - closest() returns null, and
document.querySelectorAll('[style*="overflow: auto"]') finds exactly 1
element anywhere in the page, and it isn't an ancestor of the panel. So
the lookup silently found nothing and the scrollTo never ran, for every
tool.

2. Convert.tsx - Convert only. It declared scrollContainerRef and a
scrollToBottom() wired to two useEffects, but the ref was never attached
to any element - createToolFlow() builds the JSX and no ref is passed
through. Always null, so both effects were no-ops.

Nothing else in the codebase has this pattern - I grepped for other
closest('[style*="overflow…"]') lookups and other
scrollToBottom/scrollContainerRef uses and both came back empty.



## The fix

createToolFlow.module.css (new) + createToolFlow.tsx:156 — the execute
button gets a position: sticky; bottom: 0 footer, the house pattern
already used by FormFill.module.css. Applied only when the review step
isn't visible, so it can never float over results. Sticky is inert when
content fits, so the other 46 tools are untouched.
ReviewToolStep.tsx:21 — real findScrollParent() walk replacing the
broken selector, scrolling by the minimum delta needed and only the
panel itself (never scrollIntoView(), which drags every ancestor). Also
added the missing clearTimeout cleanup.
Convert.tsx — deleted the dead ref and its two effects.

---

## 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-27 11:55:31 +00:00
ConnorYohandJames Brunton 732ef18ae5 feat(account-link): redirect-based connect handshake for self-hosted linking (#7494)
Links a self-hosted instance to a SaaS team over an ordinary redirect,
and leaves the admin's browser holding a Stirling session at the same
time.

## The problem

A self-hosted server needs a device credential bound to a SaaS team, and
the admin's Supabase JWT must never reach the instance backend. Three
things ruled out the obvious approaches:

- **A customer hostname can never be in Supabase's redirect
allow-list**, so the sign-in cannot happen on the instance's own origin.
That is why SSO and sign-up did not work for linking at all.
- **A device credential identifies a server, not a person.** Every
attended portal read (Usage, Billing, Documents, Infrastructure) goes
through `getPortalSaasToken()` and needs a *user* session, so a
credential-only link left all of them asking for a second sign-in.
- **The previous design relayed a JWT** from the browser into the
instance, which is the thing we wanted to avoid. That path is deleted
here.

## The solution

Redirect and nonce, modelled on desktop's
`authService.loginWithSelfHostedOAuth`: mint a nonce, hand the browser
off, accept only a callback carrying that nonce back. Desktop has the OS
route the reply; self-hosted has no OS hop, so our own approval page
performs it. That is the point — the human half happens on an origin we
control.

```
instance                     SaaS                        admin's browser
   |  POST connect/request     |                                |
   |  (name, callback, nonce,  |                                |
   |   claim-secret hash)      |                                |
   |-------------------------->|                                |
   |  <- requestId + authorizeUrl                               |
   |                           |      GET /link?request=...     |
   |                           |<-------------------------------|
   |                           |  sign in (SSO works here),     |
   |                           |  see ACCOUNT + ORIGIN, approve |
   |                           |------------------------------->|
   |                           |   302 callback#nonce+session    |
   |  POST connect/claim       |                                |
   |  (requestId, claim secret)|                                |
   |-------------------------->|                                |
   |  <- device credential     |                                |
```

Four properties carry the safety, and each is stated in the code because
each is easy to lose in a refactor:

- **The redirect target is never caller-supplied.** Validated once at
creation, then read back from the stored row, so nothing in the approval
page's URL can steer the token elsewhere.
- **Approval and minting are separate.** Approval records the team and
hands out nothing usable; the credential is minted only on claim,
authenticated by a secret that never entered a browser.
- **A re-authentication cannot move a server between teams.** The team
is pinned at creation from the credential only that instance holds, so
an approver from another team gets `WRONG_TEAM` instead of a rebind.
- **The approver has to confirm what they are binding.** The page shows
the address and the signed-in account, with a way to switch, and a
checkbox naming the address gates the approve button. The name the
server reports is deliberately not shown: the requester picks it on an
unauthenticated endpoint, and its honest value is the hostname already
in the address.

The session rides the URL fragment, so it stays out of access logs and
`Referer`, and is stripped before anything awaits. The claim is
row-locked, so one approval mints once. A request lives 30 minutes; a
settled one is not offered again, since approving it fails server-side.

Signing in mid-flow no longer loses the request. The id is kept on the
SaaS origin and resumed after any sign-in, which is what makes creating
an account work: the confirmation email opens a new tab, where the
`next` parameter is gone. Reading it does not consume it — the request
may be open in two tabs — and only a recorded decision retires it.

The result lands as a modal over the portal the admin started from, and
the portal re-reads its link status so the page behind agrees with the
modal.

Plaintext `http://` callbacks are accepted rather than refused, because
many self-hosted instances legitimately run plain HTTP on a private
network; the address carries a warning icon explaining the risk, derived
server-side so a requester cannot suppress it. Hard-refusing `http://`
to a public IP literal is a reasonable follow-up; a bare hostname can't
be classified without a DNS lookup, so the warning stays the general
mechanism.

## Configuration

Four surfaces. Placeholders below, not values.

**SaaS backend**

| Setting | Needed | Why |
|---|---|---|
| `stirling.billing.account-link.enabled` | Yes, `true` | The connect
controller and service are `@ConditionalOnProperty` with no default, so
without it the endpoints do not exist. |
| `system.frontendUrl` | Only when the approval page is not on the API's
own origin | Where the approver is sent. Must include the app's base
path if it is served under one, or the redirect misses `/link`. |

**SaaS frontend**

| Setting | Needed | Why |
|---|---|---|
| `VITE_SUPABASE_URL`, `VITE_SUPABASE_PUBLISHABLE_DEFAULT_KEY` | Yes |
Its own sign-in. Must be the project the SaaS backend validates tokens
against. |
| `RUN_SUBPATH` | Only if served under a subpath | Moves the approval
page to `<base>/<subpath>/link`, so `system.frontendUrl` has to agree. |

**Self-hosted backend**

| Setting | Needed | Why |
|---|---|---|
| `stirling.billing.account-link.enabled` | Yes, `true` | Defaults to
`false`. |
| `stirling.billing.account-link.saas-base-url` | Yes | Origin of the
SaaS API it links to. Not the SaaS frontend. |
| `system.frontendUrl` | Optional | Externally reachable base URL for
the callback. Otherwise derived from the request's `Origin`, which is
right for ordinary deployments and wrong behind a rewriting proxy. |

**Self-hosted frontend**

| Setting | Needed | Why |
|---|---|---|
| `VITE_SUPABASE_URL`, `VITE_SUPABASE_PUBLISHABLE_DEFAULT_KEY` | Yes |
Accepts the session handed over in the callback fragment. |
| `VITE_SAAS_API_URL` | For Usage and Billing | Attended reads go to the
SaaS API with the admin's token. Absent, those surfaces stay on the
mock. |
| `VITE_INCLUDE_PORTAL` | Production builds | Dev builds include the
portal automatically; without it there is no link UI and no callback
route. |

Two things worth stating because neither fails loudly:

- **Both frontends must use the URL *and* key of the same Supabase
project**, and the same one the SaaS backend validates against. A key
from one project with a URL from another is accepted by the browser and
rejected by Supabase, which surfaces much later as "session expired" on
Usage rather than as an error at hand-over.
- **The Supabase redirect allow-list must contain the SaaS app's
`/auth/callback`**, since a confirmation email returns through it.
Entries are matched exactly.

- **`system.frontendUrl` is the existing setting for this**, not a new
one, so each side reads its own value and there is nothing extra to
configure. It also gates share links, so on a stack with storage and
sharing already on, setting it here turns those on too.

The self-hosted side deliberately does **not** configure where the
approval page lives — SaaS answers that in the connect-request reply,
being the only party that knows.

Also here, because testing this needs two stacks side by side:
`linked:staging` / `linked:dev` (which derive `system.frontendUrl` and
`RUN_SUBPATH` themselves), the missing `frontend:staging:saas`, and a
per-mode vite `cacheDir` — two dev servers in different modes otherwise
re-optimise over one shared dep cache.

## How to test

Automated and green: `task frontend:check:all` plus both backend
modules. `ConnectRequestServiceTest` covers callback validation, the
per-IP cap, single-use approval, claim outcomes, expiry, `WRONG_TEAM`
and reauth confirming without minting; `ConnectServiceTest` covers
callback-resolution precedence including a foreign-origin callback being
discarded; `ConnectControllerTest` covers the authorize URL, including
the forwarded-header path and only the first hop being trusted;
`ConnectCallback.test.tsx` covers the fragment being stripped
synchronously and malformed fragments refused;
`LinkAccountModal.test.tsx` covers link and reauth hitting different
endpoints.

Manual walkthrough:

1. `task linked:staging` — added here; brings up a SaaS stack and a
self-hosted instance pointed at it, on discovered ports, and prints the
four addresses.
2. Open the link-account modal in the self-hosted portal and continue.
Expect the SaaS approval page at `/link?request=<id>`.
3. Sign in as a team leader, or create an account and confirm the email.
Either way you should come back to the approval page.
4. Tick the acknowledgement and approve. Expect the fragment gone from
the address bar immediately, a result modal over the portal, the portal
showing linked without a reload, and attended reads (Usage, Billing)
working without a second sign-in.
5. Repeat, approving as a member of a different team. Expect a refusal,
not a rebind.

## Outstanding

- #7415 to be reworked against this design once this lands.
- **No SaaS-side UI to disconnect a server.** `GET
/account-link/instances` and `POST /account-link/instances/{id}/revoke`
are already team-scoped and leader-gated, and the portal has a panel
that uses them, but
`portal-saas/components/settings/accountLinkSettings.tsx` exports `null`
on the reasoning that "SaaS has no account-link concept". That held when
linking was a self-hosted admin managing their own instance; here a
leader approves a server they may not administer, and has no way to
withdraw it. The seam to fill is that one file. Expected to land with
the CTA work in #7415.

---------

Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-08-27 10:32:32 +00:00
EthanHealy01andClaude f7a2c626c9 Persist the workbench session across the editor/processor switch (#7654)
## What

Switching editor -> processor (or reloading) unmounts every editor
provider, which emptied the workbench. This PR mirrors the workbench
into per-tab sessionStorage and refills an empty one from that record on
the next mount:

- **Files, selection, view and active document survive** the shell
switch and reloads. Each recorded file is resolved to its *current leaf*
version on restore, so a file versioned by a policy or another tab comes
back at its latest state.
- **The switch back lands where the user left**: the processor sidebar's
"editor" button consumes a one-shot return path saved at switch time.
- **The app switch respects unsaved changes**: `useOtherAppSwitch`
(proprietary + saas) now routes through `requestNavigation`, so the same
warning guards it as any other navigation.
- Desktop shadows `WorkbenchSessionPersistence` with a stub (OS-launched
files own boot there).

## How to test

I've run through each of these manually:

- Upload several PDFs in the editor, select a couple, and switch to the
Active Files grid. Click "Open PDF Processor" in the sidebar footer,
then switch back to the editor. The same files, selection and view
should return, and you should land on the editor page you left.
- Open a document in the viewer, then reload the tab. The workbench
should refill and come back on the viewer with the same document active.
- With unsaved changes in a tool, click the processor switch. The
unsaved-changes warning should appear, and the switch should only
proceed if you confirm.
- Open a second browser tab with different files. Each tab should
restore its own workbench independently (the record is per-tab
sessionStorage).
- While in the processor, delete one of the open files from storage,
then switch back. The remaining files should restore and a warning toast
should report "Restored X of Y files".

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-27 10:12:48 +00:00
EthanHealy01 caeca0b88a Fix classification escalation: the local pass was claiming the server dispatch key (#7667)
Follow-up to #7580: the escalation it added could never fire.

## What's broken

The auto-run skips a policy that has already run on a file, keyed on
`(categoryId, fileId)`. `recordRunStart` claims that key — and #7580 has
the **browser-side first pass** record its own run under `categoryId:
"classification"` for the uploaded file. So the local heuristic ticks
the very key the server escalation checks, and the AI is never asked, at
any confidence.

Trigger is the default seeded setup: **Classification as the only
on-upload policy**, and a local verdict below `high`. Any other
on-upload policy masks it, because classification then targets that
policy's output — a new file id whose key was never claimed. That's why
this went unnoticed.

Two smaller faults in the same path:

- A chained output carried no `classificationConfidence`, so
`shouldDispatchToAi` waited for a verdict that could never arrive (a
tool-derived file gets no local pass).
- Browser-local runs were polled against the server: 3 × 404 per file,
after which `MAX_NOT_FOUND` marked a local run that had actually
**succeeded** as `FAILED`.

## The fix

- `PolicyRunRecord.browserLocal`; `recordRunStart` skips the dispatch
claim for such a run. It is the first pass, not the policy's run.
- The local pass meters under `classification:local-meter` instead of
the category id, so metering dedupe survives without suppressing
dispatch.
- The poll effect skips browser-local runs.
- `CONSUME_FILES` inherits `classificationConfidence` alongside the
labels, so the verdict survives a version bump.

## How to test

Download
[`low-confidence-classification.pdf`](https://github.com/Stirling-Tools/Stirling-PDF/raw/fix/chained-classification-confidence/frontend/editor/src/proprietary/services/heuristic/fixtures/low-confidence-classification.pdf)
(checked in as a fixture, verdict pinned by a test).

With **Classification as the only on-upload policy**, upload it and
watch the Network tab:

- **Before:** no `POST /api/v1/policies/{id}/run` for classification,
ever. Console shows `local-classification-*` 404s.
- **After:** exactly one, and the engine receives `POST
/api/v1/documents/classify`.

Judge it on that request, not on the resulting label — the model's
answer varies, so a label comparison can pass or fail for the wrong
reason.

Headless equivalent:

```
npx vitest run --project proprietary src/proprietary/components/policies/usePolicyAutoRun.escalation.test.tsx
```

Passes here, fails on `main` on "asks the AI about an unsure verdict
even though the local pass already ran". Its other two cases pass on
both, so the guards still hold: a confident verdict still costs nothing,
and a file with no verdict yet still waits rather than racing the free
pass.

New tests drive the **real** run store — mocking it is what let this
through.

`task frontend:check`: 255 files / 2202 tests.
2026-08-26 17:34:13 +00:00
James Brunton c93feb5dfc Remove a bunch of unnecessary casts from the frontend (#7662)
# Description of Changes
Originally, I wanted to re-enable typed linting on our repo but using
Oxlint this time to avoid the memory and speed issues that ESLint was
causing. Unfortunately, it's not stable enough yet to actually use on
our repo (although it is close, I suspect it'll be stable enough fairly
soon). I was able to remove many of the unnecessary casts that it found
though, so even though this won't be enforced, it's still worth cleaning
up what I've found.
2026-08-26 14:09:55 +00:00
Anthony Stirling f945cc7dc6 Regenerate expired test certificates and guard against future expiry (#7682)
The bundled signing test certificates expired at **07:41:10 UTC on
2026-08-26**. They were issued exactly one year earlier, so they went
from fine to fatal mid-morning with no warning, and they take down
`main` and every open branch, not just one PR.

First casualty was the `docker-compose-tests` job on #6802, which
started at 07:45:

```
java.security.cert.CertificateExpiredException: NotAfter: Wed Aug 26 07:41:10 UTC 2026
    at CreateSignatureBase.checkValidity(CreateSignatureBase.java:159)
    at CertSignControllerTest.testSignPdfWithPkcs12(CertSignControllerTest.java:205)
```

```
$ openssl x509 -in app/core/src/test/resources/certs/test-cert.pem -noout -dates
notBefore=Aug 26 07:41:10 2025 GMT
notAfter =Aug 26 07:41:10 2026 GMT
```

## What was broken

`CertSignControllerTest` (7 tests) and `PdfSigningServiceImplTest` (2)
fail outright. `ValidateSignatureControllerMoreTest` and
`CertificateValidationServiceMoreTest` read the same fixtures.

Auditing the rest of the repo turned up three more time bombs that had
not gone off yet:

| Fixture | Was | Problem |
|---|---|---|
| `app/core/.../certs/test-cert.*` + `test-key.*` | expired 2026-08-26 |
**already breaking every branch** |
| `test-certs/valid-test.p12`, `valid-test.jks` (proprietary + frontend
copies) | expire 2027-03-25 | same failure, seven months out |
| `test-certs/not-yet-valid-test.p12` | valid **from** 2027-03-25 |
becomes valid, so its test silently stops proving anything, on the same
day |

## What this does

**Regenerates every fixture** with the identical subject DN, alias,
password, key size and signature algorithm as before, changing only the
validity window. Nothing that any test asserts on has moved.

- valid fixtures: `2025-01-01` to `2125-01-01`
- `not-yet-valid-test.p12`: `2125-01-01` to `2126-01-01`, so it stays in
the future
- `expired-test.p12`: pinned to its permanently-past 2024 window

**Adds `scripts/generate-test-certs.sh`** as the source of truth, so the
next regeneration is one command instead of archaeology. It documents
every DN, alias and password, pins the validity windows, and runs on
Linux, macOS and Git Bash.

**Adds two guard tests** that fail with an actionable message, naming
the script, while there is still a year of runway:

- `BundledTestCertificateExpiryTest` (app/core) checks all seven formats
parse, are in their validity window, and have more than 365 days left
- `BundledWorkflowCertificateExpiryTest` (proprietary) does the same for
the valid pair, and additionally asserts the expired fixture is still
expired and the not-yet-valid one is still in the future

That last pair matters: those two fixtures exist to test a validity
outcome, and each one silently stops testing anything once the clock
passes its window.

## Verification

Run locally against the regenerated bytes, on the exact content
committed here:

```
./gradlew :stirling-pdf:test --tests '*CertSignControllerTest*' --tests '*BundledTestCertificateExpiryTest*' \
  --tests '*PdfSigningServiceImplTest*' --tests '*ValidateSignatureControllerMoreTest*' \
  --tests '*CertificateValidationServiceMoreTest*'
BUILD SUCCESSFUL

./gradlew :proprietary:test --tests '*BundledWorkflowCertificateExpiryTest*' --tests '*CertificateValidationIntegrationTest*' \
  --tests '*SigningFinalizationServiceMoreTest*' --tests '*ServerCertificateServiceTest*' \
  --tests '*CertificateSubmissionValidatorTest*' --tests '*WorkflowSessionServiceTest*'
BUILD SUCCESSFUL
```

`spotlessCheck` passes on both modules.
2026-08-26 10:43:17 +00:00
dependabot[bot]andAnthony Stirling 72b7892312 Translations + com.squareup.okhttp3:okhttp-bom from 5.3.2 to 5.4.0 (#7599)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
Signed-off-by: dependabot[bot] <support@github.com>
2026-08-26 08:05:45 +01:00
James Brunton 353df7a647 Improve modals in Sources page in Processor (#7664)
# Description of Changes

Various changes throughout to try and convert the bulk of the dev UI
sources modals to production quality. Changes include:

- Fixing inconsistencies between different modals
- Hide things users will rarely need to change behind advanced
- Removed clutter in the UI
- Renaming settings in terms that the user will understand and care
about

<img width="2360" height="3068" alt="image"
src="https://github.com/user-attachments/assets/2c637e8f-bc1b-4c7e-98cb-d836ae626ba5"
/>

<img width="2360" height="3008" alt="image"
src="https://github.com/user-attachments/assets/d894aadc-7c83-41d1-b614-881637a6bd34"
/>
2026-08-25 15:59:16 +00:00
James Brunton 0d75715af2 Fix flaky e2e tests (#7595)
# Description of Changes
e2e Playwright tests are currently failing intermittently on all
platforms for different reasons, most notably WebKit, which seems to
fail much more often than the others. This PR attempts to fix the
issues. I've ran the e2e tests a few times now and they don't seem to be
inconsistent any more, but it's difficult to tell if all the issues are
genuinely fixed due to the inconsistent nature. As far as I can tell,
I've not broken anything though.
2026-08-25 15:56:44 +00:00
github-actions[bot]andFrooodle b44202185a chore: update Gradle to 9.7.1 (#7673)
Automated update of the Gradle wrapper and Gradle Docker build images.

Gradle version: `9.7.1`
Docker image: `gradle:9.7.1-jdk25`

Co-authored-by: Frooodle <77850077+Frooodle@users.noreply.github.com>
2026-08-25 12:36:38 +00:00
EthanHealy01 49c1e75ced Surface recorded failures in a notification bell (Review Flow PR 4) (#7478)
Review Flow PR 4. Stacked on #7477. Recorded failures appear in a
notification bell, showing each reader the failures they are allowed to
see and the actions they can actually take.

Scope is deliberately viewing and routing only. Resolving a failure —
retry, decrypt-and-retry — is #7479, which also brings the write path
for it; nothing resolution-shaped ships here, not even dark.

## What's added

**A notification bell** in the editor and the processor shell. Polls
`GET /api/v1/notifications` every 30 seconds, shows an unread badge, and
lists open failures newest first. Each row shows the failure's title,
its message with **Copy error** and **Show full message** chips, an
occurrence count, and its available actions.

**A notification API** (`stirling.software.proprietary.notification`),
derived from failures on read rather than stored in its own table:

| Route | Purpose |
|---|---|
| `GET /api/v1/notifications` | the caller's open failures, newest first
|

Read-only by design: every action the bell offers is one the client runs
on its own device, so there is nothing to post back. Every id is
prefixed (`failure:<uuid>`), so the bell never holds a raw failure id it
could hand to a failure endpoint.

**Per-reader actions.** A `FailureKind` declares each action with an
audience (`OWNER`, `TEAM_REVIEWER`, `ANYONE_WHO_SEES`). The server
resolves that against the reader and derives `Ownership` (`MINE` /
`THEIRS` / `UNOWNED`) from the row's actor, so an admin reviewing
someone else's failure is not offered a document their browser does not
hold. Adding a failure kind requires no frontend change.

**Server-run and client-run actions are distinguished.**
`FailureActionId` carries an `Execution` facet; the registry requires a
bean only for server actions, and dispatching a client action on the
failure surface returns 400. The notification projection goes further:
it carries only client-run offers, so the bell cannot be sent a button
it would refuse to draw.

**Actions in the bell:** at most two. The owner of the document gets
**View file** (opens it in the editor); a team reviewer gets **View in
processor** (dev builds only). Dismiss stays on the failure queue in
`/processor/documents` — deciding a failure's fate belongs to the review
surface, not the panel that announces it. An action id the build has not
wired is skipped rather than rendered dead, so the server can ship new
kinds ahead of the clients that understand them.

**Attended policy runs record their document.** `POST
/api/v1/policies/{id}/run` accepts an optional opaque `fileId`, recorded
when the run carries exactly one primary document. This is what lets a
repeat fold onto one incident instead of opening a new one per upload,
lets deleting the file clear its failure, and lets the owner open the
document from the row.

## Behaviour changes

- **The bell re-reads as soon as a failure you caused is recorded**,
rather than leaving you to wait out a poll interval for news of your own
upload. Applies to a failed tool run and to a policy run reaching
`FAILED`. Other people's failures still arrive on the poll, which is
what it is for.
- **An action the reader cannot use is not rendered.** Where the server
gave a reason for withholding it, that reason appears as the row's
one-line note. An action that was never offered to that reader produces
no note.
- **Deleting a document closes every incident about it that the deleter
caused**, including a failed policy run on their own upload, so a user's
own errors leave the bell with the file rather than lingering with a
dead button.
- **The failures list in `/processor/documents` stays behind
`import.meta.env.DEV`**, and View in processor is gated to match so it
cannot navigate to a section that is not mounted. Both lift when
failures get their own review screen.
- **One poll for all bells.** The bell is mounted in three places; the
list, document lookups and read marker are shared, so mounting more than
one does not multiply requests.
- `ACKNOWLEDGE` is no longer offered by any kind. The id, bean and
status remain so existing rows stay readable.

## Known limits

- The poll does not pause when the tab is hidden.
- No retention or per-team cap on `file_run_events`.

## How to test

Needs a proprietary or SaaS build with login enabled. `task dev:all`,
then sign in.

1. **Create a failure.** Add a password-protected PDF to the editor and
choose **Skip for now** when it asks to unlock. The upload starts a
policy run that fails on it.
2. **Watch the bell.** The badge should appear within a second or two,
not after 30 — this is the refresh-on-failure path. Open it: a row
titled "Password-protected document" with the error message and the two
chips.
3. **The buttons should be View file and View in processor, nothing
else.** No Dismiss and no retries: dispositions live on the review
surface, resolutions in #7479.
4. **View file** closes the panel and selects that document in the
editor.
5. **Dismiss from the queue instead.** Open `/processor/documents` (dev
build), find the row in the failures list and dismiss it there; the bell
drops it on its next read.
6. **Confirm the local-document probe.** Create a second failure, then
delete that file from the editor and reload. Its incident closes with
it; a row whose document is still present keeps **View file**.
7. **Confirm attribution end to end.** Sign in as a plain member, run a
shared policy on your own upload so it fails. The member sees their own
row in the bell. Sign in as the team leader: they see it too, but with
**View in processor** instead of **View file**, because the document is
not in their browser.
8. **Confirm folding.** Add the same locked PDF again and skip again.
The existing row's occurrence count increases rather than a second row
appearing.
9. **Confirm one poll for many bells.** Open the editor and the
processor in two tabs. Each tab issues its own poll, but within a tab
the several mounted bells share one — the Network tab should show one
`GET /api/v1/notifications` per 30s per tab, not three.

## Migration

None. No new column and no new value in any CHECK-constrained enum;
`CheckConstrainedEnumsTest` fails if that changes.
2026-08-24 22:29:41 +00:00
stirlingbot[bot] 826e487f00 Update Frontend 3rd Party Licenses (#7650)
Auto-generated by stirlingbot[bot]

This PR updates the frontend license report based on changes to
package.json dependencies.

Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2026-08-24 22:16:25 +00:00
stirlingbot[bot] bcad2cd486 Update Backend 3rd Party Licenses (#7653)
Auto-generated by stirlingbot[bot]

This PR updates the backend license report based on dependency changes.

Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2026-08-24 22:04:00 +00:00
79686a3a09 form field editing (#6655)
# Description of Changes

Building ontop of a users draft PR for form creation tools

**Fill Form** becomes a full **Form Editor**: fill, create, modify and
delete AcroForm fields visually. Builds on the community form-creation
draft, plus a UX/UI rework pass.

- **Backend**: `/api/v1/form` endpoints — `fields-with-coordinates`,
`add/modify/delete-fields`, combined `edit-fields` (one round-trip),
`fill`, `extract-csv/xlsx`; supports text (multiline, comb), checkbox,
dropdown, list box, radio, button actions (reset/print/URL/submit) and
signature placeholders
- **Create**: type palette, click-or-drag placement with snap guides,
inline property editor, batch "Add N fields"
- **Modify**: move/resize on the page, arrow-nudge + Delete key, X/Y/W/H
inputs, staged edits/deletes with chips, discard
- **Fill**: live progress + required tracking, flatten toggle, Export
menu (JSON/CSV/XLSX), Ctrl/Cmd+S
- **Safety**: confirm dialog before discarding staged work; empty
required fields warn with "Save anyway" instead of blocking
- **UI**: consistent panel skeleton (fixed header / scrolling list /
pinned actions), empty states that link into Create, full i18n with
plural keys



[walkthrough.html](https://github.com/user-attachments/files/30508976/walkthrough.html)



---

## 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: Denys Vitali <denys@denv.it>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-24 20:45:54 +00:00
dependabot[bot] e51885b379 build(deps): bump step-security/harden-runner from 2.20.0 to 2.21.0 (#7623)
Bumps
[step-security/harden-runner](https://github.com/step-security/harden-runner)
from 2.20.0 to 2.21.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.21.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Support for denied endpoints in block mode. This is included in the
enterprise tier. Customers can deny outbound calls, for example, to
public package registries.</li>
<li>Improved Support for AWS CodeBuild GitHub Actions Runners.</li>
<li>Bug fixes.</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/step-security/harden-runner/compare/v2.20.1...v2.21.0">https://github.com/step-security/harden-runner/compare/v2.20.1...v2.21.0</a></p>
<h2>v2.20.1</h2>
<h2>What's Changed</h2>
<ul>
<li>AWS CodeBuild-hosted runner support</li>
<li>Implicitly allow single-labeled (internal) domains in
block-mode</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/step-security/harden-runner/compare/v2.20.0...v2.20.1">https://github.com/step-security/harden-runner/compare/v2.20.0...v2.20.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/step-security/harden-runner/commit/05e31511f85b41b11d1cf0ef85d0992719546e2c"><code>05e3151</code></a>
Merge pull request <a
href="https://redirect.github.com/step-security/harden-runner/issues/684">#684</a>
from step-security/rc-42</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/0f37afa338f57c61ee3dfc274daca8834963d83e"><code>0f37afa</code></a>
fix: ignore denied-endpoints on non-enterprise tier</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/93b58ee491c5b6cf3a5324966fca2908f8d447f3"><code>93b58ee</code></a>
fix: resolve cache host read-first and never downgrade egress
policy</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/e7399dd3e93d6c159d314af54b4704bc48abf6bc"><code>e7399dd</code></a>
fix: align deny-list mode detection with agent and log when both
endpoint inp...</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/c16689f716a10cdfd9cfe22e63938b8c6c0657de"><code>c16689f</code></a>
test: add denied_endpoints to Configuration fixtures and cover deny-list
merge</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/40b99cf0c7161e4dcdc6c5508927188b65028df9"><code>40b99cf</code></a>
Merge pull request <a
href="https://redirect.github.com/step-security/harden-runner/issues/682">#682</a>
from rohan-stepsecurity/rp/feat/codebuild-self-v2</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/fedec027a205365a7d64001a81931e4c36a1af6e"><code>fedec02</code></a>
Merge branch 'rc-42' into rp/feat/codebuild-self-v2</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/5361fb178b926b2be6df52e11ee257823821567b"><code>5361fb1</code></a>
feat: add build artifacts</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/286474fffe0b8fe7c9db855f132d04a9b48ab564"><code>286474f</code></a>
feat: Support Bravo agent install on CodeBuild runners</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/051ec05283d064bd82f41279db4f70f0717bf778"><code>051ec05</code></a>
Merge pull request <a
href="https://redirect.github.com/step-security/harden-runner/issues/683">#683</a>
from h0x0er/jatin/deny-list</li>
<li>Additional commits viewable in <a
href="https://github.com/step-security/harden-runner/compare/v2.20.0...05e31511f85b41b11d1cf0ef85d0992719546e2c">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-24 17:39:57 +00:00
Anthony Stirling ddee690c58 Exclude Python virtualenvs from the Docker build context (#7658)
# Description of Changes

Stirling engine docker slimming

Exclude Python virtualenvs from the Docker build context
Drop unused provider SDKs from the engine dependency set
Retry the SQLite WAL switch when workers race on startup
Build the engine image in two stages and run it unprivileged
Swap voyage SDK for api call removing 200MB bloat
Bundle the AI engine in the fat image
Publish the AI engine as a standalone image


886MB to 295MB in docker file

And Docker fat is only 230MB bigger after adding (since it already has
python and some deps)

---

## 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-24 16:23:55 +00:00
James Brunton 158187ac46 Fix Documents tab in Processor (#7569)
# Description of Changes
The Documents tab in the Processor is supposed to be available to all
Processor users, but because the API is built on top of the Audit data,
which is only for enterprise users, the API call always fails with 403.
This means that it never fills the query cache, so every time you go
back to the tab it has to reload all the data for a couple of seconds
(and will fail again). This fixes the API so that it's available to any
Processor user instead of just enterprise users. Also, the documents
data was only being written to the log on an enterprise license, so I've
changed it so that data is always tracked in the audit log because
otherwise the Documents tab would still be useless to non-enterprise
users.

The Audit Log tab was also available to all Processor users, but would
have the same issue where the table would never load because the API
would 403 as well. I've just made the Audit Log tab disabled for
non-enterprise users now. We might want to do something to signpost it a
bit more that it's an enterprise-specific feature, but it's better than
nothing for now.
2026-08-24 15:06:22 +00:00
Anthony StirlingandJames Brunton e50c3de0a9 Run classification locally first and only escalate an unsure verdict to the AI (#7580)
Split out of #7574 — this is the classification half, which is
independent of the editor-source work and can land on its own.

## What this does

- **Runs the local heuristic first and only escalates an unsure verdict
to the AI.** A high-confidence local answer stands; anything less (or a
file the heuristic hasn't reached yet) goes to the engine. A wrong label
costs more than an engine call, so the bar is deliberately strict.
- **Makes `classify` an authorable pipeline task**, so it can be used as
a step like any other tool, and skips files that are already classified.
- **Leaves the seeded Classification policy unowned** rather than naming
a `system` placeholder that was never a real user; existing seeds are
repaired on boot.

## Review feedback applied

From @jbrunton96 on #7574:

- **The generic runner no longer names classification.** Everything
classification-specific moved into
`proprietary/data/classificationPolicy.ts`, and `usePolicyAutoRun` now
asks capability questions instead: `policyRewritesDocument`,
`policyDeliversOutputFiles`, `policyRequiresAiEngine`,
`shouldDispatchToAi`. There is no `id === "classification"` left in the
runner.
- **Ordering is no longer a name in the runner.**
`pinClassificationLast` is gone; the runner sorts annotating policies
after rewriting ones. The constraint is real: an annotating policy is
non-blocking, so a rewriting one running after it forks from the
pre-annotation version and drops the labels. To be straight about what
this is and isn't - see "Still open" below - `policyRewritesDocument` is
still keyed on the category id, not on a property each policy declares.
The check moved out of the runner; it did not stop being a check on one
id.
- **Confidence is typed.** New `ClassificationConfidence` union in
`core/types/fileContext.ts`, reused by `fileStorage`,
`HeuristicConfidence`, and the trusted-verdict constant instead of being
respelled at each site.
- **Comments trimmed** to the repo's 2-line guideline, and a stale
seeder javadoc that still claimed an internal-user owner was corrected.

## Still open, deliberately

`classificationPolicy.ts` answers its capability questions with
`categoryId === "classification"`. That is the same check relocated, not
removed, and the module doc now says so outright.

Deliberate, for two reasons:

- **The concept it would be declared against is going away.** Policies
are becoming pipelines with labels behind a separate enforcement layer,
which removes the category the flag would live on. A capability system
built on `categoryId` today gets migrated twice.
- **Classification is genuinely privileged, not accidentally special.**
It is the only policy with a browser-side implementation, so it can
answer without the server. That is a product decision, and a local-only
mode for set scenarios is planned - the flag for it should be designed
with that feature, not guessed at now.

The end state for the rest: an in-place output mode retires the ordering
rule and `policyDeliversOutputFiles`, and a run result that can carry
findings as well as files retires the remainder. Both touch the import
path, which is the most delicate code in `usePolicyAutoRun` - not
something to bolt on to a PR that has already been split once.

Nothing is broken by leaving it. A user-built classify pipeline still
gets its labels: the generic import path reads them off the returned
PDF. It versions the file instead of labelling in place, and it misses
the local-heuristic shortcut, so it always bills the engine.

## Testing

- `classificationPolicy.test.ts` — 12 cases covering each capability and
the escalation rule
- Full frontend `proprietary` project: 39 files / 442 tests
- `:proprietary:test` for `DefaultClassificationPolicySeederTest` +
`ClassifyLabelControllerTest`
- `tsc --noEmit` on core, proprietary, portal, saas, desktop, cloud

---------

Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-08-24 14:16:34 +00:00
dependabot[bot] 8e7501aec1 build(deps): bump org.snakeyaml:snakeyaml-engine from 3.0.1 to 3.1.1 (#7655)
Bumps org.snakeyaml:snakeyaml-engine from 3.0.1 to 3.1.1.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=org.snakeyaml:snakeyaml-engine&package-manager=gradle&previous-version=3.0.1&new-version=3.1.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-24 12:38:54 +00:00
James Brunton dbd60d4765 Replace Prettier with Oxfmt (#7422)
# Description of Changes
Prettier takes about 10 seconds to run over our frontend folder, but
[Oxfmt](https://oxc.rs/docs/guide/usage/formatter.html) does an (almost)
identical job in 0.2 seconds. This PR converts our Prettier integration
to an equivalent Oxfmt integration. There's exactly 2 files in the
frontend folder that Oxfmt formats differently to Prettier so it'll
barely cause any disruption to the source.

I've removed the `--check` option from the frontend tool models
generator as part of this because we can do the same thing with Task
easily enough and Oxfmt isn't directly importable like Prettier since
it's a Rust binary instead of a JS library. Originally I was shelling
out to Oxfmt on single-file mode to keep it all in memory but it just
seemed more likely that there'd be config mismatches between that script
and the task so I think it's better this way.
2026-08-24 10:34:12 +00:00
James Brunton 629f501e9c Fix any type usages in frontend (#7617)
# Description of Changes
Follow-on from #7334. Fix more `any` type usages and ban them in the
linter. We're starting to get down to only difficult folders left now,
so some of these fixes replace an excluded folder with a couple of
individual files to reduce scope to manageable levels.

There are two real behaviour changes in this PR because of bugs that
were never caught due to the lack of proper typing:
- In the Google Drive service, `lastModified` was always `undefined`
because it should have been read via `lastModifiedUtc`, which it now is.
This means that files being read from Google Drive should now accurately
retain their last modified date from Drive.
- In the error toasts, there was translation logic to try and make
friendlier error messages, but it'd never actually fire since it relied
on `i18n` being written to `globalThis`, which it never was. It now
imports the singleton instead so that translation should start working.

I also had to tweak the way that FitText works because it was relying on
`any` typing to mix refs between different places where they weren't
technically compatible but I've changed it to go via a function and the
behaviour doesn't change.
2026-08-24 10:33:50 +00:00
EthanHealy01 1df372764f Mobile follow-ups to #7518: tool-list search, and drop the empty overflow menu (#7660)
# Description of Changes

Follow-up to #7518, picking up two mobile rough edges found while going
over that branch. Two changes, one commit each.

## 1. Tool search back in the tool list (mobile)

Tool search lives in the workbench bar's super search, which on mobile
sits on the Workspace slide. So searching for a tool meant swiping off
the tool list, typing, then swiping back. This puts a filter at the head
of the tool panel on mobile. Reuses the existing `ToolSearch` component
in `mode="filter"`, the same one the desktop fullscreen picker uses.
Drives `setSearchQuery` on `ToolWorkflowContext`, so the query,
filtering and grouped results are all existing paths. `ToolPanel` takes
a new `showSearch` prop; `RightSidebar` passes `showSearch={isMobile}`.
Desktop renders exactly as before.

**To test:**

- Open the editor at a phone-width viewport (under 1024px).
- A "Search tools..." field should sit above Favourites / Recommended in
the Tools pane.
- Typing filters into grouped results. Clearing goes back to the compact
list.
- It hides once a tool is open, and comes back on the way out.
- On desktop the field should not appear at all.

## 2. The mobile overflow menu opened with nothing in it

`WorkbenchBarMobileActions` rendered its kebab trigger unconditionally.
But every item inside is gated on `currentView === "viewer"` or
`!isCustomView`. In a `custom:*` workbench both are false, so the
dropdown was empty. `WorkbenchBarDesktopActions` renders nothing in that
case, so this only showed on phones. Now returns `null` when neither
group applies, with the two conditions named so the trigger and the
items can't drift apart again.

**To test:**

- Phone-width viewport, load a PDF.
- Open a tool with its own workbench view: Compare, Get Info report,
Show JS, Validate Signature, Edit Table of Contents, or PDF Text Editor.
- The kebab at the right of the workbench bar should be gone entirely,
rather than opening an empty menu.
- Back in the viewer or page editor it should still be there, with Print
/ Download / Save As / Close.
2026-08-23 22:07:35 +00:00
dependabot[bot] 5f0fe06bbc build(deps): bump logback from 1.6.1 to 1.6.3 (#7622)
Bumps `logback` from 1.6.1 to 1.6.3.
Updates `ch.qos.logback:logback-core` from 1.6.1 to 1.6.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/qos-ch/logback/releases">ch.qos.logback:logback-core's
releases</a>.</em></p>
<blockquote>
<h2>Logback 1.6.3</h2>
<h1>2026-08-14 Release of logback version 1.6.3</h1>
<ul>
<li>
<p>In response <a
href="https://www.cve.org/cverecord?id=CVE-2026-19880">CVE-2026-19880</a>,
<code>MDCBasedDiscriminator</code> (used by
<code>SiftingAppender</code>) now strips forward and backward slashes
(<code>/</code>, <code>\</code>) from MDC values before they are used as
discriminating keys. This prevents path segments from escaping into
destinations controlled by an attacker. When sanitisation actually
changes a value, a warning is emitted; the warning is rate-limited (a
small batch, then a lull of about ten minutes).</p>
</li>
<li>
<p>Colour console support is split out into a dedicated <a
href="https://logback.qos.ch/manual/appenders.html#JansiConsoleAppender"><code>JansiConsoleAppender</code></a>.
It wraps stdout or stderr with Jansi so ANSI escape sequences (for
example coloured patterns) render correctly on terminals that need it,
notably Windows. Prefer this class over the older path described next.
See the <a
href="https://logback.qos.ch/manual/appenders.html#JansiConsoleAppender">appenders
documentation</a>.</p>
</li>
<li>
<p>The <code>withJansi</code> property on <code>ConsoleAppender</code>
is <strong>deprecated</strong>. Existing configurations that still set
<code>&lt;withJansi&gt;true&lt;/withJansi&gt;</code> continue to work
for compatibility, but new setups should use
<code>JansiConsoleAppender</code> instead.</p>
</li>
<li>
<p><code>ConsoleAppender</code> no longer treats the process console as
an exclusive resource: stopping it does not close
<code>System.out</code> / <code>System.err</code>.
<code>JansiConsoleAppender</code> pairs each
<code>AnsiConsole.systemInstall()</code> with
<code>systemUninstall()</code> on stop, so repeated start/stop cycles do
not leave Jansi installed or tear down streams shared with the rest of
the JVM. Related behavior is covered by tests for <a
href="https://redirect.github.com/qos-ch/logback/issues/1063">issues/1063</a>.</p>
</li>
<li>
<p>Invocation throttling helpers were reworked:
<code>SimpleInvocationGate</code> is renamed
<code>FixedIntervalInvocationGate</code>, and
<code>BatchedFixedIntervalInvocationGate</code> allows a short burst of
invocations before applying a fixed lull. The sanitisation
warning above uses the batched gate.</p>
</li>
<li>
<p>The JPMS <code>module-info</code> for logback-core now exports the
<code>ch.qos.logback.core.property</code> package, which had been
missing from the module descriptor.</p>
</li>
<li>
<p>A bit-wise identical binary of this version can be reproduced by
building from <a href="https://github.com/qos-ch/logback">source
code</a> at commit <code>e8e824dede022a6d7208b36cfa875b0d1b7772f3</code>
associated with the tag <code>v_1.6.3</code>. The release was built
using Java &quot;21&quot; 2023-10-17 LTS build 21.0.1.+12-LTS-29 under
Linux Debian 11.6.</p>
</li>
</ul>
<p>--
Sponsoring SLF4J/logback/reload4j at <a
href="https://github.com/sponsors/qos-ch">https://github.com/sponsors/qos-ch</a></p>
<h2>Logback 1.6.2</h2>
<p><a
href="https://github.com/user-attachments/assets/9ceaf157-b758-4188-815d-edfe4e1b4edd">https://github.com/user-attachments/assets/9ceaf157-b758-4188-815d-edfe4e1b4edd</a></p>
<h1>2026-08-10 Release of logback version 1.6.2</h1>
<ul>
<li>
<p>Configuration analysis now detects <em>contradictory caller-data
inclusion instructions</em>. For example, an <code>AsyncAppender</code>,
<code>SocketAppender</code> or <code>SMTPAppender</code> with
<code>includeCallerData</code> left at the default <code>false</code> is
incompatible with a layout or encoder pattern that uses a caller-data
converter such as <code>%C</code>, <code>%M</code>, <code>%L</code>,
<code>%F</code>, <code>%l</code> or <code>%caller</code>. At runtime
those converters would print question marks and still incur extraction
cost on a worker thread. Logback now emits a configuration-time warning
when such instructions disagree. See <a
href="https://logback.qos.ch/codes.html#callerContradiction">codes.html#callerContradiction</a>
for details. This issue was reported in <a
href="https://redirect.github.com/qos-ch/logback/issues/1059">issues/1059</a>
by <a href="https://github.com/leeychee">leeychee</a>. The initial
analysis was contributed by <a
href="https://github.com/seonwooj0810">seonwoo_jung</a>.</p>
</li>
<li>
<p>Caller-contradiction analysis can be turned off by setting the
<code>logback.skipCallerContradictionAnalysis</code> variable to
<code>true</code>, either as a system property
(<code>-Dlogback.skipCallerContradictionAnalysis=true</code>) or as a
property in the configuration file:</p>
<pre lang="xml"><code>&lt;property
name=&quot;logback.skipCallerContradictionAnalysis&quot;
value=&quot;true&quot;/&gt;
</code></pre>
</li>
<li>
<p><code>SimpleSocketServer</code> and
<code>SimpleSSLSocketServer</code> now require an explicit client IP
whitelist. On the command line, pass one or more allowed addresses
(single IPs or CIDR ranges) after the configuration file. An empty
whitelist means no clients are accepted. When embedding the server
programmatically, register allowed addresses with
<code>addAllowedClientAddress(String)</code> or
<code>setAllowedClientAddresses(Collection)</code> before clients
connect. See the documentation on <a
href="https://logback.qos.ch/manual/appenders.html#simpleSocketServerClientAccess">restricting
client access</a>.</p>
</li>
<li>
<p>Added <code>ThrowableProxyVOBuilder</code> for assembling a
<code>ThrowableProxyVO</code> field by field, with a corresponding
<code>ThrowableProxyVO.builder()</code> entry point.</p>
</li>
<li>
<p>Dependency analysis handlers now run their <code>postHandle</code>
method after child models have been processed, so checks that depend on
nested appenders (such as caller-contradiction analysis) see a complete
picture.</p>
</li>
<li>
<p>Updated several dependencies, including Angus Mail to 2.0.4 and Jetty
(test) to 12.1.12.</p>
</li>
<li>
<p>A bit-wise identical binary of this version can be reproduced by
building from <a href="https://github.com/qos-ch/logback">source
code</a> at commit e3d78330ad1ba024fd987fd00c3ffb9cfcdb07dc associated
with the tag <code>v_1.6.2</code>. The release was built using Java
&quot;21&quot; 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian
11.6.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/qos-ch/logback/commit/e8e824dede022a6d7208b36cfa875b0d1b7772f3"><code>e8e824d</code></a>
prepare release 1.6.3</li>
<li><a
href="https://github.com/qos-ch/logback/commit/761821bfaacac3a0ad44fa546cfc814429bf9312"><code>761821b</code></a>
MDCBasedDiscriminator has a gated warning mechanism</li>
<li><a
href="https://github.com/qos-ch/logback/commit/53ed1229008d8b1902f5c234deaa07d742890879"><code>53ed122</code></a>
update copyright year</li>
<li><a
href="https://github.com/qos-ch/logback/commit/c7e2db244671ffa916182b5da8c89579eb54a645"><code>c7e2db2</code></a>
rename SimpleInvocationGate as FixedIntervalInvocationGate</li>
<li><a
href="https://github.com/qos-ch/logback/commit/b5aa931b096a4b0b6a9e140b74fabe7da152cbf0"><code>b5aa931</code></a>
added BatchedSimpleInvocationGate</li>
<li><a
href="https://github.com/qos-ch/logback/commit/1f22af7686aadd25c08b4bd1e6943a906a743ad4"><code>1f22af7</code></a>
add javadocs to SimpleInvocationGate</li>
<li><a
href="https://github.com/qos-ch/logback/commit/638ffa7e7852478b605a91b3e91238ff26f8158c"><code>638ffa7</code></a>
prevent forward and backward slashes to escape to other directories</li>
<li><a
href="https://github.com/qos-ch/logback/commit/7d6b9a4f8c8996834c0a694f6c141705a003d7bb"><code>7d6b9a4</code></a>
add missing ch.qos.logback.core.property package</li>
<li><a
href="https://github.com/qos-ch/logback/commit/fa25930346f35636fb6a077c1f66ebb06edd3b6f"><code>fa25930</code></a>
add an extension path in ConsoleAppender for JansiConsoleAppender</li>
<li><a
href="https://github.com/qos-ch/logback/commit/c73b43f2011f9d4545abc7ea461172276a0a43b3"><code>c73b43f</code></a>
deprecate the withJansi path</li>
<li>Additional commits viewable in <a
href="https://github.com/qos-ch/logback/compare/v_1.6.1...v_1.6.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `ch.qos.logback:logback-classic` from 1.6.1 to 1.6.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/qos-ch/logback/releases">ch.qos.logback:logback-classic's
releases</a>.</em></p>
<blockquote>
<h2>Logback 1.6.3</h2>
<h1>2026-08-14 Release of logback version 1.6.3</h1>
<ul>
<li>
<p>In response <a
href="https://www.cve.org/cverecord?id=CVE-2026-19880">CVE-2026-19880</a>,
<code>MDCBasedDiscriminator</code> (used by
<code>SiftingAppender</code>) now strips forward and backward slashes
(<code>/</code>, <code>\</code>) from MDC values before they are used as
discriminating keys. This prevents path segments from escaping into
destinations controlled by an attacker. When sanitisation actually
changes a value, a warning is emitted; the warning is rate-limited (a
small batch, then a lull of about ten minutes).</p>
</li>
<li>
<p>Colour console support is split out into a dedicated <a
href="https://logback.qos.ch/manual/appenders.html#JansiConsoleAppender"><code>JansiConsoleAppender</code></a>.
It wraps stdout or stderr with Jansi so ANSI escape sequences (for
example coloured patterns) render correctly on terminals that need it,
notably Windows. Prefer this class over the older path described next.
See the <a
href="https://logback.qos.ch/manual/appenders.html#JansiConsoleAppender">appenders
documentation</a>.</p>
</li>
<li>
<p>The <code>withJansi</code> property on <code>ConsoleAppender</code>
is <strong>deprecated</strong>. Existing configurations that still set
<code>&lt;withJansi&gt;true&lt;/withJansi&gt;</code> continue to work
for compatibility, but new setups should use
<code>JansiConsoleAppender</code> instead.</p>
</li>
<li>
<p><code>ConsoleAppender</code> no longer treats the process console as
an exclusive resource: stopping it does not close
<code>System.out</code> / <code>System.err</code>.
<code>JansiConsoleAppender</code> pairs each
<code>AnsiConsole.systemInstall()</code> with
<code>systemUninstall()</code> on stop, so repeated start/stop cycles do
not leave Jansi installed or tear down streams shared with the rest of
the JVM. Related behavior is covered by tests for <a
href="https://redirect.github.com/qos-ch/logback/issues/1063">issues/1063</a>.</p>
</li>
<li>
<p>Invocation throttling helpers were reworked:
<code>SimpleInvocationGate</code> is renamed
<code>FixedIntervalInvocationGate</code>, and
<code>BatchedFixedIntervalInvocationGate</code> allows a short burst of
invocations before applying a fixed lull. The sanitisation
warning above uses the batched gate.</p>
</li>
<li>
<p>The JPMS <code>module-info</code> for logback-core now exports the
<code>ch.qos.logback.core.property</code> package, which had been
missing from the module descriptor.</p>
</li>
<li>
<p>A bit-wise identical binary of this version can be reproduced by
building from <a href="https://github.com/qos-ch/logback">source
code</a> at commit <code>e8e824dede022a6d7208b36cfa875b0d1b7772f3</code>
associated with the tag <code>v_1.6.3</code>. The release was built
using Java &quot;21&quot; 2023-10-17 LTS build 21.0.1.+12-LTS-29 under
Linux Debian 11.6.</p>
</li>
</ul>
<p>--
Sponsoring SLF4J/logback/reload4j at <a
href="https://github.com/sponsors/qos-ch">https://github.com/sponsors/qos-ch</a></p>
<h2>Logback 1.6.2</h2>
<p><a
href="https://github.com/user-attachments/assets/9ceaf157-b758-4188-815d-edfe4e1b4edd">https://github.com/user-attachments/assets/9ceaf157-b758-4188-815d-edfe4e1b4edd</a></p>
<h1>2026-08-10 Release of logback version 1.6.2</h1>
<ul>
<li>
<p>Configuration analysis now detects <em>contradictory caller-data
inclusion instructions</em>. For example, an <code>AsyncAppender</code>,
<code>SocketAppender</code> or <code>SMTPAppender</code> with
<code>includeCallerData</code> left at the default <code>false</code> is
incompatible with a layout or encoder pattern that uses a caller-data
converter such as <code>%C</code>, <code>%M</code>, <code>%L</code>,
<code>%F</code>, <code>%l</code> or <code>%caller</code>. At runtime
those converters would print question marks and still incur extraction
cost on a worker thread. Logback now emits a configuration-time warning
when such instructions disagree. See <a
href="https://logback.qos.ch/codes.html#callerContradiction">codes.html#callerContradiction</a>
for details. This issue was reported in <a
href="https://redirect.github.com/qos-ch/logback/issues/1059">issues/1059</a>
by <a href="https://github.com/leeychee">leeychee</a>. The initial
analysis was contributed by <a
href="https://github.com/seonwooj0810">seonwoo_jung</a>.</p>
</li>
<li>
<p>Caller-contradiction analysis can be turned off by setting the
<code>logback.skipCallerContradictionAnalysis</code> variable to
<code>true</code>, either as a system property
(<code>-Dlogback.skipCallerContradictionAnalysis=true</code>) or as a
property in the configuration file:</p>
<pre lang="xml"><code>&lt;property
name=&quot;logback.skipCallerContradictionAnalysis&quot;
value=&quot;true&quot;/&gt;
</code></pre>
</li>
<li>
<p><code>SimpleSocketServer</code> and
<code>SimpleSSLSocketServer</code> now require an explicit client IP
whitelist. On the command line, pass one or more allowed addresses
(single IPs or CIDR ranges) after the configuration file. An empty
whitelist means no clients are accepted. When embedding the server
programmatically, register allowed addresses with
<code>addAllowedClientAddress(String)</code> or
<code>setAllowedClientAddresses(Collection)</code> before clients
connect. See the documentation on <a
href="https://logback.qos.ch/manual/appenders.html#simpleSocketServerClientAccess">restricting
client access</a>.</p>
</li>
<li>
<p>Added <code>ThrowableProxyVOBuilder</code> for assembling a
<code>ThrowableProxyVO</code> field by field, with a corresponding
<code>ThrowableProxyVO.builder()</code> entry point.</p>
</li>
<li>
<p>Dependency analysis handlers now run their <code>postHandle</code>
method after child models have been processed, so checks that depend on
nested appenders (such as caller-contradiction analysis) see a complete
picture.</p>
</li>
<li>
<p>Updated several dependencies, including Angus Mail to 2.0.4 and Jetty
(test) to 12.1.12.</p>
</li>
<li>
<p>A bit-wise identical binary of this version can be reproduced by
building from <a href="https://github.com/qos-ch/logback">source
code</a> at commit e3d78330ad1ba024fd987fd00c3ffb9cfcdb07dc associated
with the tag <code>v_1.6.2</code>. The release was built using Java
&quot;21&quot; 2023-10-17 LTS build 21.0.1.+12-LTS-29 under Linux Debian
11.6.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/qos-ch/logback/commit/e8e824dede022a6d7208b36cfa875b0d1b7772f3"><code>e8e824d</code></a>
prepare release 1.6.3</li>
<li><a
href="https://github.com/qos-ch/logback/commit/761821bfaacac3a0ad44fa546cfc814429bf9312"><code>761821b</code></a>
MDCBasedDiscriminator has a gated warning mechanism</li>
<li><a
href="https://github.com/qos-ch/logback/commit/53ed1229008d8b1902f5c234deaa07d742890879"><code>53ed122</code></a>
update copyright year</li>
<li><a
href="https://github.com/qos-ch/logback/commit/c7e2db244671ffa916182b5da8c89579eb54a645"><code>c7e2db2</code></a>
rename SimpleInvocationGate as FixedIntervalInvocationGate</li>
<li><a
href="https://github.com/qos-ch/logback/commit/b5aa931b096a4b0b6a9e140b74fabe7da152cbf0"><code>b5aa931</code></a>
added BatchedSimpleInvocationGate</li>
<li><a
href="https://github.com/qos-ch/logback/commit/1f22af7686aadd25c08b4bd1e6943a906a743ad4"><code>1f22af7</code></a>
add javadocs to SimpleInvocationGate</li>
<li><a
href="https://github.com/qos-ch/logback/commit/638ffa7e7852478b605a91b3e91238ff26f8158c"><code>638ffa7</code></a>
prevent forward and backward slashes to escape to other directories</li>
<li><a
href="https://github.com/qos-ch/logback/commit/7d6b9a4f8c8996834c0a694f6c141705a003d7bb"><code>7d6b9a4</code></a>
add missing ch.qos.logback.core.property package</li>
<li><a
href="https://github.com/qos-ch/logback/commit/fa25930346f35636fb6a077c1f66ebb06edd3b6f"><code>fa25930</code></a>
add an extension path in ConsoleAppender for JansiConsoleAppender</li>
<li><a
href="https://github.com/qos-ch/logback/commit/c73b43f2011f9d4545abc7ea461172276a0a43b3"><code>c73b43f</code></a>
deprecate the withJansi path</li>
<li>Additional commits viewable in <a
href="https://github.com/qos-ch/logback/compare/v_1.6.1...v_1.6.3">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>
2026-08-23 12:41:05 +00:00
dependabot[bot] d34b9f0256 build(deps): bump license-report from 6.8.2 to 6.8.5 in /frontend (#7645)
Bumps [license-report](https://github.com/bepo65/license-report) from
6.8.2 to 6.8.5.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/BePo65/license-report/blob/main/CHANGELOG.md">license-report's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/bepo65/license-report/compare/v6.8.4...v6.8.5">6.8.5</a>
(2026-05-28)</h2>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.8.3...v6.8.4">6.8.4</a>
(2026-04-02)</h2>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.8.1...v6.8.3">6.8.3</a>
(2026-04-01)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>update packages to fix dependabot security warnings (<a
href="https://github.com/kessler/license-report/commit/90d39679d5c458c7d59545bb06b61c32a16bf746">90d3967</a>)</li>
<li>update packages to fix github dependabot security warnings (<a
href="https://github.com/kessler/license-report/commit/02ab3bcd7baaa7985ed3a3164aef5b66a3c58ad0">02ab3bc</a>)</li>
</ul>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.8.0...v6.8.1">6.8.1</a>
(2025-10-22)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>update packages to fix security warnings (<a
href="https://github.com/kessler/license-report/commit/de28bd74a0c98b24b09470fd48ce4324fa3e193b">de28bd7</a>)</li>
</ul>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.7.2...v6.8.0">6.8.0</a>
(2025-05-23)</h2>
<h3>Features</h3>
<ul>
<li>enable usage of .npmrc file (solves issue <a
href="https://redirect.github.com/kessler/license-report/issues/205">#205</a>)
(<a
href="https://redirect.github.com/kessler/license-report/issues/208">#208</a>)
(<a
href="https://github.com/kessler/license-report/commit/935608872386d531226e41bb90a4f1b71148aac5">9356088</a>)</li>
</ul>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.7.1...v6.7.2">6.7.2</a>
(2025-03-01)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>replace path.join for uri with own function (<a
href="https://github.com/kessler/license-report/commit/2f30a8bae9050fc2a75c228f5eea10cf91a88ab5">2f30a8b</a>)</li>
</ul>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.7.0...v6.7.1">6.7.1</a>
(2024-12-10)</h2>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.6.1...v6.7.0">6.7.0</a>
(2024-09-13)</h2>
<h3>Features</h3>
<ul>
<li>use properties of object entries as custom field (<a
href="https://redirect.github.com/kessler/license-report/issues/194">#194</a>)
(<a
href="https://github.com/kessler/license-report/commit/d9519b23d4cdf11c8659c28644eb4fe206df1b5a">d9519b2</a>)</li>
</ul>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.6.0...v6.6.1">6.6.1</a>
(2024-08-02)</h2>
<h2><a
href="https://github.com/kessler/license-report/compare/v6.5.1...v6.6.0">6.6.0</a>
(2024-06-23)</h2>
<h3>Features</h3>
<ul>
<li>change the project from 'default' to named exports (<a
href="https://github.com/kessler/license-report/commit/1e526eb2ebd4395a45473e588a6d3e774fc9dd0d">1e526eb</a>)</li>
</ul>
<h2><a
href="https://github.com/ironSource/license-report/compare/v6.5.0...v6.5.1">6.5.1</a>
(2024-04-26)</h2>
<h2><a
href="https://github.com/ironSource/license-report/compare/v6.4.0...v6.5.0">6.5.0</a>
(2023-10-09)</h2>
<h3>Features</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/BePo65/license-report/commit/a3bc6e5487f833629372a7ee9971dee94de765bd"><code>a3bc6e5</code></a>
Merge pull request <a
href="https://redirect.github.com/bepo65/license-report/issues/262">#262</a>
from BePo65/pu/create-release</li>
<li><a
href="https://github.com/BePo65/license-report/commit/f68eb4be91802b095b033407b1147cf5af1bc9f1"><code>f68eb4b</code></a>
chore(release): 6.8.5</li>
<li><a
href="https://github.com/BePo65/license-report/commit/97767e43ee578aa97696a58d78432f6cf20d1649"><code>97767e4</code></a>
Merge pull request <a
href="https://redirect.github.com/bepo65/license-report/issues/250">#250</a>
from BePo65/dependabot/github_actions/actions/stale-1...</li>
<li><a
href="https://github.com/BePo65/license-report/commit/5aa73e676f80f3bb5d9db535433fc8a6cb8ee6ef"><code>5aa73e6</code></a>
build(deps): bump actions/stale from 10.2.0 to 10.3.0</li>
<li><a
href="https://github.com/BePo65/license-report/commit/b14534d2f366c69b9617dda21e8a0ab16301c255"><code>b14534d</code></a>
Merge pull request <a
href="https://redirect.github.com/bepo65/license-report/issues/261">#261</a>
from BePo65/pu/update-gh-workflow-stale</li>
<li><a
href="https://github.com/BePo65/license-report/commit/1acbb74b7ca80c12a9308da78f309e749d926bcf"><code>1acbb74</code></a>
build: update actions/stale to v 10.2.0 and switch to double quotes</li>
<li><a
href="https://github.com/BePo65/license-report/commit/97d384bcecda69631e824b921bcc81d993e91934"><code>97d384b</code></a>
Revert &quot;chore(release): 6.8.5&quot;</li>
<li><a
href="https://github.com/BePo65/license-report/commit/3ed874213f6920c69c6d3566dfe86d05142264c5"><code>3ed8742</code></a>
Merge pull request <a
href="https://redirect.github.com/bepo65/license-report/issues/260">#260</a>
from BePo65/pu/change-ownership</li>
<li><a
href="https://github.com/BePo65/license-report/commit/5dd5be3b9f7eaa47869bf1ae675a5635647e0ecd"><code>5dd5be3</code></a>
chore(release): 6.8.5</li>
<li><a
href="https://github.com/BePo65/license-report/commit/b0851a8c7df87a956e1b1cf32790ed9486976e57"><code>b0851a8</code></a>
docs: changes caused by transfer of ownership</li>
<li>Additional commits viewable in <a
href="https://github.com/bepo65/license-report/compare/v6.8.2...v6.8.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=license-report&package-manager=npm_and_yarn&previous-version=6.8.2&new-version=6.8.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-23 10:35:29 +00:00
Anthony Stirling e9a9dbf644 fix(desktop): inset macOS and Linux app icons to platform icon grids (#7646)
# Description of Changes

The macOS Dock icon renders noticeably larger than every other app. The
cause is that
`icon.icns` was **100% full-bleed** - the red rounded square filled all
1024x1024 with zero
margin. macOS does not mask or inset legacy `.icns` icons, so the
artwork has to carry Apple's
grid itself: an **824x824 body centred on a 1024x1024 canvas**.
Full-bleed therefore rendered
**24% wider and 54% larger in area** than its neighbours.

Linux had the same defect for the same reason - the hicolor PNGs were
94.9-100% full-bleed,
and GNOME's HIG says an app icon is drawn within the canvas but must not
fill it (~10% margin,
so a body around 80%). Those small existing margins were resampling
artifacts, not padding.

Windows is deliberately **left full-bleed**. Microsoft imposes no inset:
target-size assets are
drawn without tile padding and the taskbar simply scales the bitmap into
the slot. `app.ico` is
a pure rename here, byte-identical to before.

## What changed

Icons are now split per platform, since the three platforms disagree
about how much of the
canvas the artwork may fill:

| Path | Owner | Treatment |
| --- | --- | --- |
| `icons/macos/app.icns` | `dmg`, `app` | 824/1024 Apple grid |
| `icons/macos/app-512.png` | build-time only | see note below |
| `icons/linux/app-{16..512}.png` | `deb`, `rpm`, `appimage` | ~10%
margin, KDE's small-size exception at 16/32 |
| `icons/windows/app.ico` | `msi`, NSIS | unchanged, full-bleed |

Linux is selected by a new `tauri.linux.conf.json`. Tauri merges
platform configs with
JSON Merge Patch (RFC 7396), so `bundle.icon` is **replaced wholesale**
rather than appended.

## Notes for reviewers

- **`icons/macos/app-512.png` is build ballast, not a real asset.**
`tauri-codegen` requires a
PNG in the icon list for every non-Windows target, with a hardcoded
fallback to
`icons/icon.png` - a file this PR deletes. Without it the build fails.
It is embedded as
`default_window_icon`, which tao's macOS backend discards
(`set_window_icon` there is a no-op:
  "macOS doesn't have window icons"). Nothing renders it.
- **Linux icon order matters.** The bundler derives the hicolor
directory from each PNG's real
pixel dimensions, so `app-128.png` lands in `128x128/`. `app-512.png` is
listed first because
the first PNG in the list also becomes the window icon, which GTK does
honour.
- **`.imgbotconfig` had to be repointed.** Its previous entry named
`icons/icon.png`, a path this
PR deletes. That exclusion is load-bearing: ImgBot once optimised the
icon to an indexed
palette and `tauri::generate_context!()` rejects non-RGBA icons,
breaking the desktop build
(#6990). All 15 generated PNGs, including the eight inside the `.icns`,
are verified colour
  type 6.
- **Not fixed here:** our corner radius is 14.3% of the body where macOS
and GNOME neighbours sit
near 22%, so the icon still reads squarer than its neighbours. That is a
brand-silhouette
  decision rather than the sizing bug, so it was left alone.
- The 15 pre-existing unused assets (`Square*Logo.png`, `mstile-*`,
`android-chrome-*`,
`android/`, `ios/`) are untouched. No configured bundle target consumes
them.

## Verification

`task check` was **not** run - this PR touches no Java, TypeScript or
engine Python, so it
cannot exercise the change. What was verified directly instead:

- Simulated the RFC 7396 merge and Tauri's `find_icon` resolution per
platform: Windows resolves
to `app.ico`, macOS to `app.icns` plus the stub PNG, Linux to its own
six PNGs. Every path exists.
- Both configs validate against the bundled
`@tauri-apps/cli/config.schema.json`, base and merged.
- Every PNG's real dimensions match its filename, and every body
measures exactly its nominal
  inset (410/512, 154/192, 102/128, 52/64, 28/32, 14/16).
- An overlay diff of the new macOS body against the old artwork shows
only 1px antialiasing
  hairlines - the mark itself is unchanged, only inset.
- Pre-commit hooks pass.

---

## 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-08-23 01:01:08 +00:00
dependabot[bot] 207410b50e build(deps): bump astral-sh/setup-uv from 9.0.0 to 10.0.1 (#7624)
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from
9.0.0 to 10.0.1.
<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>v10.0.1 🌈 Tolerate transient manifest timeouts</h2>
<h2>Changes</h2>
<p>Thank you <a
href="https://github.com/arguile"><code>@​arguile</code></a>- for making
this action more resilient.</p>
<h2>🐛 Bug fixes</h2>
<ul>
<li>Tolerate transient manifest timeouts <a
href="https://github.com/arguile"><code>@​arguile</code></a>- (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1016">#1016</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>chore: update known checksums for 0.12.4 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1017">#1017</a>)</li>
</ul>
<h2>📚 Documentation</h2>
<ul>
<li>docs: update version references to v10.0.0 @<a
href="https://github.com/apps/github-actions">github-actions[bot]</a>
(<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1014">#1014</a>)</li>
</ul>
<h2>v10.0.0 🌈 Disable automatic caching for sensitive events and new QOL
features</h2>
<h2>Changes</h2>
<p>Another breaking release, directly after v9.0.0 but we think the
added security justifies that.</p>
<h3>Extra security by default</h3>
<p>If you use the default <code>enable-cache: auto</code> this will now
<strong>DISABLE THE CACHE</strong> to protect against cache poisoning
for the following events:</p>
<ul>
<li><code>pull_request_target</code></li>
<li><code>workflow_run</code></li>
<li><code>release</code></li>
</ul>
<p>You can read the full reasoning in <a
href="https://redirect.github.com/astral-sh/setup-uv/issues/984">astral-sh/setup-uv#984</a></p>
<h3><code>version: latest-known</code></h3>
<pre lang="yaml"><code>- name: Install the latest version of uv known to
setup-uv
  uses: astral-sh/setup-uv@v10.0.0
  with:
    version: &quot;latest-known&quot;
</code></pre>
<p>This will now install the latest version with a checksum that is
known by this action. The <a
href="https://github.com/astral-sh/setup-uv/blob/4f6036f71cec78afb113b323f220c9185d983c12/src/download/checksum/known-checksums.ts">known
<code>uv</code> checksums</a> are automatically updated but will take a
release of this action to take effect. You won't be always using the
latest &amp; greatest but you will have an extra level of security.</p>
<h3>Read python version from <code>.tool-versions</code></h3>
<pre lang="yaml"><code>- name: Install uv based on the version defined
in .tool-versions and also set python
  uses: astral-sh/setup-uv@v10.0.0
  with:
    version-file: &quot;pyproject.toml&quot;
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/20cfd1bf945f4377ade1205e4dbc17946fc9a30d"><code>20cfd1b</code></a>
chore: update known checksums for 0.12.4 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1017">#1017</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/d73a0cab66a532d7afa440d9df4a67ea9fe65a30"><code>d73a0ca</code></a>
Tolerate transient manifest timeouts (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1016">#1016</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/ae3b92d1bdb308a10adfe7b8f408e5cc8c30f3f6"><code>ae3b92d</code></a>
docs: update version references to v10.0.0 (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1014">#1014</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/ae62891fec2bb8e7d6c99fc78c9fec3a63790f8d"><code>ae62891</code></a>
chore(deps): roll up Dependabot updates (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1013">#1013</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/f9cdb47d487aee2be8925d1e57290177ad9e1ac2"><code>f9cdb47</code></a>
Reject paths in .tool-versions (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1007">#1007</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/4f6036f71cec78afb113b323f220c9185d983c12"><code>4f6036f</code></a>
Require pull requests for Dependabot rollups (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1005">#1005</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/8d6402c9b71205b2d8d0b82de531d8fed8430182"><code>8d6402c</code></a>
chore(deps): roll up Dependabot updates (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/1004">#1004</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/46f427bd47c794e99536b75ffaa9f27602425027"><code>46f427b</code></a>
Read Python version from .tool-versions (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/996">#996</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/8ed89c51143f65ea13eaba62db51dbb8ea52d0a3"><code>8ed89c5</code></a>
ci: pin Alpine container image (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/995">#995</a>)</li>
<li><a
href="https://github.com/astral-sh/setup-uv/commit/8473c7fea42cdfd540f4b01317a17ac5f54126ae"><code>8473c7f</code></a>
chore(deps): roll up Dependabot updates (<a
href="https://redirect.github.com/astral-sh/setup-uv/issues/994">#994</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/setup-uv/compare/c771a70e6277c0a99b617c7a806ffedaca235ff9...20cfd1bf945f4377ade1205e4dbc17946fc9a30d">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=9.0.0&new-version=10.0.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-22 22:18:17 +00:00
Ludy 63ff3afb41 fix: restrict share link route tokens to UUID length (#7626) 2026-08-22 19:07:40 +01:00
Anthony StirlingandEthanHealy01 4457260c60 Make the editor and settings menu mobile friendly-er (#7518)
Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
2026-08-22 18:47:14 +01:00
dependabot[bot] 41e4b67f1d build(deps): bump the simple-java-mail group across 2 directories with 2 updates (#7621)
Bumps the simple-java-mail group with 1 update in the / directory:
[org.simplejavamail:simple-java-mail](https://github.com/bbottema/simple-java-mail).
Bumps the simple-java-mail group with 1 update in the /app/common
directory:
[org.simplejavamail:simple-java-mail](https://github.com/bbottema/simple-java-mail).

Updates `org.simplejavamail:simple-java-mail` from 9.3.1 to 9.3.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/bbottema/simple-java-mail/releases">org.simplejavamail:simple-java-mail's
releases</a>.</em></p>
<blockquote>
<h2>v9.3.2</h2>
<p>Fixed <a
href="https://redirect.github.com/bbottema/simple-java-mail/issues/702">#702</a>:
clarified that <code>RecipientBuilder</code> accepts one address, while
<code>RecipientsBuilder</code> handles comma- or semicolon-delimited
address lists; see the <a
href="https://www.simplejavamail.org/features.html#section-recipient-builders">recipient
builder examples</a>.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/bbottema/simple-java-mail/blob/master/RELEASE_HISTORY.md">org.simplejavamail:simple-java-mail's
changelog</a>.</em></p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/bbottema/simple-java-mail/commit/982007485db7a5397e7c2782bfc296c530636a14"><code>9820074</code></a>
released 9.3.2 [skip ci]</li>
<li><a
href="https://github.com/bbottema/simple-java-mail/commit/12013d9057026ab2a634f5cfa8adf584653e7a89"><code>12013d9</code></a>
docs(release): prepare 9.3.2 release notes</li>
<li><a
href="https://github.com/bbottema/simple-java-mail/commit/8746cffb54b0957b667a3fca7bd2e199611dfbbd"><code>8746cff</code></a>
fix(recipients): clarify single-address parameter (<a
href="https://redirect.github.com/bbottema/simple-java-mail/issues/702">#702</a>)</li>
<li>See full diff in <a
href="https://github.com/bbottema/simple-java-mail/compare/9.3.1...9.3.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `org.simplejavamail:outlook-module` from 9.3.1 to 9.3.2

Updates `org.simplejavamail:simple-java-mail` from 9.3.1 to 9.3.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/bbottema/simple-java-mail/releases">org.simplejavamail:simple-java-mail's
releases</a>.</em></p>
<blockquote>
<h2>v9.3.2</h2>
<p>Fixed <a
href="https://redirect.github.com/bbottema/simple-java-mail/issues/702">#702</a>:
clarified that <code>RecipientBuilder</code> accepts one address, while
<code>RecipientsBuilder</code> handles comma- or semicolon-delimited
address lists; see the <a
href="https://www.simplejavamail.org/features.html#section-recipient-builders">recipient
builder examples</a>.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/bbottema/simple-java-mail/blob/master/RELEASE_HISTORY.md">org.simplejavamail:simple-java-mail's
changelog</a>.</em></p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/bbottema/simple-java-mail/commit/982007485db7a5397e7c2782bfc296c530636a14"><code>9820074</code></a>
released 9.3.2 [skip ci]</li>
<li><a
href="https://github.com/bbottema/simple-java-mail/commit/12013d9057026ab2a634f5cfa8adf584653e7a89"><code>12013d9</code></a>
docs(release): prepare 9.3.2 release notes</li>
<li><a
href="https://github.com/bbottema/simple-java-mail/commit/8746cffb54b0957b667a3fca7bd2e199611dfbbd"><code>8746cff</code></a>
fix(recipients): clarify single-address parameter (<a
href="https://redirect.github.com/bbottema/simple-java-mail/issues/702">#702</a>)</li>
<li>See full diff in <a
href="https://github.com/bbottema/simple-java-mail/compare/9.3.1...9.3.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `org.simplejavamail:outlook-module` from 9.3.1 to 9.3.2


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-22 14:13:02 +00:00
admiralXS 1cb914023c fix: allow anonymous access to /invite/:token accept page (#7612)
## Problem

In the self-hosted build with login enabled, admin-generated invite
links point to the SPA route `/invite/<token>`, but that route is not
covered by the anonymous whitelist. Anonymous users get 401 / redirected
to `/login` before the React app can mount - even though the APIs the
page calls (`/api/v1/invite/validate`, `/api/v1/invite/accept`) are
already whitelisted. Since accepting an invite is how a *new* account is
created, requiring authentication first makes the feature unusable.

## Fix

Add `INVITE_LINK_PATTERN` (`^/invite/[^/]+/?$`) in
`RequestUriUtils.java`, matched at the end of `isPublicAuthEndpoint()` -
mirroring the existing `SHARE_LINK_PATTERN` handling. The invite data
APIs remain protected by their own token validation; only the SPA
bootstrap page becomes anonymously reachable.

## Tests

Added unit tests in `RequestUriUtilsTest.java` mirroring the share-link
tests:

- `/invite/<token>` (with/without trailing slash, with context path) ?
public
- bare `/invite` and `/invite/` ? NOT public (token segment required)
- `/invite/<token>/foo` nested paths ? NOT public
- `/inviteX` prefix over-match ? NOT public

## Verification

Pattern behavior validated against all test cases above. Live-tested on
2.14.3 self-hosted: anonymous `GET /invite/<token>` returned 401 before
the fix; the whitelisted accept flow itself (`validate` + `accept` APIs)
works anonymously end-to-end.
2026-08-21 21:47:57 +00:00
stirlingbot[bot] f5cf5f1077 Update Frontend 3rd Party Licenses (#7616)
Auto-generated by stirlingbot[bot]

This PR updates the frontend license report based on changes to
package.json dependencies.

Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2026-08-21 20:50:12 +00:00
Ludy 7fb29d002d deps(frontend): upgrade i18next ecosystem to v26 (#7356)
# Description of Changes

- Upgraded `i18next` to 26.3.6.
- Upgraded `react-i18next` to 17.0.11.
- Upgraded `i18next-browser-languagedetector` to 8.2.1.
- Replaced the removed `initImmediate` option with `initAsync`.
- Verified compatibility with the updated `<Trans>` behavior and
language detector APIs.
- No translation changes were required because all `<Trans>` usages use
explicit `i18nKey` values.

---

## 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-21 11:32:16 +00:00
Anthony Stirling 5f9c396fdd test: remove PdfUaBenchmarkTest (#7613) 2026-08-21 08:41:58 +01:00
stirlingbot[bot] e092b487ec Update Backend 3rd Party Licenses (#7608)
Auto-generated by stirlingbot[bot]

This PR updates the backend license report based on dependency changes.

Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2026-08-20 21:38:26 +00:00
dependabot[bot] a7c6fa6ef6 build(deps): bump io.swagger.core.v3:swagger-core-jakarta from 2.2.46 to 2.2.53 (#7526)
Bumps io.swagger.core.v3:swagger-core-jakarta from 2.2.46 to 2.2.53.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=io.swagger.core.v3:swagger-core-jakarta&package-manager=gradle&previous-version=2.2.46&new-version=2.2.53)](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-20 21:29:49 +00:00
brios 4e5b1102b6 refactor(search): improve TextInput clear button styling and add component unit tests (#7578)
# Description of Changes

FIxes minor stylistic problem about the search bar. Mainly the X and the
spacing on the result's icons vs text.


### New
<img width="1594" height="600" alt="image"
src="https://github.com/user-attachments/assets/f3710cad-f1a6-4aa1-9c2a-f3f474fd2dd6"
/>


### Old
<img width="1584" height="618" alt="image"
src="https://github.com/user-attachments/assets/2d9c26a8-2d68-4d86-9d51-b12f90b17fe0"
/>


<!--
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-20 21:21:50 +00:00
dependabot[bot] b3acdc4aab build(deps): bump actions/setup-java from 5.2.0 to 5.7.0 (#7530)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from
5.2.0 to 5.7.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-java/releases">actions/setup-java's
releases</a>.</em></p>
<blockquote>
<h2>v5.7.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix npm audit failures on releases/v5 by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1154">actions/setup-java#1154</a></li>
<li>Backport <a
href="https://redirect.github.com/actions/setup-java/issues/1151">#1151</a>:
Fix missing wrapper cache distributions by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1153">actions/setup-java#1153</a></li>
<li>Deprecate legacy Adopt distributions in v5 by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1186">actions/setup-java#1186</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-java/compare/v5.6.0...v5.7.0">https://github.com/actions/setup-java/compare/v5.6.0...v5.7.0</a></p>
<h2>v5.6.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Backport to v5: Add Maven compiler problem matcher for javac
diagnostics by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1087">actions/setup-java#1087</a></li>
<li>feat: expose cache-primary-key output (<a
href="https://redirect.github.com/actions/setup-java/issues/597">#597</a>)
[v5 backport] by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1089">actions/setup-java#1089</a></li>
<li>dist: Cover Tencent Kona JDK 25 (<a
href="https://redirect.github.com/actions/setup-java/issues/1108">#1108</a>)
[v5 backport] by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1110">actions/setup-java#1110</a></li>
<li>Backport <a
href="https://redirect.github.com/actions/setup-java/issues/1111">#1111</a>:
Preserve Maven toolchains across repeated setup-java runs (<a
href="https://redirect.github.com/actions/setup-java/issues/1099">#1099</a>)
by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1113">actions/setup-java#1113</a></li>
<li>Backport <a
href="https://redirect.github.com/actions/setup-java/issues/1097">#1097</a>/<a
href="https://redirect.github.com/actions/setup-java/issues/1098">#1098</a>
to v5: cache Maven and Gradle wrapper distributions separately by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1122">actions/setup-java#1122</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-java/compare/v5...v5.6.0">https://github.com/actions/setup-java/compare/v5...v5.6.0</a></p>
<h2>v5.5.0</h2>
<h2>What's Changed</h2>
<ul>
<li>chore: enforce pre-PR validation (aggregate scripts, git hooks, PR
checklist) by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1061">actions/setup-java#1061</a></li>
<li>Bump github/codeql-action from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-java/pull/1069">actions/setup-java#1069</a></li>
<li>Bump actions/checkout from 6 to 7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-java/pull/1068">actions/setup-java#1068</a></li>
<li>Bump actions/setup-python from 5 to 6 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-java/pull/1067">actions/setup-java#1067</a></li>
<li>Bump <code>@​typescript-eslint/parser</code> from 8.61.1 to 8.62.0
by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-java/pull/1062">actions/setup-java#1062</a></li>
<li>feat: Add verify-signature plumbing and Temurin+Microsoft
verification support by <a
href="https://github.com/johnoliver"><code>@​johnoliver</code></a> in <a
href="https://redirect.github.com/actions/setup-java/pull/1060">actions/setup-java#1060</a></li>
<li>Updated jetbrains test: https.request() now catches errors. This
fixes leaking tests as well by <a
href="https://github.com/jmjaffe37"><code>@​jmjaffe37</code></a> in <a
href="https://redirect.github.com/actions/setup-java/pull/1070">actions/setup-java#1070</a></li>
<li>Fix arm64 e2e workflow tests mislabeled as x64 by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a>
with <a href="https://github.com/Copilot"><code>@​Copilot</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1073">actions/setup-java#1073</a></li>
<li>feat: suppress Maven transfer progress via MAVEN_ARGS by default
(add show-download-progress input) by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1053">actions/setup-java#1053</a></li>
<li>feat: Disable interactiveMode in generated Maven settings.xml by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a>
with <a href="https://github.com/Copilot"><code>@​Copilot</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1052">actions/setup-java#1052</a></li>
<li>Bump prettier from 3.6.2 to 3.9.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-java/pull/1066">actions/setup-java#1066</a></li>
<li>chore(deps-dev): bump eslint-plugin-jest from 29.0.1 to 29.15.4 by
<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-java/pull/1074">actions/setup-java#1074</a></li>
<li>fix: Maven Toolchains grows unexpectedly by <a
href="https://github.com/Okeanos"><code>@​Okeanos</code></a> in <a
href="https://redirect.github.com/actions/setup-java/pull/534">actions/setup-java#534</a></li>
<li>dist: Support Tencent Kona JDK by <a
href="https://github.com/johnshajiang"><code>@​johnshajiang</code></a>
in <a
href="https://redirect.github.com/actions/setup-java/pull/672">actions/setup-java#672</a></li>
<li>feat: Add set-default option by <a
href="https://github.com/gsmet"><code>@​gsmet</code></a> in <a
href="https://redirect.github.com/actions/setup-java/pull/1017">actions/setup-java#1017</a></li>
<li>docs: document problem matcher (and how to disable it), Maven
Wrapper caching, and generated interactiveMode by <a
href="https://github.com/brunoborges"><code>@​brunoborges</code></a> in
<a
href="https://redirect.github.com/actions/setup-java/pull/1075">actions/setup-java#1075</a></li>
<li>feat: Add distribution detection support to .sdkmanrc file by <a
href="https://github.com/lukaszgyg"><code>@​lukaszgyg</code></a> in <a
href="https://redirect.github.com/actions/setup-java/pull/975">actions/setup-java#975</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/jmjaffe37"><code>@​jmjaffe37</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-java/pull/1070">actions/setup-java#1070</a></li>
<li><a href="https://github.com/gsmet"><code>@​gsmet</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-java/pull/1017">actions/setup-java#1017</a></li>
<li><a href="https://github.com/lukaszgyg"><code>@​lukaszgyg</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-java/pull/975">actions/setup-java#975</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-java/compare/v5...v5.5.0">https://github.com/actions/setup-java/compare/v5...v5.5.0</a></p>
<h2>v5.4.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump <code>@​typescript-eslint/parser</code> from 8.48.0 to 8.61.1
by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-java/pull/1021">actions/setup-java#1021</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/setup-java/commit/b6effb05e454b25005698d916606bdc6ffcbf961"><code>b6effb0</code></a>
Deprecate legacy Adopt distributions in v5 (<a
href="https://redirect.github.com/actions/setup-java/issues/1186">#1186</a>)</li>
<li><a
href="https://github.com/actions/setup-java/commit/e498d2a66a953492f322542257b22125c989b422"><code>e498d2a</code></a>
Backport <a
href="https://redirect.github.com/actions/setup-java/issues/1151">#1151</a>:
Fix missing wrapper cache distributions (<a
href="https://redirect.github.com/actions/setup-java/issues/1153">#1153</a>)</li>
<li><a
href="https://github.com/actions/setup-java/commit/6a3384db745932178632d0e22b2bd28cad1678e6"><code>6a3384d</code></a>
Fix npm audit failures on releases/v5 (<a
href="https://redirect.github.com/actions/setup-java/issues/1154">#1154</a>)</li>
<li><a
href="https://github.com/actions/setup-java/commit/03ad4de0992f5dab5e18fcb136590ce7c4a0ac95"><code>03ad4de</code></a>
Backport <a
href="https://redirect.github.com/actions/setup-java/issues/1097">#1097</a>/<a
href="https://redirect.github.com/actions/setup-java/issues/1098">#1098</a>:
cache Maven and Gradle wrapper distributions separately...</li>
<li><a
href="https://github.com/actions/setup-java/commit/d229d2e858d9137cc0b3f118fa5184b9f0a44ac4"><code>d229d2e</code></a>
Backport <a
href="https://redirect.github.com/actions/setup-java/issues/1111">#1111</a>:
Preserve Maven toolchains across repeated setup-java runs (<a
href="https://redirect.github.com/actions/setup-java/issues/1">#1</a>...</li>
<li><a
href="https://github.com/actions/setup-java/commit/bbf0f6967066506f72571a96d5d6c67ca42ab460"><code>bbf0f69</code></a>
dist: Cover Tencent Kona JDK 25 (<a
href="https://redirect.github.com/actions/setup-java/issues/1110">#1110</a>)</li>
<li><a
href="https://github.com/actions/setup-java/commit/513edc4f8710565e4ad696f3b7d8e3bda584a46c"><code>513edc4</code></a>
feat: expose cache-primary-key output (<a
href="https://redirect.github.com/actions/setup-java/issues/597">#597</a>)
[v5 backport] (<a
href="https://redirect.github.com/actions/setup-java/issues/1089">#1089</a>)</li>
<li><a
href="https://github.com/actions/setup-java/commit/62df799a9c6e3022bb466697c66c36e9a2dbf347"><code>62df799</code></a>
Add Maven compiler problem matcher for javac diagnostics (<a
href="https://redirect.github.com/actions/setup-java/issues/1087">#1087</a>)</li>
<li><a
href="https://github.com/actions/setup-java/commit/176156a187714aaf460b0a3c8f21e8b4f784b978"><code>176156a</code></a>
chore: bump version to 5.6.0 for v5 release line</li>
<li><a
href="https://github.com/actions/setup-java/commit/bf7b8deac240b9cee05eb15ccdb1d2f424a54b9f"><code>bf7b8de</code></a>
build: rebuild dist for backported changes (<a
href="https://redirect.github.com/actions/setup-java/issues/1079">#1079</a>,
<a
href="https://redirect.github.com/actions/setup-java/issues/1083">#1083</a>,
<a
href="https://redirect.github.com/actions/setup-java/issues/1084">#1084</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/setup-java/compare/v5.2.0...b6effb05e454b25005698d916606bdc6ffcbf961">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-20 21:10:12 +00:00
dependabot[bot] b549964529 build(deps-dev): bump fpdf2 from 2.8.7 to 2.8.8 in /engine (#7560)
Bumps [fpdf2](https://github.com/py-pdf/fpdf2) from 2.8.7 to 2.8.8.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/py-pdf/fpdf2/releases">fpdf2's
releases</a>.</em></p>
<blockquote>
<h2>Add resource access controls, SVG complexity limits, Optional
Content Groups, and other features and bug fixes</h2>
<h2>[2.8.8] - 2026-08-09</h2>
<blockquote>
<p>[!WARNING]
Upgrading to <strong>fpdf2 2.8.8</strong> is strongly recommended for
applications that render user-provided images, SVGs, or HTML
content.</p>
</blockquote>
<h3>Added</h3>
<ul>
<li>Punjabi (pa) tutorial translation - thanks to <a
href="https://github.com/Pawansingh3889"><code>@​Pawansingh3889</code></a></li>
<li><code>FPDF.svg_limits</code> and <code>SVGLimits</code> to configure
SVG complexity limits while rendering SVG images</li>
<li><code>resource_access_policy</code> and <a
href="https://py-pdf.github.io/fpdf2/Security.html">Security
considerations</a> documentation</li>
<li><a
href="https://py-pdf.github.io/fpdf2/OptionalContent.html"><code>FPDF.optional_content()</code></a>
context manager to mark content as visible on screen only or in print
only, using PDF Optional Content Groups - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/441">#441</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/441">py-pdf/fpdf2#441</a>),
based on a recipe by <a
href="https://github.com/digidigital"><code>@​digidigital</code></a> -
thanks to <a
href="https://github.com/eugen-goebel"><code>@​eugen-goebel</code></a></li>
<li>basic support for SVG <code>&lt;symbol&gt;</code> elements in the
SVG parser - thanks to <a
href="https://github.com/Theo1335"><code>@​Theo1335</code></a></li>
<li>basic support for SVG <code>&lt;switch&gt;</code> elements in the
SVG parser - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/537">#537</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/537">py-pdf/fpdf2#537</a>)
- thanks to <a
href="https://github.com/dannymaaz"><code>@​dannymaaz</code></a></li>
<li>support for keeping aspect ratio for images in templates -
<em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1118">#1118</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1118">py-pdf/fpdf2#1118</a>)
- thanks to <a
href="https://github.com/prateek-dagar"><code>@​prateek-dagar</code></a></li>
</ul>
<h3>Fixed</h3>
<ul>
<li>custom height passed to <code>Paragraph.ln()</code> in a text region
is now applied to the line it terminates instead of the first line of
the following paragraph - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1786">#1786</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1786">py-pdf/fpdf2#1786</a>)
- thanks to <a
href="https://github.com/Sanjays2402"><code>@​Sanjays2402</code></a></li>
<li>the optional <code>numpy</code> import in
<code>image_parsing.py</code> no longer crashes on CPUs unsupported by
numpy's <code>manylinux</code> wheel baseline; <code>RuntimeError</code>
is now treated the same as <code>ImportError</code>, so
<code>numpy</code> degrades to unavailable instead of taking down
<code>import fpdf</code> - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1908">#1908</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1908">py-pdf/fpdf2#1908</a>)
- thanks to <a
href="https://github.com/stumpylog"><code>@​stumpylog</code></a></li>
<li>font state (family, style, size, current font, and the page-level
&quot;font is set&quot; flag) no longer leaks back onto the
<code>FPDF</code> instance after a <code>text_columns()</code> /
<code>text_region()</code> context exits, so a subsequent
<code>pdf.cell()</code> / <code>pdf.write()</code> renders at the
caller's font instead of the last paragraph's - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1804">#1804</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1804">py-pdf/fpdf2#1804</a>)
- thanks to <a
href="https://github.com/Pawansingh3889"><code>@​Pawansingh3889</code></a></li>
<li>text rendering when the first text on a page starts with a fallback
glyph - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1772">#1772</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1772">py-pdf/fpdf2#1772</a>)</li>
<li>preserve boundary-neutral formatting during bidirectional text
preprocessing - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1779">#1779</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1779">py-pdf/fpdf2#1779</a>)</li>
<li>transform application on user space gradients - <em>cf.</em> [issue
<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1784">#1784</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1784">py-pdf/fpdf2#1784</a>)</li>
<li>dependency extras for camelot-py and endesive on pyproject.toml -
<em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1792">#1792</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1792">py-pdf/fpdf2#1792</a>)</li>
<li>preserve link annotations during dry-run of
<code>FPDF.multi_cell</code> - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1807">#1807</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1807">py-pdf/fpdf2#1807</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>preserve two consecutive markdown links (without space inbetween) -
<em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1814">#1814</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1814">py-pdf/fpdf2#1814</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>support markdown style around markdown links - <em>cf.</em> [issue
<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1826">#1826</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1826">py-pdf/fpdf2#1826</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>Reset gstate for ToC-rendering - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1837">#1837</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1837">py-pdf/fpdf2#1837</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>preserve markdown format in <code>FPDF.multi_cell</code> in dry-run
- <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1840">#1840</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1840">py-pdf/fpdf2#1840</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>fix page order after dry-run of <code>FPDF.multi_cell</code> in ToC
- <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1836">#1836</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1836">py-pdf/fpdf2#1836</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>rendering SVG arcs with very small sweeps that previously rounded to
zero - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1831">#1831</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1831">py-pdf/fpdf2#1831</a>)</li>
<li>spurious &quot;Not enough horizontal space to render a single
character&quot; error when text without break opportunities is split
into many small fragments, e.g. by a fallback font alternating with the
main font - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1250">#1250</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1250">py-pdf/fpdf2#1250</a>)
- thanks to <a
href="https://github.com/uttam12331"><code>@​uttam12331</code></a></li>
<li>number of surviving escape characters - <strong>cf.</strong> [issue
<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1215">#1215</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1215">py-pdf/fpdf2#1215</a>)
- thanks to <a
href="https://github.com/amidou-naba"><code>@​amidou-naba</code></a></li>
<li>leading spaces on new lines inside <code>&lt;pre&gt;</code> and
<code>&lt;pre&gt;&lt;code&gt;</code> blocks are no longer dropped -
<em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1063">#1063</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1063">py-pdf/fpdf2#1063</a>)
- thanks to <a
href="https://github.com/eugen-goebel"><code>@​eugen-goebel</code></a></li>
<li><code>FPDF.set_font()</code> can restore <code>current_font</code>
when the selected font state diverged - <em>cf.</em> [PR <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1872">#1872</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/pull/1872">py-pdf/fpdf2#1872</a>)
- thanks to <a
href="https://github.com/gaoflow"><code>@​gaoflow</code></a></li>
<li>embed CID-keyed CFF fonts as raw CFF programs so browser PDF viewers
render them correctly - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1874">#1874</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1874">py-pdf/fpdf2#1874</a>)</li>
<li>fixed broken links on documentation not directly leading to the API
reference - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1876">#1876</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1876">py-pdf/fpdf2#1876</a>)
- thanks to <a
href="https://github.com/iamfazakb"><code>@​iamfazakb</code></a></li>
<li>reject SVG <code>&lt;use&gt;</code> cycles and excessive nested
expansion to prevent resource exhaustion in
<code>FPDF.image()</code></li>
<li>count SVG <code>&lt;switch&gt;</code> elements in SVG complexity
limits</li>
<li>declare the default base state and display order for Optional
Content Groups so PDF viewers can list layers correctly - <em>cf.</em>
[issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1895">#1895</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1895">py-pdf/fpdf2#1895</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>skip byte-for-byte compressed data comparison when zlib-ng is
detected, regardless of OS</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/py-pdf/fpdf2/blob/master/CHANGELOG.md">fpdf2's
changelog</a>.</em></p>
<blockquote>
<h2>[2.8.8] - 2026-08-09</h2>
<h3>Added</h3>
<ul>
<li>Punjabi (pa) tutorial translation - thanks to <a
href="https://github.com/Pawansingh3889"><code>@​Pawansingh3889</code></a></li>
<li><code>FPDF.svg_limits</code> and <code>SVGLimits</code> to configure
SVG complexity limits while rendering SVG images</li>
<li><code>resource_access_policy</code> and <a
href="https://py-pdf.github.io/fpdf2/Security.html">Security
considerations</a> documentation</li>
<li><a
href="https://py-pdf.github.io/fpdf2/OptionalContent.html"><code>FPDF.optional_content()</code></a>
context manager to mark content as visible on screen only or in print
only, using PDF Optional Content Groups - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/441">#441</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/441">py-pdf/fpdf2#441</a>),
based on a recipe by <a
href="https://github.com/digidigital"><code>@​digidigital</code></a> -
thanks to <a
href="https://github.com/eugen-goebel"><code>@​eugen-goebel</code></a></li>
<li>basic support for SVG <code>&lt;symbol&gt;</code> elements in the
SVG parser - thanks to <a
href="https://github.com/Theo1335"><code>@​Theo1335</code></a></li>
<li>basic support for SVG <code>&lt;switch&gt;</code> elements in the
SVG parser - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/537">#537</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/537">py-pdf/fpdf2#537</a>)
- thanks to <a
href="https://github.com/dannymaaz"><code>@​dannymaaz</code></a></li>
<li>support for keeping aspect ratio for images in templates -
<em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1118">#1118</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1118">py-pdf/fpdf2#1118</a>)
- thanks to <a
href="https://github.com/prateek-dagar"><code>@​prateek-dagar</code></a></li>
</ul>
<h3>Fixed</h3>
<ul>
<li>custom height passed to <code>Paragraph.ln()</code> in a text region
is now applied to the line it terminates instead of the first line of
the following paragraph - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1786">#1786</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1786">py-pdf/fpdf2#1786</a>)
- thanks to <a
href="https://github.com/Sanjays2402"><code>@​Sanjays2402</code></a></li>
<li>the optional <code>numpy</code> import in
<code>image_parsing.py</code> no longer crashes on CPUs unsupported by
numpy's <code>manylinux</code> wheel baseline; <code>RuntimeError</code>
is now treated the same as <code>ImportError</code>, so
<code>numpy</code> degrades to unavailable instead of taking down
<code>import fpdf</code> - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1908">#1908</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1908">py-pdf/fpdf2#1908</a>)
- thanks to <a
href="https://github.com/stumpylog"><code>@​stumpylog</code></a></li>
<li>font state (family, style, size, current font, and the page-level
&quot;font is set&quot; flag) no longer leaks back onto the
<code>FPDF</code> instance after a <code>text_columns()</code> /
<code>text_region()</code> context exits, so a subsequent
<code>pdf.cell()</code> / <code>pdf.write()</code> renders at the
caller's font instead of the last paragraph's - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1804">#1804</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1804">py-pdf/fpdf2#1804</a>)
- thanks to <a
href="https://github.com/Pawansingh3889"><code>@​Pawansingh3889</code></a></li>
<li>text rendering when the first text on a page starts with a fallback
glyph - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1772">#1772</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1772">py-pdf/fpdf2#1772</a>)</li>
<li>preserve boundary-neutral formatting during bidirectional text
preprocessing - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1779">#1779</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1779">py-pdf/fpdf2#1779</a>)</li>
<li>transform application on user space gradients - <em>cf.</em> [issue
<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1784">#1784</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1784">py-pdf/fpdf2#1784</a>)</li>
<li>dependency extras for camelot-py and endesive on pyproject.toml -
<em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1792">#1792</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1792">py-pdf/fpdf2#1792</a>)</li>
<li>preserve link annotations during dry-run of
<code>FPDF.multi_cell</code> - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1807">#1807</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1807">py-pdf/fpdf2#1807</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>preserve two consecutive markdown links (without space inbetween) -
<em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1814">#1814</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1814">py-pdf/fpdf2#1814</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>support markdown style around markdown links - <em>cf.</em> [issue
<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1826">#1826</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1826">py-pdf/fpdf2#1826</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>Reset gstate for ToC-rendering - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1837">#1837</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1837">py-pdf/fpdf2#1837</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>preserve markdown format in <code>FPDF.multi_cell</code> in dry-run
- <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1840">#1840</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1840">py-pdf/fpdf2#1840</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>fix page order after dry-run of <code>FPDF.multi_cell</code> in ToC
- <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1836">#1836</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1836">py-pdf/fpdf2#1836</a>)
- thanks to <a
href="https://github.com/CoLa5"><code>@​CoLa5</code></a></li>
<li>rendering SVG arcs with very small sweeps that previously rounded to
zero - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1831">#1831</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1831">py-pdf/fpdf2#1831</a>)</li>
<li>spurious &quot;Not enough horizontal space to render a single
character&quot; error when text without break opportunities is split
into many small fragments, e.g. by a fallback font alternating with the
main font - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1250">#1250</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1250">py-pdf/fpdf2#1250</a>)
- thanks to <a
href="https://github.com/uttam12331"><code>@​uttam12331</code></a></li>
<li>number of surviving escape characters - <strong>cf.</strong> [issue
<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1215">#1215</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1215">py-pdf/fpdf2#1215</a>)
- thanks to <a
href="https://github.com/amidou-naba"><code>@​amidou-naba</code></a></li>
<li>leading spaces on new lines inside <code>&lt;pre&gt;</code> and
<code>&lt;pre&gt;&lt;code&gt;</code> blocks are no longer dropped -
<em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1063">#1063</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1063">py-pdf/fpdf2#1063</a>)
- thanks to <a
href="https://github.com/eugen-goebel"><code>@​eugen-goebel</code></a></li>
<li><code>FPDF.set_font()</code> can restore <code>current_font</code>
when the selected font state diverged - <em>cf.</em> [PR <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1872">#1872</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/pull/1872">py-pdf/fpdf2#1872</a>)
- thanks to <a
href="https://github.com/gaoflow"><code>@​gaoflow</code></a></li>
<li>embed CID-keyed CFF fonts as raw CFF programs so browser PDF viewers
render them correctly - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1874">#1874</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1874">py-pdf/fpdf2#1874</a>)</li>
<li>fixed broken links on documentation not directly leading to the API
reference - <em>cf.</em> [issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1876">#1876</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1876">py-pdf/fpdf2#1876</a>)
- thanks to <a
href="https://github.com/iamfazakb"><code>@​iamfazakb</code></a></li>
<li>reject SVG <code>&lt;use&gt;</code> cycles and excessive nested
expansion to prevent resource exhaustion in
<code>FPDF.image()</code></li>
<li>count SVG <code>&lt;switch&gt;</code> elements in SVG complexity
limits</li>
<li>declare the default base state and display order for Optional
Content Groups so PDF viewers can list layers correctly - <em>cf.</em>
[issue <a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1895">#1895</a>](<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1895">py-pdf/fpdf2#1895</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>skip byte-for-byte compressed data comparison when zlib-ng is
detected, regardless of OS</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/e1fc653d8fce65d2fb118755bda8581a9bf1e4d9"><code>e1fc653</code></a>
release v2.8.8 (<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1916">#1916</a>)</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/42ec66442bf278b9768ca787fe601d3d334c62e4"><code>42ec664</code></a>
add Sanjays2402 as a contributor for code (<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1915">#1915</a>)</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/af9d7dc11c36db49364c0096ad1edca5d569c676"><code>af9d7dc</code></a>
fix(text_region): apply Paragraph.ln(h) height to the line it terminates
(<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1904">#1904</a>)</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/81951f837b46782df38f7c4d6f4c8f2644ac9b7e"><code>81951f8</code></a>
add stumpylog as a contributor for bug, and code (<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1913">#1913</a>)</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/b30c38c8cfc804342f429fffb26cc44f34f20af3"><code>b30c38c</code></a>
Fix: catch RuntimeError alongside ImportError for the optional numpy
import (...</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/63df0d0f4f085d3a014166d2d752d9c1e77305e4"><code>63df0d0</code></a>
Update github/codeql-action action to v4.37.6 (<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1910">#1910</a>)</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/11a30e672cad2157b657642ed290cb27eb57e482"><code>11a30e6</code></a>
Update crate-ci/typos action to v1.49.0 (<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1911">#1911</a>)</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/f65707b369a7ca7aaa6226a77eabf69b9903eac4"><code>f65707b</code></a>
Update step-security/harden-runner action to v2.20.1 (<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1912">#1912</a>)</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/a7f7c8945139fb5a20d1993fcff6484b5c2267c7"><code>a7f7c89</code></a>
Update github/codeql-action action to v4.37.4 (<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1907">#1907</a>)</li>
<li><a
href="https://github.com/py-pdf/fpdf2/commit/fe9d8f52643c5dcb88370813f51c29410463e299"><code>fe9d8f5</code></a>
Update pypa/gh-action-pypi-publish action to v1.14.2 (<a
href="https://redirect.github.com/py-pdf/fpdf2/issues/1906">#1906</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/py-pdf/fpdf2/compare/2.8.7...2.8.8">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=fpdf2&package-manager=uv&previous-version=2.8.7&new-version=2.8.8)](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-20 21:10:05 +00:00
github-actions[bot]andLudy87 8e3ecb1fe4 chore: update Gradle to 9.7.1 (#7607)
Automated update of the Gradle wrapper and Gradle Docker build images.

Gradle version: `9.7.1`
Docker image: `gradle:9.7.1-jdk25`

Co-authored-by: Ludy87 <4592558+Ludy87@users.noreply.github.com>
2026-08-20 20:46:50 +00:00
Ludy cb0cafabd9 ci: Extract Gradle cache priming into a reusable workflow (#7572)
# Description of Changes

- What was changed
- Moved the `gradle-cache-prime` job from `build.yml` into a dedicated
reusable workflow.
  - Added `workflow_call` support for invocation from other workflows.
  - Added a `push` trigger for the `main` branch.
  - Updated `build.yml` to call the new reusable workflow.

- Why the change was made
- Keeps the shared Gradle cache warm after changes are pushed to `main`.
- Allows pull request builds to reuse the same cache and reduce
dependency resolution time.
  - Separates cache maintenance from the main build 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-20 20:03:54 +00:00
stirlingbot[bot] 90d39aec0b 🌐 Sync Translations + Update README Progress Table (#7583)
### Description of Changes

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`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.
- **Format**: TOML

#### **2. Update README.md**
- Generated the translation progress table in `README.md` using
`counter_translation_v3.py`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

#### **Why these changes are necessary**
- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2026-08-20 19:44:56 +00:00