Skip to content

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 phyware repo 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:

docker compose up -d phycomp

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:

- image: ghcr.io/phyware/phycomp-python:<old-tag>
+ image: ghcr.io/phyware/phycomp-rust:<new-tag>

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:

environment:
  PHYCOMP_AUTO_MIGRATE: "true"

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-python deployments 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