feat: decisions.explain + audit search filter parity#141
Open
saurabhjain1592 wants to merge 4 commits intomainfrom
Open
feat: decisions.explain + audit search filter parity#141saurabhjain1592 wants to merge 4 commits intomainfrom
saurabhjain1592 wants to merge 4 commits intomainfrom
Conversation
Adds Python SDK half of ADR-043 + ADR-042. New: - axonflow.decisions module with DecisionExplanation, ExplainPolicy, ExplainRule Pydantic models. Shape frozen per ADR-043. - AxonFlow.explain_decision(decision_id) async method calling GET /api/v1/decisions/:id/explain. Rejects empty decision_id with ValueError; relies on Pydantic validation for malformed responses. - AuditSearchRequest gains three optional filters: decision_id, policy_name, override_id. Back-compat — old callers ignore them, new callers include them only when set. Version: 6.3.0 -> 6.4.0. pyproject.toml + _version.py updated. Tests (10 new, all passing): - DecisionExplanation shape: minimum parse, full round-trip, forward-compat with unknown extra fields. - ExplainPolicy/ExplainRule defaults. - Client explain_decision: rejects empty id, happy path (monkeypatched orchestrator call with URL assertion), empty-response ValidationError. - AuditSearchRequest: three new filters included when set, absent when unset (exclude_none behavior). Companion to platform v7.1.0 (axonflow-enterprise PR #1605) and Go SDK v5.4.0 (axonflow-sdk-go PR #122).
Review finding: decision_id was interpolated raw into the URL path. IDs that contain "/" or "?" would break the request. Use urllib.parse.quote with safe="" to escape every reserved character. Test added: test_url_encodes_decision_id verifies "a/b" hits path containing "a%2Fb" and never the raw "a/b/explain". Parity with Go v5.4.0 post-review fix (same bug, same fix, same test).
Ruff lint green: - PLR0912 too-many-branches on search_audit_logs: extracted the body construction into a module-level _build_audit_search_body() helper. Same behavior, below the branch threshold. - PLC0415 import-not-at-top-level: moved urllib.parse.quote to the top-of-file import block. - I001 import-order: ruff auto-fix applied. - E501 line-too-long in tests/test_decisions.py: wrapped the fake_request signature across multiple lines. Changelog polish (per maintainer feedback): - Release date normalized to 2026-04-18. - Removed internal ADR-043 reference from the user-facing changelog.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Python SDK half of Plugin Batch 1 (ADR-042 + ADR-043).
Companion to:
Added
AxonFlow.explain_decision(decision_id)— async, returnsDecisionExplanation. ADR-043.axonflow.decisionsmodule:DecisionExplanation,ExplainPolicy,ExplainRulePydantic models.AuditSearchRequest.decision_id,.policy_name,.override_id— three optional filters.Version: 6.3.0 → 6.4.0
Tests
10 new unit tests, all passing:
Test plan
explain_decision, confirm full payload.search_audit_logswith new filters — confirm pass-through.