Skip to content

fix(agent-mesh): export complete audit logs - #4096

Merged
MohammadHaroonAbuomar merged 2 commits into
microsoft:mainfrom
electricwolfemarshmallowhypertext:marshmallow/audit-export-completeness-4095
Sep 22, 2026
Merged

MohammadHaroonAbuomar merged 2 commits into
microsoft:mainfrom
electricwolfemarshmallowhypertext:marshmallow/audit-export-completeness-4095

Conversation

@electricwolfemarshmallowhypertext

Copy link
Copy Markdown
Contributor

Related Issue

Fixes #4095

Problem & Solution

AuditLog.export() and AuditLog.export_cloudevents() silently returned only the newest 10,000 matching records. Larger exports omitted earlier records without warning. The plain export still reported the Merkle root for the entire log, so the exported records could not reproduce that root.

This change removes the fixed export limit by requesting the current number of records in the audit chain. Both formats now include every matching record. The separate query() API keeps its existing default and explicit limits.

Time filters and the existing full-chain root semantics are unchanged: a filtered plain export still reports the root for the complete log, not a new root calculated from the selected records.

Impact on Your Work

Found while testing audit export completeness and independent verification. This fixes incomplete exports above 10,000 records without requiring callers to retrieve the records and assemble their own export.

Timeline

None.

Alternatives Considered

Increasing the fixed limit would only move the failure to a larger log. Changing the public query() API is unnecessary for this fix.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Package(s) Affected

  • agent-governance-toolkit-core
  • agent-mesh

Only two files are changed:

  • agent-governance-python/agent-mesh/src/agentmesh/governance/audit.py
  • agent-governance-python/agent-mesh/tests/test_merkle_audit_root_reproducible.py

Testing

Unit Testing

Added seven regression cases covering:

  • All 10,001 records exported in their original order in both formats.
  • Independent reconstruction of the reported Merkle root from a complete export, including the hashes carried by CloudEvents.
  • Time filters preserving the existing full-chain root.
  • The default and explicit query() limits remaining unchanged.
  • Empty exports.

Both 10,001-record completeness tests failed before the fix because only 10,000 records were returned. Both pass after the fix.

Manual Testing

Tested on Windows 11 with Python 3.12.10 against commit c799225e50:

  • Focused AgentMesh tests: 131 passed, 20 skipped across test_merkle_audit_root_reproducible.py, test_governance.py, test_persistent_audit.py, governance/test_audit_backends.py, and governance/test_stdout_audit_sink.py.
  • The skips were 17 tests for the absent persistent_audit.py module and three POSIX-only tests.
  • Ruff passed for the modified test file. The production file retains exactly 41 pre-existing findings, unchanged from the baseline: one I001, 38 UP045, and two UP017. No new findings were introduced.
  • py_compile passed for both changed files.
  • git diff --check passed.

The initial sandboxed test runs encountered temporary-directory permission errors. The final run above completed successfully with the required filesystem access.

Checklist

  • Related issue linked.
  • Regression tests added and demonstrated to fail before the fix.
  • Focused tests and verification completed; limitations are recorded above.
  • Commit includes a DCO signoff.
  • No changes to the bounded query API, unrelated code, or documentation.

Attribution & Prior Art

The tests reuse this repository's existing independent Merkle-root helper. No code was copied from another project.

AI Assistance

Codex assisted with the investigation, implementation, regression tests, and validation. The contributor directed the scope, reviewed the reported changes and results, and explicitly authorized this PR.

Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@github-actions

Copy link
Copy Markdown

PR Review Summary

Check Status Details
🔍 Code Review ⚠️ Missing No current-run comment
🛡️ Security Scan ⚠️ Missing No current-run comment
🔄 Breaking Changes ⚠️ Missing No current-run comment
📝 Docs Sync ⚠️ Missing No current-run comment
🧪 Test Coverage ⚠️ Missing No current-run comment

Verdict: ⚠️ AI review incomplete; ready for human review

AI review comments are untrusted advisory output. The summary reports workflow-generated completion status only, not model-authored pass/fail claims.

@MohammadHaroonAbuomar MohammadHaroonAbuomar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  • agent-governance-python/agent-mesh/CHANGELOG.md:8 Add a line under Unreleased / Fixed: exports no longer cap at 10,000 records. The earlier Merkle-root fix has an entry there.
  • Nit: the large_audit_log fixture is function-scoped and builds 10,001 entries seven times (about 7.4 s for the class). Nothing mutates it, so class or module scope cuts that to about 1 s.

Comment thread agent-governance-python/agent-mesh/src/agentmesh/governance/audit.py Outdated
Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 22, 2026
@electricwolfemarshmallowhypertext

Copy link
Copy Markdown
Contributor Author
  • agent-governance-python/agent-mesh/CHANGELOG.md:8 Add a line under Unreleased / Fixed: exports no longer cap at 10,000 records. The earlier Merkle-root fix has an entry there.
  • Nit: the large_audit_log fixture is function-scoped and builds 10,001 entries seven times (about 7.4 s for the class). Nothing mutates it, so class or module scope cuts that to about 1 s.

MohammadHaroonAbuomar Addressed review items:

  • exports now use an explicit unbounded query(limit=None) path rather than deriving a limit from the current chain length
  • added regression coverage for the concurrent-append/reproducibility case
  • scoped the 10,001-entry fixture to avoid rebuilding it for every test
  • added the AgentMesh changelog entry
  • added agentmeshentryhash to the spell-check terms
  • clarified the filtered-export Merkle-root behavior in the docstring

One other thing: branch is currently 19 commits behind main, can merge cleanly. Do you want me to update it now, or leave it as-is?

@MohammadHaroonAbuomar MohammadHaroonAbuomar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approving at e1724aa. All five points are verified in code and CI is green (122 pass). The unbounded path is explicit now, the concurrent-append test discriminates (it fails with the previous form restored), the CHANGELOG line is accurate, and the fixture rebuild is down to about one second for the class.

No need to update the branch: it merges cleanly against main, and I will squash-merge it now.

One note for later, not for this PR: export() still reads the root after query() returns, so an append landing in that gap gives a root for N+1 entries against N records. AuditLog has no locking anywhere, so that is a broader question than this fix.

@MohammadHaroonAbuomar
MohammadHaroonAbuomar merged commit c9136ff into microsoft:main Sep 22, 2026
132 checks passed
@electricwolfemarshmallowhypertext

Copy link
Copy Markdown
Contributor Author

Approving at e1724aa. All five points are verified in code and CI is green (122 pass). The unbounded path is explicit now, the concurrent-append test discriminates (it fails with the previous form restored), the CHANGELOG line is accurate, and the fixture rebuild is down to about one second for the class.

No need to update the branch: it merges cleanly against main, and I will squash-merge it now.

One note for later, not for this PR: export() still reads the root after query() returns, so an append landing in that gap gives a root for N+1 entries against N records. AuditLog has no locking anywhere, so that is a broader question than this fix.

MohammadHaroonAbuomar I dug into the follow-up race you called out. I reproduced the N-records/N+1-root mismatch deterministically, including a case where merkle_root and chain_root can disagree within the same export.

I have a local fix that snapshots the entries and root together under the same synchronization used by appends, with deterministic regression coverage.

OK to open a focused follow-up PR for this?

@electricwolfemarshmallowhypertext
Tionne Smith (electricwolfemarshmallowhypertext) deleted the marshmallow/audit-export-completeness-4095 branch September 25, 2026 17:16
Yuvraj Singh (yuvrajsingh2428) pushed a commit to yuvrajsingh2428/agent-governance-toolkit that referenced this pull request Oct 1, 2026
* fix(agent-mesh): export complete audit logs

Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>

* fix(agent-mesh): address audit export review

Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>

---------

Signed-off-by: Electric Wolfe Marshmallow Hypertext <tionne@gmail.com>
Signed-off-by: yuvrajsingh2428 <offcyuvi2428@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-mesh agent-mesh package documentation Improvements or additions to documentation size/M Medium PR (< 200 lines) tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: AuditLog exports silently truncate audit evidence after 10,000 entries

2 participants