Skip to content

Complete portfolio mutation audit coverage#121

Merged
PooriaT merged 2 commits into
mainfrom
codex/complete-audit-coverage-for-api-mutations
Jun 19, 2026
Merged

Complete portfolio mutation audit coverage#121
PooriaT merged 2 commits into
mainfrom
codex/complete-audit-coverage-for-api-mutations

Conversation

@PooriaT

@PooriaT PooriaT commented Jun 19, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Provide consistent audit logging for all API and admin portfolio mutation paths using the existing audit helpers and enums.
  • Ensure failed-validation attempts record safe, non-sensitive audit events where the portfolio can be identified.
  • Capture compact before/after snapshots for affected entities to improve audit usefulness without leaking secrets.

Description

  • Added small local helpers in src/finwall/api.py (_one, _goal_snapshot, _timeline_snapshot, _risk_snapshot, _trade_snapshot, _audit_failure) to produce compact snapshots and to record sanitized failed-audit events while reusing record_update_audit and existing enums.
  • Instrumented API mutation routes to record successful audit events and safe failed-validation events where practical for cash_withdraw, holding_delete, trade_buy, trade_sell, order_upsert, order_delete, watchlist_upsert, watchlist_delete, goal_set, timeline_set, and risk_profile_set using PortfolioAuditSource.API and the authenticated actor.
  • Instrumented admin form handlers to record the same successful (and representative failed) audit events using PortfolioAuditSource.WEB and the admin actor, and added before/after snapshots where practical without changing any business logic.
  • Kept summaries compact and used safe_error_message to populate safe_error_message for failed events; avoided storing tokens, cookies, headers, or raw tracebacks.
  • Updated tests/test_api.py with focused tests that assert API/admin mutation audit coverage and that failed-validation audit events are present and sanitized (test_api_mutation_audit_coverage, test_failed_validation_audit_events_are_safe, test_admin_mutation_audit_coverage).

Testing

  • Ran lint/format checks with poetry run ruff check . and poetry run ruff format --check --line-length 88 ., both passed.
  • Ran the full test suite with poetry run pytest, and all tests passed (282 passed).
  • Added and executed the new API tests in tests/test_api.py, which assert presence of audit events, actor/source correctness, snapshots, and sanitized failed-audit messages; these tests passed as part of the suite.

Codex Task

@PooriaT PooriaT linked an issue Jun 19, 2026 that may be closed by this pull request

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b415ab3a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/finwall/api.py
Comment on lines +606 to +610
_audit_failure(
actor,
PortfolioAuditSource.API,
"order_upsert",
PortfolioAuditEntityType.ACTIVE_ORDER,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Catch decimal validation when auditing order failures

This failure audit only runs from the except ValueError block, but _to_decimal(...) raises HTTPException for malformed decimal fields. For an authenticated order request with a known ticker and shares, limit_price, or stop_price set to a non-decimal value, the route returns 422 before _audit_failure runs, so the failed mutation is omitted from the audit log even though the portfolio and entity are identifiable.

Useful? React with 👍 / 👎.

Comment thread src/finwall/api.py
async def admin_trade_buy(request: Request, actor: str = Depends(admin_auth)):
try:
return await _trade(request, "buy")
return await _trade(request, "buy", actor)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Audit failed admin trades before rendering errors

When _trade raises after parsing the form, such as an admin sell attempt for more shares than are held or an invalid trade amount/date, control jumps to this handler and returns the 422 page without recording a failed trade_buy/trade_sell audit event. That leaves identifiable failed admin trade mutations out of the audit trail while the neighboring cash/order/timeline/risk failure paths are logged.

Useful? React with 👍 / 👎.

### Motivation
- Provide consistent audit logging for all API and admin portfolio mutation paths using the existing audit helpers and enums.
- Ensure failed-validation attempts record safe, non-sensitive audit events where the portfolio can be identified.
- Capture compact before/after snapshots for affected entities to improve audit usefulness without leaking secrets.

### Description
- Added small local helpers in `src/finwall/api.py` (`_one`, `_goal_snapshot`, `_timeline_snapshot`, `_risk_snapshot`, `_trade_snapshot`, `_audit_failure`) to produce compact snapshots and to record sanitized failed-audit events while reusing `record_update_audit` and existing enums.
- Instrumented API mutation routes to record successful audit events and safe failed-validation events where practical for `cash_withdraw`, `holding_delete`, `trade_buy`, `trade_sell`, `order_upsert`, `order_delete`, `watchlist_upsert`, `watchlist_delete`, `goal_set`, `timeline_set`, and `risk_profile_set` using `PortfolioAuditSource.API` and the authenticated actor.
- Instrumented admin form handlers to record the same successful (and representative failed) audit events using `PortfolioAuditSource.WEB` and the admin actor, and added before/after snapshots where practical without changing any business logic.
- Kept summaries compact and used `safe_error_message` to populate `safe_error_message` for failed events; avoided storing tokens, cookies, headers, or raw tracebacks.
- Updated `tests/test_api.py` with focused tests that assert API/admin mutation audit coverage and that failed-validation audit events are present and sanitized (`test_api_mutation_audit_coverage`, `test_failed_validation_audit_events_are_safe`, `test_admin_mutation_audit_coverage`).

### Testing
- Ran lint/format checks with `poetry run ruff check .` and `poetry run ruff format --check --line-length 88 .`, both passed.
- Ran the full test suite with `poetry run pytest`, and all tests passed (282 passed).
- Added and executed the new API tests in `tests/test_api.py`, which assert presence of audit events, actor/source correctness, snapshots, and sanitized failed-audit messages; these tests passed as part of the suite.
@PooriaT PooriaT merged commit 738599d into main Jun 19, 2026
1 check passed
@PooriaT PooriaT deleted the codex/complete-audit-coverage-for-api-mutations branch June 19, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Complete audit coverage for API and admin portfolio changes

1 participant