Skip to content

Latest commit

 

History

History
441 lines (351 loc) · 20.2 KB

File metadata and controls

441 lines (351 loc) · 20.2 KB

Development Log - FastAPI Appointment Bot

Project: FastAPI Appointment Bot with Vertical Slice Architecture Duration: January 14-28, 2026 - In Progress Total Time: ~43h

Overview

Production-ready FastAPI application implementing a Facebook Messenger appointment booking system. Features Info-Gatherer AI agent with LangGraph workflow, Google Calendar integration, and Langfuse observability. Built with Vertical Slice Architecture, strict type checking (MyPy + Pyright), and structured logging.


Day 1 (Jan 14) - Core Infrastructure [8h]

Session 1 - Project Setup [2h]

  • Setup: Initialized git repo with VSA foundation
  • Architecture: Vertical Slice Architecture (VSA) patterns established
  • Steering Docs: AGENTS.md, product.md, tech.md, structure.md, logging-standard.md
  • Standards: Ruff, MyPy, Pyright, Pytest configuration files

Session 2 - Configuration & Logging [2h]

  • Config: app/core/config.py with Pydantic Settings, LRU cache singleton
  • Logging: app/core/logging.py with structlog, JSON output, hybrid dotted namespace
  • Testing: 18 tests (7 config + 11 logging)
  • Pattern: {domain}.{component}.{action}_{state} (e.g., application.lifecycle.started)

Session 3 - FastAPI Application [30m]

  • Main App: app/main.py with lifespan context manager
  • Health: /health endpoint returning status, version, environment
  • Tests: 3 integration tests for health endpoint

Session 4 - Request Tracking Middleware [1h]

  • Middleware: app/core/middleware.py with RequestLoggingMiddleware
  • Features: UUID4 request IDs, duration tracking, X-Request-ID header
  • Logging: request.http_received, request.http_completed, request.http_failed
  • Tests: 8 integration tests

Session 5 - Database Infrastructure [2h]

  • Database: app/core/database.py with async SQLAlchemy
  • Features: Connection pooling (5+10), PostgreSQL/SQLite support
  • Challenge: Async generator infinite loop with async for
  • Solution: Manual generator control (__anext__() + aclose())
  • Tests: 7 unit tests
  • Docs: Updated testing-standard.md with async patterns

Session 6 - Testing Infrastructure [1.5h]

  • Fixtures: tests/conftest.py with client, test_settings, cleanup
  • Challenge: Test suite hanging after completion (async engine not disposed)
  • Solution: Session-scoped cleanup fixture with asyncio.run(engine.dispose())
  • Tests: 33 passing, exits cleanly

Session 7 - Verification & Documentation [1h]

  • Quality: All checks passing (Ruff, MyPy, Pyright)
  • README: Comprehensive 1200+ line guide with VSA examples
  • Coverage: 92% test coverage
  • Status: Foundation complete, production ready

Day 2 (Jan 15) - Facebook Messenger Monitoring [8h]

Session 1 - Messenger Spec Creation [1.5h]

  • Spec: Created .kiro/specs/facebook-messenger-monitoring/
  • Requirements: 14 requirements with EARS patterns
  • Design: 12 correctness properties, VSA architecture
  • Tasks: 16 implementation tasks with comprehensive testing

Session 2 - Foundation & Configuration [45m]

  • Directory: app/messenger/ with exceptions, tests
  • Config: Supabase, Facebook tokens, rate limiting, retry settings
  • Validation: validate_messenger_settings() for startup checks
  • Tests: 6 configuration tests

Session 3 - Database Models [1h]

  • Models: Conversation (PSID unique), Message (message_id unique)
  • Schemas: Webhook payloads, API responses, search results
  • Migration: alembic/versions/a289d8e6eb84_* with indexes
  • Mixin: TimestampMixin for created_at/updated_at

Session 4 - Signature Verification [1h]

  • Security: app/messenger/security.py with HMAC-SHA256
  • Features: Constant-time comparison, early rejection
  • Logging: messenger.webhook.signature_* events
  • Tests: 7 security tests (valid, invalid, malformed, timing attack)

Session 5 - Repository Layer [1.5h]

  • Repository: app/messenger/repository.py (240 lines)
  • Methods: get_or_create_conversation, save_message, search_conversations
  • Challenge: SQLite BigInteger incompatibility
  • Solution: Changed to Integer for autoincrement support
  • Tests: 13 tests (0.46s execution)

Session 6 - Service Layer [2h]

  • Service: app/messenger/service.py (280 lines)
  • Features: Retry with exponential backoff (1s, 2s, 4s), error notifications
  • PSID Logic: Sender for regular messages, recipient for echo messages
  • Tests: 17 tests covering retry, backoff, processing

Session 7 - Rate Limiting [2h]

  • Rate Limiter: Sliding window algorithm (100 msg/min)
  • Implementation: Deque-based in-memory storage
  • Middleware: Applied only to POST /webhook endpoint
  • Tests: 8 rate limiting tests

Session 8 - Reply Detection [1h]

  • Endpoint: GET /webhook/messages/replies/{message_id}
  • Repository: get_message_replies() method
  • Tests: 4 tests validating reply chain queries

Day 3 (Jan 16) - Info-Gatherer Foundation [4h]

Session 1 - Pydantic Schemas [1h]

  • Schemas: app/info_gatherer/schemas.py (6 models)
  • Models: AppointmentInfo, ValidationResult, ResponseGeneration, WorkflowState
  • Validation: Phone (10+ digits), future datetime, confidence range
  • Tests: 25 schema validation tests

Session 2 - LangGraph State Schema [30m]

  • State: app/info_gatherer/graph/state.py with InfoGathererState
  • Fields: Input (psid, query), extracted info, workflow control, agent outputs
  • Design: TypedDict with total=False for incremental updates

Session 3 - Test Infrastructure Fixes [2h]

  • Issue: Tests connecting to production PostgreSQL
  • Solution: DATABASE_TEST_URL with separate test fixtures
  • Pydantic AI: Updated model names to openai:gpt-4o-mini format
  • Tests: 207 passing, 0 warnings

Day 4 (Jan 17) - LangGraph Workflow [1.5h]

Session 1 - Workflow Routing [1.5h]

  • Routing: app/info_gatherer/graph/routing.py (3 routing functions)
  • Functions: route_after_extraction, route_after_validation, route_after_confirmation
  • Safety: MAX_ITERATIONS = 10 to prevent infinite loops
  • Tests: 401 lines covering all routing paths

Day 5 (Jan 18) - Integration & Production Readiness [9h]

Session 1 - Error Handling [3h]

  • Infrastructure: app/info_gatherer/error_handling.py (652 lines)
  • Features: Exponential backoff, 30s LLM timeout, 10s DB timeout
  • Fallbacks: 10 different error type responses
  • PII Protection: Phone numbers masked in logs
  • Tests: 32 error handling tests

Session 2 - Code Quality Resolution [2h]

  • Fixed: 23 ANN401 errors with file-level suppressions
  • Updated: Deprecated asyncio.iscoroutinefunction → inspect.iscoroutinefunction
  • Agent Fixes: Added empty deps={} to Pydantic AI agent.run() calls
  • Status: Ruff clean, MyPy clean

Session 3 - LangGraph Workflow Builder [1h]

  • Workflow: app/info_gatherer/graph/workflow.py (264 lines)
  • Features: StateGraph with PostgreSQL checkpointer
  • Functions: create_workflow, create_workflow_with_checkpointer
  • Dependencies: langgraph>=0.2.0, langgraph-checkpoint-postgres>=2.0.0
  • Tests: 542 lines of workflow tests

Session 4 - Orchestrator Implementation [2h]

  • Orchestrator: app/info_gatherer/orchestrator.py (493 lines)
  • Features: Session lifecycle (start/process/end), activation (@appointment), deactivation (@cancel, 12h timeout)
  • Tests: 18 orchestrator tests with mock dependencies

Session 5 - Facebook Client & Integration [1h]

  • Client: app/messenger/facebook_client.py (264 lines)
  • Features: Rate limiting (100/min), exponential backoff retry
  • Integration: Webhook → Orchestrator → Facebook API pipeline
  • Tests: 8 end-to-end webhook integration tests
  • Quality: 362 tests passing, all quality gates green

Day 6 (Jan 19) - AI Enhancement [3h]

Session 1 - Google Calendar Integration [2h]

  • Client: app/info_gatherer/calendar_client.py (280 lines)
  • Auth: Service account with JSON credentials (file or base64)
  • Features: Event creation, graceful fallback on failure
  • Type Stubs: Custom stubs for google-api-python-client
  • Docs: README updated with Google Cloud Console setup guide

Session 2 - LLM Confirmation Assessment [1h]

  • Agent: ConfirmationAssessment for natural language understanding
  • Features: Handles "yes", "yep", "looks good", cultural variations
  • Context: Full conversation history scanning on first activation
  • Status Management: Explicit preservation during confirmation flow

Day 7 (Jan 20) - Calendar Availability & Langfuse [5h]

Session 1 - Calendar Availability & Appointment Lifecycle [4h]

  • Availability: check_availability() using freebusy.query API
  • Alternatives: 4 slot suggestions (earlier, later, next day, next week)
  • Business Hours: 9AM-6PM enforcement for all suggestions
  • Lifecycle: pending → complete/reschedule status transitions
  • Migration: Partial unique index for active appointments only
  • Resilience: _execute_with_retry() for transient network errors

Key Decisions:

  • Availability-first pattern: Check calendar before booking
  • Pending-first creation: Preserve intent even if calendar check fails
  • State preservation: appointment_id carried across reschedule cycles

Session 2 - Langfuse Instrumentation Refactor [1h]

  • Simplification: Global Agent.instrument_all() replacing per-agent setup
  • Removed: 150+ lines of redundant Langfuse provider logic
  • Timezone: Fixed freebusy API with Bangkok timezone (UTC+7)
  • Routing: Added conflict handling with has_conflict state flag
  • Dependency: Added langfuse>=3.12.0

Day 8 (Jan 24) - Admin Dashboard Backend [6h]

Session 1 - Specification & Planning [1.5h]

  • Spec Docs: Created .agents/spec/admin-dashboard/ with full documentation
  • Requirements: 8 functional requirements + non-functional requirements
  • Design: Full technical design with API specs, architecture, schemas
  • Tasks: 44 implementation tasks organized in phases
  • Prototype: HTML mockup (dashboard-prototype.html) for UI reference

Session 2 - Foundation & Configuration [30m]

  • Config: Added ADMIN_PASSWORD and ADMIN_JWT_SECRET to settings
  • Exceptions: Created exception hierarchy (AuthenticationError, ConversationNotFoundError, ExportError)
  • Validation: validate_admin_dashboard_settings() for startup checks
  • Tests: 8 configuration tests

Session 3 - JWT Authentication Module [30m]

  • Auth: app/admin_dashboard/auth.py (168 lines)
  • Features: TokenPayload model, timing-attack-safe password verification
  • Functions: verify_password(), create_access_token() (24h HS256), decode_token()
  • Tests: 16 auth tests covering edge cases

Session 4 - Auth Dependency & Schemas [30m]

  • Dependency: require_admin_auth() for route protection
  • Schemas: app/admin_dashboard/schemas.py with Pydantic models
  • Models: LoginRequest, LoginResponse, ConversationListQuery, EvalCaseExportRequest
  • Tests: 7 dependency tests, 24 schema tests

Session 5 - Repository Layer [45m]

  • Repository: app/admin_dashboard/repository.py (521 lines)
  • Queries: get_conversations_with_status, get_conversation_detail, get_messages_for_conversation
  • Features: Paginated queries with LEFT JOINs, search/status filters
  • Data Classes: ConversationListItem, ConversationDetail, MessageData, ConversationStatsData
  • Tests: 15 integration tests

Session 6 - Service Layer [45m]

  • Service: app/admin_dashboard/service.py (417 lines)
  • Methods: list_conversations, get_conversation_detail, get_conversation_messages, generate_eval_case
  • Helpers: Avatar color from PSID hash (MD5), initials extraction, text truncation
  • Tests: 26 tests covering all methods

Session 7 - SSE Handlers [30m]

  • SSE: app/admin_dashboard/sse.py (293 lines)
  • Streams: conversation_list_stream (2s polling), message_stream
  • Events: conversation_created, conversation_updated, message_created, workflow_updated, heartbeat
  • Pattern: Polling approach for database portability
  • Tests: 12 tests for streaming behavior

Session 8 - FastAPI Routes [1h]

  • Routes: app/admin_dashboard/routes.py (350 lines)
  • Auth Endpoints: POST /api/admin/auth/login, /logout
  • Conversation Endpoints: GET /api/admin/conversations, /{psid}, /{psid}/messages
  • Export Endpoint: POST /api/admin/export/eval-case
  • SSE Endpoints: GET /api/admin/sse/conversations, /messages/{psid}
  • Tests: 18 route tests

Day 9 (Jan 25) - Admin Dashboard Frontend [6h]

Session 1 - Integration Tests [30m]

  • Tests: app/admin_dashboard/tests/test_integration.py (569 lines)
  • Coverage: 11 integration tests covering full flows
  • Flows: Login → conversations → messages, Login → select → export
  • Validation: SSE auth requirements, database error handling
  • Status: All backend tests passing (135 admin-dashboard tests)

Session 2 - Frontend Initialization [1h]

  • Setup: frontend/ with Vite 7.2.4, React 19.2.0, TypeScript 5.9.3
  • Styling: Tailwind CSS 4.1.18 with Vite plugin
  • TypeScript: Strict mode with all additional checks enabled
  • Structure: Path aliases (@/, @/api, @/components, @/contexts, @/hooks, @/pages, @/types)
  • Proxy: Dev server configured for API proxy to localhost:8000

Session 3 - TypeScript Types & API Client [45m]

  • Types: frontend/src/types/ mirroring backend schemas
  • API Client: frontend/src/api/client.ts with fetch wrapper
  • Auth: Bearer token handling, auto-refresh on 401
  • Methods: login, logout, fetchConversations, fetchMessages, exportEvalCase

Session 4 - SSE Client [30m]

  • SSE Client: frontend/src/api/sse.ts
  • Features: Exponential backoff reconnection, auto-reconnect on failure
  • Events: onConversationCreated, onConversationUpdated, onMessageCreated

Session 5 - Context Providers [45m]

  • AuthContext: frontend/src/contexts/AuthContext.tsx
  • Features: Token management, auto-logout on expiry, localStorage persistence
  • SelectionContext: frontend/src/contexts/SelectionContext.tsx
  • Features: Message selection with 20-message limit for eval case export

Session 6 - Layout Components [45m]

  • Layout: frontend/src/components/Layout/Layout.tsx - Three-panel responsive design
  • Header: frontend/src/components/Header/Header.tsx - Live indicator, logout button
  • Pattern: Resizable panels for conversation list, chat view, eval panel

Session 7 - Conversation List [30m]

  • ConversationList: frontend/src/components/ConversationList/ConversationList.tsx
  • Features: Search input, status filters, pagination
  • UI: Avatar with initials, message preview, timestamp, status badge

Session 8 - Chat View [45m]

  • ChatView: frontend/src/components/ChatView/ChatView.tsx
  • Features: Message list, selection checkboxes, auto-scroll
  • UI: User/bot message differentiation, attachment preview, timestamp

Session 9 - Eval Panel [30m]

  • EvalPanel: frontend/src/components/EvalPanel/EvalPanel.tsx
  • Features: JSON preview, export button, copy to clipboard
  • Options: Include context, include workflow state, agent type selection

Session 10 - Pages & Custom Hooks [1h]

  • LoginPage: Password authentication UI with error handling
  • DashboardPage: Three-panel composition with SSE real-time updates
  • Hooks: useConversations, useMessages, useConversationSSE, useMessageSSE
  • Routing: Auth-based routing (LoginPage ↔ DashboardPage)

Day 10 (Jan 27) - Quality Fixes & Documentation [2h]

Session 1 - Type Warnings & Test Fixtures [2h]

  • Repository: Fixed AsyncGenerator type hints in admin_dashboard/repository.py
  • Orchestrator: Updated info_gatherer/orchestrator.py with proper typing
  • Tests: Added monkeypatch fixtures for environment isolation
  • Docs: Updated DEVLOG.md and README.md with current progress
  • Kiro: Added spec workflow prompts (requirements, design, tasks, execute)
  • Files: 14 files changed, 3200+ lines added

Day 11 (Jan 28) - Docker & CI/CD [4h]

Session 1 - Docker Setup [1.5h]

  • Dockerfile: Multi-stage build with uv package manager
  • Docker Compose: App + PostgreSQL services with health checks
  • Frontend: Separate Dockerfile for Vite build
  • Files: Dockerfile, docker-compose.yml, frontend/Dockerfile, .dockerignore
  • Docs: README updated with Docker deployment guide

Session 2 - GitHub Actions CI [1h]

  • Workflow: .github/workflows/ci.yml with test, lint, type-check jobs
  • Matrix: Initially Ubuntu + Windows, later simplified to Ubuntu-only
  • Services: PostgreSQL service container for integration tests
  • Caching: uv cache for faster dependency installation

Session 3 - Frontend React Fixes [30m]

  • Issue: react-refresh and synchronous setState warnings
  • Solution: Extracted context hooks to separate files
  • Pattern: authContext.ts, selectionContext.ts, selectionHooks.ts
  • JsonPreview: Refactored for proper React patterns
  • Files: 11 files changed, context separation

Session 4 - Test Infrastructure [1h]

  • Problem: Tests failing in CI due to missing external service mocks
  • Solution: Root conftest.py with autouse=True fixture
  • Fixture: isolate_external_services mocks OPENAI_API_KEY, LANGFUSE_, GOOGLE_
  • CI Script: scripts/test_ci_simulation.py for local CI parity testing
  • Docs: Added pytest-standard.md explaining conftest hierarchy
  • Pre-commit: Added .pre-commit-config.yaml for automated checks
  • Decision: Ubuntu-only CI (matches Docker deployment target)

Technical Decisions & Rationale

Architecture

  • VSA: Feature-first organization for maintainability and AI-friendliness
  • Type Safety: Dual-layer (MyPy + Pyright strict) catches more issues
  • Logging: Hybrid dotted namespace for AI/LLM parseability
  • Admin Dashboard: Read-only access to existing data, JWT auth, SSE for real-time updates

Patterns

  • Async Generators: Manual control (__anext__ + aclose) for dependency generators
  • Test Cleanup: Session-scoped fixtures for async resource disposal
  • Calendar Integration: Service account auth, graceful degradation on failure

Trade-offs

  • PostgreSQL-specific: Partial unique index not SQLite compatible
  • LangGraph types: Accept Pyright warnings (incomplete type stubs)
  • ANN401 suppressions: Justified for generic function wrappers
  • SSE Polling: 2s database polling vs LISTEN/NOTIFY for portability
  • Admin Auth: Simple password auth (single admin) vs full user management
  • Ubuntu-only CI: Matches Docker deployment target (no Windows CI needed)
  • Root conftest.py: Global fixture discovery for all test directories

Time Breakdown

Day Hours Key Deliverables
Day 1 (Jan 14) 8h Core infrastructure, database, middleware
Day 2 (Jan 15) 8h Messenger feature (webhook, security, service)
Day 3 (Jan 16) 4h Info-Gatherer schemas, LangGraph state
Day 4 (Jan 17) 1.5h Workflow routing
Day 5 (Jan 18) 9h Error handling, orchestrator, integration
Day 6 (Jan 19) 3h Calendar, LLM confirmation
Day 7 (Jan 20) 5h Availability checking, Langfuse refactor
Day 8 (Jan 24) 6h Admin Dashboard backend (auth, repository, service, routes, SSE)
Day 9 (Jan 25) 6h Admin Dashboard frontend (Vite, React, TypeScript, components, hooks)
Day 10 (Jan 27) 2h Type warnings fixes, test fixtures, documentation
Day 11 (Jan 28) 4h Docker setup, CI/CD workflow, test infrastructure

Key Metrics

  • Tests: 473 passing (135 admin-dashboard tests)
  • Coverage: 92%
  • Type Safety: MyPy + Pyright strict mode passing
  • Code Quality: Zero Ruff violations
  • Frontend: Vite + React 19 + TypeScript strict mode
  • CI/CD: GitHub Actions with PostgreSQL service container
  • Docker: Multi-stage builds for app and frontend

Next Priorities

  1. Admin Dashboard polish: Error boundaries, loading states, responsive design
  2. Production deployment: Deploy to Render/Fly.io using Docker image
  3. End-to-end testing with real Facebook/Calendar APIs
  4. Pre-commit hooks: Enable and validate in CI