# Bugfix Requirements Document

## Introduction

The Trading Controls page at `/trading` has two dead sections — "Pending Approvals" and "Active Lockouts" — that display data from the API but provide no way to actually trigger the underlying workflows. The operator approval system is fully implemented in the backend (`services/risk/approval.py`, `services/adapters/broker_service.py`) with an approval gate in the order processing pipeline, but it is effectively disconnected because:

1. The `requires_approval()` function returns `False` in paper mode (the default) since `auto_approve_paper` defaults to `True`, and the risk config stored in the database never overrides this default. There is no UI control to toggle approval requirements for paper mode.
2. The lockout system has a database table (`symbol_lockouts`) and a read-only API endpoint (`GET /api/admin/trading/lockouts`), but there is no API endpoint to create a manual lockout and no UI form to do so.

The result is that the operator can never exercise "human calls the final shot" control — orders bypass approval silently, and lockouts can never be created manually.

## Bug Analysis

### Current Behavior (Defect)

1.1 WHEN the system is in paper trading mode (the default) THEN the `requires_approval()` function always returns `False` because `OperatorApproval.auto_approve_paper` defaults to `True` and the risk config JSON in the database does not include operator approval settings, causing all orders to bypass the approval gate in `process_order_job()`

1.2 WHEN the operator views the Trading Controls page THEN the "Pending Approvals" section always shows "(0) — No pending approvals" because no approval requests are ever created due to defect 1.1

1.3 WHEN the operator wants to manually lock out a ticker from trading THEN there is no API endpoint to create a lockout entry in the `symbol_lockouts` table, so the "Active Lockouts" section is permanently empty unless lockouts are created by internal system processes

1.4 WHEN the operator views the Active Lockouts section on the Trading Controls page THEN there is no UI control to create a new manual lockout or to remove an existing lockout early

1.5 WHEN the operator wants to enable or disable the approval requirement for paper mode THEN there is no UI control on the Trading Controls page to toggle the `auto_approve_paper` setting in the risk config

### Expected Behavior (Correct)

2.1 WHEN the system is in paper trading mode and the operator has disabled `auto_approve_paper` via the UI THEN the `requires_approval()` function SHALL return `True`, causing orders to be held for operator approval before broker submission

2.2 WHEN `requires_approval()` returns `True` for the current trading mode THEN orders processed by `process_order_job()` SHALL create approval requests visible in the "Pending Approvals" section, and the operator SHALL be able to approve or reject them using the existing approve/reject buttons

2.3 WHEN the operator submits a manual lockout via the Trading Controls page (specifying ticker, reason, and duration) THEN the system SHALL create a new entry in the `symbol_lockouts` table via a new API endpoint, and the lockout SHALL appear in the "Active Lockouts" section

2.4 WHEN the operator views the Active Lockouts section THEN each lockout entry SHALL have a control to remove (cancel) the lockout early, and there SHALL be a form to create a new manual lockout

2.5 WHEN the operator toggles the approval requirement setting on the Trading Controls page THEN the system SHALL update the `auto_approve_paper` field in the active risk config's JSON, and the change SHALL take effect for subsequent orders without requiring a service restart

### Unchanged Behavior (Regression Prevention)

3.1 WHEN the system is in live trading mode with `require_approval_for_live` set to `True` (the default) THEN the system SHALL CONTINUE TO require operator approval for live orders as it does today

3.2 WHEN the system is in disabled trading mode THEN the `requires_approval()` function SHALL CONTINUE TO return `False` because orders are blocked upstream by the risk engine

3.3 WHEN the operator approves or rejects a pending approval via the existing approve/reject buttons THEN the system SHALL CONTINUE TO update the approval status in the `operator_approvals` table via the existing `PUT /api/admin/trading/approvals/{id}` endpoint

3.4 WHEN a pending approval expires (exceeds `approval_timeout_minutes`) THEN the system SHALL CONTINUE TO mark it as expired via the existing `expire_stale_approvals()` function

3.5 WHEN the risk engine evaluates an order and it fails risk checks THEN the order SHALL CONTINUE TO be rejected before reaching the approval gate, preserving the existing risk evaluation pipeline

3.6 WHEN system-generated lockouts are created by internal processes (news-shock, cooldown) THEN those lockouts SHALL CONTINUE TO function as they do today, unaffected by the new manual lockout feature
