Skip to content

P5 audit remediation: backup KDF portability, migration drift test, deviation log - #28

Merged
tyler-rich merged 2 commits into
claude/audit-fixes-2026-07-05-9bqe6n-p4from
claude/audit-fixes-2026-07-05-9bqe6n-p5
Jul 6, 2026
Merged

P5 audit remediation: backup KDF portability, migration drift test, deviation log#28
tyler-rich merged 2 commits into
claude/audit-fixes-2026-07-05-9bqe6n-p4from
claude/audit-fixes-2026-07-05-9bqe6n-p5

Conversation

@tyler-rich

@tyler-rich tyler-rich commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Implements the P5 tier of docs/reviews/full-audit-2026-07-05.md §10 (maintainability, process, long tail).

Stacked on #27 (P4). Base is the P4 branch so this PR's diff shows only P5. This is the final tier of the audit remediation.

Concrete fixes (with tests)

  • item (g) — backup KDF portability (§9). Restore now derives the passphrase key from the bundle's advertised scrypt parameters (kdf.n/r/p) instead of the module constants, so a bundle written under a different (e.g. older) work factor still restores. derive_key / passphrase_cipher take explicit, validated n/r/p (defaulting to the current constants for new backups); restore_bundle passes the recorded values. Tests cover parameterized derivation, invalid-param rejection, a low-param round-trip, and a bundle whose recorded n is honored (tampering it fails the restore).
  • QUA-23 — migration drift test (§7). New tests/test_migrations.py runs the real Alembic chain to head against a throwaway database and asserts the resulting tables/columns match Base.metadata — the rest of the suite builds the schema via create_all, so a migration that drifts from the models would otherwise pass unnoticed. alembic/env.py now respects a caller-provided sqlalchemy.url so the test can target its own DB.

On your item (g) question

I checked before touching the KDF code: this environment has no backup bundles at all (/data is absent; zero .scryebak files anywhere), so nothing is already unrestorable — there is no pre-2^15→2^17-bump bundle to regenerate. This fix is forward-looking: future work-factor changes won't strand existing bundles.

Required deviation-logging debt (logged regardless of fix)

Per CLAUDE.md, dated docs/PLAN.md § Deviations entries were added for the four un-logged divergences the audit named: FE-2 (hand-rolled API client), INF-10 (HIGH/CRITICAL-only dogfood floor), API-12 (created_at vs started_at scans index), FEAT-4 (DB-schedule actuation dropped from Phase 6 — now actually implemented in P3).

Explicitly deferred (recorded with rationale, not half-done)

  • QUA-4 / QUA-9 — consolidating the four secret-CRUD routers + standardizing the list envelope is a broad multi-endpoint refactor; deferred to a dedicated change to keep this batch reviewable.
  • QUA-16 — a type checker in CI first needs the existing annotation gaps (QUA-17) resolved; deferred rather than shipped red.
  • FE-10 — a frontend test runner (vitest) is still absent; the new lib/dates.ts is a natural first target. Deferred to keep P5 scoped.

Testing

Full backend suite: 440 passed. ruff + black clean.

…ion drift test, deviation log

Addresses the P5 tier of docs/reviews/full-audit-2026-07-05.md §10 (maintainability,
process, long tail):

- item (g): backup restore derives the passphrase key from the bundle's advertised
  scrypt params (kdf.n/r/p) instead of the module constants, so a bundle written
  under a different (e.g. older) work factor still restores. derive_key /
  passphrase_cipher take explicit, validated n/r/p; restore passes the recorded
  values.
- QUA-23: new tests/test_migrations.py runs the real Alembic chain to head against a
  throwaway DB and asserts the tables/columns match Base.metadata (the rest of the
  suite builds via create_all). alembic/env.py now respects a caller-provided URL.

Deviation-logging debt recorded in docs/PLAN.md (required regardless of fix):
FE-2 (hand-rolled API client), INF-10 (HIGH/CRITICAL dogfood floor), API-12
(created_at vs started_at index), FEAT-4 (DB-schedule actuation). QUA-4/QUA-9,
QUA-16, and FE-10 are explicitly deferred with rationale.
Per user decision (2026-07-05): keep the merged-PR-only :dev publish trigger for
now — while the repo is private, fork-based contributions can't happen, so the
fork-secrets gap can't be triggered. Record in docs/PLAN.md that INF-2 must be
revisited specifically before the repo is made public, since that is the event
that enables fork PRs (and therefore the actual bug). INF-3's CLAUDE.md wording
stays matched to the current trigger.
@tyler-rich
tyler-rich force-pushed the claude/audit-fixes-2026-07-05-9bqe6n-p5 branch from 6fd0808 to a09c324 Compare July 6, 2026 04:20
@tyler-rich
tyler-rich merged commit 879b544 into claude/audit-fixes-2026-07-05-9bqe6n-p4 Jul 6, 2026
4 checks passed
@tyler-rich
tyler-rich deleted the claude/audit-fixes-2026-07-05-9bqe6n-p5 branch July 6, 2026 06:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant