This repository documents and delivers the full migration of Tiny Tiny RSS from its original PHP codebase to a modern Python stack.
Source: source-repos/ttrss-php/ — original PHP application
Target: target-repos/ttrss-python/ — migrated Python application
Status: All 6 modernization phases complete. Ready for production release.
OSS_Migration/
├── source-repos/ttrss-php/ Original PHP source (read-only reference)
├── target-repos/ttrss-python/ Migrated Python application
├── specs/
│ ├── architecture/ 14 reference specs — stable, read-only
│ └── 001–006/ Phase specs (spec + plan + tasks per phase)
├── docs/
│ ├── decisions/ Architecture Decision Records (ADR-0001–0019)
│ └── reports/ Coverage and audit reports
├── tools/graph_analysis/ PHP call-graph builder + coverage validator
├── scripts/ Data conversion utilities
├── constitution.md Project principles and hard rules
└── AGENTS.md Agent/AI collaboration rules and conventions
| Phase | Spec | Deliverable | Status |
|---|---|---|---|
| 1 — Foundation | 001-foundation | Models, auth, DB, Alembic, app factory | DONE |
| 2 — Core logic | 002-core-logic | Feed parsing, counter cache, filters, labels, sanitise | DONE |
| 3 — Business logic | 003-business-logic | Prefs CRUD, digests, OPML, backend blueprint | DONE |
| 4 — API handlers | 004-api-handlers | 17 API operations, 2-guard auth, getFeedTree BFS | DONE |
| 5 — Semantic verification | 005-semantic-verification | 14 hooks wired, 40-category taxonomy, 105+ fixes, 0 gaps | DONE |
| 6 — Deployment | 006-deployment | CI, Docker, nginx, pgloader, ≥95% coverage gate, deploy.yml | DONE |
Stable, read-only specifications used across all phases:
| Spec | Topic |
|---|---|
| 00-project-charter | Goals, constraints, success criteria |
| 01-architecture | System architecture and component map |
| 02-database | Schema, ORM strategy, migration approach |
| 03-api-routing | TT-RSS API protocol and routing |
| 04-frontend | Frontend strategy (resolved by ADR-0017) |
| 05-plugin-system | pluggy hook specs |
| 06-security | Auth, CSRF, session, encryption |
| 07-caching-performance | Redis caching, counter cache |
| 08-deployment | Docker, gunicorn, nginx, CI/CD |
| 09-source-index | PHP source file inventory |
| 10-migration-dimensions | What changes, what stays the same |
| 11-business-rules | Preserved business rules catalogue |
| 12-testing-strategy | Test pyramid and coverage gates |
| 13-decomposition-map | PHP→Python module mapping |
| 14-semantic-discrepancies | Known behavioural differences |
| 15-sme-review | SME demo review — functional inventory and gap list |
| ADR | Decision | Status |
|---|---|---|
| 0001 | Migration flow: variant D-revised (schema-first) | accepted |
| 0002 | Python framework: Flask | accepted |
| 0003 | Database: PostgreSQL (MySQL dropped) | accepted |
| 0004 | Frontend strategy → resolved by ADR-0017 | accepted |
| 0005 | PHP call-graph analysis tooling | accepted |
| 0006 | ORM: SQLAlchemy 2 | accepted |
| 0007 | Session management: Flask-Login + Redis | accepted |
| 0008 | Password migration: argon2id (bcrypt/MD5 upgrade path) | accepted |
| 0009 | Feed credential encryption: Fernet (replaces mcrypt) | accepted |
| 0010 | Plugin system: pluggy | accepted |
| 0011 | Background worker: Celery (replaces pcntl_fork daemon) | accepted |
| 0012 | Logging: structlog | proposed |
| 0013 | i18n / localisation | proposed |
| 0014 | Feed parsing: feedparser | accepted |
| 0015 | HTTP client: httpx | accepted |
| 0016 | Semantic verification methodology | accepted |
| 0017 | Frontend: Vanilla JS SPA (replaces Dojo toolkit) | accepted |
| 0018 | Drag-drop category assignment deferred; dropdown used | accepted |
| 0019 | Simplified tabbed preferences modal | accepted |
The tools/graph_analysis/ toolchain builds a PHP call graph and verifies that every in-scope PHP function's behaviour is covered by the Python codebase — this is not a 1-to-1 function translation check. A single PHP function may be split across multiple Python modules, merged with related logic, replaced by a library call, or restructured entirely; what matters is that no behaviour is dropped. The validator tracks semantic coverage, not syntactic correspondence.
# Build call graphs from PHP source (run once, or after PHP source changes)
python tools/graph_analysis/build_php_graphs.py
# Validate — must report 0 gaps
python tools/graph_analysis/validate_coverage.py \
--graph-dir tools/graph_analysis/output \
--python-dir target-repos/ttrss-python/ttrss \
--min-coverage 0.95Result as of Phase 6: 0 gaps, ≥95% coverage.
| Metric | Value |
|---|---|
| Unit + integration tests | 598 passing |
| E2E browser tests (Playwright) | 67 / 68 passing |
| Coverage gaps | 0 |
| Plugin hooks wired | 14 / 14 |
| Semantic discrepancies fixed | 105+ |
| CI coverage gate | ≥ 95% (strict — no continue-on-error) |
Tag v1.0.0 to trigger the deploy pipeline:
git tag v1.0.0 && git push origin v1.0.0The .github/workflows/deploy.yml workflow runs: pgloader migration, PHP-serialized conversion, and health-check verification.
constitution.md— project principles (P1 library-first, P2 test-first, P3 source traceability)AGENTS.md— AI agent collaboration rules and spec-kit conventions