Commit Graph
357 Commits
Author SHA1 Message Date
Anthony StirlingandGitHub b355ccec9e Add Valkey cluster backplane and sticky-410 ownership (clusters) (#6472) 2026-06-02 14:59:20 +01:00
briosandGitHub 2c0ebc28a7 perf(api): optimize static asset caching, enable ETag support, and expand response compression mime types. (#6273) 2026-06-01 16:37:56 +01:00
Anthony StirlingandGitHub 30e782e29c Disable Save-to-server when storage off, fix QR port 0 (#6473) 2026-05-29 19:37:42 +01:00
EthanHealy01andGitHub 763595a5a3 feat: add Agents UI to proprietary right sidebar (#6454)
Update UI to include agents

Run `task dev:all` to test
2026-05-28 17:26:23 +00:00
Anthony StirlingandGitHub 398617391b Fix SSO auto-login and custom metadata settings not persisting on restart (#6468) 2026-05-28 17:39:05 +01:00
ConnorYohandGitHub a0e0e88f07 saas: harden CreditService Stripe ordering + lint @AutoJobPostMapping weights (#6458)
# Description of Changes

Two narrowly-scoped hardening changes to the credits engine.

## 1. CreditService — move Stripe meter call to `afterCommit`

The Stripe metered-usage call sits inside the surrounding
`@Transactional`, holding the `user_credits` row lock for the duration
of an HTTP round-trip to Supabase. Under load this starves concurrent
debits; a transient Stripe blip rolls back a (correct) free-credit
consumption and forces the caller to retry.

The Stripe call now runs in a `TransactionSynchronization.afterCommit`
hook — DB commits first, Stripe fires immediately after. If Stripe fails
after commit, we log + increment a new `credits.stripe_report.failures`
counter; the idempotency key is stable, so a manual replay recovers
without double-charging.

Applied to both `consumeCreditBySupabaseId` and
`consumeCreditWithWaterfall`.

**Dead-code removed:**
- Unreachable UUID fallback for MDC `requestId` — `CorrelationIdFilter`
already guarantees the key on every request.
- The `"Unable to report usage to Stripe"` `RuntimeException` and its
catch block — the afterCommit refactor eliminates the throw path.
- `StripeRollbackOnFailureTest` — pinned the rollback-on-Stripe-fail
behaviour this refactor replaces.

## 2. `@AutoJobPostMapping` — build-time lint for `resourceWeight`

`UnifiedCreditInterceptor` multiplies `resourceWeight` into the per-call
charge. An endpoint that falls through to the annotation default
produces a charge derived from a value nobody chose.

- Annotation default flipped from `1` to `Integer.MIN_VALUE` (sentinel).
Both runtime readers (`UnifiedCreditInterceptor`, `AutoJobAspect`)
already clamp into `[1, 100]` so behaviour is unchanged.
- New `AutoJobPostMappingWeightTest` scans the classpath and fails the
build if any method leaves the sentinel.
- Initial run caught 11 endpoints relying on the default. Explicit
weights now declared, chosen by comparing to peer endpoints:
  - `EditTextController` — LARGE
  - `EmailController#sendEmailWithAttachment` — SMALL
  - `ConvertPDFToMarkdown` — MEDIUM
  - `AttachmentController` (extract/list/rename/delete) — SMALL × 4
  - `ConvertImgPDFController` (cbr/cbz ↔ pdf) — MEDIUM × 2, LARGE × 2

## Tests

- `StripeUsageIdempotencyKeyTest` — pins the `(supabaseId, overage,
requestId)` idempotency key shape so Stripe always dedupes a retry.
- `StripeAfterCommitOrderingTest` — pins that `afterCommit` fires after
commit and NOT on rollback.
- `AutoJobPostMappingWeightTest` — the lint itself, plus a self-check
that the classpath scan finds at least 10 `@AutoJobPostMapping` methods
(guards against the lint passing vacuously).

Build verified: `ENABLE_SAAS=true ./gradlew :stirling-pdf:test
:saas:test`.

---

## 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) — no translation changes
- [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/)
— internal-billing change, no public docs impact
- [ ] 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)
— N/A

### Translations (if applicable)

- [ ] Not applicable

### UI Changes (if applicable)

- [ ] Not applicable

### Testing (if applicable)

- [x] I have run `task check` (via `./gradlew :stirling-pdf:test
:saas:test` with `ENABLE_SAAS=true`) — passes
- [x] I have tested my changes locally
2026-05-28 14:57:59 +00:00
Anthony StirlingandGitHub c80a5db5f5 folder and file fixes (#6461) 2026-05-28 15:57:35 +01:00
8bd78d2624 Add landscape page size options (#6248)
# Description of Changes

Adds orientation (portrait/landscape) to the Adjust Page Scale tool.

- Orientation as a separate parameter (per review), sent through to the
backend
- ScalePagesController simplified; PDFWithPageSize gains the orientation
field
- Regenerated tool_models.py; frontend + backend tests added

---

## 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: ConnorYoh <[email protected]>
2026-05-28 14:16:15 +00:00
Anthony StirlingandGitHub b3c4b8b463 Add S3 storage and cluster artifact backend (#6457) 2026-05-28 13:06:27 +01:00
ConnorYohandGitHub 43b67d213d feat(oauth2): opt-in claim-dump diagnostics for OIDC login failures (#6456)
# Description of Changes

## What & why

Customers using ADFS (or any generic OIDC provider that doesn't emit
`email`) hit `Attribute value for 'email' cannot be null` during OAuth2
login with no visibility into what claims the provider actually sent.
The only available remedy was guessing at
`security.oauth2.useAsUsername` until something worked.

This PR adds a new opt-in `security.oauth2.debugLogging` flag (default
`false`). When enabled, `CustomOAuth2UserService` logs:

- All ID token claims (sorted, with values)
- All UserInfo endpoint claims (if any)
- The merged attribute key set Spring exposes to `getAttribute()`
- The value the configured `useAsUsername` actually resolved to
- A **`Hint:`** line listing the claim keys present in the token that
map to a valid `UsernameAttribute` enum value — i.e. exactly what the
operator could put in `useAsUsername` to make login work

Logged at `INFO` on the success path and `ERROR` on failure (inside the
existing `catch (IllegalArgumentException)` block that throws
`OAuth2AuthenticationException`). The block is wrapped with a `[OAUTH2
DEBUG] ... [/OAUTH2 DEBUG]` banner and ends with a PII warning so
operators don't leave it on in production.

Default off → zero observable change for anyone not actively
troubleshooting.

## Files changed

| File | Why |
|---|---|
| `app/common/.../ApplicationProperties.java` | New `debugLogging` field
on the `OAUTH2` config class with javadoc warning about PII |
| `app/core/src/main/resources/settings.yml.template` | Documents
`oauth2.debugLogging` so it appears on next startup |
| `app/proprietary/.../security/service/CustomOAuth2UserService.java` |
Emits the claim dump + suggestion hint when the flag is on |
|
`app/proprietary/.../security/service/CustomOAuth2UserServiceDebugLoggingTest.java`
(new) | Unit test: mocks the OIDC delegate, asserts off-path is silent
and on-path emits the dump with the right Hint contents |

## End-to-end verification

Ran the bundled `testing/compose/docker-compose-keycloak-oauth.yml`
Keycloak realm, configured `security.oauth2.useAsUsername: mail`
(Keycloak emits `email`, not `mail`) and `provider: demarest` (matches
the original customer bug report). Triggered the OAuth flow at
`http://localhost:8080/oauth2/authorization/demarest` and confirmed:

- The ERROR-level dump fires with the full 19-claim ID token decoded
- `-- Value at 'mail' : <NULL — this is why login fails>` correctly
identifies the missing claim
- `-- Hint:` correctly suggests `[email, family_name, given_name,
preferred_username]` (the four keys present that map to valid
`UsernameAttribute` values)
- Auth still fails with the original `OAuth2AuthenticationException` —
no change to control flow, just added diagnostic logging

Unit test (`CustomOAuth2UserServiceDebugLoggingTest`) covers both
branches.

## Reviewer notes

- **No new public APIs.** The flag is config-only; no servlet endpoints
exposed.
- **PII is logged when the flag is on.** This is the whole point —
operators need to see the claims to fix their config — but it's gated,
defaults off, and the dump self-documents with a `WARNING: ... Set
security.oauth2.debugLogging=false once troubleshooting is complete.`
footer.
- **Why log everything, not just sub/email?** Because the operator
doesn't know in advance which claim they actually want. ADFS uses `upn`
in some configs and `preferred_username` in others; Azure AD uses `oid`;
the customer here had neither. Dumping the full set is the only way to
make the diagnostic self-service.
- **Out of scope for this PR (follow-ups):**
- The `UsernameAttribute` enum doesn't include `upn` / `unique_name`
(common ADFS claims). If the customer's token only has `upn`, the Hint
will be empty even though the operator can see `upn` in the dump. Worth
a separate PR to extend the enum.
- The known-provider validator in `Provider.java` (rejects e.g.
`useAsUsername: mail` for `provider: keycloak` at startup) bypasses our
diagnostic for those provider names. ADFS customers using `provider:
<name>` fall into the `default` branch so are not affected — but it's a
sharp edge worth documenting.

---

## 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) — N/A, backend-only change
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] Doc-repo update (if functionality has heavily changed) —
diagnostic flag is self-documenting via the `settings.yml.template`
comment and the in-log warning; happy to add a doc-repo entry if
reviewers want one
- [ ] Translation tags — N/A

### UI Changes (if applicable)

- [ ] N/A — backend-only

### Testing (if applicable)

- [x] Unit test added (`CustomOAuth2UserServiceDebugLoggingTest`)
covering on/off paths and Hint correctness
- [x] End-to-end verified locally against bundled Keycloak compose with
intentionally misconfigured `useAsUsername`
- [x] Full `:proprietary:test` suite passes
2026-05-27 13:01:51 +00:00
Anthony StirlingandGitHub d42b779644 Add server-side folders and files page UI (#6383) 2026-05-27 12:52:46 +01:00
Anthony StirlingandGitHub 4564ed5bec Add cluster backplane abstraction and interfaces (#6449) 2026-05-27 11:54:59 +01:00
Anthony StirlingandGitHub 56ff1e5092 impl migration to pdfium for split (#6410)
## Summary

Migrates `SplitPDFController`, `SplitPdfByChaptersController`,
`SplitPdfBySizeController` from PDFBox to JPDFium.
`SplitPdfBySectionsController` and `AutoSplitPdfController` are
intentionally left on PDFBox (require JPDFium 1.0.2 features that don't
exist yet).

## Benchmark (audited on `audit/jpdfium-split`, file
`app/core/src/test/java/stirling/software/SPDF/bench/SplitBenchmark.java`)

| Workload | PDFBox heap | JPDFium heap | PDFBox wall | JPDFium wall |
|---|---|---|---|---|
| 100 pp, chunk 10 | +21-26 MB | **+0.02 MB** | 80-106 ms | **25 ms** |
| 300 pp, chunk 10 | +59 MB | **+1.0 MB** | 232 ms | **76 ms** |

**98-99.9% heap reduction. 3-4.2x faster wall.**

## Hybrid

- AcroForm-bearing splits keep PDFBox
`FormUtils.pruneOrphanedFormFields` post-pass (FPDF_ImportPagesByIndex
drops AcroForm dict). Sub-bench shows +1.0 MB / +27 ms - tightly
bounded.
- Metadata extraction stays on PDFBox.
- `SplitPdfBySectionsController` - JPDFium `PdfPageSplitter` only does
2-up halving, not arbitrary MxN.
- `AutoSplitPdfController` - needs PDFRenderer + zxing for QR markers.

## Test plan

- [ ] 30/30 unit tests pass with PDFBox `Loader.loadPDF` as the oracle
(assert page counts + document totals)
- [ ] Existing cucumber feature `split.feature` continues to pass
- [ ] AcroForm-bearing PDF round-trips without orphaned widgets (covered
by existing FormUtils tests)
2026-05-26 17:50:13 +01:00
Reece BrowneandGitHub 4047d02086 chore: address restructure PR review feedback (#6423) 2026-05-26 14:12:05 +01:00
0a50e765b7 Restructure/frontend editor (#6404)
## Move editor under `frontend/editor/`

Pure restructure: `frontend/` becomes the workspace, `frontend/editor/`
holds
  the PDF editor. 1775 file renames + 40 wiring edits. No logic changes.

  ### Why

`frontend/` is currently the editor — its `src/`, `public/`,
`src-tauri/`,
  config files all sit at the root. Promoting `frontend/` to a
workspace and putting the editor in a sibling folder leaves room for
future
apps to drop in alongside it, sharing one `package.json` /
`node_modules` /
  lint config / Storybook.

  ### What moves

  frontend/
  ├── editor/                ← NEW: everything editor-specific
  │   ├── src/               ← was frontend/src/
  │   ├── public/            ← was frontend/public/
  │   ├── src-tauri/         ← was frontend/src-tauri/
│ ├── index.html, vite.config.ts, vitest.config.ts, playwright.config.ts
  │   ├── tsconfig*.json, tailwind.config.js, postcss.config.js
  │   ├── scripts/
  │   ├── .env, .env.desktop, .env.saas
  │   └── DeveloperGuide.md
├── package.json, package-lock.json, node_modules/ ← workspace install
  ├── eslint.config.mjs, .prettierrc, .prettierignore ← shared tooling
  ├── .gitignore
  └── README.md

  ### Wiring edits (40 files)

  - `.taskfiles/frontend.yml`, `desktop.yml`, `e2e.yml`
  - `build.gradle`, `app/core/build.gradle`
- `eslint.config.mjs`, `frontend/package.json`, `.gitignore`,
`.prettierignore`
  - `docker/frontend/Dockerfile`
  - 8 `.github/workflows/*.yml`, plus `.github/dependabot.yml`,
    `.github/config/.files.yaml`, `.github/labeler-config-srvaroa.yml`
  - `scripts/translations/**`
- Docs: `AGENTS.md`, `CLAUDE.md`, `ADDING_TOOLS.md`,
`DeveloperGuide.md`,
`WINDOWS_SIGNING.md`, `devGuide/HowToAddNewLanguage.md`,
`frontend/README.md`,
    `frontend/editor/DeveloperGuide.md`

Plus 3 renamed + edited: `editor/vite.config.ts` (env path +
node_modules
  walk-up), `editor/scripts/setup-env.mts` (renamed from `.ts` for
`import.meta.url`), `editor/scripts/build-provisioner.mjs` (resolve
src-tauri
  relative to script).

  ### Verification

  | Check | Result |
  |---|---|
  | `task frontend:typecheck:all` (6 variants) | exit 0 |
  | `task frontend:lint` (eslint + dpdm) | exit 0 |
  | `task frontend:format:check` | exit 0 |
  | `task frontend:test` | 657 tests pass, 50 files |
| `task frontend:build:{core,proprietary,saas,desktop,prototypes}` | all
green |
| `task desktop:build` | full Tauri pipeline →
`Stirling-PDF_2.11.0_x64_en-US.msi` |
  | `playwright test --list --project=stubbed` | 172 tests discovered |

`task desktop:build` exercises the heaviest path — Rust + WiX + MSI
bundle
against the moved `editor/src-tauri/`. If anything in the restructure
was
  wrong it wouldn't have built.

  ### Test plan

  - [ ] `frontend-validation.yml` green
  - [ ] `e2e-stubbed.yml` green
  - [ ] `tauri-build.yml` green on at least one platform
  - [ ] `check_toml.yml` runs on a translation-touching PR

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
2026-05-22 13:40:34 +01:00
Anthony StirlingandGitHub 48027ee9d6 JDK25 - Integrate Stirling-Tools JPDFium for PDF operations (#6387) 2026-05-22 13:19:46 +01:00
9d081d1792 SaaS Consolidation (#6384)
Co-authored-by: ConnorYoh <[email protected]>
2026-05-21 16:05:35 +01:00
2399da6893 migrate exportUpdatedPages from bytes to stream (#6201)
Co-authored-by: ConnorYoh <[email protected]>
2026-05-19 23:03:44 +01:00
6b9567cf38 Split and delete forms (#6277)
Delete orphaned forms when removing pages and maintain forms correctly
when splitting

---------

Co-authored-by: ConnorYoh <[email protected]>
2026-05-18 11:14:55 +00:00
James BruntonandGitHub beb99e273b Improve edit agent's knowledge of tools (#6356)
# Description of Changes
Give Edit Agent access to descriptions of the request from the Java API.
This opens the door to us better documenting our Java APIs to give the
stirling engine better knowledge of what the various tools are and how
to use them.

Also improves the tool selection sub-agent to get the tool parameters
and descriptions so it can more intelligently decide which operations
should be used to fulfil the user's request. Also provides it more
encouragement to string together multiple operations if necessary.
2026-05-14 18:30:39 +00:00
ece1bb6865 Feature/pdf to markdown agent (#6271)
Co-authored-by: James Brunton <[email protected]>
2026-05-14 16:20:45 +00:00
stirlingbot[bot]GitHubstirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>Anthony Stirling
8a59c10f42 Update Backend 3rd Party Licenses (#6312)
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>
Co-authored-by: Anthony Stirling <[email protected]>
2026-05-13 16:30:58 +01:00
575684ee4b Add edit text support to stirling engine (#6245)
# Description of Changes
Hooks up the (alpha) PDF Editor backend to the AI engine Edit Agent via
an intermediary API which is easier for the agent to call. It suffers
from all the same issues that the PDF Editor does in actually editing
the text, but should also benefit from any fixes to that.

It also adds protection against the underlying tools misbehaving by
hanging, and fixes a hanging bug in the PDF Editor.

---------

Co-authored-by: EthanHealy01 <[email protected]>
2026-05-11 09:57:41 +00:00
LudyandGitHub f61121953e fix: replace deprecated payload too large status (#6336)
# Description of Changes

- Replaced the deprecated `HttpStatus.PAYLOAD_TOO_LARGE` usage with
`HttpStatus.CONTENT_TOO_LARGE` in `GlobalExceptionHandler`
- Updated the upload-size exception response creation and response
status to use the newer HTTP 413 enum
- Updated related unit tests to assert `HttpStatus.CONTENT_TOO_LARGE`
- The change was made to avoid using the deprecated Spring HTTP status
enum while keeping the returned status code behavior unchanged


---

## 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-05-11 10:38:19 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
bd50e2e59d build(deps): bump commons-io:commons-io from 2.21.0 to 2.22.0 in /app/core (#6344)
Bumps commons-io:commons-io from 2.21.0 to 2.22.0.


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

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

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

---

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

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


</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-11 10:37:09 +01:00
51f5345151 Inform AI engine which endpoints are disabled on the backend (#6251)
# Description of Changes
Have the Java send a list of enabled endpoints to the AI engine so it
can intelligently respond to the user that the tool does exist but is
disabled on the server so it can't acutally run the operation, instead
of the current behaviour where it sends the API call back and then 503
errors because the execution fails when the URL is disabled.

<img width="380" height="208" alt="image"
src="https://github.com/user-attachments/assets/5842fb2e-2e55-45a5-8205-25515636daae"
/>

---------

Co-authored-by: EthanHealy01 <[email protected]>
2026-05-01 14:59:53 +00:00
86774d556e Pdf comment agent (#6196)
Co-authored-by: James Brunton <[email protected]>
2026-05-01 10:19:38 +01:00
stirlingbot[bot]GitHubstirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
b552feaf28 Update Backend 3rd Party Licenses (#6264)
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2026-04-30 10:19:08 +01:00
stirlingbot[bot]GitHubstirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
94cf25b319 Update Backend 3rd Party Licenses (#6243)
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2026-04-28 17:38:00 +01:00
Anthony StirlingandGitHub 8daee7303d playwright (#6025) 2026-04-27 11:35:50 +01:00
stirlingbot[bot]GitHubstirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>Ludy
5cfb77314f Update Backend 3rd Party Licenses (#5932)
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: Ludy <[email protected]>
2026-04-24 21:34:58 +01:00
Anthony StirlingandGitHub 177c776658 Migrate stream to resource for stability (#6160) 2026-04-23 15:56:31 +01:00
c294e9b2cb fix file sharing bug (#6161)
# Description of Changes

Fixes share-link navigation for SSO users. Reported on v2.9.2 with
`SSOAutoLogin: true`: clicking a `/share/<token>` link in an email
redirected the user to the home page after SSO instead of the shared
file.

## Root cause

Three compounding issues had to be fixed together; the first was the
initial symptom but the other two only surfaced during live
verification.

1. **Spring Security blocked `/share/<token>` for unauthenticated
users.** The route wasn't in `RequestUriUtils.isPublicAuthEndpoint`, so
the server 302'd straight to `/login` before React could load
`ShareLinkPage`. The share URL was lost because `NullRequestCache` is
configured and never persisted the original destination.

2. **`httpErrorHandler` full-page-redirected to `/login?from=<path>` on
any unhandled 401** (fired by `LicenseContext`, `AppConfig`, etc. during
normal ShareLinkPage mount). That *did* preserve the return path — but
**Spring Security strips query strings from `/login`** (302 to bare
`/login`), so `?from=` never reached React. Confirmed via `curl -i
http://localhost:8080/login?from=xyz` → `Location: /login`.

3. **`AuthCallback.tsx` unconditionally `navigate("/")`** after the
SAML/OAuth round-trip, discarding any intended destination.

## Fix

**Backend** — make `/share/<token>` a public SPA bootstrap, data APIs
stay protected:
- `RequestUriUtils.isPublicAuthEndpoint` — permits `^/share/[^/]+/?$`
(tight regex, single token segment only; `/share/<token>/anything` stays
protected).
- `ReactRoutingController` — dedicated `@GetMapping("/share/{token}")`
mirroring `/auth/callback`.
- `/api/v1/storage/share-links/**` remains behind Spring Security with
its existing `canAccessShareLink` check.

**Frontend** — persist the return path across full-page redirects via
`sessionStorage` (same-origin, survives the SSO round-trip):
- `httpErrorHandler.ts` — stashes current pathname to
`stirling_post_login_path` before the 401 → `/login` redirect.
- `springAuthClient.ts` — new `isSafePostLoginRedirect` /
`setPostLoginRedirectPath` / `consumePostLoginRedirectPath` helpers
(rejects protocol-relative URLs and auth-plumbing paths to guard against
open-redirect abuse).
- `Login.tsx` — on explicit user sign-in, read path from
`location.state` or `?from=` query and stash it; don't clobber an
already-stashed value.
- `AuthCallback.tsx` — consume the stashed path (single-use) and
`navigate(target)` instead of always `/`.


---

## 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: EthanHealy01 <[email protected]>
2026-04-23 14:52:25 +01:00
James BruntonandGitHub 3e94157137 Add document context for edit agent (#6152)
# Description of Changes
Adds the ability for the Edit agent to request the content of the
document before it decides which parameters it needs. This makes it able
to process requests like `Split the document after the page containing
the "My Section" section`, allowing for document context-based requests
for all[^1] tools.

I had to make a few changes elsewhere to make this work, including:
- Moving the requesting of content out of the Question Agent and into a
common location
- Added specific API docs for the Split param because the generic ones
were not specific enough for the AI to be able to reliably perform the
correct operation
- Fixed an issue in the tool models generator which caused the Redact
params to only be half-generated (causing Pydantic to crash when the AI
tried to run Redact)
- Added missing logging to a bunch of tools and hooked it up properly so
it'll print to stderr
- Made the limits for the max pages/chars to extract from PDFs
configurable via env var

[^1]: Many of the tools can't actually do anything useful with the
context at this stage, but will just need the tool API to be extended
with new features like page-specific operations to be automatically able
to do smart operations without needing to change the Edit agent itself.
2026-04-23 13:19:27 +00:00
089e448cf4 allow deploypr:prototypes comment to spin up the prototypes build (#6144)
Co-authored-by: James Brunton <[email protected]>
2026-04-20 18:58:33 +01:00
e5767ed58b Change AI engine to execute tools in Java instead of on frontend (#6116)
# Description of Changes
Redesign AI engine so that it autogenerates the `tool_models.py` file
from the OpenAPI spec so the Python has access to the Java API
parameters and the full list of Java tools that it can run. CI ensures
that whenever someone modifies a tool endpoint that the AI enigne tool
models get updated as well (the dev gets told to run `task
engine:tool-models`).

There's loads of advantages to having the Java be the one that actually
executes the tools, rather than the frontend as it was previously set up
to theoretically use:
- The AI gets much better descriptions of the params from the API docs
- It'll be usable headless in the future so a Java daemon could run to
execute ops on files in a folder without the need for the UI to run
- The Java already has all the logic it needs to execute the tools 
- We don't need to parse the TypeScript to find the API (which is hard
because the TS wasn't designed to be computer-read to extract the API)

I've also hooked up the prototype frontend to ensure it's working
properly, and have built it in a way that all the tool names can be
translated properly, which was always an issue with previous prototypes
of this.

---------

Co-authored-by: Anthony Stirling <[email protected]>
Co-authored-by: EthanHealy01 <[email protected]>
2026-04-20 15:57:11 +01:00
Anthony StirlingandGitHub 30aff3236f fix tests caused by streaming changes (#6137) 2026-04-19 18:35:51 +01:00
James BruntonandGitHub 688f7f2013 Add streaming to Engine orchestrator (#6094)
# Description of Changes
Adds a streaming endpoint to the Java AI orchestrator
(`/api/v1/ai/orchestrate/stream` in addition to the existing
`/api/v1/ai/orchestrate`). This allows the caller to get updates of what
stage of orchestration is being run at the time so UIs can give the user
feedback.

Also contains some dubious Gradle changes to suppress errors coming from
Spotless, when it crashes in Google stuff. I'm not sure if that's
appropriate to add, feel free to ask for changes in review.
2026-04-17 10:01:08 +01:00
Anthony StirlingandGitHub cc5a0b8def Cleanup work + stream endpoints to reduce memory usage (#6106) 2026-04-15 15:34:17 +01:00
702f4e5c2c Add Taskfile for unified dev workflow across all components (#6080)
## Add Taskfile for unified dev workflow

### Summary
- Introduces [Taskfile](https://taskfile.dev/) as the single CLI entry
point for all development workflows across backend, frontend, engine,
Docker, and desktop
- ~80 tasks organized into 6 namespaces: `backend:`, `frontend:`,
`engine:`, `docker:`, `desktop:`, plus root-level composites
- All CI workflows migrated to use Task
- Deletes `engine/Makefile` and `scripts/build-tauri-jlink.{sh,bat}` —
replaced by Task equivalents
- Removes redundant npm scripts (`dev`, `build`, `prep`, `lint`, `test`,
`typecheck:all`) from `package.json`
- Smart dependency caching: `sources`/`status`/`generates`
fingerprinting, CI-aware `npm ci` vs `npm install`, `run: once` for
parallel dep deduplication

### What this does NOT do
- Does not replace Gradle, npm, or Docker — Taskfile is a thin
orchestration wrapper
- Does not change application code or behavior

### Install
```
npm install -g @go-task/cli    # or: brew install go-task, winget install Task.Task
```

### Quick start
```
task --list       # discover all tasks
task install      # install all deps
task dev          # start backend + frontend
task dev:all      # also start AI engine
task test         # run all tests
task check        # quick quality gate (local dev)
task check:all    # full CI quality gate
```

### Test plan
- [ ] Install `task` CLI and run `task --list` — verify all tasks
display
- [ ] Run `task install` — verify frontend + engine deps install
- [ ] Run `task dev` — verify backend + frontend start, Ctrl+C exits
cleanly
- [ ] Run `task frontend:check` — verify typecheck + lint + test pass
- [ ] Run `task desktop:dev` — verify jlink builds are cached on second
run
- [ ] Verify CI passes on all workflows

---------

Co-authored-by: James Brunton <[email protected]>
2026-04-15 14:16:57 +00:00
James BruntonandGitHub 4cf797ab75 Fix Java formatting (#6114)
# Description of Changes
#6069 introduced formatting issues in the Java, this PR fixes them.
2026-04-15 15:12:04 +01:00
Anthony StirlingandGitHub 07b7c991f0 desktop mobile QR fixes (#6069) 2026-04-15 13:21:45 +01:00
James BruntonandGitHub b130242688 Add Java orchestrator to connect to the AI engine (#6003)
# Description of Changes
Add Java orchestration layer which can connect and go back and forth
with the AI engine to get results for the user. It's expected that the
AI engine will not be publicly available and this Java layer will always
be in front of it, to manage sessions and auth etc.
2026-04-09 08:04:38 +00:00
ebab5a4456 pipeline fixes (#6068)
Co-authored-by: a <a>
2026-04-04 10:19:38 +01:00
Reece BrowneandGitHub 436c8cbed2 Line seperator fix for redaction drift (#6064) 2026-04-03 17:47:48 +01:00
Anthony StirlingandGitHub 3c48740c5e dep updates (#6058) 2026-04-03 13:24:41 +01:00
DexterityandGitHub fca40e5544 Fix image stamp cropping and align preview with PDF output for add-stamp (#6013) 2026-04-02 17:54:13 +01:00
Anthony StirlingandGitHub c9a70f3754 removeffmpeg (#6053) 2026-04-02 17:40:02 +01:00
de9625942b Pipeline changes and version bump (#6047)
# Description of Changes

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

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

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/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 tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.

---------

Co-authored-by: a <a>
2026-04-02 12:52:22 +01:00
Anthony StirlingandGitHub cfa8d1e5d7 qr split fixes (#6043) 2026-04-01 11:54:33 +01:00