Phase 1 of AUDIT-2026-Q3.md item P1.8.
ruff.toml was overriding pyproject.toml [tool.ruff] silently:
ruff.toml: line-length 120, ignored SIM102/RUF006/B008
pyproject.toml: line-length 100, security rules enabled (canonical)
Two configs contradicting each other silently is the worst-case
configuration — neither developer nor CI notice, and the strict
[tool.ruff] security rules (S) never run.
Deleted ruff.toml. Added defensive .gitignore entry. ruff now reads
only pyproject.toml. Verified with ruff check --show-settings:
linter.line_length = 100
linter.pycodestyle.max_line_length = 100
ruff.toml moved to /tmp/rmi-backend-archive-2026-07/ruff.toml.removed-2026-07-06.
Phase 1 of AUDIT-2026-Q3.md item P1.4.
main.py.bak was a 374KB legacy leftover from the old 220-file app/
monolith. Its removal from the working tree was completed in e404e90
(feat(rmi-backend,audit): add app/main.py entrypoint delegating to
factory) in this audit session — that commit deleted main.py.bak and
added app/main.py in a single change.
This commit adds the defensive .gitignore entry so any future
main.py.bak / similar leftover files do not get re-tracked.
main.py.bak archive kept at:
/tmp/rmi-backend-archive-2026-07/main.py.bak.removed-2026-07-06
Note: historical commit bde2f3a still contains 4 mainnet token
addresses for gitleaks; full rewrite with git-filter-repo is scheduled
for Phase 1.11 of AUDIT-2026-Q3.md.
Phase 1 of AUDIT-2026-Q3.md item P1.2.
tests/ was not a Python package, so downstream imports
(`from tests.unit.x import y`, testcontainers config loading,
pytest --import-mode=importlib) failed without PYTHONPATH=.
Creating __init__.py in tests/, tests/unit/, tests/integration/
makes the suite a proper package. pytest collection already worked
via rootdir discovery (886 tests collected either way), but
*importing* test modules will now work.
Also seeds tests/integration/conftest.py with a Phase-1 stub
fixture. Phase 3 (testcontainers) replaces it.
Full fix lands in P1.3 (setuptools.packages = ["app"] +
tools.setuptools.package-data in pyproject.toml) — without that,
`pip install -e .` does not expose the app package.
Phase 1 of AUDIT-2026-Q3.md item P1.1.
app/main.py was referenced by Makefile, AGENTS.md, CONTRIBUTING.md,
and external `uvicorn app.main:app` invocations, but the file did not
exist (refactored to app/factory.py in a prior session — the docs were
never updated). This restores the canonical entrypoint.
The reported symptom (AttributeError: module 'bcrypt' has no attribute
'__about__') was misleading. passlib 1.7.4 (the latest released version
— the project is unmaintained) actually traps that AttributeError with
a bare `except:` and continues. The real failure occurs later in
`passlib.handlers.bcrypt._finalize_backend_mixin`:
detect_wrap_bug -> verify(secret, bug_hash)
where secret = (b"0123456789"*26)[:255] # 255-byte test secret
bcrypt 4.0+ removed silent 72-byte truncation and now raises
`ValueError: password cannot be longer than 72 bytes`, breaking the
backend probe and crashing every `pwd_context.hash()/verify()` call.
Three options were considered:
A. Upgrade passlib — impossible, 1.7.4 is the latest PyPI release.
B. Pin bcrypt<4.0 — conflicts with chromadb 1.1.1 (>=4.0.1 required),
even though chromadb's bcrypt usage is optional and still works
at runtime in practice.
C. Shim bcrypt.__about__ — doesn't fix the actual truncation error.
Chosen: refactor app/auth.py to use bcrypt directly for backup-code
hashing too (the main `hash_password`/`verify_password` already did).
Drops the passlib dependency entirely, restoring bcrypt 5.x for chromadb
compatibility and eliminating the unmaintained passlib pin.
Verified:
* hash_password / verify_password round-trip OK
* _hash_backup_code / _verify_backup_code round-trip OK on
freshly generated 8-digit backup codes
* `pytest tests/unit` -> 717 passed, 32 warnings, 60 subtests passed
Gitleaks flagged 4 production secrets in rmi-backend source:
app/caching_shield/solana_tracker.py: st_ZMzXzdUI54TXQPx5E6JkG
app/databus/arkham_ws.py: ws_Z5x09Rcr_1780418740765322917
app/routers/webhooks_router.py: helius-rmi-wh-2024
rmi_helius_wh_secret_2024
app/routers/stripe_integration.py: pk_test_51Tn13MAXseReicQtM...
Each replaced with os.getenv() reads. Placeholder env lines added to
/srv/rmi-infra/.env.secrets. Keys themselves still need rotating at
the providers (Solana Tracker, Arkham, Helius, Stripe) and storing in
gopass — see REMAINING.md.
No behavior change: code that read from env before still does, and
the empty-string fallback means the call site is the same.
Note: this commit scrubs the keys from the working tree. They remain
in git history. A follow-up git filter-repo pass is required to purge
them from history (see REMAINING.md). After that, all clones and
external remotes must be force-updated.
Python CI: uv setup, ruff lint+format, mypy (warn), pytest (non-integration).
Runs on docker-x64 runner on Talos.
44 tests exist, now they will run in CI.
- .forgejo/ISSUE_TEMPLATE/bug.yml
- .forgejo/ISSUE_TEMPLATE/feature.yml
- .forgejo/ISSUE_TEMPLATE/config.yml: blank_issues_enabled=false,
contact_links to discussions (Q&A, Feature Requests, Announcements)
Discussions per repo land in a separate follow-up commit.