forked from ChelseaKR/habitable
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_vault_capture.py
More file actions
87 lines (70 loc) · 3.14 KB
/
Copy pathtest_vault_capture.py
File metadata and controls
87 lines (70 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright 2026 Chelsea Kelly-Reif
"""Encrypted vault lifecycle and the capture pipeline."""
from __future__ import annotations
from collections.abc import Callable
from pathlib import Path
import pytest
from habitable.capture import capture, resolve_deferred
from habitable.errors import HabitableError, VaultError
from habitable.tsa import DevTSA, LocalRfc3161TSA
from habitable.vault import Vault
def test_create_open_round_trip(make_vault: Callable[..., Vault], tmp_path: Path) -> None:
vault = make_vault()
issue = vault.document.add_issue(category="mold", issue_id="i1")
vault.save()
reopened = Vault.open(tmp_path / "vault", "test-passphrase")
assert [i.issue_id for i in reopened.document.issues()] == [issue]
assert reopened.document.get_meta("unit") == "4B"
def test_wrong_passphrase_rejected(make_vault: Callable[..., Vault], tmp_path: Path) -> None:
make_vault()
with pytest.raises(HabitableError):
Vault.open(tmp_path / "vault", "wrong")
def test_double_create_rejected(make_vault: Callable[..., Vault], tmp_path: Path) -> None:
make_vault()
with pytest.raises(VaultError):
Vault.create(tmp_path / "vault", "x", case_id="c")
def test_online_capture_is_timestamped(
make_vault: Callable[..., Vault],
make_jpeg: Callable[..., Path],
local_tsa: LocalRfc3161TSA,
) -> None:
vault = make_vault()
issue = vault.document.add_issue(category="mold", issue_id="i1")
result = capture(vault, make_jpeg(with_location=True), issue_id=issue, tsa=local_tsa)
assert result.timestamped and result.had_location
assert result.timestamp_info is not None
assert vault.get_token(result.capture_id) is not None
assert vault.custody.verify().ok
def test_offline_capture_defers_then_resolves(
make_vault: Callable[..., Vault],
make_jpeg: Callable[..., Path],
dev_tsa: DevTSA,
) -> None:
vault = make_vault()
issue = vault.document.add_issue(category="mold", issue_id="i1")
result = capture(vault, make_jpeg(), issue_id=issue, tsa=None)
assert not result.timestamped
assert len(vault.deferred()) == 1
resolved = resolve_deferred(vault, dev_tsa)
assert len(resolved) == 1 and resolved[0].timestamped
assert len(vault.deferred()) == 0
assert vault.get_token(result.capture_id) is not None
def test_sealed_original_fixity_on_read(
make_vault: Callable[..., Vault],
make_jpeg: Callable[..., Path],
local_tsa: LocalRfc3161TSA,
) -> None:
vault = make_vault()
issue = vault.document.add_issue(category="mold", issue_id="i1")
result = capture(vault, make_jpeg(), issue_id=issue, tsa=local_tsa)
capture_record = vault.document.captures()[0]
raw = vault.read_original(result.capture_id, capture_record.content_hash)
assert len(raw) > 0
# Corrupt the encrypted sealed original on disk -> read must fail loudly.
sealed = vault.path / "originals" / f"{result.capture_id}.enc"
data = bytearray(sealed.read_bytes())
data[-1] ^= 0xFF
sealed.write_bytes(bytes(data))
with pytest.raises(HabitableError):
vault.read_original(result.capture_id, capture_record.content_hash)