416 Commits

Author SHA1 Message Date
James Brunton
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 <80844253+EthanHealy01@users.noreply.github.com>
2026-05-01 14:59:53 +00:00
James Brunton
5541dd666c Flesh out RAG system (#6197)
# Description of Changes
Flesh out the RAG system and connect it to the PDF Question Agent so it
can respond to questions about PDFs of an extremely large size.

I'd expect lots more work will need to be done to finish off the RAG
system to really be what we need, but this should be a reasonable start
which will let us connect it to tools and have the ingestion mostly
handled automatically. I'm leaving file deletion and proper file ID
management to be done in a future PR. We also need to consider whether
all tools should retrieve content exclusively via RAG, or whether it's
beneficial to have tools sometimes fetch the direct content and other
times fetch it from RAG.

A diagram of the expected interaction is as follows:

```mermaid
sequenceDiagram
    autonumber
    actor U as User
    participant FE as Frontend<br/>(ChatPanel)
    participant J as Java<br/>(AiWorkflowService)
    participant O as Engine:<br/>OrchestratorAgent
    participant QA as Engine:<br/>PdfQuestionAgent
    participant RAG as Engine:<br/>RagService + SqliteVecStore
    participant V as VoyageAI<br/>(embeddings)
    participant L as LLM<br/>(Claude / etc.)

    U->>FE: types "Summarise this PDF"<br/>(PDF already uploaded)
    FE->>J: POST /api/v1/ai/orchestrate/stream<br/>multipart: fileInputs[], userMessage
    Note over J: ByteHashFileIdStrategy<br/>id = sha256(bytes)[:16]
    J->>O: POST /api/v1/orchestrator<br/>{ files:[{id,name}], userMessage }

    O->>L: route via fast model
    L-->>O: delegate_pdf_question
    O->>QA: PdfQuestionRequest

    loop for each file
        QA->>RAG: has_collection(file.id)
        RAG-->>QA: false
    end
    QA-->>O: NeedIngestResponse(files_to_ingest)
    O-->>J: { outcome:"need_ingest", filesToIngest:[...] }

    Note over J: onNeedIngest
    loop per file
        J->>J: PDFBox: extract page text
        J->>O: POST /api/v1/rag/documents<br/>(long-running timeout)
        O->>RAG: chunk + stage documents
        O->>V: embed_documents (batches of 256)
        V-->>O: embeddings
        O->>RAG: add_documents
        O-->>J: { chunks_indexed: N }
    end

    Note over J: retry with resumeWith=pdf_question
    J->>O: POST /api/v1/orchestrator
    Note over O: fast-path to PdfQuestionAgent

    O->>QA: PdfQuestionRequest
    Note over QA: build RagCapability<br/>pinned to file IDs
    QA->>L: run(prompt) with search_knowledge tool

    loop up to max_searches
        L->>QA: search_knowledge(query)
        QA->>V: embed_query
        V-->>QA: query vector
        QA->>RAG: search(vector, collections=[file.id])
        RAG-->>QA: top-k chunks
        QA-->>L: formatted chunks
    end

    Note over QA: once budget spent,<br/>prepare() hides the tool
    L-->>QA: PdfQuestionAnswerResponse
    QA-->>O: answer
    O-->>J: { outcome:"answer", answer, evidence }
    J-->>FE: SSE "result"
    FE->>U: assistant bubble
```
2026-05-01 14:11:54 +01:00
ConnorYoh
86774d556e Pdf comment agent (#6196)
Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-05-01 10:19:38 +01:00
stirlingbot[bot]
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
dependabot[bot]
493757bf41 build(deps): bump com.google.guava:guava from 33.5.0-jre to 33.6.0-jre in /app/common (#6260)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-28 21:42:20 +01:00
dependabot[bot]
1c42ce7087 build(deps): bump com.github.junrar:junrar from 7.5.8 to 7.5.10 in /app/common (#6261)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-28 18:45:49 +01:00
dependabot[bot]
05e2ce45d4 build(deps): bump com.drewnoakes:metadata-extractor from 2.19.0 to 2.20.0 in /app/common (#6193)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-04-28 17:40:04 +01:00
stirlingbot[bot]
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
ConnorYoh
4e4918b91e fix(workflow): stop leaking peer share tokens from participant session API (#6241) 2026-04-28 17:36:20 +01:00
Anthony Stirling
8daee7303d playwright (#6025) 2026-04-27 11:35:50 +01:00
stirlingbot[bot]
5cfb77314f Update Backend 3rd Party Licenses (#5932)
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: Ludy <Ludy87@users.noreply.github.com>
2026-04-24 21:34:58 +01:00
dependabot[bot]
2ade011106 build(deps): bump com.bucket4j:bucket4j_jdk17-core from 8.17.0 to 8.18.0 (#6189)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-24 21:21:02 +01:00
Anthony Stirling
177c776658 Migrate stream to resource for stability (#6160) 2026-04-23 15:56:31 +01:00
Anthony Stirling
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 <80844253+EthanHealy01@users.noreply.github.com>
2026-04-23 14:52:25 +01:00
James Brunton
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
Ludy
e087b54cf0 build(docker): pin base container images to immutable digests (#6173) 2026-04-23 13:31:21 +01:00
James Brunton
2a856fbc19 Allow chat history to be sent to AI engine (#6128)
# Description of Changes
Add an extra parameter to every agent to receive the conversation
history in addition to the current message. This will make it possible
to answer followup questions from the AI without needing to give full
context in your message.
2026-04-21 15:03:10 +00:00
EthanHealy01
089e448cf4 allow deploypr:prototypes comment to spin up the prototypes build (#6144)
Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-04-20 18:58:33 +01:00
James Brunton
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 <77850077+Frooodle@users.noreply.github.com>
Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
2026-04-20 15:57:11 +01:00
Anthony Stirling
308da01d96 Fix form-fill hang when flattening with empty values (#6143) 2026-04-20 13:12:25 +01:00
Anthony Stirling
30aff3236f fix tests caused by streaming changes (#6137) 2026-04-19 18:35:51 +01:00
ConnorYoh
de8c483054 Feat/math validation agent (#6012)
Co-authored-by: James Brunton <jbrunton96@gmail.com>
Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
2026-04-17 10:36:45 +01:00
James Brunton
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 Stirling
60c036e980 thumbnail preview fixes windows (#6074) 2026-04-15 23:25:38 +01:00
Anthony Stirling
cc5a0b8def Cleanup work + stream endpoints to reduce memory usage (#6106) 2026-04-15 15:34:17 +01:00
ConnorYoh
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 <jbrunton96@gmail.com>
2026-04-15 14:16:57 +00:00
James Brunton
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 Stirling
07b7c991f0 desktop mobile QR fixes (#6069) 2026-04-15 13:21:45 +01:00
James Brunton
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
Anthony Stirling
ebab5a4456 pipeline fixes (#6068)
Co-authored-by: a <a>
2026-04-04 10:19:38 +01:00
Reece Browne
436c8cbed2 Line seperator fix for redaction drift (#6064) 2026-04-03 17:47:48 +01:00
Anthony Stirling
81dc90cd6d possible fix permission issues and fix thread timing issues (#6061)
# 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.
2026-04-03 16:49:16 +01:00
Anthony Stirling
3c48740c5e dep updates (#6058) 2026-04-03 13:24:41 +01:00
Dexterity
fca40e5544 Fix image stamp cropping and align preview with PDF output for add-stamp (#6013) 2026-04-02 17:54:13 +01:00
Anthony Stirling
c9a70f3754 removeffmpeg (#6053) 2026-04-02 17:40:02 +01:00
Anthony Stirling
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 Stirling
ecd1d3cad3 fix new line in redact (#6035) 2026-04-01 11:58:38 +01:00
Anthony Stirling
0a098cf7b7 idle cpu fix test (#6015) 2026-04-01 11:58:10 +01:00
Anthony Stirling
cfa8d1e5d7 qr split fixes (#6043) 2026-04-01 11:54:33 +01:00
Anthony Stirling
82a3b8c770 Unlock account (#5984) 2026-03-30 16:07:57 +01:00
ConnorYoh
dd44de349c Shared Sign Cert Validation (#5996)
## PR: Certificate Pre-Validation for Document Signing

### Problem

When a participant uploaded a certificate to sign a document, there was
no validation at submission time. If the certificate had the wrong
password, was expired, or was incompatible with the signing algorithm,
the error only surfaced during **finalization** — potentially days
later, after all other participants had signed. At that point the
session is stuck with no way to recover.

Additionally, `buildKeystore` in the finalization service only
recognised `"P12"` as a cert type, causing a `400 Invalid certificate
type: PKCS12` error when the **owner** signed using the standard
`PKCS12` identifier.

---

### What this PR does

#### Backend — Certificate pre-validation service

Adds `CertificateSubmissionValidator`, which validates a keystore before
it is stored by:
1. Loading the keystore with the provided password (catches wrong
password / corrupt file)
2. Checking the certificate's validity dates (catches expired and
not-yet-valid certs)
3. Test-signing a blank PDF using the same `PdfSigningService` code path
as finalization (catches algorithm incompatibilities)

This runs on both the participant submission endpoint
(`WorkflowParticipantController`) and the owner signing endpoint
(`SigningSessionController`), so both flows are protected.

#### Backend — Bug fix

`SigningFinalizationService.buildKeystore` now accepts `"PKCS12"` and
`"PFX"` as aliases for `"P12"`, consistent with how the validator
already handles them. This fixes a `400` error when the owner signed
using the `PKCS12` cert type.

#### Frontend — Real-time validation feedback

`ParticipantView` gains a debounced validation call (600ms) triggered
whenever the cert file or password changes. The UI shows:
- A spinner while validating
- Green "Certificate valid until [date] · [subject name]" on success
- Red error message on failure (wrong password, expired, not yet valid)
- The submit button is disabled while validation is in flight

#### Tests — Three layers

| Layer | File | Coverage |
|---|---|---|
| Service unit | `CertificateSubmissionValidatorTest` | 11 tests — valid
P12/JKS, wrong password, corrupt bytes, expired, not-yet-valid, signing
failure, cert type aliases |
| Controller unit | `WorkflowParticipantValidateCertificateTest` | 4
tests — valid cert, invalid cert, missing file, invalid token |
| Controller integration | `CertificateValidationIntegrationTest` | 6
tests — real `.p12`/`.jks` files through the full controller → validator
stack |
| Frontend E2E | `CertificateValidationE2E.spec.ts` | 7 Playwright tests
— all feedback states, button behaviour, SERVER type bypass |

#### CI

- **PR**: Playwright runs on chromium when frontend files change (~2-3
min)
- **Nightly / on-demand**: All three browsers (chromium, firefox,
webkit) at 2 AM UTC, also manually triggerable via `workflow_dispatch`
2026-03-27 14:01:10 +00:00
Anthony Stirling
28613caf8a fileshare (#5414)
Co-authored-by: ConnorYoh <40631091+ConnorYoh@users.noreply.github.com>
Co-authored-by: Connor Yoh <con.yoh13@gmail.com>
Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-03-25 11:00:40 +00:00
stirlingbot[bot]
4858608162 🤖 format everything with pre-commit by stirlingbot (#5946)
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-03-24 18:55:37 +00:00
OUNZAR Aymane
a1f03c844b Enhance multi-page PDF layout with advanced customization options (#397, #3655) (#5859)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-24 17:27:56 +00:00
InstaZDLL
8bbfbd63d7 feat(security): add RFC 3161 PDF timestamp tool (#5855)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2026-03-24 17:00:33 +00:00
Anthony Stirling
7b3985e34a FileReadiness (#5985) 2026-03-24 15:25:33 +00:00
Anthony Stirling
f03f0d4adb junits (#5988) 2026-03-24 14:12:31 +00:00
Anthony Stirling
c3fc200c5d Remove images (#5966) 2026-03-24 14:11:27 +00:00
ConnorYoh
081b1ec49e Invite-link-issues (#5983) 2026-03-23 19:35:41 +00:00
Anthony Stirling
9e8606cab4 XSS for eml and others (#5967) 2026-03-20 11:55:23 +00:00