# Finance API, security, and frontend convention audit

Use for read-only audits and implementation planning around sensitive portfolio ingestion, reconciliation, policy, and comparable finance-dashboard mutations.

## Establish the exact baseline

1. Read repository agent rules and the security/decision baseline first.
2. Check worktree status at the beginning and end. If it changes without your edits, report concurrent work separately and do not silently treat it as baseline.
3. Trace one complete hardened slice across router, schemas, service, migration, frontend API, component, and backend/frontend tests.
4. Prefer the newest hardened slice over older lookalike endpoints. Explicitly list weaker legacy patterns that must not be copied.

## Authentication versus write gating

Never call source-IP or CORS controls authentication. Report separately:

- default write mode and fail-closed behavior;
- exact methods covered by middleware;
- loopback/test-client rules;
- whether remote GETs remain unauthenticated;
- session, token, cookie, CSRF, Origin, Host, proxy, and audit-identity behavior;
- frontend fetch credentials/auth headers;
- whether preview is POST and therefore blocked remotely with other writes.

CORS is browser interoperability, not authorization; Tailnet reachability is not authorization either. If remote writes await a separate session/CSRF decision, do not broaden that boundary inside a feature sprint.

## Hardened Preview → Confirm → Audit

Use the detailed policy pattern in `versioned-financial-policy-contracts.md`, plus these integration checks:

1. Preview is productively read-only and binds the complete canonical business payload.
2. Confirm repeats that payload plus content-bound `preview_id`, request-scoped `confirmation_id`, and `confirm=true`.
3. Revalidate payload/readiness at confirm time; mismatches fail closed.
4. Domain writes, immutable receipt/lineage, and minimal audit commit in one explicit transaction.
5. If an existing importer commits internally or emits several audits without an outer request transaction, refactor or wrap it so HTTP confirmation owns atomicity; do not expose it directly.
6. Audit detail is an exact allowlist. Keep raw imports, payloads, paths, filenames, account secrets, hashes, and confirmation identifiers out of broad audit fields and user-visible errors.
7. Historical records are immutable; correction uses additive versions/reversals.

Optional preview IDs, generic confirm bodies, raw dictionaries, direct mutation/archive routes, and permanent content fingerprints are compatibility debt, not new conventions.

## API contract and pagination reality

- Use dedicated Pydantic request/response models, `response_model`, bounded strings/lists, enums/Literals, and explicit error responses.
- Consider `extra='forbid'` for new sensitive requests; default extra-field behavior may be too permissive.
- Represent financial Decimal values as strings and validate finite/range semantics server-side.
- Translate internal exceptions to bounded, non-identifying HTTP errors.
- Verify OpenAPI requirements, write security, and GET-only detail routes in tests.

Do not invent an existing pagination convention when the repository only has unbounded lists, raw `limit` integers, or client-side table pagination. State that absence, then define one bounded endpoint contract:

- validated `limit` (for example `Query(default=25, ge=1, le=100)`);
- deterministic SQL ordering with a unique tie-breaker;
- SQL-level bound;
- either `{items, next_cursor}` with an opaque cursor or `{items, total, limit, offset}`;
- tests for boundaries, stable ties, and no duplicate/omitted rows.

## Frontend conventions

- Use typed API wrappers; do not show or log transport/audit identifiers.
- Store a deep copy of the previewed payload; edits invalidate preview and confirmation UI.
- Use explicit confirmation UI and a synchronous duplicate-submit guard; server idempotency remains mandatory.
- After confirm, invalidate relevant cache and reload receipt/history and reconciliation independently.
- A secondary reconciliation/quality failure must not hide core portfolio data or a confirmed receipt.
- Preserve unknown financial values as `null`/“not assessable,” never zero.
- Map reason codes to bounded localized text rather than exposing internal codes.
- Reuse responsive loading/empty/error/partial/unavailable and data-quality components.
- Test stale preview, edits during preview, duplicate clicks, out-of-order responses where relevant, partial failures, mobile layout, and identifier non-disclosure with synthetic fixtures only.

## Minimal vertical slice

Prefer one end-to-end source or one existing ready execution-plan flow over a broad import framework:

1. bounded read-only queue/history;
2. strict productively read-only preview;
3. exact-payload, atomic, idempotent confirm;
4. minimal immutable audit/lineage receipt;
5. independent reconciliation refresh;
6. one usable responsive frontend panel;
7. focused backend, OpenAPI/security, and frontend tests.

## Audit report order

1. canonical hardened pattern with exact files/routes;
2. weaker legacy patterns not to copy;
3. authentication and write-security reality;
4. schema/router/error conventions;
5. actual pagination reality;
6. frontend/test conventions;
7. minimal vertical design;
8. workspace cleanliness and concurrent changes.

Separate verified facts from recommendations. A read-only audit should end with an unchanged-tree/concurrent-change check.