mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-01 18:32:05 +00:00
TS port slice 7: entry modify/archive/links + util generate-password
- core entryMod: modify_entry port with the per-kind allowed-field matrix, policy merging, blacklisted-field cleanup and timestamp touching; archive/restore; typed links (add/remove/get with Python's normalization, dedupe on target/relation/note, self-link and missing-target refusal). - Parity fixture entry_mods.json: the real Python EntryManager applies a 10-op modification sequence at a later pinned clock; TS replays the same ops from the creation state and matches byte-for-byte. - CLI: entry modify/archive/unarchive/links/link-add/link-remove, entry totp-codes (explicit egress, honors --at and archived state), util generate-password (Python parity: index 0 + gen v1 defaults, full policy flags — v1/v2 outputs verified against password fixtures). - capabilities: egress command list updated. - 148 core parity tests (Node + jsdom) + 22 CLI tests green. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
1 parent
774c992153
commit
4f2b8a79bf
11 files changed
+868
-9
No files matched your search
@@ -335,8 +335,12 @@ def gen_index_keys() -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _build_entries_index() -> dict:
|
||||
"""Build a real entries index with one entry of each kind, timestamps pinned."""
|
||||
def _build_entries_index(post_add=None) -> dict:
|
||||
"""Build a real entries index with one entry of each kind, timestamps pinned.
|
||||
|
||||
``post_add(em)`` runs extra EntryManager operations before the index is
|
||||
read back (used by the modification-parity fixture).
|
||||
"""
|
||||
from seedpass.core.backup import BackupManager
|
||||
from seedpass.core.config_manager import ConfigManager
|
||||
from seedpass.core.entry_management import EntryManager
|
||||
@@ -385,6 +389,9 @@ def _build_entries_index() -> dict:
|
||||
em.add_managed_account("example-managed", mnemonic)
|
||||
em.add_pgp_key("example-pgp", mnemonic, user_id="[email protected]")
|
||||
|
||||
if post_add is not None:
|
||||
post_add(em)
|
||||
|
||||
index = vault.load_index()
|
||||
entries = {
|
||||
k: v for k, v in index.items() if k != "_system"
|
||||
@@ -978,6 +985,51 @@ def gen_nostr_events(snapshot: dict, delta_replay: dict) -> dict:
|
||||
}
|
||||
|
||||
|
||||
MOD_UNIX = FIXED_UNIX + 100
|
||||
|
||||
|
||||
def gen_entry_mods() -> dict:
|
||||
"""Apply a modification sequence via the real EntryManager and capture
|
||||
the result; TS replicates the same ops and must match byte-for-byte."""
|
||||
from seedpass.core.entry_management import EntryManager
|
||||
|
||||
def mods(em: EntryManager) -> None:
|
||||
# Later timestamp so touched entries visibly differ from creation
|
||||
EntryManager._now_unix = staticmethod(lambda: MOD_UNIX)
|
||||
em.modify_entry(
|
||||
0,
|
||||
username="alice2",
|
||||
url="https://example.org",
|
||||
notes="updated note",
|
||||
tags=["web", "prod"],
|
||||
min_digits=3,
|
||||
special_mode="safe",
|
||||
)
|
||||
em.modify_entry(1, period=60, digits=8)
|
||||
em.modify_entry(5, label="api-token-renamed", value="rotated-value")
|
||||
em.archive_entry(6)
|
||||
em.restore_entry(6)
|
||||
em.archive_entry(3)
|
||||
em.add_link(0, 1, relation="totp", note="2fa for site")
|
||||
em.add_link(0, 5, relation="related_to")
|
||||
em.add_link(5, 0)
|
||||
em.remove_link(0, 5)
|
||||
|
||||
entries = _build_entries_index(post_add=mods)
|
||||
return {
|
||||
"description": (
|
||||
"Entries index after a modification sequence (modify_entry, "
|
||||
"archive/restore, add_link/remove_link) applied by the real "
|
||||
"EntryManager at MOD_UNIX. TS replays the same ops from the "
|
||||
"creation state and must match."
|
||||
),
|
||||
"fixed_unix": FIXED_UNIX,
|
||||
"mod_unix": MOD_UNIX,
|
||||
"mnemonic_id": PRIMARY,
|
||||
"entries": entries,
|
||||
}
|
||||
|
||||
|
||||
def gen_kdf_metadata() -> dict:
|
||||
return {
|
||||
"description": (
|
||||
@@ -1029,6 +1081,7 @@ def main() -> None:
|
||||
files["nostr_snapshot.json"] = gen_nostr_snapshot(vault_fixture["payload_b64"])
|
||||
files["portable_backup.json"] = gen_portable_backup(entries_fixture["entries"])
|
||||
files["entry_secrets.json"] = gen_entry_secrets()
|
||||
files["entry_mods.json"] = gen_entry_mods()
|
||||
files["sync_merge.json"] = gen_sync_merge()
|
||||
files["delta_replay.json"] = gen_delta_replay()
|
||||
files["nostr_events.json"] = gen_nostr_events(
|
||||
|
||||
Reference in new issue
Block a user