mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
01751bf2f0aaeff3a7973ede383516464a064a01
5475
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
41f1cb2c22 |
build(deps): bump test pypdf + add translations (#6831)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com>v2.14.0 |
||
|
|
ff3e3bd0fc |
Add desktop hardware token signing and trust-aware signature validation (#6765)
# Description of Changes <img width="432" height="800" alt="image" src="https://github.com/user-attachments/assets/a01ed9ac-220c-4911-9134-b51e0f321be8" /> <img width="408" height="859" alt="image" src="https://github.com/user-attachments/assets/a9c285b6-5b75-493a-95ec-09e08d0f58f1" /> <img width="426" height="874" alt="image" src="https://github.com/user-attachments/assets/a60db96e-be93-4cc5-ba0a-63512c2857ba" /> <img width="356" height="1076" alt="image" src="https://github.com/user-attachments/assets/24d03674-94d3-40ed-99ee-73395bafae6a" /> --- ## 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. |
||
|
|
54042c8e5e | Signing UI edge-case cleanup (#6849) | ||
|
|
bb92ecc143 |
Update Backend 3rd Party Licenses + Translations and bump versio (#6794)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com> |
||
|
|
7ab30d2629 | add file share to the top workbench bar and add shared signing (#6715) | ||
|
|
276eb8f2a7 |
Add pipelines page to portal (#6818)
# Description of Changes Connect pipelines page to the backend. Note that this is really half an implementation because the portal doesn't have access to the tools list and their settings, but I can't fix that without re-architecture work, which I'll do in another PR, then come back to finish this off in a new PR. <img width="786" height="579" alt="image" src="https://github.com/user-attachments/assets/d3f06110-a35d-4d48-a2f9-1edb900c5c35" /> <img width="1232" height="519" alt="image" src="https://github.com/user-attachments/assets/9f344648-ea45-498d-9e84-9558a3999838" /> |
||
|
|
e44da5c410 |
Fix missing refresh token on desktop (#6838)
# Description of Changes Fix #6801, along with fixing policies on desktop, which would attempt to download policy outputs from the local backend instead of the server, where they actually live. I've changed the policies logic to maintain the same backend for the file retrieval as it used for the policy running, so when we support running policies locally, it should still work correctly. |
||
|
|
0beff1a92b |
feat(shared): make @shared the single home for brand logo assets (#6714)
## What
Makes `@shared` the single home for the Stirling brand logo assets.
Moves the editor's two logo sets — `classic-logo` + `modern-logo` (22
files: marks, wordmarks, favicons, login headers, PNGs) — out of
`editor/public/` into `shared/assets/brand/`, and adds a Storybook
**Brand/Logos** gallery.
## Why this shape (not a plain move)
The editor serves logos by **URL** from `public/` and switches
`classic`/`modern` by a **user preference** (`useLogoAssets`,
`manifest.json` / `manifest-classic.json`, `index.html` favicon links).
Rewiring all that to module imports would be a large, risky change to
the variant system.
Instead the editor keeps its variant system **unchanged** and just
sources the files from shared: `vite-plugin-static-copy` copies
`shared/assets/brand/{classic,modern}-logo/*` back to the served
`/{classic,modern}-logo` paths (the editor already uses this plugin for
pdfium/pdfjs assets). Single source of truth in shared, zero editor
code/manifest/markup changes.
## Verified
- **Build:** editor builds with both sets present at
`dist/{modern,classic}-logo/`; `manifest.json` + favicon refs resolve.
- **Dev:** the vite dev server serves the bridged paths —
`/modern-logo/logo512.png`,
`/modern-logo/StirlingPDFLogoNoTextDark.svg`,
`/classic-logo/favicon.ico` all return **HTTP 200** (the plugin's dev
middleware).
- Typecheck clean on core/proprietary/saas; prettier clean; `storybook
build` succeeds with the `Brand/Logos` gallery bundled.
- The portal's existing `@shared/assets` brand imports are untouched.
## Follow-ups (not in this PR)
- **Dedup:** `shared/assets/stirling-mark-*.svg` is byte-identical to
`brand/modern-logo/StirlingPDFLogoNoTextDark.svg`, and
`stirling-pdf-logo-*` is a near-twin of the modern wordmark. Reconciling
these (and re-pointing the portal) needs a designer eye on which
wordmark is canonical, so it's left out here to avoid changing the
portal's rendered logo.
- `editor/src/logo.svg` appears unused (no references) — candidate for
deletion separately.
|
||
|
|
425b76e9a7 |
fix(portal/i18n): add inline default values to account-link + billing t() calls (#6842)
## Problem The account-link / billing / Usage strings migrated to i18next in #6738 call `t("key")` with **no inline default**. When no i18next instance is initialized — which is the case in **Storybook** (the preview doesn't load the portal i18n config) — or whenever a key is missing, react-i18next renders the **raw key** (e.g. `billing.walletMeter.title`) instead of English. That's why the billing stories regressed to showing keys. ## Fix Add the English string as the `t()` default value, matching the **existing portal convention** (`AuthGate`, `Header`, `Sidebar`) and the editor: - plain → `t("key", "English")` - interpolation → `t("key", "English {{var}}", { var })` - plural → `t("key", "{{count}} …", { count })` Dynamic keys resolved via data fields carry a sibling `*Default` string passed as the default: - `LINK_INFO` badge labels → `labelDefault` (`t(info.labelKey, info.labelDefault)`) - `PdfsProcessedCard` segment legend → `labelDefault` / `descDefault` Defaults were sourced **verbatim from the merged `en-US/translation.toml`**, so the TOML stays the source of truth — the inline default only fills in when the catalogue isn't loaded or lacks the key. ## Scope All strings added in #6738: 5 account-link + 12 billing components + the Usage view (157 static call sites + the `LINK_INFO` / segment dynamic ones). No new keys; no copy changes. ## Verification - `tsc -p portal/tsconfig.json` → 0 - `eslint --max-warnings=0` (changed files) → 0 - `prettier --check` → clean - portal `vitest` → **62/62 pass** No behaviour change when i18n is initialized; Storybook and any missing-key fallback now render English. |
||
|
|
c8af6e3b7e |
feat(policies): enforce run-on-export policies on all PDF exit paths (#6788)
> **Draft / WIP** — print enforcement is still to come (see below). ## Goal A "run on export" policy must enforce on **every** path where a PDF leaves the editor, not just the main Download/Export button. This routes the remaining exits through the existing export-policy gateway (`downloadFileWithPolicy`), which runs `enforceExportPolicies` before the file leaves and is a no-op when no export policy is active. ## Audit of exit paths | Path | Status | |---|---| | Web download / export, page-editor, file-editor, thumbnails | ✅ already covered (gateway) | | **Form-fill download** (`FormSaveBar`) | ✅ fixed here — was a raw `createObjectURL` download | | **Desktop Ctrl+S save** (`useSaveShortcut`) | ✅ fixed here — was raw `downloadService` | | **Desktop save-operation-results** (`operationResultsSaveService`) | ✅ fixed here — was raw `downloadService` | | Viewer `saveAsCopy` (annotations/redactions) | n/a — in-memory version saves, not exits | | **Print** (`printActions.print`) | ⏳ pending — enforce-then-print (below) | | Web operation-results (`downloadFromUrl`) | ⏳ pending — URL-stream, needs a fetch→enforce wrapper | | Share link | excluded by design (enforce at share-creation, not recipient download) | ## In this PR All three fixes are the same pattern — route the raw download through `downloadFileWithPolicy` instead of `URL.createObjectURL` / the raw download service. ## Still to come (why it's a draft) - **Print** — enforce-then-print: on print, run the same `enforceExportPolicies`; if it changed the doc, swap the viewer to the enforced version (new version in history) and toast *"PDF updated by policy enforcement — review, then print again"* rather than silently printing a different doc; if unchanged, print. Covers Ctrl+P, the toolbar button, and embedded PDF-JS print. - **Web operation-results** (`downloadFromUrl`) — fetch the result to a blob, enforce, then download. ## Verification Typecheck (core/proprietary) + prettier clean for the changes here; desktop tsc clean for the touched files. The print UX, once added, needs a manual run with an active export policy — there's no automated path for it. |
||
|
|
82ec2acaba |
Make explicit signed and unsigned desktop CI jobs (#6840)
# Description of Changes Makes it easier to skip signing on nightlies, which we don't need to do since we're just warming the Rust cache. |
||
|
|
5e97746721 |
UX improvement for side menu bookmark, comments and attachments (#6552)
- Inline "Add bookmark" form in the bookmark sidebar (title + page, defaults to current page) - saves via /api/v1/general/edit-table-of-contents without leaving the viewer - Persistent "+ Add" rows above the list in Bookmarks, Attachments, Comments and Files sidebars (was only in empty state) - Close (X) button in every viewer sidebar header (Bookmarks, Attachments, Comments, Layers, Thumbnails) - "Add comment" button morphs into "Click a page to place… (cancel)" while textComment is armed, ESC to cancel - "Add attachment" auto-closes the attachment sidebar so you don't end up with two stacked panels - Footer link in bookmark sidebar to the full Edit Table of Contents tool for nesting/reordering - Fix: bookmark/attachment sidebars getting stuck on "Loading…" after a file swap (cache no longer caches `loading`, retry treats null bridge as not-ready) - Fix: Save silently routing to the editor tool on a fresh /read upload when `activeFileId` is still null - New Playwright tests (stubbed + live) covering Add buttons, Save flow with PDF round-trip, and close buttons <img width="720" height="1032" alt="06-thumbnails" src="https://github.com/user-attachments/assets/62298d0d-8eba-4397-9bc2-96871be29b3c" /> <img width="790" height="1062" alt="01-bookmarks" src="https://github.com/user-attachments/assets/1eb33667-c038-4b78-8711-97f354344fae" /> <img width="720" height="1032" alt="02-bookmarks-empty" src="https://github.com/user-attachments/assets/3db263ef-9550-4bac-9ffa-c729263f42c3" /> <img width="1032" height="1032" alt="03-attachments" src="https://github.com/user-attachments/assets/33580e64-020a-4e07-bf9a-595faf695fd8" /> <img width="919" height="1062" alt="04-comments" src="https://github.com/user-attachments/assets/89ef01a8-35a6-406b-825a-f04beec02f29" /> <img width="720" height="1032" alt="05-layers" src="https://github.com/user-attachments/assets/57d3cfe9-0a4c-468d-b497-ed855ddd69e5" /> --- ## 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. |
||
|
|
14245d33d1 |
feat(saas): account-link — connected self-hosted billing (Mode A) [WIP, flag-gated] (#6738)
> **Draft / WIP.** Combined-billing **Mode A** (connected self-hosted). Entirely behind `stirling.billing.account-link.enabled` (default **off** → beans absent → 404). Pairs with Stirling-PDF-SaaS PR #313 (twin migration → `v3`). ## What this does A self-hosted instance links a SaaS account in the **Portal**, gets a **device credential**, and authenticates unattended metering/entitlement with it — no long-lived user JWT on the server. The Portal then surfaces the team's **billing** (free trial → metered Processor plan) driven by the live wallet. ```mermaid sequenceDiagram participant Portal as Portal (browser) participant Supa as SaaS Supabase Auth participant Local as Self-hosted backend participant SaaS as SaaS Java (app/saas) Portal->>Supa: signIn / signUp (Supabase JS, short-lived JWT) Supa-->>Portal: JWT (SDK-refreshed, stays in browser) Portal->>Local: hand JWT (same-origin) Local->>SaaS: POST /account-link/register (Bearer JWT, leader) SaaS-->>Local: { device_id, device_secret } (secret once) Note over Local: store device_secret server-side loop unattended Local->>SaaS: /api/v1/instance/** (X-Device-Id + X-Device-Secret) SaaS-->>Local: entitlement / gate decision end ``` **Auth model:** human auth = Supabase JS (ephemeral JWT, kept for attended portal features). Durable instance auth = a team-bound **device_id + secret** (SHA-256 stored, shown once), non-user `ROLE_LINKED_INSTANCE`, path-scoped to `/api/v1/instance/**`. Instance binds to a **team**, never a user. ## Billing surface (Portal · Mode A states) `Usage & billing` is state-driven by the link/subscription dimension and built to the marketing designs, sharing one component layer across states: - **Unlinked** → link-account prompt. - **Linked · Free** — the *Processor trial*: a one-time 500-PDF free grant ("Process 500 PDFs free, then $X/PDF"), the team's free-editor fleet, and a leader-only **Switch on the Processor →** (embedded Stripe Checkout). - **Linked · Subscribed** — the *Processor plan* dashboard: PDFs-processed split (API / Agents / Automation), **spend this month** vs. a **spend limit** meter with a run-rate projection and an **in-place cap editor** (preset buckets + suggested value + guardrail), Stripe **invoices** (with billed PDFs per invoice), and the default **payment method**. Card / subscription changes deep-link to Stripe's hosted portal. Manual PDF editing is always free — only Automation / AI / API is metered; a `$0` cap blocks all metered work (≠ "no cap"). **Shared, not duplicated:** the editor-fleet card, the Enterprise upsell, and the meter (`@shared/billing` `MeterBar`) render in both the free and subscribed views; money/cap math lives once in `@shared/billing`. The page header is a sticky, full-bleed bar. **New SaaS reads** (defensive — degrade to empty/"—" when the Stripe mirror lacks a table, never 500): - `GET /api/v1/payg/payment-method` — default card (brand / last4 / expiry) from `stripe.payment_methods`. - Invoice **PDFs processed** — billed line-item quantity from `stripe.invoice_line_items`. ## Progress - [x] Schema: `V22 linked_instance` (+ Supabase twin in #313) - [x] `AccountLinkController` register / list / revoke (leader-only, team from caller) - [x] Device-credential filter (path-scoped, constant-time, revocation-aware) + `SupabaseSecurityConfig` wiring (conditional) - [x] `GET /api/v1/instance/whoami` + **`/entitlement`** (reuses `EntitlementService`/`TeamBillingService`) + tests - [x] Self-hosted backend (`app/proprietary`): orchestrator + instance gate (dark + **fail-open**) + tests - [x] Portal: in-app Supabase login modal + register hand-off + `LinkContext` (unlinked default) + "Linked instances" view — all `@shared` Storybook components - [x] **Portal billing surface** — free (Processor trial) + subscribed (Processor plan) Usage views to marketing spec; link-state derived from the **live wallet**; in-place cap editor; over-cap banner - [x] **SaaS reads** — payment-method endpoint + invoice billed-units (defensive `stripe.*` mirror DAOs) + tests - [x] Orphan guard: block leaving/accepting away from a team whose departure orphans its linked instances - [ ] Metering Step 2 (lease + reconcile loop) + bounded fail-open cutoff - [ ] Proprietary hardening (SaaS base-url config, secret-at-rest, finer billable classification) + HTTP integration test - [ ] Cross-repo Stripe lifecycle certified end-to-end (subscribe → meter → cancel → 402) - [ ] Admin ⟺ SaaS-leader enforcement (separate portal-team-mgmt workstream) ## Verification — all green | Gate | Result | |---|---| | `STIRLING_FLAVOR=saas :saas:test` | BUILD SUCCESSFUL (account-link + payg, incl. `PaygPaymentMethodControllerTest`, `PaygInvoicesControllerTest`) | | `:proprietary:test` | BUILD SUCCESSFUL (account-link + entitlement cache/interceptor) | | portal | tsc 0 · eslint 0 · **vitest 55** · storybook build (all billing stories) | | frontend post-sync | typecheck shared + portal + editor (saas + desktop): 0 | ## Screenshots — billing UI _Latest Storybook renders (Portal/Billing). Drag each capture below its caption — kept out of the repo._ **Linked · Free — Processor trial** <img width="1648" height="503" alt="01-free-processor-trial" src="https://github.com/user-attachments/assets/afe6238a-d3b4-47fd-8ea2-cbaed8b0a653" /> **Linked · Subscribed — Processor plan dashboard** <img width="1648" height="930" alt="02-subscribed-processor-plan" src="https://github.com/user-attachments/assets/329e6808-a9a9-4e65-99af-5a8a5e6bf4ab" /> **Spend limit — in-place cap editor** <img width="1648" height="411" alt="03-spend-limit-editor" src="https://github.com/user-attachments/assets/acc95096-bf8e-4ab0-a32c-3c20dc94f816" /> ## Review feedback applied Reworked the portal after first-pass feedback: linking signs in via the **shared Supabase login** (SSO + email/password) — no bespoke form; the **device secret is never shown in or sent to the FE** (the local backend registers + stores it server-side); billing copy reads **PDFs**, not "units"; the wallet surface uses **`@shared` components** matching the SaaS Plan page. Re-verified including an assertion the link response carries no `deviceSecret`/`deviceId`. **Synced onto unified auth + in-app login (2026-06-23).** Merged `main` incl. **#6725 unified auth** (`frontend/shared/auth`); the link flow uses a shared `useSupabaseLogin` hook + `SupabaseLoginForm`, a portal `LinkAccountModal`, and `useAccountLink.completeLink(session)` (+ on-mount SSO redirect-return). Config: `VITE_SAAS_SUPABASE_URL` + `VITE_SAAS_SUPABASE_ANON_KEY`. The local `/account-link/link` call carries the Spring admin bearer with the SaaS JWT in the body. **SSO** needs the SaaS Supabase project to allow-list the portal redirect URL (email/password works without it). ## Assumptions / open - **Proprietary remains a scaffold** (placeholder SaaS base-url, plaintext device secret at rest, coarse billable classification). - Payment-method + invoice-quantity render only when `stripe.payment_methods` / `stripe.invoice_line_items` are in the Sync-Engine target (confirm in the Supabase/Sync-Engine config); otherwise they degrade gracefully. - A self-contained local HTML report + manual E2E runbook live in `notes/account-link-report/` (dev artifacts, outside the repo). --------- Co-authored-by: James Brunton <jbrunton96@gmail.com> |
||
|
|
84739e8b0e |
Align settings.yml defaults and fix dead/mismapped settings (#6816)
# Description of Changes Align settings.yml defaults and fix dead/mismapped settings --- ## 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. |
||
|
|
0996277c41 |
Brand MSI installer and rename display name to Stirling PDF (#6764)
# Description of Changes Add icons to stirling PDF installer and changed app name from Stirling-PDF to Stirling PDF <img width="495" height="387" alt="image" src="https://github.com/user-attachments/assets/6f23b501-d765-43a6-a713-b330ea199a04" /> <img width="495" height="387" alt="image" src="https://github.com/user-attachments/assets/83d50ac9-2220-474b-8269-bfcfad01166c" /> <img width="495" height="387" alt="image" src="https://github.com/user-attachments/assets/f0113ef5-9567-46d0-820c-0891d33b2355" /> vs old <img width="495" height="387" alt="image" src="https://github.com/user-attachments/assets/d50fa652-cb42-4668-b951-4f2ce52eba14" /> <img width="495" height="387" alt="image" src="https://github.com/user-attachments/assets/b113890b-f06d-4dea-9738-1b885a9ba125" /> <img width="495" height="387" alt="image" src="https://github.com/user-attachments/assets/3b6792aa-48a5-425f-9ae2-13938fd297a5" /> --- ## 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. |
||
|
|
d508bc41bf |
Fix PR docker CI when the base image changes (#6809)
# Description of Changes - Fix PR CI for base-image changes: the embedded build's buildx container builder could not resolve the locally-built `stirling-pdf-base:pr-test` and tried to pull it from a registry, failing the build - `test-build-docker.yml`: when the base changed, build the embedded image with the docker driver (`docker build`) so the locally-built base resolves from the daemon image store - `docker-compose-tests.yml`: when the base changed, skip the buildx container builder + gha cache so `test.sh`'s local base build resolves via the default docker driver --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs (if functionality has heavily changed) - [ ] I have read the section Add New Translation Tags (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached ### Testing (if applicable) - [ ] I have run `task check` to verify linters, typechecks, and tests pass - [ ] I have tested my changes locally --------- Co-authored-by: James Brunton <jbrunton96@gmail.com> |
||
|
|
6ff910f26c |
Expand any type linting in frontend (#6808)
# Description of Changes Continued effort to expand linting scope to ban the `any` type in our codebase. This PR pulls in a lot of subfolders into the linting scope, because the excluded list was getting short enough that it was feasible to move a layer down. I then fixed all the trivially fixable `any` type violations in the subfolders, which just required local changes to the one file. The aim of this PR is more to expand the scope to all the folders we can that already avoid `any` types, rather than actually fix violations. |
||
|
|
013f145462 |
Upgrade to TS7 for local type-checking (#6815)
# Description of Changes We can't convert to TS7 completely yet because it lacks the TS API, so ESLint and some of our scripts don't work, but we can do [what the TS team suggest and run TS6 and TS7 side-by-side](https://devblogs.microsoft.com/typescript/progress-on-typescript-7-december-2025/#compiler). When we do that, we take the `task frontend:typecheck:all` job from ~76s to ~13s, and everything else continues to work as it did before. I've set it so that CI will still use TS6 for the time being and locally we use TS7 out of an abundance of caution because CI time doesn't really matter but local time does. I do think it was a bit pointless doing that since the TS team claim the type checking performs identically, but we might as well have it like that for now. If it happens to go badly locally for any devs, they can use `CI=true task frontend:typecheck` to revert to use TS6 trivially. |
||
|
|
eea9696bd4 |
Actually build the frontend for Playwright nightlies (#6817)
# Description of Changes [Our nightlies have literally never passed before](https://github.com/Stirling-Tools/Stirling-PDF/actions/workflows/nightly.yml). As far as I can tell, that's because the frontend was never being built, so the Playwright tests would just never start up. I've forced a nightly run from this branch, and the Playwright tests still fail, but for legitimate failures now. It's a separate job to track down why they're actually failing, so I'm leaving that for followup work. |
||
|
|
3f7e898c69 |
Add sources service and frontend (#6774)
# Description of Changes Redesign policies backend to treat sources a lot closer to how the frontend imagined them working (they're persistent now and have an API). Then connect the portal to the sources when mocks are off to allow for source creation in the UI. It's not particularly useful to do that right now because there's no policies UI, but I've tested manually that sources set up in the UI are usable by policies created via the API. I had to change the portal so that when mocks are off, it doesn't just hard crash when attempting to connect to all the backend APIs that don't exist yet. It'll still log the errors, but just continues on rendering the UI now. I also changed all the policies backend APIs to be gated behind a flag instead of behind the SaaS profile. This is because we haven't yet got the payment model sorted, but we're going to need this stuff running self-hosted to be able to test it locally. |
||
|
|
def3cf79f6 |
More desktop CI optimisations (#6786)
# Description of Changes - Change the nightly build to not sign any of the desktop builds, since we just care about the compiled code. The restored code will still be signed dependent on the OS in the PR builds. - Change RPM Linux to use zstd for compression because the one it was using runs really slowly, and the Jar is already compressed so it makes basically no difference (arguably we shouldn't compress at all) - ~Switch to consistently use Depot for Docker caching to stop filling up the GHA cache and evicting the Rust cache~ Decided against switching to Depot because we're probably doing another PR to remove Depot altogether in the near future |
||
|
|
501a7199e0 |
Add bulk comment and annotation clearing to editor (#6792)
# Description of Changes Closes #6695 This PR adds bulk cleanup actions for comments and annotations in the PDF editor, while tightening the save and navigation behavior around annotation edits. ### Comments sidebar Adds a “Clear all comments” action to the comments sidebar overflow menu. The action opens a confirmation modal before clearing sidebar comments and replies. The implementation distinguishes between standalone comment annotations and comments attached to existing visual annotations. Standalone comments and replies are removed from the document, while comments attached to markup, shapes, ink, or other visual annotations are cleared from the sidebar without deleting the underlying annotation itself. This preserves the visible document markup while removing the comment metadata and persisted comment contents. The comments sidebar state is also reset after clearing, including draft comments, reply drafts, edit state, and open confirmation/delete modal state. ### Annotate tool Adds a document-level “Clear all annotations” action to the Annotate tool. The action is exposed through the annotation panel’s overflow menu and uses a confirmation modal before removing annotations. The clear operation is routed through the existing annotation API bridge and delegates to EmbedPDF’s document-level annotation clearing API. The UI handles unavailable annotation state, successful clears, and failures. After annotations are cleared, the editor resets annotation interaction state, exits placement/selection-specific state, returns to select mode, and marks the document as having unsaved changes only when annotations were actually removed. The user can then persist the removal through the normal Save Changes flow. ### Save and navigation hardening Improves the viewer save/apply flow used by annotations and manual redactions. Save operations are now deduplicated while an apply operation is already in flight, preventing duplicate exports or duplicate file consumption when users trigger save/navigation repeatedly. The global unsaved-changes navigation modal now waits for “Apply & Leave” to complete successfully before navigating. If saving fails, the modal keeps the user in place instead of leaving with unsaved edits still present. The Annotate panel also prevents “Save Changes” and “Clear all annotations” from running concurrently. <!-- Please provide a summary of the changes, including: - What was changed: - Why the change was made - Any challenges encountered --> --- ## Checklist ### General - [X] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [X] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [X] I have performed a self-review of my own code - [X] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [X] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [X] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) Clear all comments : <img width="310" height="397" alt="image" src="https://github.com/user-attachments/assets/d1682611-13f8-4f40-aa77-44b37450e56e" /> Clear all annotations: <img width="284" height="549" alt="image" src="https://github.com/user-attachments/assets/e4049bc1-f07b-4b36-b08e-ad6d6b86fe62" /> ### 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. |
||
|
|
bc6f1a1ff5 | Add login agreement disclaimer feature (#6766) | ||
|
|
d06d3cabaf | chore: update svg conversion and database import handling (#6796) v2.13.2 | ||
|
|
b040277220 | fast-path local PDF transport and reduce chat re-renders (#6798) | ||
|
|
f715a73f1b |
build(deps): bump astral-sh/setup-uv from 8.1.0 to 8.2.0 + translation files (#6748)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> |
||
|
|
5be9a0e1df |
fix desktop bundles (#6773)
# Description of Changes Changes - Use 127.0.0.1 instead of localhost for the local backend. The bundled backend starts on a random port and binds the IPv4 wildcard, but the frontend health-checked http://localhost:{port}. On macOS (and some Linux) localhost resolves to IPv6 ::1 first, so the connection is refused and every backend-dependent tool shows "backend offline" even though the backend started fine. Switched getBackendUrl() and the health-check URL to the 127.0.0.1 loopback literal (already in the Tauri HTTP capability allowlist, and what the OAuth loopback server already uses). Client-side tools were unaffected, which matches the reports. - Fail the desktop build when the bundled JRE is older than the app JAR. The app JAR is compiled for Java 25, but the bundle could ship an older runtime/jre (jlink:runtime short-circuits on an existing runtime, and nothing checked its version), producing UnsupportedClassVersionError at launch so the backend never starts. Added a jlink:verify task that reads the jlink release file and fails the build if the bundled JRE major is below REQUIRED_JAVA (25, kept in sync with build.gradle modernJavaVersion). It runs after the runtime is staged - including the short-circuit reuse path that lets a stale JRE slip through. Cross-platform Node script, no new dependencies. --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have run `task check` to verify linters, typechecks, and tests pass - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing) for more details. |
||
|
|
f7f7b8790e |
fix update notification visibility and install flicker (#6776)
# Description of Changes - Closes #6754 - Update popup now hidden on mobile, for non-admins, and never on SaaS - Respects admin "Show Update Notifications" setting (`showUpdate` / `showUpdateOnlyAdmin`, now default on) - Fixes update modal flickering during desktop install --- ## 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. |
||
|
|
26021425e3 |
chore(ci): upgrade Gradle to 9.6.0 across workflows, Docker builds, and wrapper (#6790)
# Description of Changes ## What was changed - Updated all GitHub Actions workflows using Gradle from older versions (9.3.1 and 9.5.1) to Gradle 9.6.0. - Updated the Gradle Wrapper distribution URL to use Gradle 9.6.0. - Updated all Gradle-based Docker build stages to use the `gradle:9.6.0-jdk25` image and corresponding image digest. - Aligned CI, Docker, and local development environments on the same Gradle version. - Included the regenerated `gradlew` script changes produced by the Gradle wrapper update process. ## Why the change was made - Ensures consistent Gradle versions across local development, CI workflows, and Docker builds. - Takes advantage of the latest Gradle 9.6.0 improvements, fixes, and compatibility updates. - Reduces the risk of version mismatches causing build or deployment inconsistencies. - Simplifies maintenance by standardizing the build toolchain throughout the repository. --- ## 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. |
||
|
|
e35594f946 |
chore(build): centralize Gradle dependency version management (#6499)
# Description of Changes This change centralizes several dependency version declarations into shared Gradle version properties and updates module build files to reference those properties instead of hardcoded version strings. ### What was changed - Added centralized version properties in the root `build.gradle` for: - commons-io - commons-lang3 - rhino - okhttp BOM - gson - guava - bucket4j - archunit - batik - jpdfium - JWT - AWS SDK - Testcontainers - Replaced hardcoded dependency versions across multiple modules with shared version variables. - Updated `resolutionStrategy.force` declarations to use centralized version properties. - Updated dependency constraints and BOM references to use shared version variables. - Removed module-specific duplicate version declarations from `app/proprietary/build.gradle`. - Standardized dependency declarations across `common`, `core`, `proprietary`, and `saas` modules. ## Why the change was made - Reduce duplication of dependency version definitions. - Simplify future dependency upgrades and maintenance. - Ensure consistent dependency versions across all modules. - Improve readability and reduce the risk of version drift between subprojects. - Make security-related dependency overrides easier to maintain from a single location. --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have run `task check` to verify linters, typechecks, and tests pass - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing) for more details. |
||
|
|
8a0b12b5ab |
Remove ffmpeg from published Docker images (#6791)
## Summary Published Docker images (`stirling-pdf:latest`, `:2.13.1`) still shipped the full `ffmpeg` package even though it was disabled in source back in #6053. **Root cause:** `push-docker.yml` passed a hardcoded `BASE_VERSION=1.0.0` build-arg for the regular image, overriding the Dockerfile's `ARG BASE_VERSION=1.0.2` default. Base `1.0.0` is the original base that still does the explicit `ffmpeg` apt install, so the published image never picked up the removal. |
||
|
|
60fff188a6 |
fix(team): hide users already assigned to the selected team (#6760)
# Description of Changes
# Description of Changes
- What was changed
- Filtered the "Add Member to Team" user picker so users who are already
members of the selected target team are no longer shown.
- Applied the same filtering in both team management entry points:
- `TeamsSection`
- `TeamDetailsSection`
- Kept users in other teams visible, so they can still be moved into the
selected team.
- Why the change was made
- The modal was showing users who were already part of the target team,
which made the action misleading and allowed redundant selection.
- Hiding already-assigned users keeps the UI aligned with the actual
action: adding new members to the team
before:
<img width="442" height="425" alt="image"
src="https://github.com/user-attachments/assets/9faf991f-a7d3-4a48-91cd-f47730decde8"
/>
after:
<img width="430" height="382" alt="image"
src="https://github.com/user-attachments/assets/f8291172-feb6-4d8d-b536-eebf752b764b"
/>
---
## 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.
|
||
|
|
41181c9da1 |
Redesign tool config types to avoid any typing (#6582)
# Description of Changes Fixes one of the main causes of `any` typing left in tools, the way that we register tool parameters in the registry. Currently, it just accepts tool params via `any`, but instead we can explicitly change them to `Record<string, unknown)`, so on the way back out they can more safely be cast back to their correct type when known. One consequence of this is that I had to redesign the way we special-case the Convert tool, which previously was a different shape than all the other param types. Now it's just got optional parameters on it, which isn't quite as type-safe as before, but it does mean all tools are a consistent shape now, which I think is worth the tradeoff. |
||
|
|
8e485801c9 |
change policies ui (#6683)
• Removed colors from policies to make them look more professional. • upgraded to enterprise link to contact us. • Hid inactive policies from users (Kept for admin and team lead). • Closing policies had wrong arrow, made a standard component for chat, tools and policies header. |
||
|
|
436afa51d7 |
Always use the modern logo in the SaaS build (#6775)
## What Make the **SaaS** build always use the modern logo, so the classic logo can no longer appear anywhere in the SaaS app. This is a minimal, SaaS-only alternative to the full classic-logo removal PR (~80 files). **OSS (`core`) and proprietary builds are untouched** — they keep the full modern/classic variant system, including the admin _Logo Style_ picker. ## How A single SaaS-layer override shadows the core hook: - `frontend/editor/src/saas/hooks/useLogoVariant.ts` → returns `"modern"` unconditionally. In the SaaS build the `@app/*` alias cascade resolves `@app/hooks/useLogoVariant` to `src/saas/*` before `src/core/*`, so this shadows the core implementation (which otherwise resolves the variant from the stored user preference or the server `logoStyle`). ## Why one file is enough All logo rendering funnels through `useLogoVariant()`: - `useLogoAssets()` → favicon, web manifest, apple-touch icon, wordmark, `logo512`, tooltip logo — consumed by `BrandingAssetManager` (which sets `<link rel="icon|manifest|apple-touch-icon">`), `Wordmark`, `LogoIcon`, `Tooltip`. - `useLogoPath()` → the no-text logo SVGs. - The login-carousel slides (`buildLoginSlides`) receive the variant from `AuthLayout`, which calls the hook. Everything else that references a logo in SaaS already hardcodes `modern-logo` (`index.html`, the SaaS `Login`/`Signup`/`AuthCallback`/`OAuthConsent` routes, cloud onboarding, account/MFA QR logos). The only hardcoded `classic-logo` reference — the admin _Logo Style_ picker in `AdminGeneralSection` — is **not shipped in SaaS**: `createSaasConfigNavSections` builds from the core nav sections and never includes the proprietary admin sections. `manifest-classic.json` and the classic assets remain in the shared `public/` folder (served by all builds) but are never referenced in the SaaS bundle. ## Test plan - [x] `task frontend:typecheck:saas` — clean - [x] `eslint` on the new file — clean |
||
|
|
0a29186ed6 |
Add JUnit tests to raise coverage across all modules (#6782)
# Description of Changes AI generated junit tests --- ## 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. |
||
|
|
101502cf4f |
Upgrade to TypeScript 6 (#6772)
# Description of Changes TS6 introduced backwards-incompatible changes which affected us a little bit. Other than that, I don't think it significantly changes things for us, but we will need to deal with these breaking changes to be able to upgrade to TS7 (the version written in Go, so dramatically faster), so I'd rather do the work now before TS7 actually releases. Main things I've done: - Removed the use of `baseUrl` in the `tsconfig.json` files - Explicitly provide the `node` types where needed - Explicitly reference the un-referenced but required Google API types - Dropped the installation of `madge` which we weren't using and wasn't directly compatible with TS6 - Updated the `i18next` packages for explicit TS6 compatibility - Explicitly override `tsconfck` to force TS6 compatibility since we can't upgrade it. We're only using that for `vite-tsconfig-paths` and it all still seems to work fine, so I don't think this is an issue. I think we can theoretically drop `vite-tsconfig-paths` when we upgrade to Vite 8 ([because it supports `paths`](https://v8.vite.dev/guide/features#paths)), but that's a bigger job than I want to do in this PR |
||
|
|
f2b65f4a77 |
Make pre-commit scripts more OS-agnostic (#6724)
# Description of Changes Fix #6723 |
||
|
|
1816bad1ba |
Unified auth for portal and editor (#6725)
# Description of Changes Refactor frontend auth to the shared folder and hook it up to both the portal and editor so they share the same system. Also adds various tasks to help run the portal, including `task dev:portal` to spawn the portal with the backend, and `task dev:portal:proxy` to spawn the editor, portal and backend, and a reverse proxy (at localhost:3000) to allow you to use both at once to simulate how this will actually be deployed, allowing you to check whether the seamless transition between the two actually works. |
||
|
|
9aee85d55e |
Wrap first login popup in a form so enter works to change password (#6769)
# Description of Changes > [!note] > GitHub absolutely mangles the diff unless you change to ignore whitespace changes This page has never had the Enter key bound to the Change Password button: <img width="673" height="745" alt="image" src="https://github.com/user-attachments/assets/7a1b06f0-2945-4270-a795-f799ec556c12" /> This PR changes the modal to be properly wrapped in a form so key commands work correctly on it. |
||
|
|
72f8705460 |
Build Rust cache on nightlies (#6768)
# Description of Changes Rust cache added in #6732 never fired because `main` builds don't include building the desktop apps. We could build them on `main` builds, but that's fairly expensive, so just build them on nightlies instead to warm the cache for any desktop PRs the next day |
||
|
|
dffc292888 |
I18n on portal (#6761)
## Overview Internationalizes the **developer portal**, which previously had **zero i18n** — every string was hardcoded across ~118 components. Rather than stand up a parallel system, this shares the **editor's** existing i18n setup (same TOML locale format, same Crowdin pipeline), then converts every portal surface to `react-i18next` and adds a CI guard so coverage can't regress. ## What's included ### 🔗 Shared i18n core (`@shared/i18n`) - Extracts the editor's `TomlBackend` (HTTP loader for `public/locales/{lng}/translation.toml`) and language metadata/helpers (the 42-language list, RTL set, `LanguageSource` priority, code normalizers) into `frontend/shared/i18n/`. - The **editor** now imports and re-exports these from `@shared/i18n` — its 20+ consumers are unchanged. Its local `tomlBackend.ts` is deleted. - The **portal** builds its own i18next instance from the shared core, with **en-US as the source of truth** and the same `/locales/{lng}/translation.toml` layout. ### 🌍 Full portal coverage - Every view and component converted to `t()` — all feature areas (home, pipelines, sources, infrastructure, usage, documents, agent-builder, editor-admin, policies, users, docs, catalogue, components view) plus app shell, nav, modals, and the home/domain widgets. - **1108 keys across ~30 namespaces** in `portal/public/locales/en-US/translation.toml`, grouped by feature; shared strings under `[common]`. Plurals use i18next count forms; dynamic labels (nav, settings sections, status badges) use template keys against populated tables. - Data-driven strings (values from `@portal/api/*` mocks, enum/id values, code samples) are intentionally left untranslated — they're data, not UI chrome. ### ✅ CI coverage guard - `portal/scripts/check-i18n.mjs` fails if any static `t("key")` in portal source is missing from the en-US locale. Wired into `frontend:check` and `frontend:check:all`, so missed keys break CI. This mirrors the editor's `missingTranslations` test for the portal, which has no vitest harness of its own. ## Testing - `task frontend:check:all` passes locally (typecheck all variants, lint, format, **portal i18n guard**, builds, tests, storybook). - Every static `t()` key verified to resolve in the locale (1108 keys / 186 source files); all dynamic key prefixes map to populated tables. - Runtime sweep of all 12 portal routes shows **no unresolved keys** on screen; nav labels, plurals, and array-backed copy all render real text. ## Follow-ups (not in this PR) - **Crowdin** — register `frontend/portal/public/locales/` as a source so portal strings flow through the same translation pipeline as the editor (an ops step on the Crowdin side; there's no Crowdin config in the repo). - Only `en-US` is populated; other languages will arrive via the pipeline. |
||
|
|
c95fb89c63 |
fix(frontend): correctly display the current user role in the edit dialog (#6758)
# Description of Changes This PR fixes the role field in the People settings "Edit User" dialog so the currently assigned role is displayed correctly. - What was changed - The edit dialog now uses the actual role identifier from the user data when preselecting the role. - The role selection is made more robust by falling back to a valid default when the backend response does not provide a usable role value. - The role label shown in the UI is derived consistently from the role identifier. - Why the change was made - The dialog could open with an empty role field even though the user already had a role assigned. - This made role editing confusing and could lead to accidental changes. - The fix keeps the People UI aligned with the backend role data model. before: <img width="438" height="465" alt="image" src="https://github.com/user-attachments/assets/929d8c63-8ae9-436a-b895-e6a746f22458" /> after: <img width="437" height="461" alt="image" src="https://github.com/user-attachments/assets/942f6787-d678-4555-90a9-bf5c7c5c363d" /> --- ## 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. |
||
|
|
956b8000e4 |
build(deps): bump ws from 8.20.1 to 8.21.0 in /frontend (#6679)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com>v2.13.1 |
||
|
|
a3fe15bfd0 | Add metrics for numerical count of total PDFs (#6737) | ||
|
|
1a770af47c |
fix create tool in the AI chat (#6673)
AI PDF creation ("create a PDF for me") has been broken since the
Policies backend (#6527) introduced PolicyExecutor as the tool execution
pipeline. PolicyExecutor runs normal single-input tools with a per-file
loop, but generator tools like `create-pdf-from-html-agent` take no
input file and build their output purely from parameters. With zero
input files the loop ran zero times, so the endpoint was never called
and the step silently produced nothing. The chat reported success
("Created Purchase Order") while no document ever appeared.
This adds an `else if (inputFiles.isEmpty())` branch so a generator tool
is called once with an empty file list, matching what the multi-input
branch already does for an empty input. Two files changed: the
one-line-ish fix in `PolicyExecutor`, and a regression test covering the
no-input case.
---------
Co-authored-by: James Brunton <jbrunton96@gmail.com>
|
||
|
|
3870ac3d7d |
Add desktop mobile-upload page and fix LAN QR URL (#6736)
# Description of Changes Desktop can not use QR code upload due to API backend not having UI for it... Because of this we add UI, has to be custom because can not support OpenCV and in app camera due to its https requirement <img width="919" height="2048" alt="image" src="https://github.com/user-attachments/assets/d84c3903-fd23-421a-8919-24d89ba6c753" /> <img width="919" height="2048" alt="image" src="https://github.com/user-attachments/assets/d6c8fdf3-837b-4dc3-92ea-37f7502f8462" /> <img width="919" height="2048" alt="image" src="https://github.com/user-attachments/assets/fd4ce3b4-69ad-45dd-b066-bff2d082c583" /> <img width="1550" height="790" alt="image" src="https://github.com/user-attachments/assets/701d4dcc-ebd6-4e03-aa7b-2d8623525fc9" /> --- ## 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. |
||
|
|
b9ea9064c7 |
Cache Rust build to improve Tauri build job times (#6732)
# Description of Changes The Tauri jobs are very slow, especially the Linux ones, which can take >1hr to build all the necessary code. A lot of that is because of the actual Rust compilation, which isn't cached at all as far as I can tell. This introduces a cache step for the Rust dependencies, so PRs will just reuse the compiled Rust from the last build of main (if it's safe to do so). |
||
|
|
fe7a2a5ac7 |
Fix Multi Tool page rotation lost on save (#6733)
# Description of Changes Rotating a page in the Multi Tool and saving could leave the page at its original rotation (the change appeared lost), with inconsistent results across pages. - Page rotation is now always written on export, including 0°, so rotating a page that already had a non-zero rotation in the source PDF (e.g. a 270° page rotated back to upright) is no longer dropped. - Per-page rotation is always read when building the Multi Tool document, so pages keep their true orientation regardless of file size. - Rotation is only applied after a page imports successfully, avoiding a misaligned or failed export when an import fails. --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] 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. |
||
|
|
6a9876a067 |
Fix more any typing usage in the frontend (#6664)
# Description of Changes Continued effort to remove the remaining uses of the `any` type from our TS code. The vast majority of these uses that it cleans up was just catching errors as `any`, which are pretty simple to fix. I couldn't completely remove the `any` type usage from `core/tools` because there were cascading issues from a couple of the files in there (most notably Automate) but still, moving in the right direction. |