mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-05 12:22:06 +00:00
Fixtures show both implementations compute the same values. This adds the
missing half: proof they can read each other's on-disk profiles and
backups, using each side's real code paths.
scripts/cross_impl_check.py (12 checks, wired into CI):
A. Python creates a profile -> TS opens the index, derives every secret
identically, and unlocks it with the master password alone
B. TS creates a profile -> Python decrypts parent_seed.enc and the index,
recovers the same seed, derives the same secrets
C. Portable backups round-trip both directions (Python verifies the
checksum of a TS-written export)
D. Both implementations reject a bad-checksum mnemonic
Two real compatibility bugs it caught, both fixed:
- TS-created profiles were unopenable by Python. Python only honors the
recorded parent-seed KDF parameters when kdf.name is exactly "pbkdf2";
TS wrote "pbkdf2-sha256" with an empty salt and 100k iterations, so
Python fell back to its config defaults (200k, fingerprint salt) and
derived a different key. TS now writes exactly what
PasswordManager._build_seed_kdf_config does, and its own unlock path
honors the recorded salt and iteration count.
- TS accepted invalid BIP-39 mnemonics. Seed derivation takes any string,
so a typo'd phrase silently produced a *different* vault -- unopenable
by Python and unrecoverable by the user. Mnemonics are now validated
wherever they enter (profile creation and SEEDPASS_MNEMONIC), with an
error that says why it matters.
Also: docs/typescript_cutover_plan.md records the gate list for promoting
TS to main and retiring Python to legacy/reference -- P0 gates 1-4 are
green, 5-7 (feature parity tail, packaging, migration/rollback) are not.
The Python tree stays in CI after cutover as the compatibility oracle.
Regression tests for both bugs. 151 core + 46 CLI tests green,
12/12 cross-implementation checks green.
Co-Authored-By: Claude Fable 5 <[email protected]>
90 lines
2.7 KiB
YAML
90 lines
2.7 KiB
YAML
name: TypeScript Parity
|
|
|
|
on:
|
|
push:
|
|
branches: ["**"]
|
|
paths:
|
|
- "js/**"
|
|
- "src/**"
|
|
- "scripts/generate_ts_port_fixtures.py"
|
|
- "scripts/cross_impl_check.py"
|
|
- ".github/workflows/ts-parity.yml"
|
|
pull_request:
|
|
branches: ["**"]
|
|
paths:
|
|
- "js/**"
|
|
- "src/**"
|
|
- "scripts/generate_ts_port_fixtures.py"
|
|
- "scripts/cross_impl_check.py"
|
|
- ".github/workflows/ts-parity.yml"
|
|
|
|
jobs:
|
|
parity:
|
|
runs-on: ubuntu-latest
|
|
defaults:
|
|
run:
|
|
working-directory: js
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
- name: Enable pnpm via corepack
|
|
run: corepack enable
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
- name: Typecheck
|
|
run: pnpm -r typecheck
|
|
- name: Parity tests (Node + jsdom)
|
|
run: pnpm -r test
|
|
|
|
# Fixtures prove the two implementations compute the same values; this job
|
|
# proves they can read each other's on-disk profiles and backups.
|
|
cross-implementation:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
cache: pip
|
|
- name: Enable pnpm via corepack
|
|
run: corepack enable
|
|
- name: Install JS dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
working-directory: js
|
|
- name: Install Poetry
|
|
run: pipx install poetry
|
|
- name: Install Python dependencies
|
|
run: poetry install --no-interaction --no-ansi
|
|
- name: Cross-implementation compatibility
|
|
run: poetry run python scripts/cross_impl_check.py
|
|
|
|
# The fixtures are committed, so the parity job never regenerates them.
|
|
# This job proves the committed fixtures actually come from the committed
|
|
# generator: it regenerates from Python and fails on any drift.
|
|
fixture-drift:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.12"
|
|
cache: pip
|
|
- name: Install Poetry
|
|
run: pipx install poetry
|
|
- name: Install dependencies
|
|
run: poetry install --no-interaction --no-ansi
|
|
- name: Regenerate fixtures
|
|
run: poetry run python scripts/generate_ts_port_fixtures.py
|
|
- name: Fail on drift
|
|
# manifest.json records the generating commit, which legitimately
|
|
# differs from the checked-out commit — everything else must match.
|
|
run: >
|
|
git diff --exit-code --
|
|
js/packages/test-vectors/fixtures
|
|
':(exclude)js/packages/test-vectors/fixtures/manifest.json'
|