Skip to content

fix(signature): realigning SignatureManager with specs (#284)#290

Merged
guzmud merged 26 commits into
mainfrom
fix/284-realigning-signature_manager
Jun 24, 2026
Merged

fix(signature): realigning SignatureManager with specs (#284)#290
guzmud merged 26 commits into
mainfrom
fix/284-realigning-signature_manager

Conversation

@guzmud

@guzmud guzmud commented Jun 16, 2026

Copy link
Copy Markdown
Member

Proposed changes

  • /api/injects/execution/callback/{injectId} as the targeted endpoint
  • realign POST outer envelope
  • replace chunking solution with a more straightforward iterative approach
    • withdrawing the previous one
    • ...
  • withdraw external injector type related elements

Testing Instructions

  1. ...?

Related issues

Checklist

  • I consider the submitted work as finished
  • I tested the code for its functionality
  • I wrote test cases for the relevant uses case
  • I added/update the relevant documentation (either on github or on notion)
  • Where necessary I refactored code to improve the overall quality
  • For bug fix -> I implemented a test that covers the bug

Further comments

@github-actions github-actions Bot added the filigran team Item from the Filigran team. label Jun 16, 2026
@Filigran-Automation

Copy link
Copy Markdown
Contributor

🤖 [AI-generated]

Hey @guzmud! 👋 Thanks a lot for opening PR #290 — really appreciate the contribution to OpenAEV! 🙏

I just had a quick look and I think the description could be enhanced a little to help reviewers get through it faster. I haven't changed anything in your description — just a gentle, optional suggestion:

Area What could help Suggestion
Proposed changes Section is still the empty template (* stubs) A couple of bullets on what was realigned in SignatureManager and why
Testing Instructions Still the placeholder steps Note how to verify (e.g. which scenarios/tests to run)
Related issues Closes #ISSUE-NUMBER placeholder is unfilled Replace with the linked issue, e.g. Closes #284 (every PR should be linked to an issue)

💡 If helpful, the contribution conventions / PR template walk through what to include.

No rush at all — thanks again for contributing to the project! 🚀

@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.27027% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.58%. Comparing base (fafa20a) to head (06dfb65).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
pyoaev/signatures/signature_manager.py 62.50% 9 Missing ⚠️
pyoaev/signatures/models.py 94.00% 6 Missing ⚠️
pyoaev/apis/signature.py 94.11% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #290      +/-   ##
==========================================
+ Coverage   73.19%   73.58%   +0.39%     
==========================================
  Files          53       54       +1     
  Lines        2350     2404      +54     
==========================================
+ Hits         1720     1769      +49     
- Misses        630      635       +5     
Flag Coverage Δ
connectors 73.58% <90.27%> (+0.39%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

guzmud and others added 19 commits June 17, 2026 16:26
…ements in the POST envelope (#284)

Also, provide a convenience function to build SignatureCallbackPayload
from a SignatureOutputStructure and a ExecutionDetails,
and move the normalize_signature_payload function into the relevant
class
…e into ExecutionSignature (#284)

rational: pre/post metadata is now more managed by ExecutionDetails
bonus: adding post_execution_update functions to both ExecutionSignature
and ExecutionDetails
@guzmud guzmud force-pushed the fix/284-realigning-signature_manager branch from 2ea960e to 2433e5c Compare June 22, 2026 11:23
compile_pre_execution_signatures becomes build_execution_signatures
compile_post_execution_signatures becomes post_execution_updates
build_payload is more OOP
@guzmud guzmud force-pushed the fix/284-realigning-signature_manager branch from 94ce2c9 to 8ab72ed Compare June 23, 2026 06:55
@guzmud guzmud force-pushed the fix/284-realigning-signature_manager branch from 8ab72ed to 9a6b7c4 Compare June 23, 2026 08:27
@guzmud

guzmud commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

Tested against openaev/platform:rolling using the updated nmap injector from OpenAEV-Platform/injectors#242.

The injector logs are the following:

{"timestamp": "2026-06-23T07:30:00.259122Z", "level": "INFO", "name": "Nmap", "message": "Executing nmap with command: nmap -Pn -sT -oX - honey.scanme.sh"}
{"timestamp": "2026-06-23T07:30:03.543616Z", "level": "INFO", "name": "Nmap", "message": "post execution updates"}
{"timestamp": "2026-06-23T07:30:03.543616Z", "level": "INFO", "name": "Nmap", "message": "start_time=datetime.datetime(2026, 6, 23, 7, 30, 0, 184567, tzinfo=datetime.timezone.utc) end_time=datetime.datetime(2026, 6, 23, 7, 30, 3, 543616, tzinfo=datetime.timezone.utc) execution_status='success' execution_action='complete' execution_message='Current action: complete - Current status: success' execution_duration=3.359049"}
{"timestamp": "2026-06-23T07:30:03.544623Z", "level": "INFO", "name": "Nmap", "message": "build payload"}
{"timestamp": "2026-06-23T07:30:03.545622Z", "level": "INFO", "name": "Nmap", "message": "", "targets": [{"signature_target": {"agent": null, "asset": "5d7ce050-04d9-4ee8-b646-fef7aec644c3", "asset_group": null}, "signature_values": [{"expectation_type": "DETECTION", "values": [{"signature_type": "start_time", "signature_value": "2026-06-23T07:30:00Z"}, {"signature_type": "end_time", "signature_value": "2026-06-23T07:30:03Z"}, {"signature_type": "source_ipv4", "signature_value": "192.168.1.77"}, {"signature_type": "source_ipv6", "signature_value": "2a01:e34:ec67:25b0:31b8:15bc:efda:411f"}, {"signature_type": "target_hostname", "signature_value": "honey.scanme.sh"}, {"signature_type": "ports_discovered", "signature_value": [22, 80, 443]}, {"signature_type": "services_discovered", "signature_value": [{"port": 22, "service": "ssh", "asset_id": "5d7ce050-04d9-4ee8-b646-fef7aec644c3", "host": "67.205.158.113"}, {"port": 80, "service": "http", "asset_id": "5d7ce050-04d9-4ee8-b646-fef7aec644c3", "host": "67.205.158.113"}, {"port": 443, "service": "https", "asset_id": "5d7ce050-04d9-4ee8-b646-fef7aec644c3", "host": "67.205.158.113"}]}]}, {"expectation_type": "PREVENTION", "values": [{"signature_type": "start_time", "signature_value": "2026-06-23T07:30:00Z"}, {"signature_type": "end_time", "signature_value": "2026-06-23T07:30:03Z"}, {"signature_type": "source_ipv4", "signature_value": "192.168.42.77"}, {"signature_type": "source_ipv6", "signature_value": "2a01:e34:ec67:25b0:31b8:15bc:efda:411f"}, {"signature_type": "target_hostname", "signature_value": "honey.scanme.sh"}, {"signature_type": "ports_discovered", "signature_value": [22, 80, 443]}, {"signature_type": "services_discovered", "signature_value": [{"port": 22, "service": "ssh", "asset_id": "5d7ce050-04d9-4ee8-b646-fef7aec644c3", "host": "67.205.158.113"}, {"port": 80, "service": "http", "asset_id": "5d7ce050-04d9-4ee8-b646-fef7aec644c3", "host": "67.205.158.113"}, {"port": 443, "service": "https", "asset_id": "5d7ce050-04d9-4ee8-b646-fef7aec644c3", "host": "67.205.158.113"}]}]}]}]}
{"timestamp": "2026-06-23T07:30:03.545622Z", "level": "INFO", "name": "Nmap", "message": "send signatures"}
{"timestamp": "2026-06-23T07:30:03.546624Z", "level": "DEBUG", "name": "pyoaev.signatures.signature_manager", "message": "send_signatures inject_id=038e222b-6488-4d6d-a0db-c678710f6be4, execution_status=success, execution_action=complete"}

with line 3 (after "post execution updates") showcasing the ExecutionDetails side and line 5 (after "build payload") showcasing the structured output to be packaged into the POST enveloppe.

Network-wise, we can see both the pre-existing callback and the new one are sent and accepted by the platform (HTTP 200 for both):

Screenshot 2026-06-23 101017

The JSON payload sent to the platform to the callback URL in the format ends up being

{
  "execution_message": "Current action: complete - Current status: success",
  "execution_output_structured": "{\"signatures\":{\"targets\":[{\"signature_target\":{\"asset\":\"5d7ce050-04d9-4ee8-b646-fef7aec644c3\"},\"signature_values\":[{\"expectation_type\":\"DETECTION\",\"values\":[{\"signature_type\":\"start_time\",\"signature_value\":\"2026-06-23T07:30:00Z\"},{\"signature_type\":\"end_time\",\"signature_value\":\"2026-06-23T07:30:03Z\"},{\"signature_type\":\"source_ipv4\",\"signature_value\":\"192.168.1.77\"},{\"signature_type\":\"source_ipv6\",\"signature_value\":\"2a01:e34:ec67:25b0:31b8:15bc:efda:411f\"},{\"signature_type\":\"target_hostname\",\"signature_value\":\"honey.scanme.sh\"},{\"signature_type\":\"ports_discovered\",\"signature_value\":[22,80,443]},{\"signature_type\":\"services_discovered\",\"signature_value\":[{\"port\":22,\"service\":\"ssh\",\"asset_id\":\"5d7ce050-04d9-4ee8-b646-fef7aec644c3\",\"host\":\"67.205.158.113\"},{\"port\":80,\"service\":\"http\",\"asset_id\":\"5d7ce050-04d9-4ee8-b646-fef7aec644c3\",\"host\":\"67.205.158.113\"},{\"port\":443,\"service\":\"https\",\"asset_id\":\"5d7ce050-04d9-4ee8-b646-fef7aec644c3\",\"host\":\"67.205.158.113\"}]}]},{\"expectation_type\":\"PREVENTION\",\"values\":[{\"signature_type\":\"start_time\",\"signature_value\":\"2026-06-23T07:30:00Z\"},{\"signature_type\":\"end_time\",\"signature_value\":\"2026-06-23T07:30:03Z\"},{\"signature_type\":\"source_ipv4\",\"signature_value\":\"192.168.42.77\"},{\"signature_type\":\"source_ipv6\",\"signature_value\":\"2a01:e34:ec67:25b0:31b8:15bc:efda:411f\"},{\"signature_type\":\"target_hostname\",\"signature_value\":\"honey.scanme.sh\"},{\"signature_type\":\"ports_discovered\",\"signature_value\":[22,80,443]},{\"signature_type\":\"services_discovered\",\"signature_value\":[{\"port\":22,\"service\":\"ssh\",\"asset_id\":\"5d7ce050-04d9-4ee8-b646-fef7aec644c3\",\"host\":\"67.205.158.113\"},{\"port\":80,\"service\":\"http\",\"asset_id\":\"5d7ce050-04d9-4ee8-b646-fef7aec644c3\",\"host\":\"67.205.158.113\"},{\"port\":443,\"service\":\"https\",\"asset_id\":\"5d7ce050-04d9-4ee8-b646-fef7aec644c3\",\"host\":\"67.205.158.113\"}]}]}]}]}}",
  "execution_status": "success",
  "execution_duration": 4,
  "execution_action": "complete"
}

@guzmud

guzmud commented Jun 23, 2026

Copy link
Copy Markdown
Member Author

Regarding the developer experience, pre-realigning the quick start was the following

from pyoaev import OpenAEV
from pyoaev.signatures import (
    SignatureManager,
    NetworkInjectorConfig,
    build_network_configs,
)

client = OpenAEV(url="https://openaev.example.com", token="my-token")
sm = SignatureManager(client)

# 1. Build typed injector configs (one per distinct target asset)
configs = build_network_configs(["10.0.0.1", "2001:db8::1", "target.example.com"])
# or hand-build them: NetworkInjectorConfig(target_ipv4="10.0.0.1")
# or build a list: [NetworkInjectorConfig(target_ipv4="10.0.0.1"), NetworkInjectorConfig(target_ipv6="2001:db8::1"), NetworkInjectorConfig(target_domain="target.example.com")]
  
# 2. Compile pre-execution signatures (category is carried by the config type)
pre = sm.compile_pre_execution_signatures(config=configs)

# 3. Run your tool...

# 4. Compile post-execution signatures
post = sm.compile_post_execution_signatures(pre, tool_output)

# 5. Build the wire payload
payload = sm.build_payload(post, expectation_types=["DETECTION"])

# 6. Send to backend
sm.send_signatures(inject_id="abc-123", phase="execution_complete", signatures=payload)

The quick start is now the following

from pyoaev import OpenAEV
from pyoaev.signatures import (
    ExecutionDetails,
    SignatureManager,
    NetworkInjectorConfig,
    build_network_configs,
)

client = OpenAEV(url="https://openaev.example.com", token="my-token")
sm = SignatureManager(client)

# 1. Create execution details
execution_details = ExecutionDetails()

# 2. Build typed injector configs (one per distinct target asset)
configs = build_network_configs(["10.0.0.1", "2001:db8::1", "target.example.com"])
# or hand-build them: NetworkInjectorConfig(target_ipv4="10.0.0.1")
# or build a list: [NetworkInjectorConfig(target_ipv4="10.0.0.1"), NetworkInjectorConfig(target_ipv6="2001:db8::1"), NetworkInjectorConfig(target_domain="target.example.com")]

# 3. Build execution signatures
execution_signatures = sm.build_execution_signatures(config=configs)

# 4. Run your tool...

# 5. Update post-execution elements
sm.post_execution_updates(execution_details, execution_signatures, tool_output)

# 6. Build the wire payload
payload = sm.build_payload(
    execution_signatures=execution_signatures,
    targets_meta=targets_meta,  # can be obtained through the new `Targets.extract_target_meta` from `injector_common`
    expectation_types=["DETECTION"]  # should be dynamically obtained from the message processed
)

# 7. Send to backend
sm.send_signatures(inject_id="abc-123", execution_details=execution_details, signatures=payload)

Comment thread pyoaev/signatures/signature_manager.py
@guzmud guzmud force-pushed the fix/284-realigning-signature_manager branch from 9a6b7c4 to 5646ab2 Compare June 23, 2026 13:45
@guzmud guzmud force-pushed the fix/284-realigning-signature_manager branch from 5646ab2 to 005315c Compare June 23, 2026 14:49
@guzmud guzmud marked this pull request as ready for review June 24, 2026 07:06
Copilot AI review requested due to automatic review settings June 24, 2026 07:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR realigns the Python client’s signature pipeline (modeling + transport + tests) with the updated OpenAEV backend callback spec, including the new callback endpoint, the updated outer envelope, and a revised approach to splitting oversized payloads.

Changes:

  • Updates the callback endpoint to /injects/execution/callback/{injectId} and adjusts transport accordingly.
  • Introduces/updates signature-related models to match the new POST envelope (e.g., ExecutionDetails, SignatureTarget, SignatureOutputStructure, InjectExecutionActions).
  • Replaces chunk-metadata-based payload chunking with sequential “self-contained envelope” splitting and updates BDD tests/features.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
pyoaev/apis/signature.py Updates callback path, envelope construction, retry logging, and replaces chunk metadata with envelope splitting.
pyoaev/signatures/models.py Adds/updates Pydantic models for the new callback envelope and structured signature output; removes external injector config model.
pyoaev/signatures/signature_manager.py Aligns SignatureManager APIs with the new models/envelope and delegates transport with new parameters.
pyoaev/signatures/types.py Adds InjectExecutionActions enum to match backend execution action values.
pyoaev/signatures/signature_type.py Tightens typing of match_score to `int
pyoaev/signatures/__init__.py Exposes new signature types/enums and removes external injector config from exports.
test/signatures/test_signature_manager_transmission.py Updates transmission tests to validate the new endpoint, envelope format, and envelope splitting behavior.
test/signatures/test_signature_manager_pre_execution.py Updates pre-execution tests for the new ExecutionSignature return types and removed external category.
test/signatures/test_signature_manager_post_execution.py Updates post-execution tests to reflect the new split between execution details vs execution signatures updates.
test/signatures/features/signature_manager_transmission.feature Updates BDD feature steps to pass execution details and assert new endpoint/payload structure.
test/signatures/features/signature_manager_pre_execution.feature Updates BDD feature steps for renamed pre-execution API and removed external category scenario.
test/signatures/features/signature_manager_post_execution.feature Updates post-execution feature to the new “update models in-place” workflow.
test/signatures/constraints/signature_manager_transmission_constraints.feature Updates constraints to assert envelope splitting (no chunk metadata) and new endpoint.
test/signatures/constraints/signature_manager_pre_execution_constraints.feature Updates constraints to use build_execution_signatures.
test/signatures/constraints/signature_manager_post_execution_constraints.feature Updates constraints to the new post-execution update flow.
Comments suppressed due to low confidence (1)

test/signatures/test_signature_manager_pre_execution.py:356

  • This step still uses dict-style membership ("field not in result"), but result is now an ExecutionSignature model. That assertion will always pass and no longer verifies that the field is omitted from the serialized payload. Check the model_dump(exclude_none=True) instead.
@then(parsers.parse("the returned dict does not contain {field}"))
def returned_dict_does_not_contain_field(result, field):
    assert field not in result


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pyoaev/signatures/models.py
Comment thread pyoaev/signatures/models.py Outdated
Comment thread pyoaev/signatures/models.py
Comment thread pyoaev/signatures/models.py
Comment thread pyoaev/signatures/signature_manager.py
Comment thread test/signatures/features/signature_manager_post_execution.feature Outdated
Comment thread test/signatures/constraints/signature_manager_post_execution_constraints.feature Outdated
Comment thread test/signatures/constraints/signature_manager_post_execution_constraints.feature Outdated
Comment thread test/signatures/constraints/signature_manager_post_execution_constraints.feature Outdated
Comment thread test/signatures/constraints/signature_manager_post_execution_constraints.feature Outdated
@guzmud guzmud force-pushed the fix/284-realigning-signature_manager branch from c573afc to 34731f1 Compare June 24, 2026 07:59
@guzmud guzmud force-pushed the fix/284-realigning-signature_manager branch from 34731f1 to 06dfb65 Compare June 24, 2026 08:28

@Kakudou Kakudou left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM ;)

@guzmud guzmud merged commit 8283bfe into main Jun 24, 2026
13 checks passed
@guzmud guzmud deleted the fix/284-realigning-signature_manager branch June 24, 2026 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

filigran team Item from the Filigran team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(signature): realigning SignatureManager with specs

5 participants