Skip to content

feat: decisions.explain + audit search filter parity#141

Open
saurabhjain1592 wants to merge 4 commits intomainfrom
feat/plugin-batch-1
Open

feat: decisions.explain + audit search filter parity#141
saurabhjain1592 wants to merge 4 commits intomainfrom
feat/plugin-batch-1

Conversation

@saurabhjain1592
Copy link
Copy Markdown
Member

Summary

Python SDK half of Plugin Batch 1 (ADR-042 + ADR-043).

Companion to:

Added

  • AxonFlow.explain_decision(decision_id) — async, returns DecisionExplanation. ADR-043.
  • axonflow.decisions module: DecisionExplanation, ExplainPolicy, ExplainRule Pydantic 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:

  • DecisionExplanation shape (minimum + full round-trip + forward-compat for unknown fields)
  • ExplainPolicy/ExplainRule defaults
  • Client explain_decision: empty ID rejection, happy path with URL assertion, empty-response validation error
  • AuditSearchRequest serialization (new filters present when set, absent when unset)

Test plan

  • Against a platform on v7.1.0: create a decision, call explain_decision, confirm full payload.
  • Against a platform on 7.0.x: call search_audit_logs with new filters — confirm pass-through.

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).
@saurabhjain1592 saurabhjain1592 added the enhancement New feature or request label Apr 17, 2026
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).
@saurabhjain1592 saurabhjain1592 changed the title Plugin Batch 1: decisions.explain + audit search filter parity feat: decisions.explain + audit search filter parity Apr 17, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant