Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 8m0s
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
105 lines
4.7 KiB
Python
105 lines
4.7 KiB
Python
"""Receipt guards and full-store fingerprints use synthetic records only."""
|
|
|
|
import copy
|
|
from datetime import UTC, datetime, timedelta
|
|
|
|
import pytest
|
|
|
|
from coulomb_social.apps.spaces.date_backfill_operation import (
|
|
_content_lock,
|
|
_set_date,
|
|
execute_date_operation,
|
|
source_fingerprint,
|
|
validate_backup,
|
|
)
|
|
from coulomb_social.apps.spaces.models import Space
|
|
|
|
IMAGE = "forgejo.coulomb.social/coulomb/coulomb-social@sha256:" + "a" * 64
|
|
RECIPIENT = "age1synthetic-public-recipient"
|
|
NOW = datetime(2026, 10, 30, 12, 5, tzinfo=UTC)
|
|
|
|
|
|
def backup():
|
|
key = "platform-pg/application-archives/coulomb-social/synthetic.tar.age"
|
|
return {
|
|
"schema": "platform.application-primary-archive.v1", "application": "coulomb-social",
|
|
"status": "offsite_fetched_verified", "captured_at": "2026-10-30T12:00:00Z",
|
|
"completed_at": "2026-10-30T12:01:00Z", "image": IMAGE, "age_recipient": RECIPIENT,
|
|
"immutable_create": True, "remote_retrieval_verified": True, "version_id": "synthetic-v1",
|
|
"object_key": key, "destination": "s3://railiance-platform-pg-backup/" + key,
|
|
"encrypted_sha256": "b" * 64, "ciphertext_sha256": "b" * 64,
|
|
"database_sha256": "c" * 64, "content_sha256": "d" * 64,
|
|
"encrypted_bytes": 1234, "ciphertext_bytes": 1234,
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize("change", [
|
|
{"status": "uploaded"}, {"remote_retrieval_verified": False}, {"immutable_create": False},
|
|
{"version_id": "null"}, {"image": IMAGE + "0"}, {"age_recipient": "age1other"},
|
|
{"object_key": "platform-pg/application-archives/another/synthetic.tar.age"},
|
|
{"destination": "s3://another/synthetic"}, {"ciphertext_sha256": "e" * 64},
|
|
{"encrypted_bytes": True}, {"ciphertext_bytes": True}, {"database_sha256": "missing"},
|
|
{"captured_at": "2026-10-30T11:00:00Z"}, {"completed_at": "2026-10-31T12:00:00Z"},
|
|
{"captured_at": "2026-10-30T12:02:00Z"},
|
|
])
|
|
def test_stale_unverified_or_changed_backup_metadata_refuses(change):
|
|
receipt = {**backup(), **change}
|
|
with pytest.raises(ValueError):
|
|
validate_backup(receipt, IMAGE, RECIPIENT, now=NOW)
|
|
|
|
|
|
def test_backup_binding_is_stable_and_recovery_retains_original_even_when_old():
|
|
receipt = backup()
|
|
original = copy.deepcopy(receipt)
|
|
digest = validate_backup(receipt, IMAGE, RECIPIENT, now=NOW)
|
|
reordered = dict(reversed(list(receipt.items())))
|
|
assert validate_backup(reordered, IMAGE, RECIPIENT, now=NOW) == digest
|
|
assert receipt == original
|
|
with pytest.raises(ValueError):
|
|
validate_backup(receipt, IMAGE, RECIPIENT, now=NOW + timedelta(days=1))
|
|
assert validate_backup(receipt, IMAGE, RECIPIENT, now=NOW + timedelta(days=1),
|
|
require_fresh=False) == digest
|
|
|
|
|
|
def test_legacy_slug_collision_refuses_even_when_selected_sql_identity_is_exact():
|
|
selected = {"space_id": "selected", "tenant_id": "tenant:a", "space_slug": "same"}
|
|
snapshot = {"rows": {"spaces_space": [
|
|
{"id": "selected", "tenant_id": "tenant:a", "slug": "same", "created_at": NOW},
|
|
{"id": "another", "tenant_id": "tenant:b", "slug": "same", "created_at": NOW},
|
|
]}}
|
|
before = copy.deepcopy(snapshot)
|
|
with pytest.raises(ValueError, match="unambiguous"):
|
|
_set_date(snapshot, {"selection": selected}, "2020-01-01T00:00:00Z")
|
|
assert snapshot == before
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_fingerprints_cover_other_tables_and_all_content_not_only_selected_pages(tmp_path):
|
|
Space.objects.create(tenant_id="tenant:synthetic", slug="synthetic")
|
|
baseline = source_fingerprint(tmp_path)
|
|
assert baseline["tables"] >= 4
|
|
(tmp_path / "arbitrary-unrelated-asset.bin").write_bytes(b"unrelated")
|
|
after_file = source_fingerprint(tmp_path)
|
|
assert after_file["tables_sha256"] == baseline["tables_sha256"]
|
|
assert after_file["files_sha256"] != baseline["files_sha256"]
|
|
Space.objects.update(title="another update")
|
|
after_sql = source_fingerprint(tmp_path)
|
|
assert after_sql["tables_sha256"] != baseline["tables_sha256"]
|
|
assert after_sql["files_sha256"] == after_file["files_sha256"]
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_sqlite_is_observation_only_never_an_execution_backend(tmp_path):
|
|
with pytest.raises(ValueError, match="PostgreSQL execution required"):
|
|
execute_date_operation(tmp_path, {}, tmp_path / "journal.json", {}, {},
|
|
image=IMAGE, recipient=RECIPIENT)
|
|
assert not (tmp_path / "journal.json").exists()
|
|
|
|
|
|
def test_writer_lock_refuses_another_holder_and_never_creates_missing_lock(tmp_path):
|
|
with pytest.raises(FileNotFoundError), _content_lock(tmp_path):
|
|
pass
|
|
assert not list(tmp_path.iterdir())
|
|
(tmp_path / ".writer.lock").touch()
|
|
with _content_lock(tmp_path), pytest.raises(BlockingIOError), _content_lock(tmp_path):
|
|
pass
|