Files
redshift d1feddbd21 chore(deps): patch all Dependabot security alerts
Closes 29 of 30 open Dependabot alerts (all 3 critical, all 17 high):

Python (uv.lock):
- litellm 1.83.0 -> 1.84.10  (CVE-2026-49468, CVE-2026-42208 criticals
  + 8 more high/med/low)
- starlette 0.46.2 -> 1.6.0  (CVE-2026-54283, CVE-2026-48818,
  CVE-2026-48817, CVE-2026-48710, CVE-2025-62727, CVE-2025-54121)
- cryptography 43.0.3 -> 50.0.1  (CVE-2026-69249, CVE-2026-26007,
  CVE-2026-34073, CVE-2024-12797)
- h11 0.14.0 -> 0.16.0  (CVE-2025-43859 critical)
- fastapi 0.115.14 -> 0.141.1  (starlette 1.x support)
- httpx 0.25.2 -> 0.28.1, setuptools 75.9.1 -> 84.0.0,
  wheel 0.41.3 -> 0.48.0

cashu 0.20.x pins conservative upper bounds (httpx<0.26, h11<0.15,
fastapi<0.116, cryptography<44, setuptools<76, wheel<0.42,
importlib-metadata<7) that conflict with every patched version, so the
gated packages are lifted via [tool.uv] override-dependencies. routstr
only imports cashu's wallet-side modules, not its mint/fastapi server
paths. starlette is forced via constraint-dependencies since fastapi
0.141 permits the old in-range 0.46.2.

Code changes required by the bumps:
- httpx 0.28 removed `proxies=`: use `proxy=` in
  routstr/nostr/discovery.py (Tor .onion health fetches) and
  examples/tor.py. The discovery.py path was untested and would have
  raised TypeError at runtime on any .onion provider check.
- tests/integration/test_admin_pricing_rate_validation.py: httpx 0.28
  refuses to encode NaN/Inf client-side (allow_nan=False); send raw
  JSON bytes so the bare NaN/Infinity literals still reach the server,
  which is the behavior under test.

UI (pnpm-lock.yaml):
- browserslist 4.28.1 -> 4.28.9  (CVE-2026-73089, CVE-2026-73088)
- @humanfs/node 0.16.7 -> 0.16.8

Remaining alert: ecdsa (GHSA-wj6h-64fc-37mp, Minerva timing attack) is
already at the latest release 0.19.2 with no fix available upstream;
cashu pins ecdsa<0.20. Deferred until cashu migrates off python-ecdsa.

Verified: 1336 unit + 439 integration tests pass, mypy, ruff, UI lint /
format-check / build all clean. 2 unit test failures
(test_provider_slugs) are pre-existing environment leaks (python-dotenv
loads the parent checkout's .env containing TINFOIL_API_KEY and fail
identically on main.
EOF
)
2026-09-07 20:14:28 +02:00
..
2025-08-09 12:44:21 -03:00
2025-07-26 15:18:31 -04:00
fmt
2026-04-26 22:19:30 +02:00
2025-08-13 17:54:04 -03:00
2025-12-11 13:58:57 +08:00
2026-01-31 07:37:39 +08:00
2026-01-03 22:49:46 +01:00
2026-08-03 23:32:06 +02:00
2026-03-13 23:04:17 +01:00
2025-08-06 23:25:06 -03:00
2026-09-04 01:35:43 +02:00
2026-07-07 14:29:39 +02:00
2025-08-09 14:55:26 -03:00

Integration Tests

End-to-end tests for API endpoints, Cashu wallet operations, and database interactions.

Quick Start

# First-time setup (installs uv if needed)
make setup

# Check if all dependencies are installed
make check-deps

# Run tests
make test

Test Modes

The integration tests support two execution modes:

🎭 Mock Mode (Default - Fast)

  • Uses in-memory mocks for external services
  • No Docker required
  • Runs quickly, ideal for CI/CD
  • Good for rapid development iteration

🐳 Docker Mode (Realistic)

  • Uses real Docker services (Cashu mint, mock OpenAI, Nostr relay)
  • More accurate testing environment
  • Slower but catches more edge cases
  • Recommended before releases

Running Tests

Quick Mode (Mocked Services)

# All integration tests with mocks
pytest tests/integration/ -v

# Specific test file
pytest tests/integration/test_wallet_topup.py -v

# Skip slow tests
pytest tests/integration/ -m "not slow" -v

# Run only unit-style integration tests
pytest tests/integration/ -m "not requires_docker" -v

Full Integration Mode (Docker Services)

# Using the automated script (recommended)
./tests/run_integration.py

# Or manually:
docker-compose -f compose.testing.yml up -d
USE_LOCAL_SERVICES=1 pytest tests/integration/ -v
docker-compose -f compose.testing.yml down -v

CI/CD Mode

# Fast tests only for continuous integration
pytest tests/integration/ -m "not slow and not requires_docker" -v

# Performance tests
pytest tests/integration/ -m "performance" -v

Test Infrastructure

Core Fixtures

  • integration_client - Async HTTP client configured for testing
  • authenticated_client - Pre-authenticated client with API key
  • testmint_wallet - Mock/real Cashu wallet for token generation
  • db_snapshot - Database state tracking for verification
  • test_mode - Reports current execution mode (mock/docker)

Utility Classes

  • ResponseValidator - Validates API response formats
  • PerformanceValidator - Tracks and validates performance metrics
  • ConcurrencyTester - Tests concurrent request handling
  • CashuTokenGenerator - Generates valid/invalid test tokens

Environment Configuration

Test environment configuration is handled directly in conftest.py. The configuration automatically switches between:

  • Mock mode: Fast, uses mocked services (default)
  • Docker mode: Uses real Docker services when USE_LOCAL_SERVICES=1

This keeps all test configuration in one place and avoids file duplication.

Writing Tests

Basic Test Structure

@pytest.mark.integration
@pytest.mark.asyncio
async def test_wallet_topup(
    authenticated_client: AsyncClient,
    testmint_wallet: Any,
    db_snapshot: Any
):
    # Capture initial state
    await db_snapshot.capture()
    
    # Generate test token
    token = await testmint_wallet.mint_tokens(1000)
    
    # Make API request
    response = await authenticated_client.post(
        "/v1/wallet/topup", 
        params={"cashu_token": token}
    )
    
    # Validate response
    assert response.status_code == 200
    
    # Verify database changes
    diff = await db_snapshot.diff()
    assert len(diff["api_keys"]["modified"]) == 1

Testing Concurrent Operations

async def test_concurrent_topups(
    integration_client: AsyncClient,
    testmint_wallet: Any,
    create_api_key: Callable
):
    # Create multiple API keys
    keys = []
    for i in range(5):
        key, _ = await create_api_key(integration_client, testmint_wallet)
        keys.append(key)
    
    # Test concurrent requests
    tester = ConcurrencyTester()
    responses = await tester.run_concurrent_requests(
        integration_client,
        [{"method": "GET", "url": "/v1/wallet/", 
          "headers": {"Authorization": f"Bearer {key}"}} 
         for key in keys],
        max_concurrent=5
    )
    
    # All should succeed
    assert all(r.status_code == 200 for r in responses)

Performance Testing

@pytest.mark.performance
async def test_endpoint_performance(
    authenticated_client: AsyncClient,
    performance_validator: PerformanceValidator
):
    # Run multiple requests
    for i in range(100):
        start = performance_validator.start_timing("wallet_info")
        response = await authenticated_client.get("/v1/wallet/")
        performance_validator.end_timing("wallet_info", start)
    
    # Validate 95th percentile < 100ms
    result = performance_validator.validate_response_time(
        "wallet_info", max_duration=0.1, percentile=0.95
    )
    assert result["valid"], f"P95: {result['percentile_time']:.3f}s"

Troubleshooting

Tests Failing with Connection Errors

  • Ensure Docker services are running: docker ps
  • Check service logs: docker-compose -f compose.testing.yml logs
  • Verify ports aren't in use: lsof -i :3338,3000,8000,8088

Mock vs Docker Mode Confusion

  • Check current mode: Look for 🎭 or 🐳 emoji in test output
  • Force mock mode: Unset USE_LOCAL_SERVICES
  • Force Docker mode: export USE_LOCAL_SERVICES=1

Slow Test Execution

  • Use mock mode for development: pytest tests/integration/
  • Skip slow tests: pytest -m "not slow"
  • Run specific test files only
  • Use pytest-xdist for parallel execution: pytest -n auto

Installing uv Manually

If make dev-setup fails to install uv automatically:

# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Or with pip
pip install uv

# Or with Homebrew
brew install uv

Best Practices

  1. Use Mock Mode for Development - It's fast and catches most issues
  2. Run Docker Mode Before PRs - Ensures realistic testing
  3. Add Appropriate Markers - Help others run relevant test subsets
    • Use @pytest.mark.slow for tests that take significant time (e.g., memory/load tests)
    • Use @pytest.mark.requires_docker for tests needing Docker services
  4. Verify Database State - Use db_snapshot for state verification
  5. Test Edge Cases - Invalid inputs, network failures, race conditions
  6. Monitor Performance - Add performance tests for critical paths