Interfaces¶
Functional Requirements¶
| ID | Requirement | Priority | Status |
|---|---|---|---|
| FR-6.1 | Python API: create_pipeline() and CreditRiskCalc for programmatic access |
P0 | Done |
| FR-6.2 | Server-rendered web UI (FastAPI + Jinja) for running calculations, results exploration, and dual-framework comparison | P1 | Done |
| FR-6.3 | CLI entry point (rwa-ui) for launching the web interface |
P2 | Done |
| FR-6.4 | API input validation with clear error messages | P1 | Done |
| FR-6.5 | REST API over CreditRiskCalc (calculate / validate / results / comparison / export) |
P1 | Done |
| FR-6.6 | UI can write results to a user-chosen local output folder (calc-time + on-demand save), loopback-guarded | P1 | Done |
| FR-6.7 | Reconciliation can reuse a completed calculation instead of re-running the pipeline (UI: fingerprint-verified reuse checkbox; REST: explicit run_id) |
P1 | Done |
Python API¶
create_pipeline()— primary entry point for programmatic RWA calculationCreditRiskCalc— higher-level service wrapper
REST API (ui/app + api/rest.py)¶
The rwa-ui server (rwa_calc.ui.app.main:main) is a FastAPI + Jinja app that
serves the read-only surface and mounts the REST API in the same process
(create_api_app / api_router, also importable standalone):
POST /api/calculate— run a calculation; returns arun_id+ summaryPOST /api/validate— validate a data directoryGET /api/results— page exposure-level results for a runGET /api/results/summary/{class|approach}— portfolio summariesPOST /api/comparison— dual-framework run with deltas (usesDualFrameworkRunner+CapitalImpactAnalyzer, transformed byui/views/comparison.py)POST /api/reconcile— reconcile against a mapped legacy output; an optionalrun_idreuses a registered calculation instead of re-running the pipeline (an explicit run_id is an instruction: unknown → 404, mismatched framework/date, failed run or vanished results → 422 — never a silent recompute)GET /api/export/{parquet|csv|excel|corep}— download an export
Calculation reuse for reconciliation (FR-6.7)¶
A reconciliation embeds a full pipeline run for our side
(CreditRiskCalc.reconcile). When the identical calculation has already run,
that run is reused instead:
CreditRiskCalc.reconcile(settings, calculation=...)accepts an already-completedCalculationResponse; the embedded pipeline run is skipped and the supplied response's cached results parquet is reconciled. The caller owns freshness verification. The response also carries the our-side run back (ReconciliationResponse.calculation) so callers can index it.rwa_calc.api.run_indexis that verification: it fingerprints each calculation request (parameters plus a stat-based(relpath, size, mtime_ns)signature of every input file the loader would read, captured before the run) and indexes successful runs.find_reusablerecomputes the signature at lookup time, so any input-file change, addition or removal — or a vanished results parquet — misses and forces a recompute.- Every run seeds the index: the UI calculator, the UI comparison page
(both embedded framework runs are formatted and registered; the comparison
itself still computes from the rich bundle — its capital-impact attribution
needs floor-impact/pre-factor frames a cached response does not persist), a
full UI reconciliation's embedded run,
POST /api/calculateandPOST /api/comparison. - Persistence: the UI app calls
run_index.configure_persistence(state home)at startup — registrations write through to$RWA_STATE_DIR/run_index.json(default~/.rwa_calc/), each UI run's parquet cache lives under<state>/runs/<run_id>/(run_cache_dir), and the index (capped atMAX_INDEXED_RUNS, oldest evicted) is reloaded at the next startup with reloaded runs re-registered so/results/{run_id}resolves again. Run directories are never deleted mid-session; unreferenced ones are swept at the next startup. The standalone REST app stays in-process only. - The UI reconciliation form offers a pre-ticked reuse checkbox when a fresh matching run exists (a passive "input data has changed" note when only the data moved), re-verifies at submit time, and degrades silently to a full run on any miss; on reuse the stepper ticks every engine stage instantly and parks on the reconcile tail. The calculator page shows a non-blocking "already ran — view its results" banner on a fresh match.
UI page routes that write to disk (FR-6.6)¶
The UI can write a run's results to a folder on the local machine (the server is the user's own process, so a server-side write is a write to the user's disk):
POST /calculate— accepts an optionaloutput_folder+output_formats; when set, the background worker writes the selected formats after the run, into a run-stampedrwa_export_<run_id>subfolder of the chosen folder.POST /results/{run_id}/save— re-exports an already-computed run (looked up byrun_id) to a chosen folder without recomputing.
Security posture (deliberate reversal). The REST export endpoints keep user
input out of the filesystem path (temp dir + literal filenames). FR-6.6 instead
lets a user-supplied output_folder become a real write target — acceptable only
because the app is loopback single-user. It is guarded by
TrustedHostMiddleware(["localhost", "127.0.0.1"]) (DNS-rebinding) and a
same-origin check (require_same_origin) on the write routes; output_folder is
validated by validate_output_path (absolute, parent exists, no reserved names),
and run_id never becomes a path component.
CLI¶
rwa-ui— launches the server-rendered web UI + REST API
Status¶
All interface requirements implemented.