Files
SeedPass/js/packages/core/test/entryOps.test.ts
T
thePR0M3TH3ANandClaude Fable 5 e91d5d0be2 TS port slice 5: agent-blind provisioning, entry-secret parity, nostr app fix
- core entryOps: add* functions for all creatable kinds rebuild the Python
  EntryManager fixture index byte-for-byte under a pinned clock — field
  shapes, id allocation, independent TOTP derivation-index allocation, and
  Python's ISO timestamp format all verified.
- CLI 'entry add password/totp/key-value/document/seed/managed-account/
  nostr': provision-blind — returns the reference and metadata, never the
  secret the entry represents; tests assert the derived password / imported
  secret / child mnemonic appear nowhere in provisioning output.
- Parity bug found and fixed by the new entry_secrets fixtures: nostr ENTRY
  keys derive via the default BIP-85 app 39 path (EntryManager), not app
  1237 (sync client identity); the CLI had used 1237. Reveal values for
  password/TOTP/nostr/seed/managed-account now match Python retrieval.
- 129 core parity tests (Node + jsdom) + 16 CLI tests green.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-13 21:31:32 -04:00

86 lines
3.2 KiB
TypeScript

/**
* Entry-creation parity: rebuild the Python EntryManager-generated fixture
* index from scratch with the same calls and a pinned clock, and require
* deep equality. Any drift in field shapes, index allocation, or timestamp
* formatting fails here.
*/
import { describe, expect, it } from "vitest";
import { entriesIndex, mnemonics } from "@seedpass/test-vectors";
import {
addPasswordEntry,
addTotpDeterministic,
addTotpImported,
addSshKeyEntry,
addNostrKeyEntry,
addKeyValueEntry,
addDocumentEntry,
addSeedEntry,
addManagedAccountEntry,
addPgpKeyEntry,
parseVaultIndex,
type Clock,
type VaultIndex,
} from "@seedpass/core";
const FIXED_UNIX = 1700000000;
const clock: Clock = { nowUnix: () => FIXED_UNIX };
const MNEMONIC = mnemonics["abandon12"]!;
describe("entry creation parity", () => {
it("rebuilds the fixture index byte-for-byte", () => {
const index = { schema_version: 4, entries: {} } as unknown as VaultIndex;
// Mirrors scripts/generate_ts_port_fixtures.py::_build_entries_index
addPasswordEntry(index, "example.com", 16, {
username: "alice",
url: "https://example.com",
notes: "password note",
tags: ["web"],
clock,
});
addTotpDeterministic(index, "example-totp", MNEMONIC, { tags: ["otp"], clock });
addTotpImported(index, "imported-totp", "JBSWY3DPEHPK3PXP", {
period: 45,
digits: 8,
clock,
});
addSshKeyEntry(index, "example-ssh", { notes: "ssh note", clock });
addNostrKeyEntry(index, "example-nostr", { clock });
addKeyValueEntry(index, "api-token", "token", "abc123", { tags: ["api"], clock });
addDocumentEntry(index, "example-doc", "hello fixture world", { clock });
addSeedEntry(index, "example-seed", { wordCount: 24, clock });
addManagedAccountEntry(index, "example-managed", MNEMONIC, { clock });
addPgpKeyEntry(index, "example-pgp", { userId: "[email protected]", clock });
expect(JSON.parse(JSON.stringify(index))).toEqual(entriesIndex.entries);
});
it("produces schema-valid entries", () => {
const index = { schema_version: 4, entries: {} } as unknown as VaultIndex;
addPasswordEntry(index, "x.com", 20, { clock });
addTotpDeterministic(index, "x-totp", MNEMONIC, { clock });
expect(() => parseVaultIndex(JSON.parse(JSON.stringify(index)))).not.toThrow();
});
it("allocates ids and totp derivation indices independently", () => {
const index = { schema_version: 4, entries: {} } as unknown as VaultIndex;
addPasswordEntry(index, "a", 16, { clock });
addPasswordEntry(index, "b", 16, { clock });
const totpId = addTotpDeterministic(index, "t1", MNEMONIC, { clock });
expect(totpId).toBe("2");
const entry = (index.entries as Record<string, { index?: number }>)["2"]!;
expect(entry.index).toBe(0); // first TOTP derivation index despite id 2
addTotpDeterministic(index, "t2", MNEMONIC, { clock });
const entry2 = (index.entries as Record<string, { index?: number }>)["3"]!;
expect(entry2.index).toBe(1);
});
it("rejects invalid imported TOTP secrets", () => {
const index = { schema_version: 4, entries: {} } as unknown as VaultIndex;
expect(() => addTotpImported(index, "bad", "not base32!", { clock })).toThrow(
"Invalid TOTP secret",
);
});
});