AGENT DIRECTIVE: This document is the single source of truth for all improvements. Execute each task sequentially within each phase. Do NOT skip tasks. Do NOT reorder tasks. Mark each checkbox upon completion. Do NOT proceed to the next phase until all tasks in the current phase are complete.
| Attribute | Value |
|---|---|
| Current Version | 2.0.0 |
| Target Version | 2.1.0 |
| Total Phases | 7 |
| Total Tasks | 47 |
| Priority Order | Security → Code Quality → Testing → DevOps → Documentation → UI/UX → Final |
| Phase | Name | Tasks | Status |
|---|---|---|---|
| 1 | Security Hardening | 10 | ✅ Complete |
| 2 | Code Quality & DRY | 8 | ✅ Complete |
| 3 | Testing Improvements | 7 | ✅ Complete |
| 4 | DevOps & Infrastructure | 8 | ✅ Complete |
| 5 | Documentation | 6 | ✅ Complete |
| 6 | Performance & Modernization | 5 | ✅ Complete |
| 7 | Final Validation | 3 | ✅ Complete |
Priority: CRITICAL
Objective: Eliminate all security vulnerabilities identified in code review
File: app/security.py
- 1.1.1 Remove file-based encryption key storage
- 1.1.2 Add
ENCRYPTION_KEYtoapp/config.pySettings class - 1.1.3 Modify
EncryptionServiceto read key from environment variable - 1.1.4 Add fallback key generation ONLY for development environment with warning log
- 1.1.5 Update
.env.examplewithENCRYPTION_KEYplaceholder
Acceptance Criteria:
- ✅
encryption.keyfile is no longer created - ✅ Key is read from
ENCRYPTION_KEYenvironment variable - ✅ Application fails to start in production if key is not set
Files: app/security.py, app/exceptions.py
- 1.2.1 Remove
SecurityErrorclass fromapp/security.py - 1.2.2 Update import in
app/security.pyto usefrom app.exceptions import SecurityError - 1.2.3 Verify all files importing SecurityError use the correct source
Acceptance Criteria:
- ✅ Only ONE
SecurityErrorclass exists inapp/exceptions.py - ✅ All imports reference
app.exceptions.SecurityError
Files: app/main.py, app/templates/*.html
- 1.3.1 Create
app/csrf.pywith CSRF token generation and validation - 1.3.2 Add CSRF middleware to
app/main.py - 1.3.3 Create Jinja2 global function for CSRF token insertion
- 1.3.4 Update
base.htmlto include CSRF meta tag - 1.3.5 Update ALL form templates to include CSRF hidden input:
-
index.html(tracker create form) -
tracker.html(refresh form, selector form) -
tracker_edit.html(edit form, delete form) -
admin/profiles.html(delete forms) -
admin/profile_form.html(create/edit form)
-
- 1.3.6 Add CSRF validation to ALL POST endpoints in
app/main.py
Acceptance Criteria:
- ✅ All forms include
<input type="hidden" name="csrf_token" value="..."> - ✅ POST requests without valid CSRF token return 403
- ✅ CSRF tokens are tied to user session
File: app/main.py
- 1.4.1 Create security headers middleware class
- 1.4.2 Add the following headers:
X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockReferrer-Policy: strict-origin-when-cross-originPermissions-Policy: geolocation=(), microphone=(), camera=()
- 1.4.3 Add Content-Security-Policy header (report-only mode initially)
- 1.4.4 Register middleware in application startup
Acceptance Criteria:
- ✅ All responses include security headers
- ✅ Headers verified via
curl -I http://localhost:8000/
File: app/security.py
- 1.5.1 Add
_last_cleanuptimestamp toRateLimiter.__init__ - 1.5.2 Add
_cleanup_intervalconstant (300 seconds) - 1.5.3 Implement
_cleanup_old_entries()method to remove stale IPs - 1.5.4 Call cleanup in
is_allowed()when interval exceeded - 1.5.5 Add maximum entries limit (10,000) with oldest-first eviction
Acceptance Criteria:
- ✅ Rate limiter memory usage stays bounded
- ✅ Old IP entries are automatically purged after window expiration
File: app/security.py
- 1.6.1 Create
is_private_ip()function to check all private ranges:10.0.0.0/8172.16.0.0/12192.168.0.0/16127.0.0.0/8169.254.0.0/16(link-local)::1(IPv6 localhost)fc00::/7(IPv6 private)
- 1.6.2 Update
validate_url()to useis_private_ip()in ALL environments - 1.6.3 Add URL scheme validation (only http/https)
- 1.6.4 Block URLs with IP addresses in non-development environments
Acceptance Criteria:
- ✅ Private IP URLs are blocked in production/staging
- ✅ SSRF attempts are logged as security warnings
File: app/config.py
- 1.7.1 Remove default value from
secret_keyfield (kept default for dev, validated in production) - 1.7.2 Add validation to fail startup if
SECRET_KEYnot set in production - 1.7.3 Add
encryption_keyfield with same validation - 1.7.4 Increase minimum
secret_keylength to 64 characters for production - 1.7.5 Add warning log if running in development mode
Acceptance Criteria:
- ✅ Application fails to start in production without required secrets
- ✅ Development mode shows clear warning in logs
File: app/logging_config.py
- 1.8.1 Create
SensitiveDataFilterlogging filter class - 1.8.2 Define patterns to mask: passwords, tokens, keys, credentials
- 1.8.3 Apply filter to all log handlers
- 1.8.4 Test that sensitive data is masked in log output
Acceptance Criteria:
- ✅ Passwords and tokens appear as
***REDACTED***in logs - ✅ No sensitive data visible in
app.log
Files: app/main.py, app/logging_config.py
- 1.9.1 Create middleware to generate UUID for each request
- 1.9.2 Store request ID in context variable
- 1.9.3 Include request ID in all log entries
- 1.9.4 Return request ID in response header
X-Request-ID
Acceptance Criteria:
- ✅ Each request has unique ID visible in logs
- ✅ Request ID can be used to trace full request lifecycle
Files: app/schemas.py, app/main.py
- 1.10.1 Add
max_lengthconstraints to all Pydantic string fields:- URL: 2000 chars
- Name: 500 chars
- Selector: 1000 chars
- Contact: 255 chars
- 1.10.2 Add form field
maxlengthattributes to all HTML inputs - 1.10.3 Add server-side length validation before database operations
Acceptance Criteria:
- ✅ Oversized inputs are rejected with clear error message
- ✅ No truncation occurs silently
Priority: HIGH
Objective: Eliminate code duplication and improve maintainability
Files: app/services/notification_service.py (new), app/services/tracker_service.py, app/services/scheduler_service.py
- 2.1.1 Create new file
app/services/notification_service.py - 2.1.2 Move
_send_price_notification()logic toNotificationServiceclass - 2.1.3 Add methods:
send_price_alert(),send_email(),send_sms() - 2.1.4 Update
TrackerServiceto useNotificationService - 2.1.5 Update
SchedulerServiceto useNotificationService - 2.1.6 Remove duplicate notification methods from both services
Acceptance Criteria:
- ✅ Single source of truth for notification logic
- ✅ Both services delegate to
NotificationService
Files: app/__init__.py, app/services/__init__.py
- 2.2.1 Update
app/__init__.pywith version and public exports:__version__ = "2.1.0" __all__ = ["app", "settings", "get_db"]
- 2.2.2 Update
app/services/__init__.pywith service exports:__all__ = ["TrackerService", "ProfileService", "SchedulerService", "NotificationService"]
- 2.2.3 Add
__all__toapp/exceptions.py - 2.2.4 Add
__all__toapp/security.py
Acceptance Criteria:
- ✅ All modules have explicit
__all__exports - ✅
from app.services import TrackerServiceworks cleanly
File: app/scraper.py
- 2.3.1 Add type hints to all functions:
fetch_html(url: str) -> strfetch_html_js(url: str) -> str_text(el: Tag) -> str_nearby_text(el: Tag, limit_nodes: int = 3) -> str_candidate_score(el: Tag, price_val: float, raw_text: str) -> intsmart_find_price(soup: BeautifulSoup) -> Optional[Tuple[float, str]]
- 2.3.2 Add return type hints to all parse functions
- 2.3.3 Add type alias:
PriceResult = Tuple[Optional[float], str, Optional[str]] - 2.3.4 Add docstrings to all public functions
Acceptance Criteria:
- ✅
mypy app/scraper.pypasses with no errors - ✅ All functions have docstrings
Files: app/models.py, any file using datetime.utcnow()
- 2.4.1 Add import:
from datetime import datetime, timezone - 2.4.2 Replace all
datetime.utcnowwithlambda: datetime.now(timezone.utc) - 2.4.3 Update any code comparing datetimes to use timezone-aware comparisons
Acceptance Criteria:
- ✅ No deprecation warnings for datetime usage
- ✅ All timestamps are timezone-aware UTC
File: app/services/base.py (new)
- 2.5.1 Create
BaseServiceabstract class with:__init__(self, db: Session)_commit()helper with error handling_rollback()helper- Common logging setup
- 2.5.2 Update
TrackerServiceto inherit fromBaseService - 2.5.3 Update
ProfileServiceto inherit fromBaseService - 2.5.4 Update
SchedulerServiceto inherit fromBaseService
Acceptance Criteria:
- ✅ Common database operations handled by base class
- ✅ Reduced boilerplate in service classes
File: app/scraper.py
- 2.6.1 Remove direct
os.getenv()calls fromscraper.py - 2.6.2 Use
settings.use_js_fallbackinstead ofUSE_JSconstant - 2.6.3 Use
settings.request_timeoutinstead of hardcoded30 - 2.6.4 Remove module-level constants that duplicate config
Acceptance Criteria:
- ✅ All configuration accessed via
settingsobject - ✅ No
os.getenv()calls outsideconfig.py
Files: app/exceptions.py, all service files
- 2.7.1 Add
codefield to all exception classes for machine-readable errors - 2.7.2 Add
detailsfield for additional context - 2.7.3 Create exception handler in
main.pyfor consistent JSON error responses - 2.7.4 Update all
raisestatements to include meaningful messages
Acceptance Criteria:
- ✅ All API errors return structured JSON:
{"error": "...", "code": "...", "details": {...}} - ✅ Error messages are user-friendly
File: tests/test_price_regex.py
- 2.8.1 Delete
tests/test_price_regex.py(duplicate oftest_price_parsing.py) - 2.8.2 Ensure
tests/test_price_parsing.pyhas comprehensive regex tests - 2.8.3 Add edge case tests to
test_price_parsing.py:- Currency symbols (€, £, ¥)
- Negative prices (error case)
- Prices with spaces
Acceptance Criteria:
- ✅ No duplicate test files
- ✅ Price parsing has comprehensive test coverage
Priority: HIGH
Objective: Achieve 75%+ test coverage with meaningful tests
File: tests/test_scraper.py (new)
- 3.1.1 Create test file with fixtures for HTML samples
- 3.1.2 Test
parse_price_from_jsonld()with valid/invalid JSON-LD - 3.1.3 Test
parse_price_from_meta()with various meta tag formats - 3.1.4 Test
smart_find_price()with complex HTML - 3.1.5 Test
extract_title()with various title formats - 3.1.6 Test
_candidate_score()scoring logic - 3.1.7 Mock
requests.get()to avoid network calls in tests
Acceptance Criteria:
- ✅ Scraper module has 90%+ test coverage
- ✅ All tests pass without network access
File: tests/test_notifications.py (new)
- 3.2.1 Create test file with SMTP/Twilio mocks
- 3.2.2 Test
send_email()with valid configuration - 3.2.3 Test
send_email()with missing SMTP config (skip behavior) - 3.2.4 Test
send_sms()with valid configuration - 3.2.5 Test
send_sms()with missing Twilio config (skip behavior) - 3.2.6 Test credential decryption in notification flow
Acceptance Criteria:
- ✅ Notification sending is fully tested with mocks
- ✅ No actual emails/SMS sent during tests
File: tests/test_integration.py (new)
- 3.3.1 Test full tracker creation flow (form → database → response)
- 3.3.2 Test price refresh flow with mocked scraper
- 3.3.3 Test profile creation with encrypted storage
- 3.3.4 Test scheduler polling with mocked scraper
- 3.3.5 Test rate limiting behavior (exceed limit → 429)
Acceptance Criteria:
- ✅ End-to-end flows tested
- ✅ All tests use test database (not production)
File: tests/test_security.py (update existing)
- 3.4.1 Add CSRF protection tests
- 3.4.2 Add SSRF protection tests (private IP blocking)
- 3.4.3 Add rate limiter cleanup tests
- 3.4.4 Add input length validation tests
- 3.4.5 Add XSS sanitization tests with malicious payloads
Acceptance Criteria:
- ✅ Security features have explicit test coverage
- ✅ Attack vectors are tested and blocked
File: tests/test_monitoring.py (new)
- 3.5.1 Test
HealthChecker.check_database()success/failure - 3.5.2 Test
HealthChecker.check_system_resources() - 3.5.3 Test
HealthChecker.comprehensive_health_check()overall status - 3.5.4 Test health endpoints return correct structure
Acceptance Criteria:
- ✅ Monitoring functionality fully tested
- ✅ Health check failures handled gracefully
Files: pyproject.toml or setup.cfg, .coveragerc
- 3.6.1 Create
.coveragercwith coverage settings:[run] source = app omit = app/__init__.py, */tests/* [report] fail_under = 75 show_missing = true
- 3.6.2 Add coverage badge generation
- 3.6.3 Document coverage requirements in README
Acceptance Criteria:
- ✅
pytest --cov=app --cov-fail-under=75passes - ✅ Coverage report generated
File: tests/conftest.py (update)
- 3.7.1 Add fixture for authenticated session (future use)
- 3.7.2 Add fixture for tracker with price history
- 3.7.3 Add fixture for profile with encrypted credentials
- 3.7.4 Add fixture for mock scraper responses
- 3.7.5 Add fixture for mock SMTP server
Acceptance Criteria:
- ✅ Common test scenarios easily reusable
- ✅ Tests are DRY and readable
Priority: MEDIUM
Objective: Production-ready deployment configuration
File: .gitignore (new)
- 4.1.1 Create comprehensive
.gitignore:# Python __pycache__/ *.py[cod] *$py.class *.so .Python build/ dist/ eggs/ *.egg-info/ .venv/ venv/ ENV/ # Environment .env .env.local .env.*.local # Secrets encryption.key *.pem *.key # Database *.db *.sqlite3 # Logs *.log logs/ # IDE .idea/ .vscode/ *.swp *.swo # Testing .coverage htmlcov/ .pytest_cache/ .tox/ # OS .DS_Store Thumbs.db
Acceptance Criteria:
- ✅ Sensitive files not tracked
- ✅ Clean repository state
File: .env.example (new)
- 4.2.1 Create template with all environment variables:
# Application SECRET_KEY=generate-a-64-character-random-string-here ENCRYPTION_KEY=generate-a-fernet-key-here ENVIRONMENT=development DEBUG=false # Database DATABASE_URL=sqlite:///pricewatch.db # Rate Limiting RATE_LIMIT_PER_MINUTE=60 RATE_LIMIT_BURST=10 # Scraping REQUEST_TIMEOUT=30 MAX_RETRIES=3 USE_JS_FALLBACK=false SCHEDULE_MINUTES=30 # Logging LOG_LEVEL=INFO LOG_FORMAT=json # SMTP (Optional) SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASS= FROM_EMAIL= # Twilio (Optional) TWILIO_ACCOUNT_SID= TWILIO_AUTH_TOKEN= TWILIO_FROM_NUMBER=
- 4.2.2 Add comments explaining each variable
- 4.2.3 Add instructions for generating secrets
Acceptance Criteria:
- ✅ New developers can copy and configure easily
- ✅ All variables documented
File: Dockerfile
- 4.3.1 Implement multi-stage build:
# Build stage FROM python:3.12-slim as builder ... # Production stage FROM python:3.12-slim as production ...
- 4.3.2 Create non-root user
appuser - 4.3.3 Add health check:
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8000/health || exit 1
- 4.3.4 Optimize layer caching
- 4.3.5 Add labels for image metadata
Acceptance Criteria:
- ✅ Image size reduced by 50%+
- ✅ Container runs as non-root
- ✅ Health check works
File: .dockerignore (new)
- 4.4.1 Create
.dockerignore:.git .gitignore .env .env.* *.md !README.md tests/ __pycache__/ *.pyc *.pyo .venv/ venv/ .coverage htmlcov/ *.db *.log .idea/ .vscode/
Acceptance Criteria:
- ✅ Unnecessary files excluded from Docker context
- ✅ Build time reduced
File: docker-compose.yml
- 4.5.1 Add health check configuration
- 4.5.2 Add resource limits
- 4.5.3 Add logging configuration
- 4.5.4 Add volume for persistent database
- 4.5.5 Add restart policy
- 4.5.6 Create
docker-compose.prod.ymlfor production overrides
Acceptance Criteria:
- ✅ Production-ready compose configuration
- ✅ Data persists across restarts
File: .github/workflows/ci.yml (new)
- 4.6.1 Create workflow file with:
name: CI on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 - run: pip install -r requirements.txt - run: pytest --cov=app --cov-fail-under=80 lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 - run: pip install ruff mypy - run: ruff check app/ - run: mypy app/ security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pip install bandit safety - run: bandit -r app/ - run: safety check
- 4.6.2 Add status badge to README
Acceptance Criteria:
- ✅ CI runs on every push/PR
- ✅ Tests, linting, security checks automated
File: .pre-commit-config.yaml (new)
- 4.7.1 Create pre-commit config:
repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.1.6 hooks: - id: ruff args: [--fix] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-added-large-files - id: detect-private-key - repo: https://github.com/pre-commit/mirrors-mypy rev: v1.7.1 hooks: - id: mypy additional_dependencies: [pydantic, sqlalchemy]
- 4.7.2 Add install instructions to README
- 4.7.3 Run pre-commit on all files to fix existing issues
Acceptance Criteria:
- ✅ Pre-commit hooks catch issues before commit
- ✅ All existing code passes pre-commit
File: pyproject.toml (new)
- 4.8.1 Create modern Python project configuration:
[project] name = "pricewatch" version = "2.1.0" description = "Enterprise price tracking application" requires-python = ">=3.10" [tool.ruff] line-length = 100 target-version = "py310" select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"] [tool.mypy] python_version = "3.10" strict = true [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto"
- 4.8.2 Configure all tools via pyproject.toml
- 4.8.3 Remove any redundant config files
Acceptance Criteria:
- ✅ Single source of project configuration
- ✅ Modern Python packaging standards
Priority: MEDIUM
Objective: Complete documentation for open source readiness
File: CONTRIBUTING.md (new)
- 5.1.1 Write contribution guidelines including:
- How to set up development environment
- Code style guidelines
- How to run tests
- How to submit pull requests
- Commit message format
- 5.1.2 Add issue/PR templates reference
Acceptance Criteria:
- ✅ New contributors can onboard easily
- ✅ Clear expectations set
File: CODE_OF_CONDUCT.md (new)
- 5.2.1 Adopt Contributor Covenant v2.1
- 5.2.2 Add enforcement contact information
Acceptance Criteria:
- ✅ Community standards documented
- ✅ Enforcement process clear
File: SECURITY.md (new)
- 5.3.1 Write security policy including:
- Supported versions
- How to report vulnerabilities
- Expected response time
- Disclosure policy
- 5.3.2 Add security contact email
Acceptance Criteria:
- ✅ Security researchers know how to report issues
- ✅ Responsible disclosure process documented
Files: .github/ISSUE_TEMPLATE/*.yml (new)
- 5.4.1 Create bug report template
- 5.4.2 Create feature request template
- 5.4.3 Create question template
- 5.4.4 Create config.yml to configure template chooser
Acceptance Criteria:
- ✅ Issues have consistent structure
- ✅ Required information collected
File: .github/PULL_REQUEST_TEMPLATE.md (new)
- 5.5.1 Create PR template with:
- Description section
- Type of change checkboxes
- Testing checklist
- Documentation checklist
Acceptance Criteria:
- ✅ PRs have consistent structure
- ✅ Review process streamlined
File: README.md
- 5.6.1 Add badges (CI status, coverage, license, Python version)
- 5.6.2 Add table of contents
- 5.6.3 Add architecture diagram (ASCII or link to image)
- 5.6.4 Update version references to 2.1.0
- 5.6.5 Add "Built With" section listing technologies
- 5.6.6 Add acknowledgments section
Acceptance Criteria:
- ✅ README is visually appealing
- ✅ All information current
Priority: LOW
Objective: Modern async patterns and performance improvements
File: app/scraper.py, requirements.txt
- 6.1.1 Add
httpxto requirements.txt - 6.1.2 Create async version of
fetch_html():async def fetch_html_async(url: str) -> str: async with httpx.AsyncClient() as client: response = await client.get(url, headers=HEADERS, timeout=30) response.raise_for_status() return response.text
- 6.1.3 Keep sync version for background scheduler compatibility
- 6.1.4 Add configuration flag to choose sync/async mode
Acceptance Criteria:
- ✅ API endpoints don't block event loop
- ✅ Background jobs still work synchronously
File: app/database.py, app/config.py
- 6.2.1 Add pool configuration to Settings:
db_pool_size: int = 5 db_max_overflow: int = 10 db_pool_timeout: int = 30
- 6.2.2 Configure SQLAlchemy engine with pool settings for PostgreSQL
- 6.2.3 Keep StaticPool for SQLite development
Acceptance Criteria:
- ✅ Database connections properly pooled
- ✅ Configuration documented
File: app/main.py
- 6.3.1 Add
Cache-Controlheaders to static responses - 6.3.2 Add
ETagsupport for tracker detail pages - 6.3.3 Add
no-cachefor sensitive endpoints (admin, health)
Acceptance Criteria:
- ✅ Static assets cacheable
- ✅ Dynamic content not cached inappropriately
Files: app/services/*.py, app/monitoring.py
- 6.4.1 Add
joinedloadfor tracker→profile relationship - 6.4.2 Add pagination to
get_all_trackers()method - 6.4.3 Add query timeout configuration
- 6.4.4 Add query count logging in debug mode
Acceptance Criteria:
- ✅ N+1 queries eliminated
- ✅ Large datasets handled efficiently
Files: app/monitoring.py, app/main.py
- 6.5.1 Add prometheus_client metrics:
pricewatch_requests_total(counter)pricewatch_request_duration_seconds(histogram)pricewatch_trackers_total(gauge)pricewatch_scrape_errors_total(counter)
- 6.5.2 Add
/metricsendpoint returning Prometheus format - 6.5.3 Add middleware for request metrics collection
Acceptance Criteria:
- ✅ Prometheus can scrape metrics
- ✅ Key application metrics exposed
Priority: CRITICAL
Objective: Ensure all improvements work together
Command: pytest tests/ -v --cov=app --cov-report=html
- 7.1.1 Run complete test suite
- 7.1.2 Verify 75%+ coverage achieved
- 7.1.3 Fix any failing tests
- 7.1.4 Review coverage report for gaps
Acceptance Criteria:
- ✅ All tests pass (240 passed)
- ✅ Coverage ≥ 75% (80.67% achieved)
Commands: Various security tools
- 7.2.1 Run
bandit -r app/- fix all high/medium issues - 7.2.2 Run
safety check- update vulnerable dependencies - 7.2.3 Run
pip-audit- check for known vulnerabilities - 7.2.4 Manual review of authentication/authorization flows
- 7.2.5 Test CSRF protection manually
- 7.2.6 Test rate limiting manually
Acceptance Criteria:
- ✅ Zero high/medium security issues (acceptable uses marked with nosec)
- ✅ All dependencies up-to-date (cryptography updated, pip vulnerability noted)
Files: Various
- 7.3.1 Update version to
2.1.0in:app/__init__.pypyproject.tomlapp/main.py(FastAPI app version)app/monitoring.py(health check version)
- 7.3.2 Update
CHANGELOG.mdwith all changes - 7.3.3 Create git tag
v2.1.0 - 7.3.4 Final README review
Acceptance Criteria:
- ✅ Version consistent everywhere (2.1.0)
- ✅ Changelog complete with all Phase 1-6 improvements
- ✅ Git tag v2.1.0 created
- ✅ Ready for release
- Sequential Execution: Complete tasks in order within each phase
- No Skipping: Every checkbox must be addressed
- Atomic Commits: Commit after each major task (e.g., 1.1, 1.2, etc.)
- Testing: Run
pytestafter each phase to ensure no regressions - Documentation: Update docs as code changes
- Mark Progress: Update checkboxes in this file as tasks complete
- Blockers: If blocked, document reason and continue to next task within same phase
- ✅ Task 7.1: Full Test Suite Execution (4/4 subtasks complete)
- ✅ Task 7.2: Security Audit (6/6 subtasks complete)
- ✅ Task 7.3: Update Version and Release (4/4 subtasks complete)
- ✅ Task 6.1: Add Async HTTP Client (4/4 subtasks complete)
- ✅ Task 6.2: Add Database Connection Pooling Config (3/3 subtasks complete)
- ✅ Task 6.3: Add Response Caching Headers (3/3 subtasks complete)
- ✅ Task 6.4: Optimize Database Queries (4/4 subtasks complete)
- ✅ Task 6.5: Add Prometheus Metrics (3/3 subtasks complete)
- ✅ Task 5.1: Create CONTRIBUTING.md (2/2 subtasks complete)
- ✅ Task 5.2: Create CODE_OF_CONDUCT.md (2/2 subtasks complete)
- ✅ Task 5.3: Create SECURITY.md (2/2 subtasks complete)
- ✅ Task 5.4: Create GitHub Issue Templates (4/4 subtasks complete)
- ✅ Task 5.5: Create Pull Request Template (1/1 subtasks complete)
- ✅ Task 5.6: Update README.md (6/6 subtasks complete)
- ✅ Task 4.1: Create .gitignore (1/1 subtasks complete)
- ✅ Task 4.2: Create .env.example (3/3 subtasks complete)
- ✅ Task 4.3: Improve Dockerfile (5/5 subtasks complete)
- ✅ Task 4.4: Create .dockerignore (1/1 subtasks complete)
- ✅ Task 4.5: Improve docker-compose.yml (6/6 subtasks complete)
- ✅ Task 4.6: Add GitHub Actions CI (2/2 subtasks complete)
- ✅ Task 4.7: Add Pre-commit Configuration (3/3 subtasks complete)
- ✅ Task 4.8: Add pyproject.toml (3/3 subtasks complete)
- ✅ Task 3.1: Add Scraper Unit Tests (7/7 subtasks complete)
- ✅ Task 3.2: Add Notification Tests (6/6 subtasks complete)
- ✅ Task 3.3: Add Integration Tests (5/5 subtasks complete)
- ✅ Task 3.4: Add Security Tests (5/5 subtasks complete)
- ✅ Task 3.5: Add Monitoring Tests (4/4 subtasks complete)
- ✅ Task 3.6: Add Test Coverage Configuration (3/3 subtasks complete)
- ✅ Task 3.7: Add Test Fixtures for Common Scenarios (5/5 subtasks complete)
- ✅ Task 2.1: Extract Notification Service (6/6 subtasks complete)
- ✅ Task 2.2: Improve Module Exports (4/4 subtasks complete)
- ✅ Task 2.3: Add Type Hints to Scraper (4/4 subtasks complete)
- ✅ Task 2.4: Fix Deprecated datetime.utcnow() (3/3 subtasks complete)
- ✅ Task 2.5: Create Base Service Class (4/4 subtasks complete)
- ✅ Task 2.6: Consolidate Configuration Access (4/4 subtasks complete)
- ✅ Task 2.7: Improve Error Messages (4/4 subtasks complete)
- ✅ Task 2.8: Remove Duplicate Test File (3/3 subtasks complete)
- ✅ Task 1.1: Fix Encryption Key Storage (5/5 subtasks complete)
- ✅ Task 1.2: Remove Duplicate SecurityError Class (3/3 subtasks complete)
- ✅ Task 1.3: Add CSRF Protection (6/6 subtasks complete)
- ✅ Task 1.4: Add Security Headers Middleware (4/4 subtasks complete)
- ✅ Task 1.5: Fix Rate Limiter Memory Leak (5/5 subtasks complete)
- ✅ Task 1.6: Expand SSRF Protection (4/4 subtasks complete)
- ✅ Task 1.7: Secure Default Configuration (5/5 subtasks complete)
- ✅ Task 1.8: Add Password/Secret Masking in Logs (4/4 subtasks complete)
- ✅ Task 1.9: Add Request ID Tracking (4/4 subtasks complete)
- ✅ Task 1.10: Add Input Length Limits (3/3 subtasks complete)
This document is the authoritative guide for the Pricewatch v2.1 improvement project.