feat(reports): store and browse report artifacts

This commit is contained in:
zwitschi committed 2026-11-06 12:27:00 +01:00
1 parent 5967a43eb5
commit 6f2e479958
13 files changed
+875 -93

No files matched your search

+50 -1
View File
@@ -47,7 +47,7 @@ class SchemaTest(unittest.TestCase):
"blocklist_reasons", "whitelist_entries",
"whitelist_sources", "firewall_snapshots",
"firewall_address_list_entries", "firewall_rule_entries",
"whois_info", "log_sources"):
"whois_info", "log_sources", "report_artifacts"):
self.assertIn(t, tables, f"missing table {t}")
conn.close()
@@ -195,5 +195,54 @@ class FirewallTest(unittest.TestCase):
"SELECT COUNT(*) FROM firewall_rule_entries").fetchone()[0], 1)
class ReportArtifactTest(unittest.TestCase):
def setUp(self):
self.conn = _new_conn()
def tearDown(self):
self.conn.close()
def test_artifact_insert_is_idempotent_and_detail_decodes_payload(self):
kwargs = {
"source": "copyparty", "report_type": "analyzer_summary",
"generated_at": "2026-11-01T10:00:00+00:00",
"payload": {"summary": {"requests": 12}},
"original_path": "reports/copyparty/2026-11-01.txt",
"content_sha256": "a" * 64,
}
first_id = repo.insert_report_artifact(self.conn, **kwargs)
duplicate_id = repo.insert_report_artifact(self.conn, **kwargs)
self.assertEqual(first_id, duplicate_id)
self.assertEqual(self.conn.execute(
"SELECT COUNT(*) FROM report_artifacts").fetchone()[0], 1)
self.assertEqual(repo.get_report_artifact(self.conn, first_id)["payload"],
kwargs["payload"])
def test_artifact_cursor_orders_stably_and_filters_source(self):
for day, source in (("01", "npm"), ("02", "copyparty"),
("03", "npm")):
repo.insert_report_artifact(
self.conn, source=source, report_type="summary",
generated_at=f"2026-11-{day}T00:00:00+00:00",
payload={"day": day}, original_path=f"reports/{day}.txt",
content_sha256=day * 64,
)
first = repo.list_report_artifacts(self.conn, source="npm", limit=1)
self.assertEqual(len(first["items"]), 1)
self.assertIsNotNone(first["next_cursor"])
second = repo.list_report_artifacts(
self.conn, source="npm", limit=1, cursor=first["next_cursor"])
self.assertEqual(len(second["items"]), 1)
self.assertIsNone(second["next_cursor"])
self.assertGreater(first["items"][0]["generated_at"],
second["items"][0]["generated_at"])
def test_artifact_cursor_rejects_invalid_token(self):
with self.assertRaises(ValueError):
repo.list_report_artifacts(self.conn, cursor="invalid")
if __name__ == "__main__":
unittest.main()