From 1751ba1ba0ef0b04869a10ac7525f0ce6ee1f43b Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 23:54:35 +0000 Subject: [PATCH] Integrate audit findings into docs/api_reference.md - cmd_audit now appends a Runtime Mismatches section to docs/api_reference.md with summary count, table (Method, Path, Issue Type, Details, Client IP), and audit timestamp - Section is inserted before the auto-generated footer line - Running audit again replaces the previous section (no stale accumulation) - Running baseline fully regenerates api_reference.md, clearing the audit section - artifacts/audit_report.md kept as-is for CI artifact uploads Co-Authored-By: unknown <> --- drift_guard/guard.py | 87 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/drift_guard/guard.py b/drift_guard/guard.py index d8210db..cd593bc 100644 --- a/drift_guard/guard.py +++ b/drift_guard/guard.py @@ -198,6 +198,85 @@ def cmd_check(url: str = DEFAULT_OPENAPI_URL) -> None: # CLI dispatcher # --------------------------------------------------------------------------- +# The auto-generated footer line used as a marker in api_reference.md. +# The audit section is inserted just before this line. +_AUTOGEN_FOOTER_PREFIX = "_This file was auto-generated by" + + +def _append_audit_section_to_api_ref( + entries: list[dict], total: int, timestamp: str +) -> None: + """Append (or replace) a Runtime Mismatches section in api_reference.md. + + The section is inserted just before the auto-generated footer line. + If a previous audit section exists it is replaced so we don't accumulate + stale data across multiple audit runs. + """ + if not API_REF_PATH.exists(): + return + + content = API_REF_PATH.read_text() + + # Strip any existing audit section (between marker and footer) + audit_header = "## Runtime Mismatches" + if audit_header in content: + # Remove from the audit header to just before the footer + before_audit = content[: content.index(audit_header)] + # Find the footer after the audit section + footer_idx = content.find(_AUTOGEN_FOOTER_PREFIX, content.index(audit_header)) + if footer_idx != -1: + after_audit = content[footer_idx:] + else: + after_audit = "" + content = before_audit + after_audit + + # Build the audit section + section_lines = [ + "## Runtime Mismatches", + "", + ] + + if total == 0: + section_lines.append("No runtime mismatches recorded.") + section_lines.append("") + else: + section_lines.append(f"**{total} mismatch(es) recorded**") + section_lines.append("") + section_lines.append( + "| Method | Path | Issue Type | Details | Client IP |" + ) + section_lines.append( + "|--------|------|------------|---------|-----------|" + ) + for entry in entries: + method = entry.get("method", "") + path = entry.get("path", "") + issue_type = entry.get("issue_type", "") + details = entry.get("details", "").replace("|", "\\|") + client_ip = entry.get("client_ip", "") + section_lines.append( + f"| {method} | `{path}` | {issue_type} | {details} | {client_ip} |" + ) + section_lines.append("") + + section_lines.append(f"_Audit last run: {timestamp}_") + section_lines.append("") + section_lines.append("---") + section_lines.append("") + + audit_section = "\n".join(section_lines) + + # Insert before the footer line + if _AUTOGEN_FOOTER_PREFIX in content: + footer_pos = content.index(_AUTOGEN_FOOTER_PREFIX) + new_content = content[:footer_pos] + audit_section + content[footer_pos:] + else: + # No footer found — just append at the end + new_content = content.rstrip("\n") + "\n\n" + audit_section + + _write_text(API_REF_PATH, new_content) + + def cmd_audit(url: str = DEFAULT_AUDIT_URL) -> None: """Fetch the runtime audit log, summarise mismatches, and notify Slack.""" console.rule("[bold blue]Drift Guard – Audit[/bold blue]") @@ -236,7 +315,7 @@ def cmd_audit(url: str = DEFAULT_AUDIT_URL) -> None: summary = "\n".join(lines) console.print(summary) - # Write audit report + # Write standalone audit report (kept for CI artifact uploads) now = _timestamp() machine = _machine() audit_report = ( @@ -253,6 +332,12 @@ def cmd_audit(url: str = DEFAULT_AUDIT_URL) -> None: _write_text(audit_path, audit_report) console.print(f"\n Wrote audit report to [cyan]{audit_path}[/cyan]") + # Append Runtime Mismatches section to docs/api_reference.md + _append_audit_section_to_api_ref(entries, total, now) + console.print( + f" Appended Runtime Mismatches section to [cyan]{API_REF_PATH}[/cyan]" + ) + # Slack notification send_slack_notification( title="\U0001f6a8 API Call Guard: Runtime mismatches detected",