# 2FAuth Rust compatibility implementation — 0.3.0 Targets 2FAuth **8.0.3**, upstream commit `3516c776a1fcbd83d234efc007e3a49807d6ed91`. AGPL-3.0-only; upstream source and frontend provenance are retained. See [README.ru.md](README.ru.md) for deployment/configuration instructions in Russian. **This is not a certified complete PHP replacement.** Current evidence and remaining gaps are in [compatibility/CURRENT.md](compatibility/CURRENT.md). Never infer total coverage from test counts or from displaying the original Vue frontend. Implemented areas include OTP/URI/export, Laravel encryption and rotation, account/group CRUD, per-user orders/groups, sharing and ownership, registration/profile/password recovery, Passport RSA bearer/PAT and PHP browser cookie interoperability, migrated WebAuthn credentials, SSO/proxy authentication, imports/icons/QR, preferences/settings, SMTP notifications and authentication/OTP auditing. The original Vue build is served, including subdirectory mounting. ## Build and test A current stable Rust toolchain, C compiler, make and Perl are required. OpenSSL is vendored for WebAuthn; no external OpenSSL development package is required. ```sh cargo fmt --all -- --check cargo clippy --locked --all-targets -- -D warnings cargo test --locked --all-targets cargo build --locked --release python3 tests/http_smoke.py target/release/twofauth-rs python3 tests/differential_harness.py python3 tests/laravel_session_http.py target/release/twofauth-rs PHP_BINARY=/path/to/php python3 tests/oauth_interop.py target/release/twofauth-rs PHP_BINARY=/path/to/php python3 tests/device_interop.py target/release/twofauth-rs --output compatibility/device-interop.json python3 tests/crypto_interop.py --check-php ``` The PHP crypto check requires PHP/OpenSSL. Full reference runs additionally require PHP 8.4+, locked Composer dependencies and the PHP extensions required by the pinned upstream. ```sh python3 tools/run_reference.py --php /path/to/php \ --source ../upstream --candidate-binary target/release/twofauth-rs \ --candidate-db native --semantic-checks --passport-interop \ --extra-cases compatibility/cases.oauth.json --extra-cases compatibility/cases.device.json --output compatibility/reference-results.native.json python3 tools/run_reference.py --php /path/to/php \ --source ../upstream --candidate-binary target/release/twofauth-rs \ --candidate-db laravel-copy --semantic-checks --passport-interop \ --extra-cases compatibility/cases.oauth.json --extra-cases compatibility/cases.device.json --output compatibility/reference-results.laravel.json ``` Each run uses disposable databases, credentials, application state and isolated server ports. Semantic login/QR checks precede the extra OAuth error burst because the PHP unnamed OAuth throttle shares its bucket with password login. The Laravel-copy mode runs real PHP migrations, seeds a synthetic user, copies the database through SQLite backup, and invokes `prepare-sqlite`. Do not point differential tests at live services. `tools/passport_interop.py --help` documents the separate bidirectional Passport and PHP-browser-session upgrade test. It creates disposable fixture material rather than shipping deployment keys. ## Local development ```sh mkdir -p data cargo run -- init RUST_COOKIE_SECURE=false cargo run -- serve ``` Open `http://127.0.0.1:8080`; the first self-registered user becomes administrator. `init` refuses an existing users table. `prepare-sqlite` validates an already migrated Laravel SQLite schema and adds Rust-only session/ceremony metadata. `serve` also creates this metadata if absent after validation; it never runs application migrations or resets user tables. Preserve original `APP_KEY`, `APP_PREVIOUS_KEYS`, Passport key files and storage. `DATABASE_URL` overrides Laravel `DB_DATABASE`; only SQLite is implemented. `DB_CONNECTION` selecting another driver fails explicitly. All switching exercises must use a backup/copy until complete compatibility is established. The included Dockerfile/Compose were updated for static assets, vendored cryptography and writable storage. Docker itself was unavailable in the development environment, so image build/run is not claimed verified. ## Laravel sessions and OAuth additions File and SQLite database Laravel sessions can be imported using the original APP_KEY, SESSION_COOKIE, SESSION_DRIVER, SESSION_TABLE, SESSION_ENCRYPT and STORAGE_PATH. JSON and scalar/array PHP serialization are supported; PHP objects and references are rejected. Both store encryption and remember-me recallers are checked with real pinned PHP fixtures. Native session rotation destroys the imported store; logout rotates remember tokens. Redis, cookie and other session drivers remain outside this implementation. Standard `/oauth/token` supports authorization-code/PKCE, refresh rotation, client credentials and device authorization/polling using the actual Defuse PHP encrypted wire format and Passport RSA keys. The pinned application registers Passport JSON management routes too late and lacks an authorization view binding. Defaults preserve the observed disabled/broken management and consent behavior. `PASSPORT_JSON_API_ROUTES=true` and `RUST_OAUTH_CONSENT_ENABLED=true` explicitly enable repaired management and consent. These optional routes are extensions, not an assertion that the original defects were absent. SQLite startup now checks used application columns, primary/unique keys and foreign-key delete actions against the real migrated schema before adding Rust metadata. See compatibility/database-portability.md for the remaining engine-specific work.