mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-02 19:02:06 +00:00
Continues the security-review fixes. Durability and concurrency: - Vault, config, fingerprint-registry and parent-seed writes are now atomic: temp file in the same directory, fsync, rename, then an fsync of the directory. Previously the target was truncated and rewritten in place, so a crash could destroy the vault. - The lock now spans the whole read-modify-write cycle, not just the write. Serializing writes alone still lost changes -- two commands each read the same index, mutated their copy, and wrote in turn. Every mutating command goes through mutateVault(), which holds the lock from open to save. A test runs five concurrent writers and asserts all five entries survive. - 0600 is now enforced on existing files too: writeFile's mode argument only applies on creation, so a loosened vault stayed loosened. - The index is schema-validated before it can reach disk. Path handling: - Profile fingerprints are validated (16 uppercase hex) before being used in any path, and removeProfile additionally checks the resolved directory still sits directly under the app directory. A tampered registry could otherwise have steered a recursive delete elsewhere. - Malformed entries in fingerprints.json are dropped on read. Restore semantics: - `nostr restore` merges remote state into the local vault instead of replacing it. Replacing silently discarded entries created since the last sync; that now requires --replace --yes, and any overwritten vault is copied aside first. - Deltas are bound to the manifest they extend (filtered on the e tag, and re-checked locally), so a relay cannot replay a validly-signed delta from another snapshot lineage into a restore. - Manifest selection breaks created_at ties by relay order, so a same-second republish cannot leave a restore on a stale snapshot. - mergeIndexPayloads gained an index0 option. The default still refuses to merge populated Python atlas state rather than drop it; restore uses preserve-current, keeping the local block verbatim, because Python recomputes canonical views on load and the default would block every restore into a Python-created profile. 193 core + 69 CLI tests green; 36/36 cross-implementation checks green. Co-Authored-By: Claude Fable 5 <[email protected]>
173 lines
3.8 KiB
TypeScript
173 lines
3.8 KiB
TypeScript
/**
|
|
* @seedpass/core — SeedPass protocol core (TypeScript port).
|
|
*
|
|
* Python remains the normative reference until the compatibility matrix is
|
|
* green; see docs/typescript_web_extension_port_plan.md.
|
|
*/
|
|
|
|
export {
|
|
Bip85,
|
|
isValidMnemonic,
|
|
assertValidMnemonic,
|
|
type DeriveEntropyOptions,
|
|
} from "./derive/bip85.js";
|
|
export {
|
|
generatePassword,
|
|
passwordPolicyFromRecord,
|
|
derivePasswordDk,
|
|
type PasswordPolicy,
|
|
LEGACY_PASSWORD_GEN_VERSION,
|
|
CURRENT_PASSWORD_GEN_VERSION,
|
|
MIN_PASSWORD_LENGTH,
|
|
MAX_PASSWORD_LENGTH,
|
|
DEFAULT_PASSWORD_LENGTH,
|
|
SAFE_SPECIAL_CHARS,
|
|
} from "./derive/password.js";
|
|
export { deriveTotpSecret, totpCodeAt, hotp } from "./derive/totp.js";
|
|
export {
|
|
deriveNostrKeys,
|
|
hexToBech32,
|
|
bech32ToHex,
|
|
NOSTR_KEY_APP_ID,
|
|
type NostrKeys,
|
|
} from "./derive/nostr.js";
|
|
export { generateFingerprint } from "./derive/fingerprint.js";
|
|
export {
|
|
derivePgpKey,
|
|
pgpFingerprint,
|
|
PGP_CREATED_AT,
|
|
type PgpKeyPair,
|
|
} from "./derive/pgp.js";
|
|
export {
|
|
deriveSshKeyPair,
|
|
deriveSshEntropy,
|
|
sshPublicKeyOpenSsh,
|
|
type SshKeyPair,
|
|
} from "./derive/ssh.js";
|
|
export { deriveIndexKey, deriveIndexKeyBytes } from "./vault/indexKey.js";
|
|
export { decryptV3, encryptV3, isV3Payload } from "./vault/aead.js";
|
|
export {
|
|
deriveKeyFromPassword,
|
|
deriveKeyFromPasswordArgon2,
|
|
kdfConfigSchema,
|
|
type KdfConfig,
|
|
} from "./vault/passwordKdf.js";
|
|
export { fernetDecrypt, FernetError } from "./vault/fernet.js";
|
|
export { decryptPayload, parseEncryptedFile, type EncryptedFile } from "./vault/payload.js";
|
|
export {
|
|
entrySchema,
|
|
vaultIndexSchema,
|
|
parseVaultIndex,
|
|
customFieldSchema,
|
|
passwordEntrySchema,
|
|
totpEntrySchema,
|
|
sshEntrySchema,
|
|
seedEntrySchema,
|
|
pgpEntrySchema,
|
|
nostrEntrySchema,
|
|
keyValueEntrySchema,
|
|
managedAccountEntrySchema,
|
|
documentEntrySchema,
|
|
UnsupportedSchemaVersionError,
|
|
CURRENT_SCHEMA_VERSION,
|
|
type Entry,
|
|
type VaultIndex,
|
|
} from "./schema/entries.js";
|
|
export {
|
|
applyMigrations,
|
|
needsMigration,
|
|
SchemaMigrationError,
|
|
} from "./schema/migrations.js";
|
|
export {
|
|
importBackup,
|
|
exportBackup,
|
|
portableBackupSchema,
|
|
BackupImportError,
|
|
PORTABLE_FORMAT_VERSION,
|
|
type PortableBackup,
|
|
} from "./vault/portableBackup.js";
|
|
export {
|
|
addPasswordEntry,
|
|
addTotpDeterministic,
|
|
addTotpImported,
|
|
addSshKeyEntry,
|
|
addNostrKeyEntry,
|
|
addKeyValueEntry,
|
|
addDocumentEntry,
|
|
addSeedEntry,
|
|
addManagedAccountEntry,
|
|
addPgpKeyEntry,
|
|
nextIndex,
|
|
nextTotpIndex,
|
|
isoFromUnix,
|
|
systemClock,
|
|
type Clock,
|
|
} from "./vault/entryOps.js";
|
|
export {
|
|
modifyEntry,
|
|
archiveEntry,
|
|
restoreEntry,
|
|
addLink,
|
|
removeLink,
|
|
getLinks,
|
|
normalizeLinks,
|
|
type ModifyChanges,
|
|
type EntryLink,
|
|
type ResolvedLink,
|
|
} from "./vault/entryMod.js";
|
|
export { canonicalJson, canonicalHash } from "./sync/canonical.js";
|
|
export {
|
|
mergeIndexPayloads,
|
|
emptyIndex0,
|
|
safeInt,
|
|
TOMBSTONE_RETENTION_CAP,
|
|
MERGE_STRATEGY,
|
|
type MergeOptions,
|
|
} from "./sync/merge.js";
|
|
export {
|
|
KIND_MANIFEST,
|
|
KIND_SNAPSHOT_CHUNK,
|
|
KIND_DELTA,
|
|
chunkMetaSchema,
|
|
manifestSchema,
|
|
parseManifest,
|
|
prepareSnapshot,
|
|
reassembleSnapshot,
|
|
gzipCompress,
|
|
gzipDecompress,
|
|
deriveKeyIndex,
|
|
manifestIdFromNonce,
|
|
newManifestId,
|
|
ChunkVerificationError,
|
|
type ChunkMeta,
|
|
type Manifest,
|
|
} from "./sync/snapshot.js";
|
|
export {
|
|
computeEventId,
|
|
serializeEventForId,
|
|
signEvent,
|
|
verifyEvent,
|
|
signerPublicKeyHex,
|
|
buildChunkEvent,
|
|
buildManifestEvent,
|
|
buildDeltaEvent,
|
|
reqMessage,
|
|
eventMessage,
|
|
closeMessage,
|
|
parseRelayMessage,
|
|
type NostrEvent,
|
|
type UnsignedEvent,
|
|
type Filter,
|
|
type RelayMessage,
|
|
} from "./sync/events.js";
|
|
export { RelayPool, type PublishResult, type RelayPoolOptions } from "./sync/relay.js";
|
|
export {
|
|
publishSnapshot,
|
|
fetchLatestSnapshot,
|
|
publishDelta,
|
|
fetchDeltasSince,
|
|
type PublishedSnapshot,
|
|
type FetchedSnapshot,
|
|
} from "./sync/syncFlows.js";
|
|
export * from "./util/bytes.js";
|