Operator Migration Guide — Python → Rust PhyComp¶
This guide describes the cutover from the historical Python PhyComp MVP to the canonical Rust PhyComp service (PhyComp/rust/). The cutover was completed in PhyWare issue #235, the final step of the Python → Rust migration epic #219. The legacy Python source tree has now been removed from the repository.
If you are still running the Python service, the steps below describe a drain → switch → verify rollout to the Rust binary.
Compatibility at a glance¶
| Surface | Compatibility |
|---|---|
| Public HTTP API (paths, headers, response shapes) | Byte-compatible — clients (phyware CLI, admin dashboard, custom callers, the PhyTrace orchestrator) need no changes |
phycomp_… API key format | Identical |
PhyCloud federation (/api/v1/registration/register, POST /oauth/introspect) | Identical — the Rust service reuses PhyCloud's introspection endpoint exactly as the Python service did |
| Rule / violation / report payloads | Identical — DTOs are shared with PhyCloud Rust (issue #225) |
PHYCOMP_* environment variables | Mostly identical (see variable mapping below) |
| Database schema | Compatible — Rust ships sqlx migrate files equivalent to the historical Alembic head; you can either point the Rust service at the existing database or rebuild from scratch |
| Database URL scheme | postgres://… / sqlite:… (no +asyncpg / +aiosqlite driver suffix) for the Rust service |
| Migration tool | sqlx migrate (auto-run at startup when PHYCOMP_AUTO_MIGRATE=true) replaces alembic upgrade head |
Cutover plan¶
1. Pre-flight¶
- Snapshot your PhyComp database (PostgreSQL:
pg_dump). - Note any custom values for
PHYCOMP_*environment variables in your deployment so they can be replayed against the Rust service. - Pin the Rust container image tag (or the
phywarerepo commit SHA) you intend to roll forward to.
2. Verify against the Rust service in staging¶
The repo-root docker-compose.yml builds the canonical phycomp service from the Rust Dockerfile:
Verify your existing phyware CLI scripts, dashboard, and any custom integrations can read rules, evaluate, and fetch violations / reports against the Rust service unchanged. The repo-level integration suites already drive the Rust service end-to-end — see tests/integration/test_phycomp_rust_phycloud_rust_smoke.py.
3. Switch production traffic¶
For a Kubernetes / Compose deployment the change is a one-line image swap — the Rust service listens on the same port (8001) and serves the same API surface:
For bespoke deployments built from source: change the dockerfile: field in your Compose / Helm chart to ./PhyComp/rust/Dockerfile (built from the repo root) and rebuild.
4. Run database migrations¶
The Rust service can run sqlx::migrate!() at startup:
This replaces the standalone phycomp-migrate (Alembic) job that the historical Python service required. If you prefer to apply migrations out-of-band, run sqlx migrate run --source PhyComp/rust/migrations against your database URL before starting the service.
The schema is forward-compatible with the historical Alembic head — no data re-keying is required.
5. Verify¶
After cutover, exercise the standard smoke checks against the new service:
# Health
curl -sf http://phycomp.example.com/health
# Bootstrap status (should report `bootstrapped: true` after first call)
curl -sf http://phycomp.example.com/api/v1/admin/bootstrap/status
# Rules + evaluate round-trip via the phyware CLI
phyware comp register --endpoint https://phycomp.example.com
phyware comp rules list
phyware comp evaluate --window 5m
phyware comp violations list --limit 10
6. Decommission the Python service¶
Once you are satisfied the Rust service is stable:
- Remove any explicit
phycomp-pythondeployments from your Compose / Helm manifests. - Stop building from the historical Python Dockerfile in your downstream pipelines.
Environment variable mapping¶
Most PHYCOMP_* variables are accepted unchanged. Exceptions worth calling out:
| Variable | Python (historical) | Rust (canonical) | Notes |
|---|---|---|---|
PHYCOMP_DATABASE_URL | postgresql+asyncpg://… or sqlite+aiosqlite://… | postgres://… or sqlite:… | Drop the +asyncpg / +aiosqlite driver suffix; sqlx uses the bare scheme. |
PHYCOMP_AUTO_MIGRATE | n/a | true / false | New flag; tells the Rust binary to run sqlx::migrate!() at startup. |
PHYCOMP_CORS_ORIGINS | JSON list (e.g. '["http://…"]') | currently a no-op | The Rust service does not yet honour this variable; CORS is open in dev mode (PHYWARE_DEV_MODE=1) and disabled in production. Track future work in the migration epic. |
PHYCOMP_LOG_JSON | derived from structlog config | true / false | Default true; emits structured JSON identical in shape to the historical structlog output. |
PHYCOMP_BOOTSTRAP_TOKEN / PHYCOMP_REGISTRATION_TOKEN | required in prod | required in prod | Unchanged. |
PHYCOMP_RATE_LIMIT_* | required for slowapi | required for tower-governor | Unchanged grammar (<count>/<period>). |
PHYCOMP_PHYCLOUD_URL / PHYCOMP_PHYCLOUD_API_KEY | required | required | Unchanged. |
A full list of supported variables is documented in PhyComp/rust/phycomp-core/src/settings.rs and the crate README.md.
Getting help¶
- File issues against the PhyWare repository.
- The canonical service README lives at
PhyComp/rust/README.md. - The cutover tracking issue is #235.