mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-10-28 08:22:03 +00:00
`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
200 lines
7.2 KiB
YAML
200 lines
7.2 KiB
YAML
name: TypeScript Parity
|
|
|
|
on:
|
|
push:
|
|
branches: ["**"]
|
|
paths:
|
|
- "js/**"
|
|
- "src/**"
|
|
- "scripts/generate_ts_port_fixtures.py"
|
|
- "scripts/cross_impl_check.py"
|
|
- "scripts/differential_fuzz.py"
|
|
- ".github/workflows/ts-parity.yml"
|
|
pull_request:
|
|
branches: ["**"]
|
|
paths:
|
|
- "js/**"
|
|
- "src/**"
|
|
- "scripts/generate_ts_port_fixtures.py"
|
|
- "scripts/cross_impl_check.py"
|
|
- "scripts/differential_fuzz.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
|
|
- name: Build the distributable CLI
|
|
run: pnpm --filter @seedpass/cli build
|
|
- name: Smoke-test the bundle standalone
|
|
# Run from a directory with no node_modules to prove the bundle
|
|
# carries everything it needs.
|
|
run: |
|
|
set -eu
|
|
BIN="$PWD/packages/cli/dist/seedpass-js.mjs"
|
|
APP_DIR="$(mktemp -d)"
|
|
cd "$(mktemp -d)"
|
|
node "$BIN" --version
|
|
node "$BIN" capabilities > /dev/null
|
|
export SEEDPASS_APP_DIR="$APP_DIR"
|
|
export SEEDPASS_MNEMONIC="abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
|
|
export SEEDPASS_PASSWORD="ci-smoke-password"
|
|
node "$BIN" fingerprint add --name ci > /dev/null
|
|
node "$BIN" entry add password ci-site --length 16 > /dev/null
|
|
test -n "$(node "$BIN" entry reveal ci-site)"
|
|
- name: Verify the packed npm tarball installs and runs
|
|
# `files`/`exports` mistakes only surface at install time: a package
|
|
# that omits its entry point still builds and tests fine here.
|
|
run: |
|
|
set -eu
|
|
pnpm --filter @seedpass/cli pack --pack-destination "$RUNNER_TEMP"
|
|
TARBALL="$(ls "$RUNNER_TEMP"/seedpass-cli-*.tgz)"
|
|
mkdir -p "$RUNNER_TEMP/packtest" && cd "$RUNNER_TEMP/packtest"
|
|
npm init -y > /dev/null
|
|
npm install "$TARBALL" > /dev/null
|
|
./node_modules/.bin/seedpass-js --version
|
|
- name: Upload CLI bundle
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: seedpass-js-cli
|
|
path: |
|
|
js/packages/cli/dist/seedpass-js.mjs
|
|
js/packages/cli/dist/seedpass-js.mjs.sha256
|
|
|
|
javascript-supply-chain:
|
|
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: Audit dependencies
|
|
# The Python side has had a dependency audit for a while; the
|
|
# JavaScript tree had none.
|
|
run: pnpm audit --audit-level moderate
|
|
- name: Generate a CycloneDX SBOM
|
|
run: |
|
|
npx --yes @cyclonedx/cyclonedx-npm@latest \
|
|
--output-format JSON \
|
|
--output-file "$RUNNER_TEMP/seedpass-js-sbom.json" \
|
|
--package-lock-only || echo "SBOM generation failed (non-fatal)"
|
|
- name: Upload SBOM
|
|
uses: actions/upload-artifact@v4
|
|
if: always()
|
|
with:
|
|
name: seedpass-js-sbom
|
|
path: ${{ runner.temp }}/seedpass-js-sbom.json
|
|
if-no-files-found: warn
|
|
|
|
# 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
|
|
|
|
# Differential fuzzing: random inputs to BOTH implementations, compared as
|
|
# canonical JSON. Fixtures prove agreement on inputs a human chose; this
|
|
# proves it on inputs nobody chose, which is where the bugs that survive to
|
|
# production live. It found a real silent-divergence defect in canonical
|
|
# number encoding the first time it ran at scale.
|
|
differential-fuzz:
|
|
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
|
|
# Fixed seeds so a regression is deterministic and bisectable: the same
|
|
# commit always gets the same cases.
|
|
- name: Differential fuzz (fixed seeds)
|
|
run: |
|
|
for seed in 1 2 3; do
|
|
poetry run python scripts/differential_fuzz.py --cases 150 --seed "$seed"
|
|
done
|
|
# Plus one seed nobody has run before, so the explored input space grows
|
|
# over time instead of freezing at whatever was chosen today. The script
|
|
# prints its seed, so a failure here is still reproducible exactly.
|
|
- name: Differential fuzz (exploratory seed)
|
|
run: |
|
|
poetry run python scripts/differential_fuzz.py \
|
|
--cases 150 --seed "${{ github.run_id }}"
|
|
|
|
# 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'
|