CI went red where the Tests workflow stayed green, and the reason is that the
two install from different lockfiles which had drifted apart: poetry.lock
held nostr-sdk 0.43.0, requirements.lock had resolved to 0.45.0 under the
unbounded `>=0.43`. Two lockfiles disagreeing about a protocol SDK is not a
CI quirk — it means the code was being tested against one version and shipped
against another.
0.44 removed NostrSigner's constructors, including the NostrSigner.keys the
client calls, and changed Client's constructor. Verified against 0.45.0:
NostrSigner is left with only get_public_key, sign_event and the nip04/nip44
methods, and Client.__init__ takes no arguments. So this is a real migration
touching signing and client setup, not a rename to be done in passing.
Bounded at <0.44 in all three places the constraint is declared, and both
lockfiles regenerated: requirements.lock resolves 0.43.1, poetry.lock keeps
0.43.0, and the relock changed exactly one line — the content hash — with no
version churn anywhere else. Confirmed 0.43.1 still exposes NostrSigner.keys
and a Client that takes an argument, since that is what CI will actually
install. pip-audit reports no advisory against the 0.43 line, so the bound
costs nothing today.
The migration is recorded in TODO.md rather than attempted here: it wants the
sync round-trip re-validated against a real relay, not folded into a CI fix.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Vtx94nXDmNgXEeThUZP4QN
`dependency_scan.sh` had been failing CI on the port branch, and it was right
to: pip-audit reported 100 known vulnerabilities across 15 packages, including
`cryptography` itself — the library doing the vault's actual encryption.
Raised the floors to the fixed versions pip-audit named. `pip-audit` on the
regenerated lock now reports zero (one ignored exception remains, the
pre-existing GHSA-wj6h-64fc-37mp).
The one that needed judgement was starlette. It was pinned `<0.48` "must
remain compatible with FastAPI", which kept seven advisories permanently open.
That ceiling predated fastapi 0.141, which requires `starlette>=0.46` with no
upper bound — so the pin was protecting against a constraint that no longer
exists. Lifting it took starlette across a major version (0.47 -> 1.6), which
is why this was verified rather than assumed:
- 1223 Python tests pass, 171 of them API tests
- the API app builds all 64 routes and still answers 401 for a missing
token, a bad token, and 404 for an unknown path
- cross_impl_check: 41/41
- differential fuzz: no divergences
poetry.lock was regenerated too. It dated from March, and `poetry check --lock`
reported it inconsistent with pyproject.toml — CI runs `poetry install`, so
that alone would have kept the build red no matter what else was fixed.
None of this touches the TypeScript port, which has an empty production
dependency list. It matters because the Python implementation is still the
normative reference and still what a user runs today.
Also wires the differential fuzzer into ts-parity: three fixed seeds so a
regression is deterministic and bisectable, plus one seed derived from the run
id so the explored input space grows over time rather than freezing at
whatever was chosen today.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Vtx94nXDmNgXEeThUZP4QN
This change explicitly adds `pycryptodome` to `pyproject.toml` and `src/requirements.txt` to resolve a `ModuleNotFoundError` when generating PGP RSA keys. The `Crypto` namespace provided by `pycryptodome` is required by `src/seedpass/core/password_generation.py`.
Verified with `reproduce_issue.py` (which now passes) and `src/tests/test_pgp_entry.py`.
Co-authored-by: PR0M3TH3AN <[email protected]>