Journal refs are plain pointers — no checksum ceremony for agents

Tamper-evidence stays internal to the stores; agents just reference files.
This commit is contained in:
Rohit C Prasad
2026-08-16 06:55:29 -07:00
committed by Rohit P
parent 1d12fe96d2
commit 054f807d4e
4 changed files with 13 additions and 14 deletions
+2 -3
View File
@@ -123,9 +123,8 @@ class JournalStore:
raise BoardError(f"unknown entry kind: {kind} (use one of {JOURNAL_KINDS})")
if len(body) > JOURNAL_BODY_LIMIT:
raise BoardError(
f"entry body over {JOURNAL_BODY_LIMIT} chars — store the full"
" payload as an artifact and journal an excerpt with a"
" sha256-qualified ref"
f"entry body over {JOURNAL_BODY_LIMIT} chars — save the full"
" capture to a file and journal an excerpt that references it"
)
with self._lock:
exists = self._case_exists(case)
+2 -2
View File
@@ -64,11 +64,11 @@ LINK_KINDS = ("parent", "blocks") # link(src, "parent", dst): dst is src's pare
# `note` is any observation — the journal is not only for investigations. `raw` is
# a capture (log excerpt, command output); reads skip raw unless asked, and large
# payloads belong in the artifact store with a sha256-qualified ref on the entry.
# payloads belong in a file the entry references.
JOURNAL_KINDS = ("finding", "evidence", "decision", "note", "raw")
# An entry body is an excerpt/summary, never a blob: oversized payloads make every
# chain-verify and unfiltered read drag. Full captures go to the artifact store.
# read (and replay) drag. Full captures live as files the entry points at.
JOURNAL_BODY_LIMIT = 16_000
+5 -5
View File
@@ -166,11 +166,11 @@ def journal_tools(
refs: Optional[list] = None,
) -> dict:
"""Append an entry to a journal case as you work: kind is finding,
evidence, decision, note (any observation), or raw (a capture — put an
excerpt here and store the full payload as an artifact, referenced with
a sha256-qualified ref). `entities` are the concrete things it is about
(file paths, resource names, CVE ids) — they power later recall;
`refs` are pointers (file:line, commit, url, artifact)."""
evidence, decision, note (any observation), or raw (a capture like a log
excerpt — for large captures, save the full output to a file and journal
an excerpt that references it). `entities` are the concrete things it is
about (file paths, resource names, CVE ids) — they power later recall;
`refs` are pointers (file:line, commit, url)."""
return _call(
journal.append,
actor,
+4 -4
View File
@@ -130,15 +130,15 @@ def test_raw_captures_are_opt_in_on_read(journal):
journal.append(LEAD, "ops", "deploy finished 14:01", kind="note")
journal.append(
LEAD, "ops", "nginx 5xx burst 14:02-14:04 (2,400 lines)", kind="raw",
refs=["artifact:sha256:ab12...:nginx-error.log"],
refs=["logs/nginx-error-1402.log"],
)
assert len(journal.read(LEAD, "ops")) == 1 # raw skipped by default
assert len(journal.read(LEAD, "ops", include_raw=True)) == 2
assert journal.read(LEAD, "ops", kind="raw")[0]["refs"][0].startswith("artifact:")
assert journal.read(LEAD, "ops", kind="raw")[0]["refs"] == ["logs/nginx-error-1402.log"]
def test_oversized_bodies_are_refused_with_the_artifact_pattern(journal):
with pytest.raises(BoardError, match="artifact"):
def test_oversized_bodies_are_refused_with_the_excerpt_pattern(journal):
with pytest.raises(BoardError, match="excerpt"):
journal.append(LEAD, "ops", "x" * (JOURNAL_BODY_LIMIT + 1), kind="raw")