INTEGRATION-CONTRACT.md

7.3 KB · raw

rendered · source

Test Expansion Integration Contract

Generated by session: test coverage expansion
Agent: claude-sonnet-4-6
Priority 1: T-001–T-010 (10 files), Priority 2: T-011–T-024 (11 files, T-011–T-014 in one file), Priority 3: T-025, T-030, T-037 (3 files)


Test File Index

File T-numbers Asserts Notes
recovery-words.integrity.test.ts T-001 5 Word list structural checks
recovery-words.checksum.test.ts T-002 6 Round-trip, swap, order, length
recovery-words.kek.test.ts T-003 5 HKDF round-trip, zero-pad bytes[16-31]
totp.rfc6238.test.ts T-004 6 RFC 6238 SHA1/256/512, boundary, URI parse
peachPayload.bomb.test.ts T-005 4 MV-4 length-bomb, decompressZstd NOT called
backup.nfc-fallback.test.ts T-006 5 LV-1 NFD-sealed unlocked with NFC
pdf-import.sandbox.test.ts T-007 4 MV-9 pdf.js hardened flags
messages.batch-sanitize.test.ts T-008 6 PCH-01-016 canary/tag sanitization
license.verification.test.ts T-009 6 live + 2 todo Ed25519 verify, structural checks
chirp-transport.probe.test.ts T-010 3 PCH-01-018 no-msg3 identity leak
content.orchestration.test.ts T-011–T-014 0 live + 11 todo All stubs (index.ts exports nothing)
passkey.ed25519.test.ts T-015 7 Ed25519 COSE, sign, verify, replay
vault.rotate-sync-identity.test.ts T-016 7 MV-8 rotation: new key, clear peers, recovery pending
codex.multistripe.test.ts T-017 5 Multi-stripe RS round-trip + erasure
vault.corruption.test.ts T-018 5 live + 1 todo corrupted vs wrong_key discrimination
argon2id.kat.test.ts T-019 6 (1 skipped until KAT generated) KDF params, determinism, NFC
sync.disconnect.test.ts T-020 4 PCH-01-026 #9 onerror/onclose
import.csv.formulainjection.test.ts T-021 6 Formula-injection round-trip
messages.edit-origin.test.ts T-022 5 GET_ENTRY_FOR_EDIT origin check, includeAll guard
vault.consolidate-passkeys.test.ts T-023 4 mergePasskeyOnlyIntoLogins lastUsed sort
vault.purge-trash.test.ts T-024 5 Retention cutoff, 0-day guard, count
generate.empty-pool.test.ts T-025 8 Empty pool fallback, 128-char, min/max
ml.predictbatch.test.ts T-030 8 Batch sizes, softmax stability
clipboard.double-failure.test.ts T-037 4 alreadyWritten skip, double-fail no throw

Total: 24 test files, ~150 live assertions, ~13 todos


Real Crypto vs. Mocked Crypto (Priority 1)

All Priority 1 tests use real cryptographic primitives:

Test Crypto used Notes
T-001 None Word list structural
T-002 SubtleCrypto AES-GCM, HKDF, BLAKE2s Via recovery-words.ts
T-003 SubtleCrypto HKDF, AES-GCM Via recovery-words.ts
T-004 HMAC-SHA1/256/512 Via otpauth library
T-005 Argon2id (m=65536, t=3, p=4), AES-GCM vi.mock("../../crypto/zstd") for decompressZstd spy only
T-006 Argon2id, AES-GCM Via backup.ts / derivePeachExportKey
T-007 None vi.mock("pdfjs-dist") — testing flag plumbing only
T-008 Argon2id, AES-GCM Via full vault setup
T-009 Ed25519 sign/verify Local validateLicenseWithKey re-impl; prod validateLicense for structural checks
T-010 Curve25519 DH (Noise NK) Via noiseNKInitiator + noiseNKResponder

New Dependencies Added

These dependencies are used in the draft tests but are already present in package.json:

No new npm dependencies are required.


Source Refactoring Recommendations

Required for T-011–T-014 (content orchestration) — HIGH PRIORITY

src/content/index.ts exports nothing. All orchestration state and functions are module-private. To make the autofill orchestration tests runnable:

// src/content/index.ts — add these exports

export { handleFieldInteraction }       // T-012
export { initialScan }                  // T-013
export { wasAlreadyFilled }             // T-011

export const _testSeam = {
  getLastDismissedField(): HTMLInputElement | null { return lastDismissedField; },
  setLastDismissedField(f: HTMLInputElement | null): void { lastDismissedField = f; },
  isDismissLocked(): boolean { return dismissLock !== null; },
  DISMISS_LOCK_MS,
} as const;

Additionally, the vitest environment for this file must be switched to jsdom:

// vitest.config.ts
environmentMatchGlobs: [
  ['src/drafts/TEST-EXPANSION/content.orchestration.test.ts', 'jsdom'],
]

Required for T-009f/g (license + chrome storage)

Add validateLicenseWithKey(keyString: string, pubKeyHex: string) as an exported helper in src/background/license.ts with injectable public key. Currently the public key is hardcoded in a private importPublicKey() closure.

Required for T-018f (consumeLastUnlockFailureReason integration)

The test needs chrome.storage mock setup identical to T-008/T-016. The it.todo can be promoted to a live test using the same mock pattern.

Recommended for T-019a (Argon2id KAT)

Add a script at scripts/gen-argon2id-kat.ts to generate the expected hash vector and update KAT_EXPECTED_HEX in argon2id.kat.test.ts. Run once and commit. See the inline documentation in the test for the script body.


Environment Requirements

Test file Environment Notes
All current tests node (default vitest env) —
content.orchestration.test.ts jsdom required Needs environmentMatchGlobs
sync.disconnect.test.ts node Uses vi.stubGlobal("WebSocket", ...)

CI/Exclusion Configuration

The vitest.config.ts already excludes src/drafts/** from CI runs:

exclude: ["src/drafts/**"]

Draft tests do not run automatically. To promote a test file to CI, move it from src/drafts/TEST-EXPANSION/ to the canonical location beside its source (e.g., src/background/vault.rotate-sync-identity.test.ts) and remove it from the drafts directory.


T-numbers Not Implemented

The following Priority 3 test numbers from the brief were not implemented in this session (available for follow-up):


Summary Statistics

Category Count
Priority 1 files 10
Priority 2 files 11
Priority 3 files 3
Total draft files 24
Live assertions (approx.) ~150
it.todo stubs ~13
Tests using real crypto All P1 (except T-007 which tests flag plumbing)
Tests requiring source refactoring T-011–T-014 (index.ts exports)