generated from coulomb/repo-seed
feat: persist accountability evidence identities
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from railiance_fabric.accountability_roots import collect_accountability_root_evidence
|
||||
from railiance_fabric.accountability_roots import (
|
||||
AccountabilityEvidenceStore,
|
||||
build_identity_projection,
|
||||
collect_accountability_root_evidence,
|
||||
load_accountability_root_manifest,
|
||||
)
|
||||
from railiance_fabric.cli import main as cli_main
|
||||
from railiance_fabric.schema_validation import draft202012_validator
|
||||
|
||||
@@ -32,6 +37,46 @@ def test_collect_accountability_root_evidence_from_manifest(tmp_path: Path) -> N
|
||||
assert "secret-value" not in json.dumps(secret_root)
|
||||
|
||||
|
||||
def test_identity_projection_is_stable_and_reviewable(tmp_path: Path) -> None:
|
||||
manifest_path = _fixture_manifest(tmp_path)
|
||||
manifest = load_accountability_root_manifest(manifest_path)
|
||||
|
||||
first = build_identity_projection(collect_accountability_root_evidence(manifest_path), manifest)
|
||||
second = build_identity_projection(collect_accountability_root_evidence(manifest_path), manifest)
|
||||
|
||||
validator = draft202012_validator(Path("schemas/accountability-identity-projection.schema.yaml"))
|
||||
assert list(validator.iter_errors(first)) == []
|
||||
|
||||
first_keys = {candidate["stable_key"] for candidate in first["identity_candidates"]}
|
||||
second_keys = {candidate["stable_key"] for candidate in second["identity_candidates"]}
|
||||
assert first_keys == second_keys
|
||||
assert {
|
||||
"Actor",
|
||||
"Fabric",
|
||||
"Repository",
|
||||
"Deployable",
|
||||
"SecretRoot",
|
||||
} <= {candidate["identity_type"] for candidate in first["identity_candidates"]}
|
||||
assert first["candidate_graph"]["nodes"]
|
||||
assert first["candidate_graph"]["edges"]
|
||||
|
||||
|
||||
def test_evidence_store_persists_runs_items_and_identities(tmp_path: Path) -> None:
|
||||
manifest_path = _fixture_manifest(tmp_path)
|
||||
manifest = load_accountability_root_manifest(manifest_path)
|
||||
evidence_run = collect_accountability_root_evidence(manifest_path)
|
||||
projection = build_identity_projection(evidence_run, manifest)
|
||||
store = AccountabilityEvidenceStore(tmp_path / "evidence.sqlite3")
|
||||
|
||||
stored = store.add_evidence_run(evidence_run, projection)
|
||||
latest = store.latest_run()
|
||||
|
||||
assert latest is not None
|
||||
assert latest["id"] == stored["run_id"]
|
||||
assert stored["evidence_count"] == len(store.list_evidence(stored["run_id"]))
|
||||
assert stored["identity_candidate_count"] == len(store.list_identity_candidates(stored["run_id"]))
|
||||
|
||||
|
||||
def test_discover_roots_cli_prints_evidence_json(tmp_path: Path, capsys) -> None:
|
||||
manifest = _fixture_manifest(tmp_path)
|
||||
|
||||
@@ -42,6 +87,29 @@ def test_discover_roots_cli_prints_evidence_json(tmp_path: Path, capsys) -> None
|
||||
assert payload["roots"]
|
||||
|
||||
|
||||
def test_discover_roots_cli_can_print_identities_and_store(tmp_path: Path, capsys) -> None:
|
||||
manifest = _fixture_manifest(tmp_path)
|
||||
store_path = tmp_path / "evidence.sqlite3"
|
||||
|
||||
assert (
|
||||
cli_main(
|
||||
[
|
||||
"discover-roots",
|
||||
"--manifest",
|
||||
str(manifest),
|
||||
"--identity-projection",
|
||||
"--store-db",
|
||||
str(store_path),
|
||||
]
|
||||
)
|
||||
== 0
|
||||
)
|
||||
|
||||
payload = json.loads(capsys.readouterr().out)
|
||||
assert payload["kind"] == "AccountabilityIdentityProjection"
|
||||
assert AccountabilityEvidenceStore(store_path).latest_run() is not None
|
||||
|
||||
|
||||
def _fixture_manifest(tmp_path: Path) -> Path:
|
||||
workspace = tmp_path / "workspace"
|
||||
repo = workspace / "fixture-repo"
|
||||
|
||||
Reference in New Issue
Block a user