Files
finance_bot/.history/docs/MVP_QUICK_START_20251210210643.md
2025-12-10 22:09:31 +09:00

10 KiB

🚀 MVP Implementation Quick Start

Phase-by-Phase Implementation Guide

Phase 1: Complete (Existing)

  • Database schema with 10 tables
  • Environment variable management
  • Docker Compose setup
  • API health endpoint

🔄 Phase 2: Security Foundation (THIS DELIVERABLE)

2.1 Database Migrations

# Run the new migration
cd /home/data/finance_bot
source .venv/bin/activate
alembic upgrade head

What it creates:

  • sessions table (for refresh token tracking)
  • telegram_identities table (Telegram user binding)
  • event_log table (audit trail)
  • access_log table (request logging)
  • Enhanced transactions (with approval workflow)
  • Enhanced family_members (RBAC)

2.2 Install Dependencies

pip install -r requirements.txt

Key additions:

PyJWT==2.8.1           # JWT token management
aiohttp==3.9.1         # Async HTTP client
python-multipart==0.0.6  # Form data parsing
redis==5.0.1          # Redis client

2.3 Update Configuration

# Add to .env
JWT_SECRET_KEY=your-super-secret-key-min-32-chars-here-please
HMAC_SECRET_KEY=your-hmac-secret-key-min-32-chars-please
REQUIRE_HMAC_VERIFICATION=false  # Disabled in MVP

2.4 Verify API Starts

# Start FastAPI server
python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

# In another terminal, test
curl http://localhost:8000/health
# Response: {"status":"ok","environment":"development","version":"1.0.0"}

📋 Phase 3: API Endpoints (EXAMPLES)

3.1 Authentication Endpoints

Login:

POST /api/v1/auth/login
{
  "email": "user@example.com",
  "password": "password123"
}

Response 200:
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user_id": 1,
  "expires_in": 900
}

Telegram Binding (Start):

POST /api/v1/auth/telegram/start
{
  "chat_id": 12345
}

Response 200:
{
  "code": "ABC123XYZ...",
  "expires_in": 600
}

Telegram Binding (Confirm):

POST /api/v1/auth/telegram/confirm
Authorization: Bearer <user_access_token>
{
  "code": "ABC123XYZ...",
  "chat_id": 12345,
  "username": "john_doe",
  "first_name": "John"
}

Response 200:
{
  "success": true,
  "user_id": 1,
  "jwt_token": "eyJhbGc...",
  "expires_at": "2024-01-09T12:30:00Z"
}

3.2 Transaction Endpoints

Create Transaction (Small Amount - Auto-executed):

POST /api/v1/transactions
Authorization: Bearer <jwt_token>
X-Client-Id: telegram_bot
X-Timestamp: 1702237800
X-Signature: <hmac_sha256>

{
  "family_id": 1,
  "from_wallet_id": 10,
  "to_wallet_id": 11,
  "amount": 50.00,
  "category_id": 5,
  "description": "Groceries"
}

Response 201:
{
  "id": 100,
  "status": "executed",
  "amount": "50.00",
  "confirmation_required": false,
  "created_at": "2023-12-10T12:30:00Z"
}

Create Transaction (Large Amount - Requires Approval):

POST /api/v1/transactions
...
{
  ...
  "amount": 600.00,  # > threshold
}

Response 201:
{
  "id": 101,
  "status": "pending_approval",
  "amount": "600.00",
  "confirmation_required": true,
  "created_at": "2023-12-10T12:30:00Z"
}

# Bot notifies owner in Telegram

Approve Transaction:

POST /api/v1/transactions/101/confirm
Authorization: Bearer <owner_jwt>
{
  "confirmation_token": null
}

Response 200:
{
  "id": 101,
  "status": "executed",
  "executed_at": "2023-12-10T12:35:00Z"
}

Reverse Transaction:

DELETE /api/v1/transactions/100
Authorization: Bearer <jwt>
{
  "reason": "User requested refund"
}

Response 200:
{
  "original_transaction_id": 100,
  "reversal_transaction_id": 102,
  "reversed_at": "2023-12-10T12:40:00Z"
}

3.3 Wallet Endpoints

List Wallets:

GET /api/v1/wallets?family_id=1
Authorization: Bearer <jwt>

Response 200:
{
  "wallets": [
    {
      "id": 10,
      "name": "Cash",
      "balance": "150.00",
      "type": "cash"
    },
    {
      "id": 11,
      "name": "Bank Account",
      "balance": "1250.00",
      "type": "bank"
    }
  ]
}

🧪 Testing the MVP

1. Unit Tests

# Run security tests
pytest tests/test_security.py -v

# Run specific test
pytest tests/test_security.py::TestJWTManager::test_create_access_token -v

2. Integration Tests

# Start API server in background
python -m uvicorn app.main:app &

# Run full test suite
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=app --cov-report=html

3. Manual API Testing

Using curl:

# Get health
curl http://localhost:8000/health

# Create transaction (need valid JWT)
JWT_TOKEN=$(curl -s -X POST http://localhost:8000/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"pass"}' | jq -r '.access_token')

curl -X POST http://localhost:8000/api/v1/transactions \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "X-Client-Id: manual_test" \
  -H "Content-Type: application/json" \
  -d '{
    "family_id": 1,
    "from_wallet_id": 10,
    "to_wallet_id": 11,
    "amount": 50.00,
    "category_id": 5,
    "description": "Test transaction"
  }'

Using Swagger UI:

http://localhost:8000/docs
  • All endpoints documented with interactive testing
  • Try endpoints directly from browser

Using Postman:

  1. Open Postman
  2. Create new request
  3. Set URL: http://localhost:8000/api/v1/transactions
  4. Set Method: POST
  5. Add Headers:
    • Authorization: Bearer <your_jwt>
    • X-Client-Id: postman
  6. Set Body (JSON):
    {
      "family_id": 1,
      "from_wallet_id": 10,
      "to_wallet_id": 11,
      "amount": 50.00,
      "category_id": 5,
      "description": "Postman test"
    }
    
  7. Send!

🤖 Telegram Bot Testing

1. Local Bot Testing

Create test bot:

  1. Open Telegram
  2. Chat with @BotFather
  3. /newbot
  4. Follow instructions
  5. Get BOT_TOKEN

Update .env:

BOT_TOKEN=<your_test_bot_token>

Run bot:

# Terminal 1: API server
python -m uvicorn app.main:app --reload

# Terminal 2: Bot client (polling)
# TODO: Implement bot polling in app/bot/worker.py

Test flow:

Your Telegram → /start
Bot → "Click link to bind: https://..."
You → Click link (authenticate)
API → Create TelegramIdentity
You → Bot says "Connected!"
You → /balance
Bot → Shows wallets via API call

📊 RBAC Testing

Test Permission Checking

# python -i
from app.security.rbac import RBACEngine, MemberRole, Permission, UserContext

# Create contexts for different roles
owner = UserContext(
    user_id=1,
    family_id=1,
    role=MemberRole.OWNER,
    permissions=RBACEngine.get_permissions(MemberRole.OWNER),
    family_ids=[1],
)

member = UserContext(
    user_id=2,
    family_id=1,
    role=MemberRole.MEMBER,
    permissions=RBACEngine.get_permissions(MemberRole.MEMBER),
    family_ids=[1],
)

# Test owner permissions
RBACEngine.has_permission(owner, Permission.DELETE_FAMILY)  # True
RBACEngine.has_permission(member, Permission.DELETE_FAMILY)  # False

# Test family access
RBACEngine.check_family_access(owner, 1)  # OK
RBACEngine.check_family_access(member, 2, raise_exception=False)  # False

🚀 Deployment Steps

Docker Compose Deployment

# Navigate to project
cd /home/data/finance_bot

# Build images
docker-compose build

# Start services
docker-compose up -d

# Run migrations
docker-compose exec migrations python -m alembic upgrade head

# Verify
docker-compose ps
curl http://localhost:8000/health

# Check logs
docker-compose logs -f api
docker-compose logs -f bot

Docker-Free Deployment

# Setup environment
source .venv/bin/activate

# Update .env
export $(cat .env | grep -v '#' | xargs)

# Start services (in separate terminals)
# Terminal 1: API
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000

# Terminal 2: Bot (polling)
# TODO: Implement in app/bot/worker.py
python -m app.bot.worker

# Terminal 3: Worker (event processing)
# TODO: Implement in app/workers/event_processor.py
python -m app.workers.event_processor

📈 Monitoring & Debugging

Enable Debug Logging

# In app/core/config.py
log_level: str = "DEBUG"

# In .env
LOG_LEVEL=DEBUG

View Event Log

# python -i
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.db.models import EventLog

engine = create_engine("postgresql://...")
Session = sessionmaker(bind=engine)
session = Session()

# Query recent events
events = session.query(EventLog).order_by(EventLog.created_at.desc()).limit(10)
for e in events:
    print(f"{e.created_at} | {e.action} | {e.entity_type} #{e.entity_id} | Actor: {e.actor_id}")

View Access Log

from app.db.models import AccessLog

access = session.query(AccessLog).order_by(AccessLog.created_at.desc()).limit(10)
for a in access:
    print(f"{a.created_at} | {a.method} {a.endpoint} | {a.status_code} | {a.user_id} | {a.ip_address}")

Troubleshooting

Issue: "type already exists"

Solution:

# Drop conflicting type in PostgreSQL
docker exec finance_bot_postgres psql -U trevor -d finance_db -c \
  "DROP TYPE IF EXISTS family_role CASCADE;"

# Re-run migration
docker-compose exec migrations python -m alembic downgrade -1
docker-compose exec migrations python -m alembic upgrade head

Issue: JWT token verification fails

Solution:

# Check token expiration
from app.security.jwt_manager import jwt_manager
token_payload = jwt_manager.decode_token(token)  # Ignore signature
print(f"Expires at: {token_payload.get('exp')}")
print(f"Current time: {datetime.utcnow().timestamp()}")

Issue: HMAC signature mismatch

Solution:

  1. Verify base_string format: METHOD:ENDPOINT:TIMESTAMP:BODY_HASH
  2. Verify client_secret matches on both sides
  3. Check timestamp isn't too old (±30 seconds)

📚 Next Steps

To Complete MVP:

  1. Security foundation created
  2. Add remaining endpoints (Wallets, Budgets, Goals, Reports)
  3. Implement worker process (event consumer)
  4. Implement Telegram bot webhook (instead of polling)
  5. Add comprehensive tests
  6. Generate API documentation

To Extend MVP:

  1. Web frontend (React)
  2. Mobile app (React Native)
  3. Advanced reporting
  4. Kubernetes deployment
  5. Multi-region setup

Document Version: 1.0
Last Updated: 2025-12-10
Next Review: 2025-12-24