From 57088de68205b3cfaaf9148edf9048f79f26c422 Mon Sep 17 00:00:00 2001 From: uvasoftware-skippy <30219621+uvasoftware-skippy@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:55:47 -0400 Subject: [PATCH 1/3] feat: add file delete API method Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 7 +++++++ README.md | 1 + src/main/java/com/scanii/ScaniiClient.java | 9 +++++++++ .../com/scanii/internal/DefaultScaniiClient.java | 15 +++++++++++++++ src/test/java/com/scanii/ScaniiClientTest.java | 10 ++++++++++ 5 files changed, 42 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 170988a..6611d8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [8.4.0] — 2026-08-29 + +### Added + +- `delete(String id)` — hard-deletes a previously processed file and its trace + (`DELETE /v2.2/files/{id}`). Returns `true` on success. + ## [8.3.0] — 2026-08-14 ### Changed diff --git a/README.md b/README.md index 76b3034..7a0eab8 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ System.out.printf("findings: %s%n", result.getFindings()); | `processFromUrl(URI location)` | Synchronous remote-URL scan | | `processFromUrl(URI location, Map metadata)` | Remote-URL scan with metadata | | `retrieve(String id)` | Retrieve previous scan result | +| `delete(String id)` | Hard-delete a previous scan result and its trace | | `retrieveTrace(String id)` | Retrieve ordered processing events for a result (preview) | | `fetch(String location)` | Server-side async fetch-and-scan of a remote URL | | `ping()` | Health check | diff --git a/src/main/java/com/scanii/ScaniiClient.java b/src/main/java/com/scanii/ScaniiClient.java index daae1b8..8d1b670 100644 --- a/src/main/java/com/scanii/ScaniiClient.java +++ b/src/main/java/com/scanii/ScaniiClient.java @@ -132,6 +132,15 @@ public interface ScaniiClient { */ Optional retrieve(String id); + /** + * Hard-deletes a previously processed file and its trace. + * + * @param id id of the previously processed content + * @return true when the resource was deleted + * @see spec + */ + boolean delete(String id); + /** * Retrieves the processing trace for a previously processed file. * Returns an ordered list of events describing each stage of the processing pipeline. diff --git a/src/main/java/com/scanii/internal/DefaultScaniiClient.java b/src/main/java/com/scanii/internal/DefaultScaniiClient.java index e8fe499..c2b7a18 100644 --- a/src/main/java/com/scanii/internal/DefaultScaniiClient.java +++ b/src/main/java/com/scanii/internal/DefaultScaniiClient.java @@ -187,6 +187,21 @@ public Optional retrieve(String id) { return Optional.of(result); } + @Override + public boolean delete(String id) { + Objects.requireNonNull(id, "resource id cannot be null"); + + HttpRequest req = newRequestBuilder(target.resolve("/v2.2/files/" + id)) + .DELETE() + .build(); + HttpResponse response = send(req); + + if (response.statusCode() != 204) { + parseAndThrowError(response); + } + return true; + } + @Override public Optional retrieveTrace(String id) { Objects.requireNonNull(id, "resource id cannot be null"); diff --git a/src/test/java/com/scanii/ScaniiClientTest.java b/src/test/java/com/scanii/ScaniiClientTest.java index 9695614..e0d9071 100644 --- a/src/test/java/com/scanii/ScaniiClientTest.java +++ b/src/test/java/com/scanii/ScaniiClientTest.java @@ -204,6 +204,16 @@ void testRetrieveTraceUnknownId() { assertTrue(opt.isEmpty()); } + @Test + void testDelete() throws Exception { + ScaniiProcessingResult processed = client.process(Systems.randomFile(1024)); + assertNotNull(processed.getResourceId()); + + assertTrue(client.delete(processed.getResourceId())); + assertTrue(client.retrieve(processed.getResourceId()).isEmpty()); + assertTrue(client.retrieveTrace(processed.getResourceId()).isEmpty()); + } + @Test void testProcessFromUrl() throws Exception { // scanii-cli serves the EICAR file at this well-known path From 724c26403699a396fdb15762fa31415f6a75487e Mon Sep 17 00:00:00 2001 From: uvasoftware-skippy <30219621+uvasoftware-skippy@users.noreply.github.com> Date: Sun, 30 Aug 2026 08:47:59 -0400 Subject: [PATCH 2/3] test: assert delete of an unknown id raises ScaniiException Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/test/java/com/scanii/ScaniiClientTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/com/scanii/ScaniiClientTest.java b/src/test/java/com/scanii/ScaniiClientTest.java index e0d9071..7da276b 100644 --- a/src/test/java/com/scanii/ScaniiClientTest.java +++ b/src/test/java/com/scanii/ScaniiClientTest.java @@ -214,6 +214,11 @@ void testDelete() throws Exception { assertTrue(client.retrieveTrace(processed.getResourceId()).isEmpty()); } + @Test + void testDeleteUnknownId() { + assertThrows(ScaniiException.class, () -> client.delete("doesnotexist")); + } + @Test void testProcessFromUrl() throws Exception { // scanii-cli serves the EICAR file at this well-known path From 786627b93404fe1f5ba76122aee4cad533e20663 Mon Sep 17 00:00:00 2001 From: uvasoftware-skippy <30219621+uvasoftware-skippy@users.noreply.github.com> Date: Sun, 30 Aug 2026 18:06:50 -0400 Subject: [PATCH 3/3] feat: split file and trace deletion Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 6 ++++-- README.md | 3 ++- src/main/java/com/scanii/ScaniiClient.java | 11 ++++++++++- .../com/scanii/internal/DefaultScaniiClient.java | 15 +++++++++++++++ src/test/java/com/scanii/ScaniiClientTest.java | 7 +++++++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6611d8e..a9091e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,10 @@ ### Added -- `delete(String id)` — hard-deletes a previously processed file and its trace - (`DELETE /v2.2/files/{id}`). Returns `true` on success. +- `delete(String id)` — deletes a previously processed file + (`DELETE /v2.2/files/{id}`). Returns `true` on success; its trace is unaffected. +- `deleteTrace(String id)` — deletes the processing trace separately + (`DELETE /v2.2/files/{id}/trace`). Returns `true` on success. ## [8.3.0] — 2026-08-14 diff --git a/README.md b/README.md index 7a0eab8..44a11ba 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,8 @@ System.out.printf("findings: %s%n", result.getFindings()); | `processFromUrl(URI location)` | Synchronous remote-URL scan | | `processFromUrl(URI location, Map metadata)` | Remote-URL scan with metadata | | `retrieve(String id)` | Retrieve previous scan result | -| `delete(String id)` | Hard-delete a previous scan result and its trace | +| `delete(String id)` | Delete a previous scan result | +| `deleteTrace(String id)` | Delete the processing trace for a previous scan result | | `retrieveTrace(String id)` | Retrieve ordered processing events for a result (preview) | | `fetch(String location)` | Server-side async fetch-and-scan of a remote URL | | `ping()` | Health check | diff --git a/src/main/java/com/scanii/ScaniiClient.java b/src/main/java/com/scanii/ScaniiClient.java index 8d1b670..8377001 100644 --- a/src/main/java/com/scanii/ScaniiClient.java +++ b/src/main/java/com/scanii/ScaniiClient.java @@ -133,7 +133,7 @@ public interface ScaniiClient { Optional retrieve(String id); /** - * Hard-deletes a previously processed file and its trace. + * Deletes a previously processed file. Its processing trace is unaffected. * * @param id id of the previously processed content * @return true when the resource was deleted @@ -141,6 +141,15 @@ public interface ScaniiClient { */ boolean delete(String id); + /** + * Deletes the processing trace for a previously processed file. + * + * @param id id of the previously processed content + * @return true when the trace was deleted + * @see spec + */ + boolean deleteTrace(String id); + /** * Retrieves the processing trace for a previously processed file. * Returns an ordered list of events describing each stage of the processing pipeline. diff --git a/src/main/java/com/scanii/internal/DefaultScaniiClient.java b/src/main/java/com/scanii/internal/DefaultScaniiClient.java index c2b7a18..b7fcaef 100644 --- a/src/main/java/com/scanii/internal/DefaultScaniiClient.java +++ b/src/main/java/com/scanii/internal/DefaultScaniiClient.java @@ -202,6 +202,21 @@ public boolean delete(String id) { return true; } + @Override + public boolean deleteTrace(String id) { + Objects.requireNonNull(id, "resource id cannot be null"); + + HttpRequest req = newRequestBuilder(target.resolve("/v2.2/files/" + id + "/trace")) + .DELETE() + .build(); + HttpResponse response = send(req); + + if (response.statusCode() != 204) { + parseAndThrowError(response); + } + return true; + } + @Override public Optional retrieveTrace(String id) { Objects.requireNonNull(id, "resource id cannot be null"); diff --git a/src/test/java/com/scanii/ScaniiClientTest.java b/src/test/java/com/scanii/ScaniiClientTest.java index 7da276b..ec64379 100644 --- a/src/test/java/com/scanii/ScaniiClientTest.java +++ b/src/test/java/com/scanii/ScaniiClientTest.java @@ -211,6 +211,8 @@ void testDelete() throws Exception { assertTrue(client.delete(processed.getResourceId())); assertTrue(client.retrieve(processed.getResourceId()).isEmpty()); + assertTrue(client.retrieveTrace(processed.getResourceId()).isPresent()); + assertTrue(client.deleteTrace(processed.getResourceId())); assertTrue(client.retrieveTrace(processed.getResourceId()).isEmpty()); } @@ -219,6 +221,11 @@ void testDeleteUnknownId() { assertThrows(ScaniiException.class, () -> client.delete("doesnotexist")); } + @Test + void testDeleteTraceUnknownId() { + assertThrows(ScaniiException.class, () -> client.deleteTrace("doesnotexist")); + } + @Test void testProcessFromUrl() throws Exception { // scanii-cli serves the EICAR file at this well-known path