fix: enforce trade-write permission check on v1 ledger trade endpoint

Security Fix:
- Update v1_ledger.py to require trade_write permission instead of read
- Fix authentication dependency from require_read to require_trade_write
- Ensure trade operations cannot be performed with read-only service tokens

Test Coverage:
- Add test_v1_ledger_trade_requires_trade_write_permission() to verify permission boundary
- Confirm read-only tokens are rejected with 403 Forbidden status
- Validate repository methods are not called on permission failure

Documentation:
- Add new Discovery dcy-005 for production admin bootstrap and operator access
- Update docs/discovery/index.md with dcy-005 entry
- Update release rel-001 with additional verification notes and issue references
This commit is contained in:
2026-05-11 14:17:27 +00:00
parent d20d784452
commit 2e1298a978
5 changed files with 302 additions and 16 deletions
+28
View File
@@ -528,6 +528,34 @@ def test_v1_ledger_trade_asset_not_found(monkeypatch) -> None:
assert resp.status_code == 404
def test_v1_ledger_trade_requires_trade_write_permission(monkeypatch) -> None:
"""Read-only service token must be rejected before asset lookup."""
_make_app_db(monkeypatch)
principal = TokenPrincipal(
token_id="t1",
user_id="user-1",
permission="read",
token_type="service",
runtime_id="rt-1",
)
mock_repo = MagicMock()
mock_repo.get_token_principal.return_value = principal
with patch("app.core.auth.get_portfolio_repository_from_settings", return_value=mock_repo):
client = _make_app(_make_settings(credential_encryption_key=_TEST_ENC_KEY))
resp = client.post(
"/v1/assets/005930/ledger/trades",
json=_trade_payload(),
headers=_service_token_header(),
)
assert resp.status_code == 403
assert resp.json()["detail"] == "Insufficient permission"
mock_repo.get.assert_not_called()
mock_repo.insert_ledger_trade.assert_not_called()
# ---------------------------------------------------------------------------
# REQ-010: startup validation
# ---------------------------------------------------------------------------