From 2967de4ea049a265e8eba6b95645f804e1df616e Mon Sep 17 00:00:00 2001 From: Claude Code Date: Tue, 20 Oct 2026 17:46:46 -0300 Subject: [PATCH 1/7] feat: historical_create takes window_days A historical hunt can now be bounded to the last 30, 60, 90 or 180 days. The new optional keyword goes into the POST body as an int; None drops the key, so a bare call sends what it always did and the server applies its own default (the platform maximum). The SDK does not validate the value: the server owns the enum and answers anything else with a 400, which surfaces as the usual typed exception. The sync mirror is regenerated from the async source. Co-Authored-By: Alan Justino --- specs/03-endpoints.md | 2 +- src/polyswarm_api/aio/api.py | 7 +++++-- src/polyswarm_api/api.py | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/specs/03-endpoints.md b/specs/03-endpoints.md index e46353b5..225f6bd0 100644 --- a/specs/03-endpoints.md +++ b/specs/03-endpoints.md @@ -72,7 +72,7 @@ Internal-only CRUD for the `/known-good` binary resource (distinct from the IOC | Method | Resource builder | |---|---| -| `historical_create(rule=None, ruleset_name=None)` | `HistoricalHunt.create` | +| `historical_create(rule=None, ruleset_name=None, window_days=None)` | `HistoricalHunt.create` — `window_days` (4.8.0) is how many days back the hunt reaches; the server accepts 30, 60, 90 or 180 and answers anything else with a 400, which surfaces as the usual typed exception (the SDK does not validate it). It is an int and rides the JSON body. `None` leaves the key out, the server keeps its default and the hunt reaches the platform maximum, so a bare call sends exactly what it always did. | | `historical_get(hunt=None)` | `HistoricalHunt.get` | | `historical_update(hunt)` | `HistoricalHunt.update` | | `historical_delete(hunt)` | `HistoricalHunt.delete` | diff --git a/src/polyswarm_api/aio/api.py b/src/polyswarm_api/aio/api.py index 8e1dde5c..37b91990 100644 --- a/src/polyswarm_api/aio/api.py +++ b/src/polyswarm_api/aio/api.py @@ -642,18 +642,21 @@ async def live_result(self, result_id): """ return await self._single(resources.LiveHuntResult.get(self, id=result_id)) - async def historical_create(self, rule=None, ruleset_name=None): + async def historical_create(self, rule=None, ruleset_name=None, window_days=None): """ Run a new historical hunt. :param rule: YaraRuleset object or string containing YARA rules to install :param ruleset_name: Name of the ruleset. + :param window_days: Days back the hunt reaches: 30, 60, 90 or 180. Omit it for the + platform maximum. The server validates the value; the SDK does not. :return: The created Hunt resource """ logger.info('Create historical hunt %s', rule) rule, rule_id = self._parse_rule(rule) return await self._single(resources.HistoricalHunt.create(self, yara=rule.yara if rule else None, rule_id=rule_id, - ruleset_name=ruleset_name, community=self.community)) + ruleset_name=ruleset_name, window_days=window_days, + community=self.community)) async def historical_get(self, hunt=None): """ diff --git a/src/polyswarm_api/api.py b/src/polyswarm_api/api.py index 69dde0ef..4b751f8e 100644 --- a/src/polyswarm_api/api.py +++ b/src/polyswarm_api/api.py @@ -735,12 +735,14 @@ def live_result(self, result_id): """ return self._single(resources.LiveHuntResult.get(self, id=result_id)) - def historical_create(self, rule=None, ruleset_name=None): + def historical_create(self, rule=None, ruleset_name=None, window_days=None): """ Run a new historical hunt. :param rule: YaraRuleset object or string containing YARA rules to install :param ruleset_name: Name of the ruleset. + :param window_days: Days back the hunt reaches: 30, 60, 90 or 180. Omit it for the + platform maximum. The server validates the value; the SDK does not. :return: The created Hunt resource """ logger.info("Create historical hunt %s", rule) @@ -751,6 +753,7 @@ def historical_create(self, rule=None, ruleset_name=None): yara=rule.yara if rule else None, rule_id=rule_id, ruleset_name=ruleset_name, + window_days=window_days, community=self.community, ) ) From 6e7ed294e24ad04732150ca20cfdb15a7dc2e8fe Mon Sep 17 00:00:00 2001 From: Claude Code Date: Tue, 20 Oct 2026 17:46:59 -0300 Subject: [PATCH 2/7] feat: HistoricalHunt parses window_days The server now returns the hunt's time window on the single GET and on the list. It is an additive .get() like the provenance fields: an int for a hunt created with a window, None for one created without (it reaches the platform maximum) or for a server that predates the field. HistoricalHuntList inherits the parse, so both endpoints are covered. Co-Authored-By: Alan Justino --- specs/02-resources.md | 2 +- src/polyswarm_api/resources.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/specs/02-resources.md b/specs/02-resources.md index 06e30c50..97451b6a 100644 --- a/specs/02-resources.md +++ b/specs/02-resources.md @@ -389,7 +389,7 @@ Holds `handle`, `artifact_name`, `artifact_type`, `sha256`, `sha1`, `md5`. Also Several resources add domain-specific classmethods on top of the standard CRUD set: - `IOC` — `iocs_by_hash`, `ioc_search`, `check_known_hosts`, `create_known_good`, `create_known_bad`, `update_known_good`, `delete_known_good`. -- `LiveYaraRuleset` / `HistoricalHunt` / `YaraRuleset` — standard CRUD plus list/delete-batch variants. `YaraRuleset` also parses the hunt-page tracking fields (`favorite`, `favorited_at`, `rule_count` — `None` means the server had no answer, distinct from 0 — `historical_hunt_count`, and the stored `new_results_count` with its staleness marker `new_results_counted_at`: the server refreshes the counter on a schedule and the marker says when, so `None` means "not yet refreshed / no live hunt", never 0), and `HistoricalHunt` the source-rule provenance (`rule_id`, `rule_modified`, and the tri-state `source_rule_changed` — `None` is "unknown", never "unchanged"). All additive `.get()` parses; an older server leaves them `None`. +- `LiveYaraRuleset` / `HistoricalHunt` / `YaraRuleset` — standard CRUD plus list/delete-batch variants. `YaraRuleset` also parses the hunt-page tracking fields (`favorite`, `favorited_at`, `rule_count` — `None` means the server had no answer, distinct from 0 — `historical_hunt_count`, and the stored `new_results_count` with its staleness marker `new_results_counted_at`: the server refreshes the counter on a schedule and the marker says when, so `None` means "not yet refreshed / no live hunt", never 0), and `HistoricalHunt` the source-rule provenance (`rule_id`, `rule_modified`, and the tri-state `source_rule_changed` — `None` is "unknown", never "unchanged") and its time window `window_days` (4.8.0: the int the hunt was created with, on the single GET and the list alike; `None` means no window was requested, so the hunt reaches the platform maximum). All additive `.get()` parses; an older server leaves them `None`. - `YaraRulesetFavorite` — `RESOURCE_ENDPOINT = '/hunt/rule/favorite'`, **`RESOURCE_ID_KEYS = ['community']`**: a deliberate deviation from the default `['id']`, splitting the request the way the server reads it — the toggle reads BOTH `id` and `favorite` from the PUT **body** (the default would move `id` into the query string and the server would 400 with "A valid rule id must be provided"), while `community` rides the **query string** to match where the ruleset GET/list calls send it. (The server's community middleware accepts the value from either the query or the body — but never both at once — so the placement here is about consistency and the id-400, not about a silently-ignored body value.) `favorite` serialises as `1`/`0` (the `_params` bool→int coercion), which the server's boolean parser accepts. Response carries the star state plus the team's `favorites_used`/`favorites_limit`. Pinned by `test/hunt_tracking_builder_test.py` and both transports of `test/ruleset_favorite_respx_test.py`. - `SandboxTask` — `create_file`, `update_file`, `latest`, `my_tasks` for the various sandbox-submission shapes. **No `upload_file` instance method** in 4.0. - `Sample` — `create` with `endpoint_fmt={'sha256': sha256}` for the URL-parametrised path. diff --git a/src/polyswarm_api/resources.py b/src/polyswarm_api/resources.py index 74cfe898..4732d07b 100644 --- a/src/polyswarm_api/resources.py +++ b/src/polyswarm_api/resources.py @@ -872,6 +872,8 @@ def __init__(self, content, api=None): # unknown (no source rule, or nothing to compare against) — not # "unchanged". self.source_rule_changed = content.get('source_rule_changed') + # None: no window requested (platform maximum), or a server predating the field. + self.window_days = content.get('window_days') class HistoricalHuntList(HistoricalHunt): From 530c27e92a7a18c99d225b7a8b9c7ee0af7d61e0 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Tue, 20 Oct 2026 17:49:21 -0300 Subject: [PATCH 3/7] test: pin window_days on the builder, both clients and the parse Pure-unit tests cover the request shape (an int in the body, the key absent for None, no client-side validation) and the parse (int, explicit null, missing key). One respx body per client pair checks what historical_create sends and what the create, get and list responses carry; VCR cannot, because it does not match bodies and the recorded hunts predate the field. The live round trip needs a fresh e2e stack, so it is recorded as an open question rather than faked into the existing cassettes. Co-Authored-By: Alan Justino --- specs/04-testing.md | 1 + specs/99-open-questions.md | 18 +++++ test/historical_window_test.py | 125 +++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 test/historical_window_test.py diff --git a/specs/04-testing.md b/specs/04-testing.md index 5471b626..5e9a884b 100644 --- a/specs/04-testing.md +++ b/specs/04-testing.md @@ -33,6 +33,7 @@ How the test suite is organised. Three layers: pure unit tests (no HTTP at all - `test/hunt_tracking_builder_test.py` — pure-unit request-shape and parse tests for the hunt-page tracking builders/resources. - `test/refang_test.py` — pure-unit tests for `polyswarm_api.refang` (driven by the shared case table `test/fixtures/refang_cases.json`, kept byte-identical with the other clients that implement the same contract) and request-shape tests for every client method that refangs its IoC inputs, captured at the `_paginate` / `_single` boundary for both transports. Pure-unit because this is client-side input normalization: the server contract is unchanged, so there is no new endpoint behaviour for a cassette to pin. - `test/ioc_search_test.py` — `search_by_ioc(with_artifacts=)`: pure-unit request shape (the int flag, the unchanged default and bare call), pass-through on both client methods, and a dual-transport (`ClientTestCase`) respx parse of an artifact row — a stand-in until the e2e stack serves the parameter (see `99-open-questions.md`). +- `test/historical_window_test.py` — `historical_create(window_days=)` and `HistoricalHunt.window_days`: pure-unit request shape (the int in the body, the key absent for `None`, no client-side validation) and parse (int, explicit null, missing key — on `HistoricalHunt` and `HistoricalHuntList`), plus dual-transport (`ClientTestCase`) respx cases for the body each client sends and for the window on the create response, the single GET and the list. Respx because VCR does not match bodies and the recorded hunts predate the field; the live round trip is pending (see `99-open-questions.md`). - `test/ruleset_favorite_respx_test.py` — dual-transport (`ClientTestCase`) respx suite for the favorite toggle: the `FAVORITE_LIMIT` refusal envelope and the query/body split. - `test/sandbox_file_qrcode_respx_test.py` — dual-transport (`ClientTestCase`) respx suite pinning that a QR-code `sandbox_file` submission uploads the image's bytes (the S3 PUT body) under its unrefanged basename. Respx rather than e2e because the stack's sandbox providers cannot reasonably process a QR image. diff --git a/specs/99-open-questions.md b/specs/99-open-questions.md index 5d4dfc1a..5fce1ccf 100644 --- a/specs/99-open-questions.md +++ b/specs/99-open-questions.md @@ -226,3 +226,21 @@ invariant 1 exists to close. the live `test_search_by_ioc` pair, record both cassettes against a fresh stack, and delete the respx `IocSearchWithArtifactsTestCase` along with this entry. The builder and pass-through tests in that module stay: they pin request shape, which a cassette cannot. + +## `window_days` on historical hunts is not pinned against a live server + +**Status:** gap, pending a recording against a fresh e2e stack. + +The window is asserted only at the SDK boundary (`test/historical_window_test.py`): the body +each client sends, and the parse of hand-built envelopes. The recorded `test_historical` / +`test_list_historical` cassettes (sync and async) predate the field, so their responses carry +no `window_days`, and VCR does not match request bodies — replaying them proves neither that +the server accepts the key nor that it echoes it back. That is the "asserts what we *think* +the server returns" gap invariant 1 exists to close. + +**Action:** against a fresh e2e stack, record a lifecycle exchange with a window — create with +`window_days`, then get and list it, asserting the value round-trips (and that a hunt created +without one reads back `None`) — in the live pair, on both transports. Re-record by deleting +the cassette, never by editing it. Then delete the respx `HistoricalWindowResponseTestCase` +along with this entry. The builder, pass-through and parse tests stay: a cassette cannot see +the request body. diff --git a/test/historical_window_test.py b/test/historical_window_test.py new file mode 100644 index 00000000..555ab554 --- /dev/null +++ b/test/historical_window_test.py @@ -0,0 +1,125 @@ +"""``window_days`` on historical hunts: request shape, pass-through on both clients, parse. + +Builder and parse cases are pure-unit. The pass-through cases are respx because VCR does +not match bodies and the recorded cassettes predate the field, so only a mocked boundary +can see what the body carried. The live round trip is pending (specs/99-open-questions.md). +""" +import pytest + +from polyswarm_api import resources +from test._client_harness import BASE_URL, COMMUNITY, ClientTestCase + +_YARA = 'rule window_probe { condition: true }' +_HUNT_URL = f'{BASE_URL}/hunt/historical' + + +class _FakeApi: + uri = 'https://api.example.test' + community = 'gamma' + + +def _hunt(**extra): + """A hunt row as the server returns it, without the optional fields.""" + return { + 'id': '7', 'created': '2026-10-01T12:00:00+00:00', 'status': 'PENDING', + 'progress': 0.0, 'results_csv_uri': None, **extra} + + +def _create(**kwargs): + return resources.HistoricalHunt.create(_FakeApi(), community='gamma', **kwargs) + + +class TestHistoricalCreateBuilder: + def test_window_rides_the_body_as_an_int(self): + req = _create(yara=_YARA, window_days=30) + assert req.method == 'POST' + assert req.url == f'{_FakeApi.uri}/hunt/historical' + assert req.input_json == {'yara': _YARA, 'window_days': 30, 'community': 'gamma'} + assert req.params is None + # A JSON number, not the string "30". + assert type(req.input_json['window_days']) is int + assert req.result_parser is resources.HistoricalHunt + + def test_no_window_leaves_the_key_out(self): + req = _create(yara=_YARA, window_days=None) + assert req.input_json == {'yara': _YARA, 'community': 'gamma'} + + def test_none_and_omitted_build_the_same_request(self): + omitted, explicit = _create(yara=_YARA), _create(yara=_YARA, window_days=None) + assert (explicit.method, explicit.url, explicit.params, explicit.input_json) == ( + omitted.method, omitted.url, omitted.params, omitted.input_json) + + def test_window_stays_an_int_beside_a_stored_rule_id(self): + # core._params stringifies *_id keys only; the window is not one. + req = _create(rule_id=5, window_days=90) + assert req.input_json == {'rule_id': '5', 'window_days': 90, 'community': 'gamma'} + + def test_the_sdk_does_not_validate_the_value(self): + # The server owns the enum and answers anything else with a 400. + assert _create(yara=_YARA, window_days=45).input_json['window_days'] == 45 + + +class HistoricalCreateWindowTestCase(ClientTestCase): + """What ``historical_create`` puts on the wire, one body over both clients.""" + + def setUp(self): + super().setUp() + self.mock.add('POST', _HUNT_URL, json={'status': 'OK', 'result': _hunt()}) + + def test_window_reaches_the_body_as_an_int(self): + self.api.historical_create(_YARA, window_days=30) + assert self.mock.last_request_body == { + 'yara': _YARA, 'window_days': 30, 'community': COMMUNITY} + + def test_window_composes_with_a_stored_rule(self): + self.api.historical_create(5, window_days=90) + assert self.mock.last_request_body == { + 'rule_id': '5', 'window_days': 90, 'community': COMMUNITY} + + def test_no_window_sends_no_key(self): + self.api.historical_create(_YARA) + assert self.mock.last_request_body == {'yara': _YARA, 'community': COMMUNITY} + + def test_explicit_none_is_byte_identical_to_a_bare_call(self): + self.api.historical_create(_YARA) + self.api.historical_create(_YARA, window_days=None) + bare, explicit = self.mock.requests + assert explicit.content == bare.content + + +class TestHistoricalHuntWindowParse: + @pytest.mark.parametrize('cls', [resources.HistoricalHunt, resources.HistoricalHuntList]) + def test_the_window_parses_as_the_int(self, cls): + assert cls(_hunt(window_days=30), api=None).window_days == 30 + + @pytest.mark.parametrize('cls', [resources.HistoricalHunt, resources.HistoricalHuntList]) + def test_an_explicit_null_is_none(self, cls): + assert cls(_hunt(window_days=None), api=None).window_days is None + + @pytest.mark.parametrize('cls', [resources.HistoricalHunt, resources.HistoricalHuntList]) + def test_a_missing_key_is_none(self, cls): + # A server predating the field omits the key altogether. + assert 'window_days' not in _hunt() + assert cls(_hunt(), api=None).window_days is None + + +class HistoricalWindowResponseTestCase(ClientTestCase): + """The window on the create response, the single GET and the list, through the full + pipeline. A fabricated envelope, standing in until a live round trip is recorded. + """ + + def test_create_returns_the_window(self): + self.mock.add('POST', _HUNT_URL, json={'status': 'OK', 'result': _hunt(window_days=30)}) + assert self.api.historical_create(_YARA, window_days=30).window_days == 30 + + def test_get_returns_the_window(self): + self.mock.add('GET', f'{_HUNT_URL}?id=7&community={COMMUNITY}', + json={'status': 'OK', 'result': _hunt(window_days=60)}) + assert self.api.historical_get(7).window_days == 60 + + def test_list_returns_the_window_on_every_hunt(self): + rows = [_hunt(id='7', window_days=30), _hunt(id='8', window_days=None)] + self.mock.add('GET', f'{_HUNT_URL}/list?community={COMMUNITY}', json={ + 'status': 'OK', 'result': rows, 'has_more': False, 'limit': 50, 'offset': None}) + hunts = list(self.api.historical_list()) + assert [(h.id, h.window_days) for h in hunts] == [('7', 30), ('8', None)] From 367d6b3efec5a7a968dda62dbfda0ccc6f1fca79 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Tue, 20 Oct 2026 17:49:45 -0300 Subject: [PATCH 4/7] feat: release 4.8.0, the floor the CLI now pins The CLI client adopts `historical_create(window_days=)` in the paired change set and expresses that as `polyswarm_api>=4.8.0`. develop already declares 4.7.0 for a surface that does not include this keyword, so the floor needs the next version up; a floor cannot name a version this repo has not declared, so the bump lands here, in the feature PR (AGENTS.md's standing exception). Minor: one new optional keyword whose default preserves today's request, plus an additive resource field, so no existing call changes behaviour. Bumped with bump-my-version; the emitted string is a clean `4.8.0`. The server already accepts and returns `window_days`, so this repo can release ahead of the CLI. Co-Authored-By: Alan Justino --- pyproject.toml | 4 ++-- src/polyswarm_api/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 142d64bc..0c910191 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "polyswarm_api" -version = "4.7.0" +version = "4.8.0" description = "Client library to simplify interacting with the PolySwarm consumer API" readme = "README.md" requires-python = ">=3.10,<4" @@ -55,7 +55,7 @@ package-dir = { "" = "src" } where = ["src"] [tool.bumpversion] -current_version = "4.7.0" +current_version = "4.8.0" commit = true tag = false sign_tags = true diff --git a/src/polyswarm_api/__init__.py b/src/polyswarm_api/__init__.py index 5cf1f295..6c1d0b88 100644 --- a/src/polyswarm_api/__init__.py +++ b/src/polyswarm_api/__init__.py @@ -1,5 +1,5 @@ # https://www.python.org/dev/peps/pep-0008/#module-level-dunder-names -__version__ = '4.7.0' +__version__ = '4.8.0' __release_url__ = 'https://api.github.com/repos/polyswarm/polyswarm-api/releases/latest' from . import api From 0de0d9bd651e3331008ac1980250a2f6cb48433e Mon Sep 17 00:00:00 2001 From: Claude Code Date: Wed, 21 Oct 2026 10:15:40 -0300 Subject: [PATCH 5/7] test: pin window_days on the server's own responses A live pair, sync and async, creates one hunt with a 30-day window and one without, then reads both back on create, get and list: 30 and None. The cassettes were recorded against the e2e stack, and the pair also passes with VCR off. It replaces the respx stand-in that asserted fabricated envelopes, and closes the open question that tracked the gap. The builder, pass-through and parse tests stay: a cassette cannot see request bodies. Co-Authored-By: Alan Justino --- specs/04-testing.md | 2 +- specs/99-open-questions.md | 18 - test/async_client_test.py | 18 + test/client_scan_test.py | 18 + test/historical_window_test.py | 26 +- .../vcr/test_async_historical_window_days.vcr | 326 ++++++++++++++++++ test/vcr/test_historical_window_days.vcr | 326 ++++++++++++++++++ 7 files changed, 691 insertions(+), 43 deletions(-) create mode 100644 test/vcr/test_async_historical_window_days.vcr create mode 100644 test/vcr/test_historical_window_days.vcr diff --git a/specs/04-testing.md b/specs/04-testing.md index 5e9a884b..5a84bd9d 100644 --- a/specs/04-testing.md +++ b/specs/04-testing.md @@ -33,7 +33,7 @@ How the test suite is organised. Three layers: pure unit tests (no HTTP at all - `test/hunt_tracking_builder_test.py` — pure-unit request-shape and parse tests for the hunt-page tracking builders/resources. - `test/refang_test.py` — pure-unit tests for `polyswarm_api.refang` (driven by the shared case table `test/fixtures/refang_cases.json`, kept byte-identical with the other clients that implement the same contract) and request-shape tests for every client method that refangs its IoC inputs, captured at the `_paginate` / `_single` boundary for both transports. Pure-unit because this is client-side input normalization: the server contract is unchanged, so there is no new endpoint behaviour for a cassette to pin. - `test/ioc_search_test.py` — `search_by_ioc(with_artifacts=)`: pure-unit request shape (the int flag, the unchanged default and bare call), pass-through on both client methods, and a dual-transport (`ClientTestCase`) respx parse of an artifact row — a stand-in until the e2e stack serves the parameter (see `99-open-questions.md`). -- `test/historical_window_test.py` — `historical_create(window_days=)` and `HistoricalHunt.window_days`: pure-unit request shape (the int in the body, the key absent for `None`, no client-side validation) and parse (int, explicit null, missing key — on `HistoricalHunt` and `HistoricalHuntList`), plus dual-transport (`ClientTestCase`) respx cases for the body each client sends and for the window on the create response, the single GET and the list. Respx because VCR does not match bodies and the recorded hunts predate the field; the live round trip is pending (see `99-open-questions.md`). +- `test/historical_window_test.py` — `historical_create(window_days=)` and `HistoricalHunt.window_days`: pure-unit request shape (the int in the body, the key absent for `None`, no client-side validation) and parse (int, explicit null, missing key — on `HistoricalHunt` and `HistoricalHuntList`), plus dual-transport (`ClientTestCase`) respx cases for the body each client sends — respx because VCR does not match bodies. What the server returns is pinned live by `test_historical_window_days` / `test_async_historical_window_days` (a hunt with a window and one without, read back on create, get and list). - `test/ruleset_favorite_respx_test.py` — dual-transport (`ClientTestCase`) respx suite for the favorite toggle: the `FAVORITE_LIMIT` refusal envelope and the query/body split. - `test/sandbox_file_qrcode_respx_test.py` — dual-transport (`ClientTestCase`) respx suite pinning that a QR-code `sandbox_file` submission uploads the image's bytes (the S3 PUT body) under its unrefanged basename. Respx rather than e2e because the stack's sandbox providers cannot reasonably process a QR image. diff --git a/specs/99-open-questions.md b/specs/99-open-questions.md index 5fce1ccf..5d4dfc1a 100644 --- a/specs/99-open-questions.md +++ b/specs/99-open-questions.md @@ -226,21 +226,3 @@ invariant 1 exists to close. the live `test_search_by_ioc` pair, record both cassettes against a fresh stack, and delete the respx `IocSearchWithArtifactsTestCase` along with this entry. The builder and pass-through tests in that module stay: they pin request shape, which a cassette cannot. - -## `window_days` on historical hunts is not pinned against a live server - -**Status:** gap, pending a recording against a fresh e2e stack. - -The window is asserted only at the SDK boundary (`test/historical_window_test.py`): the body -each client sends, and the parse of hand-built envelopes. The recorded `test_historical` / -`test_list_historical` cassettes (sync and async) predate the field, so their responses carry -no `window_days`, and VCR does not match request bodies — replaying them proves neither that -the server accepts the key nor that it echoes it back. That is the "asserts what we *think* -the server returns" gap invariant 1 exists to close. - -**Action:** against a fresh e2e stack, record a lifecycle exchange with a window — create with -`window_days`, then get and list it, asserting the value round-trips (and that a hunt created -without one reads back `None`) — in the live pair, on both transports. Re-record by deleting -the cassette, never by editing it. Then delete the respx `HistoricalWindowResponseTestCase` -along with this entry. The builder, pass-through and parse tests stay: a cassette cannot see -the request body. diff --git a/test/async_client_test.py b/test/async_client_test.py index ae0d6184..1be7113b 100644 --- a/test/async_client_test.py +++ b/test/async_client_test.py @@ -867,6 +867,24 @@ async def test_async_list_historical(self, uid): listed_ids = {h.id async for h in api.historical_list()} assert set(historical_ids) <= listed_ids + @vcr.use_cassette() + async def test_async_historical_window_days(self, uid): + async with self._api() as api: + yara_content = uid_yara(uid) + windowed = await api.historical_create(yara_content, window_days=30) + unbounded = await api.historical_create(yara_content) + try: + # The server echoes the window on create, get and list; None means none requested. + assert (windowed.window_days, unbounded.window_days) == (30, None) + assert (await api.historical_get(windowed.id)).window_days == 30 + assert (await api.historical_get(unbounded.id)).window_days is None + ids = {windowed.id, unbounded.id} + listed = {h.id: h.window_days async for h in api.historical_list() if h.id in ids} + assert listed == {windowed.id: 30, unbounded.id: None} + finally: + for hunt in (windowed, unbounded): + await api.historical_delete(hunt.id) + @vcr.use_cassette() async def test_async_historical_results(self, uid): async with self._api() as api: diff --git a/test/client_scan_test.py b/test/client_scan_test.py index 78f63790..567b00e2 100644 --- a/test/client_scan_test.py +++ b/test/client_scan_test.py @@ -628,6 +628,24 @@ def test_list_historical(self): listed_ids = {h.id for h in api.historical_list()} assert set(historical_ids) <= listed_ids + @vcr.use_cassette() + def test_historical_window_days(self): + api = PolyswarmAPI(self.test_api_key, uri=f'http://ai:9696/{self.api_version}', community='gamma') + yara_content = uid_yara(self._testMethodName) + windowed = api.historical_create(yara_content, window_days=30) + unbounded = api.historical_create(yara_content) + try: + # The server echoes the window on create, get and list; None means none requested. + assert (windowed.window_days, unbounded.window_days) == (30, None) + assert api.historical_get(windowed.id).window_days == 30 + assert api.historical_get(unbounded.id).window_days is None + ids = {windowed.id, unbounded.id} + listed = {h.id: h.window_days for h in api.historical_list() if h.id in ids} + assert listed == {windowed.id: 30, unbounded.id: None} + finally: + for hunt in (windowed, unbounded): + api.historical_delete(hunt.id) + @vcr.use_cassette() def test_historical_results(self): api = PolyswarmAPI(self.test_api_key, uri=f'http://ai:9696/{self.api_version}', community='gamma') diff --git a/test/historical_window_test.py b/test/historical_window_test.py index 555ab554..4d026fc2 100644 --- a/test/historical_window_test.py +++ b/test/historical_window_test.py @@ -1,8 +1,8 @@ """``window_days`` on historical hunts: request shape, pass-through on both clients, parse. Builder and parse cases are pure-unit. The pass-through cases are respx because VCR does -not match bodies and the recorded cassettes predate the field, so only a mocked boundary -can see what the body carried. The live round trip is pending (specs/99-open-questions.md). +not match bodies, so only a mocked boundary can see what the body carried. The server's +side is pinned live by ``test_historical_window_days`` and its async twin. """ import pytest @@ -101,25 +101,3 @@ def test_a_missing_key_is_none(self, cls): # A server predating the field omits the key altogether. assert 'window_days' not in _hunt() assert cls(_hunt(), api=None).window_days is None - - -class HistoricalWindowResponseTestCase(ClientTestCase): - """The window on the create response, the single GET and the list, through the full - pipeline. A fabricated envelope, standing in until a live round trip is recorded. - """ - - def test_create_returns_the_window(self): - self.mock.add('POST', _HUNT_URL, json={'status': 'OK', 'result': _hunt(window_days=30)}) - assert self.api.historical_create(_YARA, window_days=30).window_days == 30 - - def test_get_returns_the_window(self): - self.mock.add('GET', f'{_HUNT_URL}?id=7&community={COMMUNITY}', - json={'status': 'OK', 'result': _hunt(window_days=60)}) - assert self.api.historical_get(7).window_days == 60 - - def test_list_returns_the_window_on_every_hunt(self): - rows = [_hunt(id='7', window_days=30), _hunt(id='8', window_days=None)] - self.mock.add('GET', f'{_HUNT_URL}/list?community={COMMUNITY}', json={ - 'status': 'OK', 'result': rows, 'has_more': False, 'limit': 50, 'offset': None}) - hunts = list(self.api.historical_list()) - assert [(h.id, h.window_days) for h in hunts] == [('7', 30), ('8', None)] diff --git a/test/vcr/test_async_historical_window_days.vcr b/test/vcr/test_async_historical_window_days.vcr new file mode 100644 index 00000000..43fa12b4 --- /dev/null +++ b/test/vcr/test_async_historical_window_days.vcr @@ -0,0 +1,326 @@ +interactions: +- request: + body: '{"yara":"rule sdk_test_async_historical_window_days { strings: $u = \"test_async_historical_window_days\" + condition: $u }","window_days":30,"community":"gamma"}' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + content-length: + - '160' + content-type: + - application/json + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: POST + uri: http://ai:9696/v3/hunt/historical + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.679196+00:00","failed_max_retries":0,"failed_other":0,"id":"27363494633339458","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":30,"yara":"rule + sdk_test_async_historical_window_days { strings: $u = \"test_async_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '570' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '{"yara":"rule sdk_test_async_historical_window_days { strings: $u = \"test_async_historical_window_days\" + condition: $u }","community":"gamma"}' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + content-length: + - '143' + content-type: + - application/json + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: POST + uri: http://ai:9696/v3/hunt/historical + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.724288+00:00","failed_max_retries":0,"failed_other":0,"id":"40075594027765663","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule + sdk_test_async_historical_window_days { strings: $u = \"test_async_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '572' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: GET + uri: http://ai:9696/v3/hunt/historical?id=27363494633339458&community=gamma + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.679196+00:00","failed_max_retries":0,"failed_other":0,"id":"27363494633339458","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":30,"yara":"rule + sdk_test_async_historical_window_days { strings: $u = \"test_async_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '570' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: GET + uri: http://ai:9696/v3/hunt/historical?id=40075594027765663&community=gamma + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.724288+00:00","failed_max_retries":0,"failed_other":0,"id":"40075594027765663","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule + sdk_test_async_historical_window_days { strings: $u = \"test_async_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '572' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: GET + uri: http://ai:9696/v3/hunt/historical/list?community=gamma + response: + body: + string: '{"has_more":false,"limit":50,"result":[{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.724288+00:00","id":"40075594027765663","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.679196+00:00","id":"27363494633339458","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":30,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.606259+00:00","id":"4134553051212861","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.559119+00:00","id":"63790780453166614","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.513053+00:00","id":"83945889672772698","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.459810+00:00","id":"58040492053046630","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.411681+00:00","id":"17372717959168159","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.141062+00:00","id":"43783504355477803","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.809660+00:00","id":"6447048420148760","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.768119+00:00","id":"27886352331973438","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.723965+00:00","id":"2049602096428236","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.681280+00:00","id":"7126890832542907","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.629460+00:00","id":"59350603088096354","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null}],"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '4898' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '{"community":"gamma"}' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + content-length: + - '21' + content-type: + - application/json + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: DELETE + uri: http://ai:9696/v3/hunt/historical?id=27363494633339458 + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.679196+00:00","failed_max_retries":0,"failed_other":0,"id":"27363494633339458","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"DELETING","summary":null,"user_account_number":"111","window_days":30,"yara":"rule + sdk_test_async_historical_window_days { strings: $u = \"test_async_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '571' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '{"community":"gamma"}' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + content-length: + - '21' + content-type: + - application/json + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: DELETE + uri: http://ai:9696/v3/hunt/historical?id=40075594027765663 + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.724288+00:00","failed_max_retries":0,"failed_other":0,"id":"40075594027765663","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"DELETING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule + sdk_test_async_historical_window_days { strings: $u = \"test_async_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '573' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +version: 1 diff --git a/test/vcr/test_historical_window_days.vcr b/test/vcr/test_historical_window_days.vcr new file mode 100644 index 00000000..fe5ea610 --- /dev/null +++ b/test/vcr/test_historical_window_days.vcr @@ -0,0 +1,326 @@ +interactions: +- request: + body: '{"yara":"rule sdk_test_historical_window_days { strings: $u = \"test_historical_window_days\" + condition: $u }","window_days":30,"community":"gamma"}' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + content-length: + - '148' + content-type: + - application/json + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: POST + uri: http://ai:9696/v3/hunt/historical + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.882427+00:00","failed_max_retries":0,"failed_other":0,"id":"55340953576717196","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":30,"yara":"rule + sdk_test_historical_window_days { strings: $u = \"test_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '558' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:46 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '{"yara":"rule sdk_test_historical_window_days { strings: $u = \"test_historical_window_days\" + condition: $u }","community":"gamma"}' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + content-length: + - '131' + content-type: + - application/json + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: POST + uri: http://ai:9696/v3/hunt/historical + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.928345+00:00","failed_max_retries":0,"failed_other":0,"id":"99256637874103471","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule + sdk_test_historical_window_days { strings: $u = \"test_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '560' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:46 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: GET + uri: http://ai:9696/v3/hunt/historical?id=55340953576717196&community=gamma + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.882427+00:00","failed_max_retries":0,"failed_other":0,"id":"55340953576717196","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":30,"yara":"rule + sdk_test_historical_window_days { strings: $u = \"test_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '558' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:46 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: GET + uri: http://ai:9696/v3/hunt/historical?id=99256637874103471&community=gamma + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.928345+00:00","failed_max_retries":0,"failed_other":0,"id":"99256637874103471","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule + sdk_test_historical_window_days { strings: $u = \"test_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '560' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:46 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: GET + uri: http://ai:9696/v3/hunt/historical/list?community=gamma + response: + body: + string: '{"has_more":false,"limit":50,"result":[{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.928345+00:00","id":"99256637874103471","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.882427+00:00","id":"55340953576717196","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":30,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.809660+00:00","id":"6447048420148760","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.768119+00:00","id":"27886352331973438","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.723965+00:00","id":"2049602096428236","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.681280+00:00","id":"7126890832542907","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.629460+00:00","id":"59350603088096354","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null}],"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '2661' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '{"community":"gamma"}' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + content-length: + - '21' + content-type: + - application/json + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: DELETE + uri: http://ai:9696/v3/hunt/historical?id=55340953576717196 + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.882427+00:00","failed_max_retries":0,"failed_other":0,"id":"55340953576717196","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"DELETING","summary":null,"user_account_number":"111","window_days":30,"yara":"rule + sdk_test_historical_window_days { strings: $u = \"test_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '559' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +- request: + body: '{"community":"gamma"}' + headers: + accept: + - '*/*' + accept-encoding: + - gzip, deflate + authorization: + - '11111111111111111111111111111111' + connection: + - keep-alive + content-length: + - '21' + content-type: + - application/json + host: + - ai:9696 + user-agent: + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) + method: DELETE + uri: http://ai:9696/v3/hunt/historical?id=99256637874103471 + response: + body: + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.928345+00:00","failed_max_retries":0,"failed_other":0,"id":"99256637874103471","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"DELETING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule + sdk_test_historical_window_days { strings: $u = \"test_historical_window_days\" + condition: $u }"},"status":"OK"} + + ' + headers: + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - Authorization + Connection: + - keep-alive + Content-Length: + - '561' + Content-Type: + - application/json + Date: + - Wed, 21 Oct 2026 13:14:47 GMT + Server: + - gunicorn + X-Billing-ID: + - '111' + status: + code: 200 + message: OK +version: 1 From 4c2554578d97aa23dd799439d3c972bb040e2ded Mon Sep 17 00:00:00 2001 From: Claude Code Date: Wed, 21 Oct 2026 10:15:40 -0300 Subject: [PATCH 6/7] test: re-record the historical hunt cassettes Their recorded create, get and list responses predated window_days. Re-recorded by deleting each cassette and running its test against the e2e stack, so replay serves the shape the server returns today, the key included. Co-Authored-By: Alan Justino --- test/vcr/test_async_historical.vcr | 28 ++++++------- test/vcr/test_async_historical_results.vcr | 14 +++---- test/vcr/test_async_list_historical.vcr | 48 +++++++++++----------- test/vcr/test_historical.vcr | 28 ++++++------- test/vcr/test_historical_results.vcr | 14 +++---- test/vcr/test_list_historical.vcr | 48 +++++++++++----------- 6 files changed, 90 insertions(+), 90 deletions(-) diff --git a/test/vcr/test_async_historical.vcr b/test/vcr/test_async_historical.vcr index 359fb21a..f5631529 100644 --- a/test/vcr/test_async_historical.vcr +++ b/test/vcr/test_async_historical.vcr @@ -18,12 +18,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.403459+00:00","failed_max_retries":0,"failed_other":0,"id":"35934095384555821","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.216631+00:00","failed_max_retries":0,"failed_other":0,"id":"46202933697126034","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_historical { strings: $u = \"test_async_historical\" condition: $u }"},"status":"OK"} @@ -36,11 +36,11 @@ interactions: Connection: - keep-alive Content-Length: - - '466' + - '548' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -62,12 +62,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: GET - uri: http://ai:9696/v3/hunt/historical?id=35934095384555821&community=gamma + uri: http://ai:9696/v3/hunt/historical?id=46202933697126034&community=gamma response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.403459+00:00","failed_max_retries":0,"failed_other":0,"id":"35934095384555821","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.216631+00:00","failed_max_retries":0,"failed_other":0,"id":"46202933697126034","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_historical { strings: $u = \"test_async_historical\" condition: $u }"},"status":"OK"} @@ -80,11 +80,11 @@ interactions: Connection: - keep-alive Content-Length: - - '466' + - '548' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -110,12 +110,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: DELETE - uri: http://ai:9696/v3/hunt/historical?id=35934095384555821 + uri: http://ai:9696/v3/hunt/historical?id=46202933697126034 response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.403459+00:00","failed_max_retries":0,"failed_other":0,"id":"35934095384555821","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"DELETING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.216631+00:00","failed_max_retries":0,"failed_other":0,"id":"46202933697126034","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"DELETING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_historical { strings: $u = \"test_async_historical\" condition: $u }"},"status":"OK"} @@ -128,11 +128,11 @@ interactions: Connection: - keep-alive Content-Length: - - '467' + - '549' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: diff --git a/test/vcr/test_async_historical_results.vcr b/test/vcr/test_async_historical_results.vcr index 33303359..af61265a 100644 --- a/test/vcr/test_async_historical_results.vcr +++ b/test/vcr/test_async_historical_results.vcr @@ -18,12 +18,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.755351+00:00","failed_max_retries":0,"failed_other":0,"id":"51213972298513151","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.915116+00:00","failed_max_retries":0,"failed_other":0,"id":"88337888683381847","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_historical_results { strings: $u = \"test_async_historical_results\" condition: $u }"},"status":"OK"} @@ -36,11 +36,11 @@ interactions: Connection: - keep-alive Content-Length: - - '482' + - '564' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -62,9 +62,9 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: GET - uri: http://ai:9696/v3/hunt/historical/results/list?id=51213972298513151&community=gamma + uri: http://ai:9696/v3/hunt/historical/results/list?id=88337888683381847&community=gamma response: body: string: '' @@ -78,7 +78,7 @@ interactions: Content-Type: - text/html; charset=utf-8 Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn status: diff --git a/test/vcr/test_async_list_historical.vcr b/test/vcr/test_async_list_historical.vcr index b05e4c0f..1a191f81 100644 --- a/test/vcr/test_async_list_historical.vcr +++ b/test/vcr/test_async_list_historical.vcr @@ -18,12 +18,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.504860+00:00","failed_max_retries":0,"failed_other":0,"id":"8290930961482725","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.411681+00:00","failed_max_retries":0,"failed_other":0,"id":"17372717959168159","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_list_historical { strings: $u = \"test_async_list_historical\" condition: $u }"},"status":"OK"} @@ -36,11 +36,11 @@ interactions: Connection: - keep-alive Content-Length: - - '475' + - '558' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -67,12 +67,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.550525+00:00","failed_max_retries":0,"failed_other":0,"id":"45949838125672986","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.459810+00:00","failed_max_retries":0,"failed_other":0,"id":"58040492053046630","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_list_historical { strings: $u = \"test_async_list_historical\" condition: $u }"},"status":"OK"} @@ -85,11 +85,11 @@ interactions: Connection: - keep-alive Content-Length: - - '476' + - '558' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -116,12 +116,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.592366+00:00","failed_max_retries":0,"failed_other":0,"id":"15725209613415703","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.513053+00:00","failed_max_retries":0,"failed_other":0,"id":"83945889672772698","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_list_historical { strings: $u = \"test_async_list_historical\" condition: $u }"},"status":"OK"} @@ -134,11 +134,11 @@ interactions: Connection: - keep-alive Content-Length: - - '476' + - '558' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -165,12 +165,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.656995+00:00","failed_max_retries":0,"failed_other":0,"id":"88826403627398312","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.559119+00:00","failed_max_retries":0,"failed_other":0,"id":"63790780453166614","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_list_historical { strings: $u = \"test_async_list_historical\" condition: $u }"},"status":"OK"} @@ -183,11 +183,11 @@ interactions: Connection: - keep-alive Content-Length: - - '476' + - '558' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -214,12 +214,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:37:20.695183+00:00","failed_max_retries":0,"failed_other":0,"id":"13919779479626947","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.606259+00:00","failed_max_retries":0,"failed_other":0,"id":"4134553051212861","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_async_list_historical { strings: $u = \"test_async_list_historical\" condition: $u }"},"status":"OK"} @@ -232,11 +232,11 @@ interactions: Connection: - keep-alive Content-Length: - - '476' + - '557' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -258,12 +258,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: GET uri: http://ai:9696/v3/hunt/historical/list?community=gamma response: body: - string: '{"has_more":false,"limit":50,"result":[{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:37:20.695183+00:00","id":"13919779479626947","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:37:20.656995+00:00","id":"88826403627398312","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:37:20.592366+00:00","id":"15725209613415703","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:37:20.550525+00:00","id":"45949838125672986","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:37:20.504860+00:00","id":"8290930961482725","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.562853+00:00","id":"53359932363657862","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.521466+00:00","id":"24956296142984681","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.480348+00:00","id":"54272719094803031","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.441527+00:00","id":"58288022169534211","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.397319+00:00","id":"86221284475520679","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.255339+00:00","id":"46026864008511354","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:31:26.868688+00:00","id":"51603247373653891","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null}],"status":"OK"} + string: '{"has_more":false,"limit":50,"result":[{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.606259+00:00","id":"4134553051212861","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.559119+00:00","id":"63790780453166614","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.513053+00:00","id":"83945889672772698","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.459810+00:00","id":"58040492053046630","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.411681+00:00","id":"17372717959168159","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:47.141062+00:00","id":"43783504355477803","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.809660+00:00","id":"6447048420148760","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.768119+00:00","id":"27886352331973438","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.723965+00:00","id":"2049602096428236","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.681280+00:00","id":"7126890832542907","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.629460+00:00","id":"59350603088096354","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null}],"status":"OK"} ' headers: @@ -274,11 +274,11 @@ interactions: Connection: - keep-alive Content-Length: - - '3546' + - '4154' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:37:20 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: diff --git a/test/vcr/test_historical.vcr b/test/vcr/test_historical.vcr index 28a8b201..5cceb9a4 100644 --- a/test/vcr/test_historical.vcr +++ b/test/vcr/test_historical.vcr @@ -18,12 +18,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.115323+00:00","failed_max_retries":0,"failed_other":0,"id":"29328811284340624","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.386019+00:00","failed_max_retries":0,"failed_other":0,"id":"93048973633363425","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_historical { strings: $u = \"test_historical\" condition: $u }"},"status":"OK"} ' @@ -35,11 +35,11 @@ interactions: Connection: - keep-alive Content-Length: - - '454' + - '536' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: @@ -61,12 +61,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: GET - uri: http://ai:9696/v3/hunt/historical?id=29328811284340624&community=gamma + uri: http://ai:9696/v3/hunt/historical?id=93048973633363425&community=gamma response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.115323+00:00","failed_max_retries":0,"failed_other":0,"id":"29328811284340624","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.386019+00:00","failed_max_retries":0,"failed_other":0,"id":"93048973633363425","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_historical { strings: $u = \"test_historical\" condition: $u }"},"status":"OK"} ' @@ -78,11 +78,11 @@ interactions: Connection: - keep-alive Content-Length: - - '454' + - '536' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: @@ -108,12 +108,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: DELETE - uri: http://ai:9696/v3/hunt/historical?id=29328811284340624 + uri: http://ai:9696/v3/hunt/historical?id=93048973633363425 response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.115323+00:00","failed_max_retries":0,"failed_other":0,"id":"29328811284340624","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"DELETING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.386019+00:00","failed_max_retries":0,"failed_other":0,"id":"93048973633363425","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"DELETING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_historical { strings: $u = \"test_historical\" condition: $u }"},"status":"OK"} ' @@ -125,11 +125,11 @@ interactions: Connection: - keep-alive Content-Length: - - '455' + - '537' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: diff --git a/test/vcr/test_historical_results.vcr b/test/vcr/test_historical_results.vcr index 1756c2ff..1676b855 100644 --- a/test/vcr/test_historical_results.vcr +++ b/test/vcr/test_historical_results.vcr @@ -18,12 +18,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.255339+00:00","failed_max_retries":0,"failed_other":0,"id":"46026864008511354","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:47.141062+00:00","failed_max_retries":0,"failed_other":0,"id":"43783504355477803","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_historical_results { strings: $u = \"test_historical_results\" condition: $u }"},"status":"OK"} @@ -36,11 +36,11 @@ interactions: Connection: - keep-alive Content-Length: - - '470' + - '552' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn X-Billing-ID: @@ -62,9 +62,9 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: GET - uri: http://ai:9696/v3/hunt/historical/results/list?id=46026864008511354&community=gamma + uri: http://ai:9696/v3/hunt/historical/results/list?id=43783504355477803&community=gamma response: body: string: '' @@ -78,7 +78,7 @@ interactions: Content-Type: - text/html; charset=utf-8 Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:47 GMT Server: - gunicorn status: diff --git a/test/vcr/test_list_historical.vcr b/test/vcr/test_list_historical.vcr index f735f4b5..a9ddc9f7 100644 --- a/test/vcr/test_list_historical.vcr +++ b/test/vcr/test_list_historical.vcr @@ -18,12 +18,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.397319+00:00","failed_max_retries":0,"failed_other":0,"id":"86221284475520679","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.629460+00:00","failed_max_retries":0,"failed_other":0,"id":"59350603088096354","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_list_historical { strings: $u = \"test_list_historical\" condition: $u }"},"status":"OK"} @@ -36,11 +36,11 @@ interactions: Connection: - keep-alive Content-Length: - - '464' + - '546' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: @@ -67,12 +67,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.441527+00:00","failed_max_retries":0,"failed_other":0,"id":"58288022169534211","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.681280+00:00","failed_max_retries":0,"failed_other":0,"id":"7126890832542907","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_list_historical { strings: $u = \"test_list_historical\" condition: $u }"},"status":"OK"} @@ -85,11 +85,11 @@ interactions: Connection: - keep-alive Content-Length: - - '464' + - '545' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: @@ -116,12 +116,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.480348+00:00","failed_max_retries":0,"failed_other":0,"id":"54272719094803031","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.723965+00:00","failed_max_retries":0,"failed_other":0,"id":"2049602096428236","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_list_historical { strings: $u = \"test_list_historical\" condition: $u }"},"status":"OK"} @@ -134,11 +134,11 @@ interactions: Connection: - keep-alive Content-Length: - - '464' + - '545' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: @@ -165,12 +165,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.521466+00:00","failed_max_retries":0,"failed_other":0,"id":"24956296142984681","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.768119+00:00","failed_max_retries":0,"failed_other":0,"id":"27886352331973438","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_list_historical { strings: $u = \"test_list_historical\" condition: $u }"},"status":"OK"} @@ -183,11 +183,11 @@ interactions: Connection: - keep-alive Content-Length: - - '464' + - '546' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: @@ -214,12 +214,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: POST uri: http://ai:9696/v3/hunt/historical response: body: - string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-06-03T22:35:46.562853+00:00","failed_max_retries":0,"failed_other":0,"id":"53359932363657862","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":"rule + string: '{"result":{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"communities":["gamma"],"created":"2026-10-21T13:14:46.809660+00:00","failed_max_retries":0,"failed_other":0,"id":"6447048420148760","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":"rule sdk_test_list_historical { strings: $u = \"test_list_historical\" condition: $u }"},"status":"OK"} @@ -232,11 +232,11 @@ interactions: Connection: - keep-alive Content-Length: - - '464' + - '545' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: @@ -258,12 +258,12 @@ interactions: host: - ai:9696 user-agent: - - polyswarm_api/3.21.0 (x86_64-Linux-CPython-3.14.4) + - polyswarm_api/4.8.0 (x86_64-Linux-CPython-3.12.15) method: GET uri: http://ai:9696/v3/hunt/historical/list?community=gamma response: body: - string: '{"has_more":false,"limit":50,"result":[{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.562853+00:00","id":"53359932363657862","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.521466+00:00","id":"24956296142984681","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.480348+00:00","id":"54272719094803031","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.441527+00:00","id":"58288022169534211","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.397319+00:00","id":"86221284475520679","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:35:46.255339+00:00","id":"46026864008511354","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-06-03T22:31:26.868688+00:00","id":"51603247373653891","progress":null,"results_csv_uri":null,"ruleset_name":null,"status":"PENDING","summary":null,"user_account_number":"111","yara":null}],"status":"OK"} + string: '{"has_more":false,"limit":50,"result":[{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.809660+00:00","id":"6447048420148760","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.768119+00:00","id":"27886352331973438","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.723965+00:00","id":"2049602096428236","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.681280+00:00","id":"7126890832542907","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null},{"account_number":"111","archives_in_flight":0,"archives_scanned":0,"archives_total":0,"created":"2026-10-21T13:14:46.629460+00:00","id":"59350603088096354","progress":null,"results_csv_uri":null,"rule_id":null,"rule_modified":null,"ruleset_name":null,"source_rule_changed":null,"status":"PENDING","summary":null,"user_account_number":"111","window_days":null,"yara":null}],"status":"OK"} ' headers: @@ -274,11 +274,11 @@ interactions: Connection: - keep-alive Content-Length: - - '2092' + - '1917' Content-Type: - application/json Date: - - Wed, 03 Jun 2026 22:35:46 GMT + - Wed, 21 Oct 2026 13:14:46 GMT Server: - gunicorn X-Billing-ID: From d5502a75c8d933544b80c5488ef6115ef30ce815 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Wed, 21 Oct 2026 11:03:57 -0300 Subject: [PATCH 7/7] ci: re-run the PR checks Co-Authored-By: Alan Justino